Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/lang/Locale.hpp>
30 : : #include <com/sun/star/util/SearchOptions.hpp>
31 : : #include <com/sun/star/util/SearchFlags.hpp>
32 : : #include <i18npool/mslangid.hxx>
33 : : #include <hintids.hxx>
34 : : #include <vcl/svapp.hxx>
35 : : #include <svl/itemiter.hxx>
36 : : #include <svl/whiter.hxx>
37 : : #include <editeng/brkitem.hxx>
38 : : #include <editeng/colritem.hxx>
39 : : #include <editeng/fontitem.hxx>
40 : : #include <fmtpdsc.hxx>
41 : : #include <txatbase.hxx>
42 : : #include <fchrfmt.hxx>
43 : : #include <charfmt.hxx>
44 : : #include <doc.hxx>
45 : : #include <IDocumentUndoRedo.hxx>
46 : : #include <swcrsr.hxx>
47 : : #include <editsh.hxx>
48 : : #include <ndtxt.hxx>
49 : : #include <pamtyp.hxx>
50 : : #include <swundo.hxx>
51 : : #include <crsskip.hxx>
52 : :
53 : :
54 : : using namespace ::com::sun::star;
55 : : using namespace ::com::sun::star::lang;
56 : : using namespace ::com::sun::star::util;
57 : :
58 : : typedef std::set<SwFmt*> SwpFmts;
59 : :
60 : : // Special case for SvxFontItem: only compare the name
61 : 0 : int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
62 : : {
63 [ # # # # ]: 0 : switch( rItem1.Which() )
64 : : {
65 : : case RES_CHRATR_FONT:
66 : 0 : return ((SvxFontItem&)rItem1).GetFamilyName() ==
67 : 0 : ((SvxFontItem&)rItem2).GetFamilyName();
68 : :
69 : : case RES_CHRATR_COLOR:
70 : 0 : return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
71 : 0 : ((SvxColorItem&)rItem2).GetValue() );
72 : : case RES_PAGEDESC:
73 : 0 : return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
74 : 0 : ((SwFmtPageDesc&)rItem2).GetNumOffset() &&
75 : 0 : ((SwFmtPageDesc&)rItem1).GetPageDesc() ==
76 [ # # # # ]: 0 : ((SwFmtPageDesc&)rItem2).GetPageDesc();
77 : : }
78 : 0 : return rItem1 == rItem2;
79 : : }
80 : :
81 : :
82 : 0 : const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
83 : : xub_StrLen nCntntPos )
84 : : {
85 [ # # ]: 0 : while( rPos < rHtsArr.Count() )
86 : : {
87 : 0 : const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
88 : : // the start of an attribute has to be in the section
89 [ # # ]: 0 : if( *pTxtHt->GetStart() >= nCntntPos )
90 : 0 : return pTxtHt; // valid text attribute
91 : : }
92 : 0 : return 0; // invalid text attribute
93 : : }
94 : :
95 : :
96 : 0 : const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
97 : : xub_StrLen nCntntPos )
98 : : {
99 [ # # ]: 0 : while( rPos > 0 )
100 : : {
101 : 0 : const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
102 : : // the start of an attribute has to be in the section
103 [ # # ]: 0 : if( *pTxtHt->GetStart() < nCntntPos )
104 : 0 : return pTxtHt; // valid text attribute
105 : : }
106 : 0 : return 0; // invalid text attribute
107 : : }
108 : :
109 : 0 : void lcl_SetAttrPam( SwPaM& rPam, xub_StrLen nStart, const xub_StrLen* pEnd,
110 : : const sal_Bool bSaveMark )
111 : : {
112 : : xub_StrLen nCntntPos;
113 [ # # ]: 0 : if( bSaveMark )
114 : 0 : nCntntPos = rPam.GetMark()->nContent.GetIndex();
115 : : else
116 : 0 : nCntntPos = rPam.GetPoint()->nContent.GetIndex();
117 : 0 : bool bTstEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
118 : :
119 : 0 : SwCntntNode* pCNd = rPam.GetCntntNode();
120 [ # # ]: 0 : rPam.GetPoint()->nContent.Assign( pCNd, nStart );
121 : 0 : rPam.SetMark(); // Point == GetMark
122 : :
123 : : // Point points to end of search area or end of attribute
124 [ # # ]: 0 : if( pEnd )
125 : : {
126 [ # # ][ # # ]: 0 : if( bTstEnd && *pEnd > nCntntPos )
127 : 0 : rPam.GetPoint()->nContent = nCntntPos;
128 : : else
129 : 0 : rPam.GetPoint()->nContent = *pEnd;
130 : : }
131 : 0 : }
132 : :
133 : : // TODO: provide documentation
134 : : /** search for a text attribute
135 : :
136 : : This function searches in a text node for a given attribute.
137 : : If that is found then the SwPaM contains the section that surrounds the
138 : : attribute (w.r.t. the search area).
139 : :
140 : : @param rTxtNd Text node to search in.
141 : : @param rPam ???
142 : : @param rCmpItem ???
143 : : @param fnMove ???
144 : : @param bValue ???
145 : : @return Returns <true> if found, <false> otherwise.
146 : : */
147 : 0 : sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
148 : : const SfxPoolItem& rCmpItem,
149 : : SwMoveFn fnMove, sal_Bool bValue )
150 : : {
151 [ # # ]: 0 : if ( !rTxtNd.HasHints() )
152 : 0 : return sal_False;
153 : 0 : const SwTxtAttr *pTxtHt = 0;
154 : 0 : sal_Bool bForward = fnMove == fnMoveForward;
155 [ # # ]: 0 : sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
156 : 0 : xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
157 : :
158 [ # # ][ # # ]: 0 : while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
159 [ # # ][ # # ]: 0 : if( pTxtHt->Which() == rCmpItem.Which() &&
[ # # ][ # # ]
[ # # ]
160 [ # # ]: 0 : ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
161 : : {
162 [ # # ][ # # ]: 0 : lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->GetEnd(), bForward );
163 : 0 : return sal_True;
164 : : }
165 : 0 : return sal_False;
166 : : }
167 : :
168 : : /// search for multiple text attributes
169 : : struct _SwSrchChrAttr
170 : : {
171 : : sal_uInt16 nWhich;
172 : : xub_StrLen nStt, nEnd;
173 : :
174 : 0 : _SwSrchChrAttr( const SfxPoolItem& rItem,
175 : : xub_StrLen nStart, xub_StrLen nAnyEnd )
176 : 0 : : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
177 : 0 : {}
178 : : };
179 : :
180 : : class SwAttrCheckArr
181 : : {
182 : : _SwSrchChrAttr *pFndArr, *pStackArr;
183 : : xub_StrLen nNdStt, nNdEnd;
184 : : sal_uInt16 nArrStart, nArrLen;
185 : : sal_uInt16 nFound, nStackCnt;
186 : : SfxItemSet aCmpSet;
187 : : sal_Bool bNoColls;
188 : : sal_Bool bForward;
189 : :
190 : : public:
191 : : SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
192 : : ~SwAttrCheckArr();
193 : :
194 : : void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
195 : :
196 : : /// how many attributes are there in total?
197 : 0 : sal_uInt16 Count() const { return aCmpSet.Count(); }
198 : 0 : int Found() const { return nFound == aCmpSet.Count(); }
199 : : int CheckStack();
200 : :
201 : : xub_StrLen Start() const;
202 : : xub_StrLen End() const;
203 : :
204 : 0 : xub_StrLen GetNdStt() const { return nNdStt; }
205 : 0 : xub_StrLen GetNdEnd() const { return nNdEnd; }
206 : :
207 : : int SetAttrFwd( const SwTxtAttr& rAttr );
208 : : int SetAttrBwd( const SwTxtAttr& rAttr );
209 : : };
210 : :
211 : :
212 : :
213 : 0 : SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
214 : : int bNoCollections )
215 : 0 : : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
216 : : {
217 [ # # ]: 0 : aCmpSet.Put( rSet, sal_False );
218 : 0 : bNoColls = 0 != bNoCollections;
219 : :
220 : 0 : bForward = 0 != bFwd;
221 : :
222 : : // determine area of Fnd/Stack array (Min/Max)
223 [ # # ]: 0 : SfxItemIter aIter( aCmpSet );
224 [ # # ]: 0 : nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
225 [ # # ]: 0 : nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
226 : :
227 [ # # ]: 0 : char* pFndChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
228 [ # # ]: 0 : char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
229 : :
230 : 0 : pFndArr = (_SwSrchChrAttr*)pFndChar;
231 [ # # ]: 0 : pStackArr = (_SwSrchChrAttr*)pStackChar;
232 : 0 : }
233 : :
234 : 0 : SwAttrCheckArr::~SwAttrCheckArr()
235 : : {
236 [ # # ]: 0 : delete[] (char*)pFndArr;
237 [ # # ]: 0 : delete[] (char*)pStackArr;
238 : 0 : }
239 : :
240 : 0 : void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
241 : : {
242 : 0 : memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
243 : 0 : memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
244 : 0 : nFound = 0;
245 : 0 : nStackCnt = 0;
246 : :
247 [ # # ]: 0 : if( bForward )
248 : : {
249 : 0 : nNdStt = rPam.GetPoint()->nContent.GetIndex();
250 : 0 : nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
251 : 0 : ? rPam.GetMark()->nContent.GetIndex()
252 [ # # ]: 0 : : rTxtNd.GetTxt().Len();
253 : : }
254 : : else
255 : : {
256 : 0 : nNdEnd = rPam.GetPoint()->nContent.GetIndex();
257 : 0 : nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
258 : 0 : ? rPam.GetMark()->nContent.GetIndex()
259 [ # # ]: 0 : : 0;
260 : : }
261 : :
262 [ # # ][ # # ]: 0 : if( bNoColls && !rTxtNd.HasSwAttrSet() )
[ # # ][ # # ]
263 : 0 : return ;
264 : :
265 [ # # ]: 0 : const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
266 : :
267 [ # # ]: 0 : SfxItemIter aIter( aCmpSet );
268 : 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
269 : : const SfxPoolItem* pFndItem;
270 : : sal_uInt16 nWhich;
271 : :
272 : 0 : while( sal_True )
273 : : {
274 [ # # ]: 0 : if( IsInvalidItem( pItem ) )
275 : : {
276 [ # # ]: 0 : nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
277 [ # # ]: 0 : if( RES_TXTATR_END <= nWhich )
278 : 0 : break; // end of text attributes
279 : :
280 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
[ # # ][ # # ]
281 [ # # ][ # # ]: 0 : && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
282 : : {
283 : : pFndArr[ nWhich - nArrStart ] =
284 : 0 : _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
285 : 0 : nFound++;
286 : : }
287 : : }
288 : : else
289 : : {
290 [ # # ]: 0 : if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
291 : 0 : break; // end of text attributes
292 : :
293 [ # # ][ # # ]: 0 : if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
[ # # ]
294 : : {
295 : : pFndArr[ nWhich - nArrStart ] =
296 : 0 : _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
297 : 0 : nFound++;
298 : : }
299 : : }
300 : :
301 [ # # ]: 0 : if( aIter.IsAtEnd() )
302 : 0 : break;
303 [ # # ]: 0 : pItem = aIter.NextItem();
304 [ # # ]: 0 : }
305 : : }
306 : :
307 : : static bool
308 : 0 : lcl_IsAttributeIgnorable(xub_StrLen const nNdStart, xub_StrLen const nNdEnd,
309 : : _SwSrchChrAttr const& rTmp)
310 : : {
311 : : // #i115528#: if there is a paragraph attribute, it has been added by the
312 : : // SwAttrCheckArr ctor, and nFound is 1.
313 : : // if the paragraph is entirely covered by hints that override the paragraph
314 : : // attribute, then this function must find an attribute to decrement nFound!
315 : : // so check for an empty search range, let attributes that start/end there
316 : : // cover it, and hope for the best...
317 : : return ((nNdEnd == nNdStart)
318 : : ? ((rTmp.nEnd < nNdStart) || (nNdEnd < rTmp.nStt))
319 [ # # ][ # # ]: 0 : : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt)));
[ # # ][ # # ]
[ # # ]
320 : : }
321 : :
322 : 0 : int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
323 : : {
324 [ # # ]: 0 : _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
325 : :
326 : : // ignore all attributes not in search range
327 [ # # ]: 0 : if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
328 : : {
329 : 0 : return Found();
330 : : }
331 : :
332 : : const SfxPoolItem* pItem;
333 : : // here we explicitly also search in character templates
334 [ # # ]: 0 : sal_uInt16 nWhch = rAttr.Which();
335 : 0 : SfxWhichIter* pIter = NULL;
336 : 0 : const SfxPoolItem* pTmpItem = NULL;
337 : 0 : const SfxItemSet* pSet = NULL;
338 [ # # ][ # # ]: 0 : if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
339 : : {
340 [ # # ][ # # ]: 0 : if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
341 : 0 : return Found();
342 : 0 : pTmpItem = NULL;
343 [ # # ]: 0 : pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
344 [ # # ]: 0 : if ( pSet )
345 : : {
346 [ # # ][ # # ]: 0 : pIter = new SfxWhichIter( *pSet );
347 [ # # ]: 0 : nWhch = pIter->FirstWhich();
348 [ # # ][ # # ]: 0 : while( nWhch &&
[ # # ]
349 [ # # ]: 0 : SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
350 [ # # ]: 0 : nWhch = pIter->NextWhich();
351 [ # # ]: 0 : if( !nWhch )
352 : 0 : pTmpItem = NULL;
353 : : }
354 : : }
355 : : else
356 : 0 : pTmpItem = &rAttr.GetAttr();
357 [ # # ]: 0 : while( pTmpItem )
358 : : {
359 [ # # ]: 0 : SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
360 [ # # ][ # # ]: 0 : if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
361 : : {
362 : : sal_uInt16 n;
363 : : _SwSrchChrAttr* pCmp;
364 : :
365 : : // first delete all up to start position that are already invalid
366 : : _SwSrchChrAttr* pArrPtr;
367 [ # # ]: 0 : if( nFound )
368 [ # # ]: 0 : for( pArrPtr = pFndArr, n = 0; n < nArrLen;
369 : : ++n, ++pArrPtr )
370 [ # # ][ # # ]: 0 : if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
371 : : {
372 : 0 : pArrPtr->nWhich = 0; // deleted
373 : 0 : nFound--;
374 : : }
375 : :
376 : : // delete all up to start position that are already invalid and
377 : : // move all "open" ones (= stick out over start position) from stack
378 : : // into FndSet
379 [ # # ]: 0 : if( nStackCnt )
380 [ # # ]: 0 : for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
381 : : {
382 [ # # ]: 0 : if( !pArrPtr->nWhich )
383 : 0 : continue;
384 : :
385 [ # # ]: 0 : if( pArrPtr->nEnd <= aTmp.nStt )
386 : : {
387 : 0 : pArrPtr->nWhich = 0; // deleted
388 [ # # ]: 0 : if( !--nStackCnt )
389 : 0 : break;
390 : : }
391 [ # # ]: 0 : else if( pArrPtr->nStt <= aTmp.nStt )
392 : : {
393 [ # # ]: 0 : if( ( pCmp = &pFndArr[ n ])->nWhich )
394 : : {
395 [ # # ]: 0 : if( pCmp->nEnd < pArrPtr->nEnd ) // extend
396 : 0 : pCmp->nEnd = pArrPtr->nEnd;
397 : : }
398 : : else
399 : : {
400 : 0 : *pCmp = *pArrPtr;
401 : 0 : nFound++;
402 : : }
403 : 0 : pArrPtr->nWhich = 0;
404 [ # # ]: 0 : if( !--nStackCnt )
405 : 0 : break;
406 : : }
407 : : }
408 : :
409 : 0 : bool bContinue = false;
410 : :
411 [ # # ]: 0 : if( SFX_ITEM_DONTCARE == eState )
412 : : {
413 : : // Will the attribute become valid?
414 [ # # ][ # # ]: 0 : if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
415 [ # # ]: 0 : *pTmpItem ))
416 : : {
417 : : // search attribute and extend if needed
418 [ # # ]: 0 : if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
419 : : {
420 : 0 : *pCmp = aTmp; // not found, insert
421 : 0 : nFound++;
422 : : }
423 [ # # ]: 0 : else if( pCmp->nEnd < aTmp.nEnd ) // extend?
424 : 0 : pCmp->nEnd = aTmp.nEnd;
425 : :
426 : 0 : bContinue = true;
427 : : }
428 : : }
429 : : // Will the attribute become valid?
430 [ # # ][ # # ]: 0 : else if( CmpAttr( *pItem, *pTmpItem ) )
431 : : {
432 : 0 : pFndArr[ nWhch - nArrStart ] = aTmp;
433 : 0 : ++nFound;
434 : 0 : bContinue = true;
435 : : }
436 : :
437 : : // then is has to go on the stack
438 [ # # ][ # # ]: 0 : if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
[ # # ]
439 : : {
440 : : // exists on stack, only if it is even bigger
441 [ # # ]: 0 : if( pCmp->nEnd > aTmp.nEnd )
442 : : {
443 : : OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
444 : : "slot on stack is still in use" );
445 : :
446 [ # # ]: 0 : if( aTmp.nStt <= pCmp->nStt )
447 : 0 : pCmp->nStt = aTmp.nEnd;
448 : : else
449 : 0 : pCmp->nEnd = aTmp.nStt;
450 : :
451 : 0 : pStackArr[ nWhch - nArrStart ] = *pCmp;
452 : 0 : nStackCnt++;
453 : : }
454 : 0 : pCmp->nWhich = 0;
455 : 0 : nFound--;
456 : : }
457 : : }
458 [ # # ]: 0 : if( pIter )
459 : : {
460 [ # # ]: 0 : nWhch = pIter->NextWhich();
461 [ # # ][ # # ]: 0 : while( nWhch &&
[ # # ]
462 [ # # ]: 0 : SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
463 [ # # ]: 0 : nWhch = pIter->NextWhich();
464 [ # # ]: 0 : if( !nWhch )
465 : 0 : break;
466 : : }
467 : : else
468 : 0 : break;
469 : : }
470 : 0 : return Found();
471 : : }
472 : :
473 : :
474 : 0 : int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
475 : : {
476 [ # # ]: 0 : _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
477 : :
478 : : // ignore all attributes not in search range
479 [ # # ]: 0 : if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
480 : : {
481 : 0 : return Found();
482 : : }
483 : :
484 : : const SfxPoolItem* pItem;
485 : : // here we explicitly also search in character templates
486 [ # # ]: 0 : sal_uInt16 nWhch = rAttr.Which();
487 : 0 : SfxWhichIter* pIter = NULL;
488 : 0 : const SfxPoolItem* pTmpItem = NULL;
489 : 0 : const SfxItemSet* pSet = NULL;
490 [ # # ][ # # ]: 0 : if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
491 : : {
492 [ # # ][ # # ]: 0 : if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
493 : 0 : return Found();
494 : :
495 [ # # ]: 0 : pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
496 [ # # ]: 0 : if ( pSet )
497 : : {
498 [ # # ][ # # ]: 0 : pIter = new SfxWhichIter( *pSet );
499 [ # # ]: 0 : nWhch = pIter->FirstWhich();
500 [ # # ][ # # ]: 0 : while( nWhch &&
[ # # ]
501 [ # # ]: 0 : SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
502 [ # # ]: 0 : nWhch = pIter->NextWhich();
503 [ # # ]: 0 : if( !nWhch )
504 : 0 : pTmpItem = NULL;
505 : : }
506 : : }
507 : : else
508 : 0 : pTmpItem = &rAttr.GetAttr();
509 [ # # ]: 0 : while( pTmpItem )
510 : : {
511 [ # # ]: 0 : SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
512 [ # # ][ # # ]: 0 : if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
513 : : {
514 : : sal_uInt16 n;
515 : : _SwSrchChrAttr* pCmp;
516 : :
517 : : // first delete all up to start position that are already invalid
518 : : _SwSrchChrAttr* pArrPtr;
519 [ # # ]: 0 : if( nFound )
520 [ # # ]: 0 : for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
521 [ # # ][ # # ]: 0 : if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
522 : : {
523 : 0 : pArrPtr->nWhich = 0; // deleted
524 : 0 : nFound--;
525 : : }
526 : :
527 : : // delete all up to start position that are already invalid and
528 : : // move all "open" ones (= stick out over start position) from stack
529 : : // into FndSet
530 [ # # ]: 0 : if( nStackCnt )
531 [ # # ]: 0 : for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
532 : : {
533 [ # # ]: 0 : if( !pArrPtr->nWhich )
534 : 0 : continue;
535 : :
536 [ # # ]: 0 : if( pArrPtr->nStt >= aTmp.nEnd )
537 : : {
538 : 0 : pArrPtr->nWhich = 0; // deleted
539 [ # # ]: 0 : if( !--nStackCnt )
540 : 0 : break;
541 : : }
542 [ # # ]: 0 : else if( pArrPtr->nEnd >= aTmp.nEnd )
543 : : {
544 [ # # ]: 0 : if( ( pCmp = &pFndArr[ n ])->nWhich )
545 : : {
546 [ # # ]: 0 : if( pCmp->nStt > pArrPtr->nStt ) // extend
547 : 0 : pCmp->nStt = pArrPtr->nStt;
548 : : }
549 : : else
550 : : {
551 : 0 : *pCmp = *pArrPtr;
552 : 0 : nFound++;
553 : : }
554 : 0 : pArrPtr->nWhich = 0;
555 [ # # ]: 0 : if( !--nStackCnt )
556 : 0 : break;
557 : : }
558 : : }
559 : :
560 : 0 : sal_Bool bContinue = sal_False;
561 [ # # ]: 0 : if( SFX_ITEM_DONTCARE == eState )
562 : : {
563 : : // Will the attribute become valid?
564 [ # # ][ # # ]: 0 : if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
565 [ # # ]: 0 : *pTmpItem ) )
566 : : {
567 : : // search attribute and extend if needed
568 [ # # ]: 0 : if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
569 : : {
570 : 0 : *pCmp = aTmp; // not found, insert
571 : 0 : nFound++;
572 : : }
573 [ # # ]: 0 : else if( pCmp->nStt > aTmp.nStt ) // extend?
574 : 0 : pCmp->nStt = aTmp.nStt;
575 : :
576 : 0 : bContinue = sal_True;
577 : : }
578 : : }
579 : : // Will the attribute become valid?
580 [ # # ][ # # ]: 0 : else if( CmpAttr( *pItem, *pTmpItem ))
581 : : {
582 : 0 : pFndArr[ nWhch - nArrStart ] = aTmp;
583 : 0 : ++nFound;
584 : 0 : bContinue = sal_True;
585 : : }
586 : :
587 : : // then is has to go on the stack
588 [ # # ][ # # ]: 0 : if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
[ # # ]
589 : : {
590 : : // exists on stack, only if it is even bigger
591 [ # # ]: 0 : if( pCmp->nStt < aTmp.nStt )
592 : : {
593 : : OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
594 : : "slot on stack is still in use" );
595 : :
596 [ # # ]: 0 : if( aTmp.nEnd <= pCmp->nEnd )
597 : 0 : pCmp->nEnd = aTmp.nStt;
598 : : else
599 : 0 : pCmp->nStt = aTmp.nEnd;
600 : :
601 : 0 : pStackArr[ nWhch - nArrStart ] = *pCmp;
602 : 0 : nStackCnt++;
603 : : }
604 : 0 : pCmp->nWhich = 0;
605 : 0 : nFound--;
606 : : }
607 : : }
608 [ # # ]: 0 : if( pIter )
609 : : {
610 [ # # ]: 0 : nWhch = pIter->NextWhich();
611 [ # # ][ # # ]: 0 : while( nWhch &&
[ # # ]
612 [ # # ]: 0 : SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
613 [ # # ]: 0 : nWhch = pIter->NextWhich();
614 [ # # ]: 0 : if( !nWhch )
615 : 0 : break;
616 : : }
617 : : else
618 : 0 : break;
619 : : }
620 : 0 : return Found();
621 : : }
622 : :
623 : :
624 : 0 : xub_StrLen SwAttrCheckArr::Start() const
625 : : {
626 : 0 : xub_StrLen nStart = nNdStt;
627 : 0 : _SwSrchChrAttr* pArrPtr = pFndArr;
628 [ # # ]: 0 : for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
629 [ # # ][ # # ]: 0 : if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
630 : 0 : nStart = pArrPtr->nStt;
631 : :
632 : 0 : return nStart;
633 : : }
634 : :
635 : :
636 : 0 : xub_StrLen SwAttrCheckArr::End() const
637 : : {
638 : 0 : _SwSrchChrAttr* pArrPtr = pFndArr;
639 : 0 : xub_StrLen nEnd = nNdEnd;
640 [ # # ]: 0 : for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
641 [ # # ][ # # ]: 0 : if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
642 : 0 : nEnd = pArrPtr->nEnd;
643 : :
644 : 0 : return nEnd;
645 : : }
646 : :
647 : :
648 : 0 : int SwAttrCheckArr::CheckStack()
649 : : {
650 [ # # ]: 0 : if( !nStackCnt )
651 : 0 : return sal_False;
652 : :
653 : : sal_uInt16 n;
654 : 0 : xub_StrLen nSttPos = Start(), nEndPos = End();
655 : : _SwSrchChrAttr* pArrPtr;
656 [ # # ]: 0 : for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
657 : : {
658 [ # # ]: 0 : if( !pArrPtr->nWhich )
659 : 0 : continue;
660 : :
661 [ # # ][ # # ]: 0 : if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
662 : : {
663 : 0 : pArrPtr->nWhich = 0; // deleted
664 [ # # ]: 0 : if( !--nStackCnt )
665 : 0 : return nFound == aCmpSet.Count();
666 : : }
667 [ # # ][ # # ]: 0 : else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
668 : : {
669 : : // move all "open" ones (= stick out over start position) into FndSet
670 : : OSL_ENSURE( !pFndArr[ n ].nWhich, "slot in array is already in use" );
671 : 0 : pFndArr[ n ] = *pArrPtr;
672 : 0 : pArrPtr->nWhich = 0;
673 : 0 : nFound++;
674 [ # # ]: 0 : if( !--nStackCnt )
675 : 0 : return nFound == aCmpSet.Count();
676 : : }
677 : : }
678 : 0 : return nFound == aCmpSet.Count();
679 : : }
680 : :
681 : :
682 : :
683 : 0 : int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
684 : : SwPaM& rPam )
685 : : {
686 : : xub_StrLen nEndPos, nSttPos;
687 [ # # ]: 0 : rCmpArr.SetNewSet( rTxtNd, rPam );
688 [ # # ]: 0 : if( !rTxtNd.HasHints() )
689 : : {
690 [ # # ]: 0 : if( !rCmpArr.Found() )
691 : 0 : return sal_False;
692 : 0 : nEndPos = rCmpArr.GetNdEnd();
693 [ # # ]: 0 : lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
694 : 0 : return sal_True;
695 : : }
696 : :
697 : 0 : const SwpHints& rHtArr = rTxtNd.GetSwpHints();
698 : : const SwTxtAttr* pAttr;
699 : 0 : sal_uInt16 nPos = 0;
700 : :
701 : : // if everything is already there then check with which it will be ended
702 [ # # ]: 0 : if( rCmpArr.Found() )
703 : : {
704 [ # # ]: 0 : for( ; nPos < rHtArr.Count(); ++nPos )
705 [ # # ][ # # ]: 0 : if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
[ # # ]
706 : : {
707 [ # # ]: 0 : if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
708 : : {
709 : : // found end
710 : 0 : lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
711 [ # # ]: 0 : pAttr->GetStart(), sal_True );
712 : 0 : return sal_True;
713 : : }
714 : : // continue search
715 : 0 : break;
716 : : }
717 : :
718 [ # # ][ # # ]: 0 : if( nPos == rHtArr.Count() && rCmpArr.Found() )
[ # # ]
719 : : {
720 : : // found
721 : 0 : nEndPos = rCmpArr.GetNdEnd();
722 [ # # ]: 0 : lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
723 : 0 : return sal_True;
724 : : }
725 : : }
726 : :
727 [ # # ]: 0 : for( ; nPos < rHtArr.Count(); ++nPos )
728 [ # # ][ # # ]: 0 : if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
[ # # ]
729 : : {
730 : : // Do multiple start at that position? Do also check those:
731 : 0 : nSttPos = *pAttr->GetStart();
732 [ # # ]: 0 : while( ++nPos < rHtArr.Count() && nSttPos ==
[ # # # # ]
[ # # ][ # # ]
733 : 0 : *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
734 [ # # ]: 0 : rCmpArr.SetAttrFwd( *pAttr ) )
735 : : ;
736 [ # # ]: 0 : if( !rCmpArr.Found() )
737 : 0 : continue;
738 : :
739 : : // then we have our search area
740 [ # # ]: 0 : if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
741 : 0 : return sal_False;
742 [ # # ]: 0 : lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
743 : 0 : return sal_True;
744 : : }
745 : :
746 [ # # ][ # # ]: 0 : if( !rCmpArr.CheckStack() ||
[ # # ]
747 : 0 : (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
748 : 0 : return sal_False;
749 [ # # ]: 0 : lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
750 : 0 : return sal_True;
751 : : }
752 : :
753 : :
754 : 0 : int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
755 : : SwPaM& rPam )
756 : : {
757 : : xub_StrLen nEndPos, nSttPos;
758 [ # # ]: 0 : rCmpArr.SetNewSet( rTxtNd, rPam );
759 [ # # ]: 0 : if( !rTxtNd.HasHints() )
760 : : {
761 [ # # ]: 0 : if( !rCmpArr.Found() )
762 : 0 : return sal_False;
763 : 0 : nEndPos = rCmpArr.GetNdEnd();
764 [ # # ]: 0 : lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
765 : 0 : return sal_True;
766 : : }
767 : :
768 : 0 : const SwpHints& rHtArr = rTxtNd.GetSwpHints();
769 : : const SwTxtAttr* pAttr;
770 : 0 : sal_uInt16 nPos = rHtArr.Count();
771 : :
772 : : // if everything is already there then check with which it will be ended
773 [ # # ]: 0 : if( rCmpArr.Found() )
774 : : {
775 [ # # ]: 0 : while( nPos )
776 [ # # ][ # # ]: 0 : if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
[ # # ]
777 : : {
778 [ # # ]: 0 : nSttPos = *pAttr->GetAnyEnd();
779 [ # # ]: 0 : if( nSttPos < rCmpArr.GetNdEnd() )
780 : : {
781 : : // found end
782 : 0 : nEndPos = rCmpArr.GetNdEnd();
783 [ # # ]: 0 : lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
784 : 0 : return sal_True;
785 : : }
786 : :
787 : : // continue search
788 : 0 : break;
789 : : }
790 : :
791 [ # # ][ # # ]: 0 : if( !nPos && rCmpArr.Found() )
[ # # ]
792 : : {
793 : : // found
794 : 0 : nEndPos = rCmpArr.GetNdEnd();
795 [ # # ]: 0 : lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
796 : 0 : return sal_True;
797 : : }
798 : : }
799 : :
800 [ # # ]: 0 : while( nPos )
801 [ # # ][ # # ]: 0 : if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
[ # # ]
802 : : {
803 : : // Do multiple start at that position? Do also check those:
804 [ # # ]: 0 : if( nPos )
805 : : {
806 [ # # ]: 0 : nEndPos = *pAttr->GetAnyEnd();
807 [ # # ][ # # ]: 0 : while( --nPos && nEndPos ==
[ # # ][ # # ]
[ # # ]
808 [ # # ]: 0 : *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
809 [ # # ]: 0 : rCmpArr.SetAttrBwd( *pAttr ) )
810 : : ;
811 : : }
812 [ # # ]: 0 : if( !rCmpArr.Found() )
813 : 0 : continue;
814 : :
815 : : // then we have our search area
816 [ # # ]: 0 : if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
817 : 0 : return sal_False;
818 [ # # ]: 0 : lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
819 : 0 : return sal_True;
820 : : }
821 : :
822 [ # # ][ # # ]: 0 : if( !rCmpArr.CheckStack() ||
[ # # ]
823 : 0 : (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
824 : 0 : return sal_False;
825 [ # # ]: 0 : lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
826 : 0 : return sal_True;
827 : : }
828 : :
829 : :
830 : 0 : int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
831 : : {
832 : : // search only hard attribution?
833 [ # # ][ # # ]: 0 : if( bNoColls && !rCNd.HasSwAttrSet() )
[ # # ][ # # ]
834 : 0 : return sal_False;
835 : :
836 [ # # ]: 0 : const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
837 [ # # ]: 0 : SfxItemIter aIter( rCmpSet );
838 : 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
839 : : const SfxPoolItem* pNdItem;
840 : : sal_uInt16 nWhich;
841 : :
842 : 0 : while( sal_True )
843 : : {
844 [ # # ]: 0 : if( IsInvalidItem( pItem ))
845 : : {
846 [ # # ]: 0 : nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
847 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
[ # # ][ # # ]
848 [ # # ][ # # ]: 0 : || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
849 : 0 : return sal_False;
850 : : }
851 : : else
852 : : {
853 : 0 : nWhich = pItem->Which();
854 : :
855 [ # # ][ # # ]: 0 : if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
[ # # ]
856 : 0 : return sal_False;
857 : : }
858 : :
859 [ # # ]: 0 : if( aIter.IsAtEnd() )
860 : 0 : break;
861 [ # # ]: 0 : pItem = aIter.NextItem();
862 : : }
863 [ # # ]: 0 : return sal_True; // found
864 : : }
865 : :
866 : :
867 : 0 : sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
868 : : const SwPaM *pRegion, sal_Bool bInReadOnly )
869 : : {
870 : : // determine which attribute is searched:
871 : 0 : sal_uInt16 nWhich = rAttr.Which();
872 [ # # ][ # # ]: 0 : int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
873 : :
874 [ # # ]: 0 : SwPaM* pPam = MakeRegion( fnMove, pRegion );
875 : :
876 : 0 : sal_Bool bFound = sal_False;
877 : 0 : sal_Bool bFirst = sal_True;
878 : 0 : sal_Bool bSrchForward = fnMove == fnMoveForward;
879 : : SwCntntNode * pNode;
880 : : const SfxPoolItem* pItem;
881 [ # # ]: 0 : SwpFmts aFmtArr;
882 : :
883 : : // if at beginning/end then move it out of the node
884 [ # # ][ # # ]: 0 : if( bSrchForward
885 [ # # ]: 0 : ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
886 : 0 : : !pPam->GetPoint()->nContent.GetIndex() )
887 : : {
888 [ # # ][ # # ]: 0 : if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
889 : : {
890 [ # # ][ # # ]: 0 : delete pPam;
891 : 0 : return sal_False;
892 : : }
893 : 0 : SwCntntNode *pNd = pPam->GetCntntNode();
894 [ # # ][ # # ]: 0 : xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
895 [ # # ][ # # ]: 0 : pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
896 : : }
897 : :
898 [ # # ][ # # ]: 0 : while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
899 : : {
900 [ # # ]: 0 : if( bCharAttr )
901 : : {
902 [ # # ]: 0 : if( !pNode->IsTxtNode() ) // CharAttr are only in text nodes
903 : 0 : continue;
904 : :
905 [ # # ][ # # ]: 0 : if( ((SwTxtNode*)pNode)->HasHints() &&
[ # # ]
906 [ # # ]: 0 : lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue ))
907 : : {
908 : : // set to the values of the attribute
909 [ # # ]: 0 : SetMark();
910 [ # # ]: 0 : *GetPoint() = *pPam->GetPoint();
911 [ # # ]: 0 : *GetMark() = *pPam->GetMark();
912 : 0 : bFound = sal_True;
913 : 0 : break;
914 : : }
915 [ # # ]: 0 : else if (isTXTATR(nWhich))
916 : 0 : continue;
917 : : }
918 : :
919 : : // no hard attribution, so check if node was asked for this attr before
920 [ # # ][ # # ]: 0 : if( !pNode->HasSwAttrSet() )
921 : : {
922 : 0 : SwFmt* pTmpFmt = pNode->GetFmtColl();
923 [ # # ][ # # ]: 0 : if( aFmtArr.find( pTmpFmt ) != aFmtArr.end() )
[ # # ]
924 : 0 : continue; // collection was requested earlier
925 [ # # ]: 0 : aFmtArr.insert( pTmpFmt );
926 : : }
927 : :
928 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
[ # # ][ # # ]
[ # # ]
929 [ # # ][ # # ]: 0 : sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
930 : : {
931 : : // FORWARD: SPoint at the end, GetMark at the beginning of the node
932 : : // BACKWARD: SPoint at the beginning, GetMark at the end of the node
933 : : // always: incl. start and incl. end
934 [ # # ]: 0 : *GetPoint() = *pPam->GetPoint();
935 [ # # ]: 0 : SetMark();
936 [ # # ]: 0 : pNode->MakeEndIndex( &GetPoint()->nContent );
937 : 0 : bFound = sal_True;
938 : 0 : break;
939 : : }
940 : : }
941 : :
942 : : // if backward search, switch point and mark
943 [ # # ][ # # ]: 0 : if( bFound && !bSrchForward )
944 : 0 : Exchange();
945 : :
946 [ # # ][ # # ]: 0 : delete pPam;
947 : 0 : return bFound;
948 : : }
949 : :
950 : :
951 : : typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
952 : :
953 : 0 : sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
954 : : const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
955 : : {
956 [ # # ]: 0 : SwPaM* pPam = MakeRegion( fnMove, pRegion );
957 : :
958 : 0 : sal_Bool bFound = sal_False;
959 : 0 : sal_Bool bFirst = sal_True;
960 : 0 : sal_Bool bSrchForward = fnMove == fnMoveForward;
961 : : SwCntntNode * pNode;
962 [ # # ]: 0 : SwpFmts aFmtArr;
963 : :
964 : : // check which text/char attributes are searched
965 [ # # ]: 0 : SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
966 : 0 : SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
967 [ # # ]: 0 : RES_PARATR_BEGIN, RES_GRFATR_END-1 );
968 [ # # ]: 0 : aOtherSet.Put( rSet, sal_False ); // got all invalid items
969 : :
970 : : FnSearchAttr fnSearch = bSrchForward
971 : : ? (&::lcl_SearchForward)
972 [ # # ]: 0 : : (&::lcl_SearchBackward);
973 : :
974 : : // if at beginning/end then move it out of the node
975 [ # # ][ # # ]: 0 : if( bMoveFirst &&
[ # # # # ]
[ # # ]
976 : : ( bSrchForward
977 [ # # ]: 0 : ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
978 : 0 : : !pPam->GetPoint()->nContent.GetIndex() ) )
979 : : {
980 [ # # ][ # # ]: 0 : if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
981 : : {
982 [ # # ][ # # ]: 0 : delete pPam;
983 : 0 : return sal_False;
984 : : }
985 : 0 : SwCntntNode *pNd = pPam->GetCntntNode();
986 [ # # ][ # # ]: 0 : xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
987 [ # # ][ # # ]: 0 : pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
988 : : }
989 : :
990 : :
991 [ # # ][ # # ]: 0 : while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
992 : : {
993 [ # # ]: 0 : if( aCmpArr.Count() )
994 : : {
995 [ # # ]: 0 : if( !pNode->IsTxtNode() ) // CharAttr are only in text nodes
996 : 0 : continue;
997 : :
998 [ # # ][ # # ]: 0 : if( (!aOtherSet.Count() ||
[ # # ][ # # ]
999 [ # # ]: 0 : lcl_Search( *pNode, aOtherSet, bNoColls )) &&
1000 [ # # ]: 0 : (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
1001 : : {
1002 : : // set to the values of the attribute
1003 [ # # ]: 0 : SetMark();
1004 [ # # ]: 0 : *GetPoint() = *pPam->GetPoint();
1005 [ # # ]: 0 : *GetMark() = *pPam->GetMark();
1006 : 0 : bFound = sal_True;
1007 : 0 : break;
1008 : : }
1009 : 0 : continue; // text attribute
1010 : : }
1011 : :
1012 [ # # ]: 0 : if( !aOtherSet.Count() )
1013 : 0 : continue;
1014 : :
1015 : : // no hard attribution, so check if node was asked for this attr before
1016 [ # # ][ # # ]: 0 : if( !pNode->HasSwAttrSet() )
1017 : : {
1018 : 0 : SwFmt* pTmpFmt = pNode->GetFmtColl();
1019 [ # # ][ # # ]: 0 : if( aFmtArr.find( pTmpFmt ) != aFmtArr.end() )
[ # # ]
1020 : 0 : continue; // collection was requested earlier
1021 [ # # ]: 0 : aFmtArr.insert( pTmpFmt );
1022 : : }
1023 : :
1024 [ # # ][ # # ]: 0 : if( lcl_Search( *pNode, aOtherSet, bNoColls ))
1025 : : {
1026 : : // FORWARD: SPoint at the end, GetMark at the beginning of the node
1027 : : // BACKWARD: SPoint at the beginning, GetMark at the end of the node
1028 : : // always: incl. start and incl. end
1029 [ # # ]: 0 : *GetPoint() = *pPam->GetPoint();
1030 [ # # ]: 0 : SetMark();
1031 [ # # ]: 0 : pNode->MakeEndIndex( &GetPoint()->nContent );
1032 : 0 : bFound = sal_True;
1033 : 0 : break;
1034 : : }
1035 : : }
1036 : :
1037 : : // if backward search, switch point and mark
1038 [ # # ][ # # ]: 0 : if( bFound && !bSrchForward )
1039 : 0 : Exchange();
1040 : :
1041 [ # # ][ # # ]: 0 : delete pPam;
1042 [ # # ][ # # ]: 0 : return bFound;
1043 : : }
1044 : :
1045 : : /// parameters for search for attributes
1046 : : struct SwFindParaAttr : public SwFindParas
1047 : : {
1048 : : sal_Bool bValue;
1049 : : const SfxItemSet *pSet, *pReplSet;
1050 : : const SearchOptions *pSearchOpt;
1051 : : SwCursor& rCursor;
1052 : : utl::TextSearch* pSTxt;
1053 : :
1054 : 0 : SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
1055 : : const SearchOptions* pOpt, const SfxItemSet* pRSet,
1056 : : SwCursor& rCrsr )
1057 : : : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
1058 : 0 : pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
1059 : :
1060 [ # # ][ # # ]: 0 : virtual ~SwFindParaAttr() { delete pSTxt; }
[ # # ]
1061 : :
1062 : : virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
1063 : : virtual int IsReplaceMode() const;
1064 : : };
1065 : :
1066 : :
1067 : 0 : int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
1068 : : sal_Bool bInReadOnly )
1069 : : {
1070 : : // replace string (only if text given and search is not parameterized)?
1071 : 0 : sal_Bool bReplaceTxt = pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() ||
1072 [ # # # # ]: 0 : !pSet->Count() );
[ # # ]
1073 [ # # ][ # # ]: 0 : sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
1074 : 0 : sal_Bool bMoveFirst = !bReplaceAttr;
1075 [ # # ][ # # ]: 0 : if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
[ # # ]
1076 : 0 : bInReadOnly = sal_False;
1077 : :
1078 : : // We search for attributes, should we search for text as well?
1079 : : {
1080 [ # # ]: 0 : SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
1081 : 0 : SwPaM* pTextRegion = &aRegion;
1082 [ # # ]: 0 : SwPaM aSrchPam( *pCrsr->GetPoint() );
1083 : :
1084 : 0 : while( sal_True )
1085 : : {
1086 [ # # ]: 0 : if( pSet->Count() ) // any attributes?
1087 : : {
1088 : : // first attributes
1089 [ # # ][ # # ]: 0 : if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
1090 : 0 : return FIND_NOT_FOUND;
1091 : 0 : bMoveFirst = sal_True;
1092 : :
1093 [ # # ]: 0 : if( !pSearchOpt )
1094 : 0 : break; // ok, only attributes, so found
1095 : :
1096 : 0 : pTextRegion = &aSrchPam;
1097 : : }
1098 [ # # ]: 0 : else if( !pSearchOpt )
1099 : 0 : return FIND_NOT_FOUND;
1100 : :
1101 : : // then search in text of it
1102 [ # # ]: 0 : if( !pSTxt )
1103 : : {
1104 : 0 : SearchOptions aTmp( *pSearchOpt );
1105 : :
1106 : : // search in selection
1107 : : aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
1108 : 0 : SearchFlags::REG_NOT_ENDOFLINE);
1109 : :
1110 [ # # ]: 0 : MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
1111 : :
1112 [ # # ][ # # ]: 0 : pSTxt = new utl::TextSearch( aTmp );
1113 : : }
1114 : :
1115 : : // TODO: searching for attributes in Outliner text?!
1116 : 0 : sal_Bool bSearchInNotes = sal_False;
1117 : :
1118 : : // continue search in correct section (pTextRegion)
1119 [ # # ][ # # ]: 0 : if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
[ # # ][ # # ]
1120 [ # # ]: 0 : *aSrchPam.GetMark() != *aSrchPam.GetPoint() )
1121 : 0 : break; // found
1122 [ # # ]: 0 : else if( !pSet->Count() )
1123 : 0 : return FIND_NOT_FOUND; // only text and nothing found
1124 : :
1125 [ # # ]: 0 : *aRegion.GetMark() = *aSrchPam.GetPoint();
1126 : : }
1127 : :
1128 [ # # ]: 0 : *pCrsr->GetPoint() = *aSrchPam.GetPoint();
1129 [ # # ]: 0 : pCrsr->SetMark();
1130 [ # # ][ # # ]: 0 : *pCrsr->GetMark() = *aSrchPam.GetMark();
[ # # ][ # # ]
[ # # ]
1131 : : }
1132 : :
1133 [ # # ]: 0 : if( bReplaceTxt )
1134 : : {
1135 : : const bool bRegExp(
1136 : 0 : SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
1137 [ # # ]: 0 : SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
1138 : 0 : xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
1139 : :
1140 : : // add to shell-cursor-ring so that the regions will be moved enventually
1141 : 0 : Ring *pPrevRing = 0;
1142 [ # # ]: 0 : if( bRegExp )
1143 : : {
1144 : 0 : pPrevRing = pRegion->GetPrev();
1145 [ # # ]: 0 : ((Ring*)pRegion)->MoveRingTo( &rCursor );
1146 : : }
1147 : :
1148 : : ::std::auto_ptr<String> pRepl( (bRegExp) ?
1149 [ # # ][ # # ]: 0 : ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
1150 : 0 : rCursor.GetDoc()->ReplaceRange( *pCrsr,
1151 : 0 : (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
1152 [ # # ][ # # ]: 0 : bRegExp );
[ # # ]
[ # # # # ]
1153 [ # # ]: 0 : rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
1154 : :
1155 [ # # ]: 0 : if( bRegExp )
1156 : : {
1157 : : // and remove region again
1158 : 0 : Ring *p, *pNext = (Ring*)pRegion;
1159 [ # # ]: 0 : do {
1160 : 0 : p = pNext;
1161 : 0 : pNext = p->GetNext();
1162 [ # # ]: 0 : p->MoveTo( (Ring*)pRegion );
1163 : : } while( p != pPrevRing );
1164 : : }
1165 [ # # ][ # # ]: 0 : rSttCntIdx = nSttCnt;
1166 : : }
1167 : :
1168 [ # # ]: 0 : if( bReplaceAttr )
1169 : : {
1170 : : // is the selection still existent?
1171 : : // all searched attributes are reset to default if
1172 : : // they are not in ReplaceSet
1173 [ # # ]: 0 : if( !pSet->Count() )
1174 : : {
1175 : 0 : pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
1176 : : }
1177 : : else
1178 : : {
1179 : 0 : SfxItemPool* pPool = pReplSet->GetPool();
1180 [ # # ]: 0 : SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
1181 : :
1182 [ # # ]: 0 : SfxItemIter aIter( *pSet );
1183 : 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
1184 : 0 : while( sal_True )
1185 : : {
1186 : : // reset all that are not set with pool defaults
1187 [ # # ][ # # ]: 0 : if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
[ # # ]
1188 [ # # ]: 0 : pReplSet->GetItemState( pItem->Which(), sal_False ))
1189 [ # # ][ # # ]: 0 : aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
1190 : :
1191 [ # # ]: 0 : if( aIter.IsAtEnd() )
1192 : 0 : break;
1193 [ # # ]: 0 : pItem = aIter.NextItem();
1194 : : }
1195 [ # # ]: 0 : aSet.Put( *pReplSet );
1196 [ # # ][ # # ]: 0 : pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
[ # # ]
1197 : : }
1198 : :
1199 : 0 : return FIND_NO_RING;
1200 : : }
1201 : :
1202 : : else
1203 : 0 : return FIND_FOUND;
1204 : : }
1205 : :
1206 : :
1207 : 0 : int SwFindParaAttr::IsReplaceMode() const
1208 : : {
1209 : 0 : return ( pSearchOpt && !pSearchOpt->replaceString.isEmpty() ) ||
1210 [ # # # # ]: 0 : ( pReplSet && pReplSet->Count() );
[ # # ][ # # ]
1211 : : }
1212 : :
1213 : : /// search for attributes
1214 : 0 : sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
1215 : : SwDocPositions nStart, SwDocPositions nEnd,
1216 : : sal_Bool& bCancel, FindRanges eFndRngs,
1217 : : const SearchOptions* pSearchOpt,
1218 : : const SfxItemSet* pReplSet )
1219 : : {
1220 : : // switch off OLE-notifications
1221 : 0 : SwDoc* pDoc = GetDoc();
1222 : 0 : Link aLnk( pDoc->GetOle2Link() );
1223 [ # # ]: 0 : pDoc->SetOle2Link( Link() );
1224 : :
1225 : 0 : sal_Bool bReplace = ( pSearchOpt && ( !pSearchOpt->replaceString.isEmpty() ||
1226 : 0 : !rSet.Count() ) ) ||
1227 [ # # ][ # # ]: 0 : (pReplSet && pReplSet->Count());
[ # # # #
# # ]
1228 [ # # ][ # # ]: 0 : bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
[ # # ][ # # ]
1229 [ # # ]: 0 : if (bStartUndo)
1230 : : {
1231 [ # # ][ # # ]: 0 : pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
1232 : : }
1233 : :
1234 : : SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
1235 : 0 : pReplSet, *this );
1236 : :
1237 [ # # ]: 0 : sal_uLong nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel );
1238 : 0 : pDoc->SetOle2Link( aLnk );
1239 [ # # ][ # # ]: 0 : if( nRet && bReplace )
1240 [ # # ]: 0 : pDoc->SetModified();
1241 : :
1242 [ # # ]: 0 : if (bStartUndo)
1243 : : {
1244 [ # # ][ # # ]: 0 : pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
1245 : : }
1246 : :
1247 [ # # ]: 0 : return nRet;
1248 : : }
1249 : :
1250 : :
1251 : :
1252 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|