1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27
28 #include <com/sun/star/lang/Locale.hpp>
29 #include <com/sun/star/util/SearchOptions.hpp>
30 #include <com/sun/star/util/SearchFlags.hpp>
31 #include <i18npool/mslangid.hxx>
32 #include <hintids.hxx>
33 #include <vcl/svapp.hxx>
34 #include <svl/itemiter.hxx>
35 #include <svl/whiter.hxx>
36 #include <editeng/brkitem.hxx>
37 #include <editeng/colritem.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <fmtpdsc.hxx>
40 #include <txatbase.hxx>
41 #include <fchrfmt.hxx>
42 #include <charfmt.hxx>
43 #include <doc.hxx>
44 #include <IDocumentUndoRedo.hxx>
45 #include <swcrsr.hxx>
46 #include <editsh.hxx>
47 #include <ndtxt.hxx>
48 #include <pamtyp.hxx>
49 #include <swundo.hxx>
50 #include <crsskip.hxx>
51
52
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::util;
56
57 SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 )
SV_IMPL_PTRARR_SORT(SwpFmts,SwFmt *)58 SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* )
59
60 // Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen:
61 int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
62 {
63 switch( rItem1.Which() )
64 {
65 case RES_CHRATR_FONT:
66 return ((SvxFontItem&)rItem1).GetFamilyName() ==
67 ((SvxFontItem&)rItem2).GetFamilyName();
68
69 case RES_CHRATR_COLOR:
70 return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
71 ((SvxColorItem&)rItem2).GetValue() );
72 case RES_PAGEDESC:
73 return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
74 ((SwFmtPageDesc&)rItem2).GetNumOffset() &&
75 ((SwFmtPageDesc&)rItem1).GetPageDesc() ==
76 ((SwFmtPageDesc&)rItem2).GetPageDesc();
77 }
78 return rItem1 == rItem2;
79 }
80
81
GetFrwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)82 const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
83 xub_StrLen nCntntPos )
84 {
85 while( rPos < rHtsArr.Count() )
86 {
87 const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
88 // der Start vom Attribut muss innerhalb des Bereiches liegen !!
89 if( *pTxtHt->GetStart() >= nCntntPos )
90 return pTxtHt; // gueltiges TextAttribut
91 }
92 return 0; // kein gueltiges TextAttribut
93 }
94
95
GetBkwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)96 const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
97 xub_StrLen nCntntPos )
98 {
99 while( rPos > 0 )
100 {
101 //Hack mit cast fuer das Update
102 const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
103 // der Start vom Attribut muss innerhalb des Bereiches liegen !!
104 if( *pTxtHt->GetStart() < nCntntPos )
105 return pTxtHt; // gueltiges TextAttribut
106 }
107 return 0; // kein gueltiges TextAttribut
108 }
109
110
lcl_SetAttrPam(SwPaM & rPam,xub_StrLen nStart,const xub_StrLen * pEnde,const sal_Bool bSaveMark)111 void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde,
112 const sal_Bool bSaveMark )
113 {
114 xub_StrLen nCntntPos;
115 if( bSaveMark )
116 nCntntPos = rPam.GetMark()->nContent.GetIndex();
117 else
118 nCntntPos = rPam.GetPoint()->nContent.GetIndex();
119 sal_Bool bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
120
121 SwCntntNode* pCNd = rPam.GetCntntNode();
122 rPam.GetPoint()->nContent.Assign( pCNd, nStart );
123 rPam.SetMark(); // Point == GetMark
124
125 // Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut
126 if( pEnde )
127 {
128 if( bTstEnde && *pEnde > nCntntPos )
129 rPam.GetPoint()->nContent = nCntntPos;
130 else
131 rPam.GetPoint()->nContent = *pEnde;
132 }
133 }
134
135 //------------------ Suche nach einem Text Attribut -----------------------
136
137 // diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut.
138 // Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut
139 // umspannt, unter Beachtung des Suchbereiches
140
141
lcl_Search(const SwTxtNode & rTxtNd,SwPaM & rPam,const SfxPoolItem & rCmpItem,SwMoveFn fnMove,sal_Bool bValue)142 sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
143 const SfxPoolItem& rCmpItem,
144 SwMoveFn fnMove, sal_Bool bValue )
145 {
146 if ( !rTxtNd.HasHints() )
147 return sal_False;
148 const SwTxtAttr *pTxtHt = 0;
149 sal_Bool bForward = fnMove == fnMoveForward;
150 sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
151 xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
152
153 while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
154 if( pTxtHt->Which() == rCmpItem.Which() &&
155 ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
156 {
157 lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->End(), bForward );
158 return sal_True;
159 }
160 return sal_False;
161 }
162
163
164 //------------------ Suche nach mehren Text Attributen -------------------
165
166 struct _SwSrchChrAttr
167 {
168 sal_uInt16 nWhich;
169 xub_StrLen nStt, nEnd;
170
_SwSrchChrAttr_SwSrchChrAttr171 _SwSrchChrAttr( const SfxPoolItem& rItem,
172 xub_StrLen nStart, xub_StrLen nAnyEnd )
173 : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
174 {}
175 };
176
177 class SwAttrCheckArr
178 {
179 _SwSrchChrAttr *pFndArr, *pStackArr;
180 xub_StrLen nNdStt, nNdEnd;
181 sal_uInt16 nArrStart, nArrLen;
182 sal_uInt16 nFound, nStackCnt;
183 SfxItemSet aCmpSet;
184 sal_Bool bNoColls;
185 sal_Bool bForward;
186
187 public:
188 SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
189 ~SwAttrCheckArr();
190
191 void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
192
193 // wieviele Attribute ueberhaupt ??
Count() const194 sal_uInt16 Count() const { return aCmpSet.Count(); }
Found() const195 int Found() const { return nFound == aCmpSet.Count(); }
196 int CheckStack();
197
198 xub_StrLen Start() const;
199 xub_StrLen End() const;
200
GetNdStt() const201 xub_StrLen GetNdStt() const { return nNdStt; }
GetNdEnd() const202 xub_StrLen GetNdEnd() const { return nNdEnd; }
203
204 int SetAttrFwd( const SwTxtAttr& rAttr );
205 int SetAttrBwd( const SwTxtAttr& rAttr );
206 };
207
208
209
SwAttrCheckArr(const SfxItemSet & rSet,int bFwd,int bNoCollections)210 SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
211 int bNoCollections )
212 : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
213 {
214 aCmpSet.Put( rSet, sal_False );
215 bNoColls = 0 != bNoCollections;
216
217 bForward = 0 != bFwd;
218
219 // Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max)
220 SfxItemIter aIter( aCmpSet );
221 nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
222 nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
223
224 char* pFndChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
225 char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
226
227 pFndArr = (_SwSrchChrAttr*)pFndChar;
228 pStackArr = (_SwSrchChrAttr*)pStackChar;
229 }
230
~SwAttrCheckArr()231 SwAttrCheckArr::~SwAttrCheckArr()
232 {
233 delete[] (char*)pFndArr;
234 delete[] (char*)pStackArr;
235 }
236
SetNewSet(const SwTxtNode & rTxtNd,const SwPaM & rPam)237 void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
238 {
239 memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
240 memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
241 nFound = 0;
242 nStackCnt = 0;
243
244 if( bForward )
245 {
246 nNdStt = rPam.GetPoint()->nContent.GetIndex();
247 nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
248 ? rPam.GetMark()->nContent.GetIndex()
249 : rTxtNd.GetTxt().Len();
250 }
251 else
252 {
253 nNdEnd = rPam.GetPoint()->nContent.GetIndex();
254 nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
255 ? rPam.GetMark()->nContent.GetIndex()
256 : 0;
257 }
258
259 if( bNoColls && !rTxtNd.HasSwAttrSet() )
260 return ;
261
262 const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
263 // if( !rSet.Count() )
264 // return;
265
266 SfxItemIter aIter( aCmpSet );
267 const SfxPoolItem* pItem = aIter.GetCurItem();
268 const SfxPoolItem* pFndItem;
269 sal_uInt16 nWhich;
270
271 while( sal_True )
272 {
273 // nur testen, ob vorhanden ist ?
274 if( IsInvalidItem( pItem ) )
275 {
276 nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
277 if( RES_TXTATR_END <= nWhich )
278 break; // Ende der TextAttribute
279
280 if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
281 && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
282 {
283 pFndArr[ nWhich - nArrStart ] =
284 _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
285 nFound++;
286 }
287 }
288 else
289 {
290 if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
291 break; // Ende der TextAttribute
292
293 //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
294 // runter
295 // if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
296 // && *pFndItem == *pItem )
297 if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
298 {
299 pFndArr[ nWhich - nArrStart ] =
300 _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
301 nFound++;
302 }
303 }
304
305 if( aIter.IsAtEnd() )
306 break;
307 pItem = aIter.NextItem();
308 }
309 }
310
311 static bool
lcl_IsAttributeIgnorable(xub_StrLen const nNdStart,xub_StrLen const nNdEnd,_SwSrchChrAttr const & rTmp)312 lcl_IsAttributeIgnorable(xub_StrLen const nNdStart, xub_StrLen const nNdEnd,
313 _SwSrchChrAttr const& rTmp)
314 {
315 // #i115528#: if there is a paragraph attribute, it has been added by the
316 // SwAttrCheckArr ctor, and nFound is 1.
317 // if the paragraph is entirely covered by hints that override the paragraph
318 // attribute, then this function must find an attribute to decrement nFound!
319 // so check for an empty search range, let attributes that start/end there
320 // cover it, and hope for the best...
321 return ((nNdEnd == nNdStart)
322 ? ((rTmp.nEnd < nNdStart) || (nNdEnd < rTmp.nStt))
323 : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt)));
324 }
325
SetAttrFwd(const SwTxtAttr & rAttr)326 int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
327 {
328 _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
329
330 // ignore all attributes not in search range
331 if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
332 {
333 return Found();
334 }
335
336 const SfxPoolItem* pItem;
337 // --------------------------------------------------------------
338 // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
339 // --------------------------------------------------------------
340 sal_uInt16 nWhch = rAttr.Which();
341 SfxWhichIter* pIter = NULL;
342 const SfxPoolItem* pTmpItem = NULL;
343 const SfxItemSet* pSet = NULL;
344 if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
345 {
346 if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
347 return Found();
348 pTmpItem = NULL;
349 pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
350 if ( pSet )
351 {
352 pIter = new SfxWhichIter( *pSet );
353 nWhch = pIter->FirstWhich();
354 while( nWhch &&
355 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
356 nWhch = pIter->NextWhich();
357 if( !nWhch )
358 pTmpItem = NULL;
359 }
360 }
361 else
362 pTmpItem = &rAttr.GetAttr();
363 while( pTmpItem )
364 {
365 SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
366 if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
367 {
368 sal_uInt16 n;
369 _SwSrchChrAttr* pCmp;
370
371 // loesche erstmal alle, die bis zu der Start Position schon wieder
372 // ungueltig sind:
373
374 _SwSrchChrAttr* pArrPtr;
375 if( nFound )
376 for( pArrPtr = pFndArr, n = 0; n < nArrLen;
377 ++n, ++pArrPtr )
378 if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
379 {
380 pArrPtr->nWhich = 0; // geloescht
381 nFound--;
382 }
383
384 // loesche erstmal alle, die bis zu der Start Position schon wieder
385 // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
386 // die Start Position ragen, vom Stack in den FndSet
387
388 if( nStackCnt )
389 for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
390 {
391 if( !pArrPtr->nWhich )
392 continue;
393
394 if( pArrPtr->nEnd <= aTmp.nStt )
395 {
396 pArrPtr->nWhich = 0; // geloescht
397 if( !--nStackCnt )
398 break;
399 }
400 else if( pArrPtr->nStt <= aTmp.nStt )
401 {
402 if( ( pCmp = &pFndArr[ n ])->nWhich )
403 {
404 if( pCmp->nEnd < pArrPtr->nEnd ) // erweitern
405 pCmp->nEnd = pArrPtr->nEnd;
406 }
407 else
408 {
409 *pCmp = *pArrPtr;
410 nFound++;
411 }
412 pArrPtr->nWhich = 0;
413 if( !--nStackCnt )
414 break;
415 }
416 }
417
418 sal_Bool bContinue = sal_False;
419
420 if( SFX_ITEM_DONTCARE == eState )
421 {
422 // wird Attribut gueltig ?
423 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
424 *pTmpItem ))
425 {
426 // suche das Attribut und erweiter es gegebenenfalls
427 if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
428 {
429 *pCmp = aTmp; // nicht gefunden, eintragen
430 nFound++;
431 }
432 else if( pCmp->nEnd < aTmp.nEnd ) // erweitern ?
433 pCmp->nEnd = aTmp.nEnd;
434
435 bContinue = sal_True;
436 }
437 }
438 // wird Attribut gueltig ?
439 else if( CmpAttr( *pItem, *pTmpItem ) )
440 {
441 pFndArr[ nWhch - nArrStart ] = aTmp;
442 ++nFound;
443 bContinue = sal_True;
444 }
445
446 // tja, dann muss es auf den Stack
447 if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
448 {
449 // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
450 if( pCmp->nEnd > aTmp.nEnd )
451 {
452 ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
453 "Stack-Platz ist noch belegt" );
454
455 // ---------
456 // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
457 // pCmp->nStt = aTmp.nEnd;
458 if( aTmp.nStt <= pCmp->nStt )
459 pCmp->nStt = aTmp.nEnd;
460 else
461 pCmp->nEnd = aTmp.nStt;
462 // ---------
463
464 pStackArr[ nWhch - nArrStart ] = *pCmp;
465 nStackCnt++;
466 }
467 pCmp->nWhich = 0;
468 nFound--;
469 }
470 }
471 if( pIter )
472 {
473 nWhch = pIter->NextWhich();
474 while( nWhch &&
475 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
476 nWhch = pIter->NextWhich();
477 if( !nWhch )
478 break;
479 }
480 else
481 break;
482 }
483 delete pIter;
484 return Found();
485 }
486
487
SetAttrBwd(const SwTxtAttr & rAttr)488 int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
489 {
490 _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
491
492 // ignore all attributes not in search range
493 if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
494 {
495 return Found();
496 }
497
498 const SfxPoolItem* pItem;
499 // --------------------------------------------------------------
500 // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
501 // --------------------------------------------------------------
502 sal_uInt16 nWhch = rAttr.Which();
503 SfxWhichIter* pIter = NULL;
504 const SfxPoolItem* pTmpItem = NULL;
505 const SfxItemSet* pSet = NULL;
506 if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
507 {
508 if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
509 return Found();
510
511 pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
512 if ( pSet )
513 {
514 pIter = new SfxWhichIter( *pSet );
515 nWhch = pIter->FirstWhich();
516 while( nWhch &&
517 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
518 nWhch = pIter->NextWhich();
519 if( !nWhch )
520 pTmpItem = NULL;
521 }
522 }
523 else
524 pTmpItem = &rAttr.GetAttr();
525 while( pTmpItem )
526 {
527 SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
528 if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
529 {
530 sal_uInt16 n;
531 _SwSrchChrAttr* pCmp;
532
533 // loesche erstmal alle, die bis zu der Start Position schon wieder
534 // ungueltig sind:
535
536 _SwSrchChrAttr* pArrPtr;
537 if( nFound )
538 for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
539 if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
540 {
541 pArrPtr->nWhich = 0; // geloescht
542 nFound--;
543 }
544
545 // loesche erstmal alle, die bis zu der Start Position schon wieder
546 // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
547 // die Start Position ragen, vom Stack in den FndSet
548
549 if( nStackCnt )
550 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
551 {
552 if( !pArrPtr->nWhich )
553 continue;
554
555 if( pArrPtr->nStt >= aTmp.nEnd )
556 {
557 pArrPtr->nWhich = 0; // geloescht
558 if( !--nStackCnt )
559 break;
560 }
561 else if( pArrPtr->nEnd >= aTmp.nEnd )
562 {
563 if( ( pCmp = &pFndArr[ n ])->nWhich )
564 {
565 if( pCmp->nStt > pArrPtr->nStt ) // erweitern
566 pCmp->nStt = pArrPtr->nStt;
567 }
568 else
569 {
570 *pCmp = *pArrPtr;
571 nFound++;
572 }
573 pArrPtr->nWhich = 0;
574 if( !--nStackCnt )
575 break;
576 }
577 }
578
579 sal_Bool bContinue = sal_False;
580 if( SFX_ITEM_DONTCARE == eState )
581 {
582 // wird Attribut gueltig ?
583 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
584 *pTmpItem ) )
585 {
586 // suche das Attribut und erweiter es gegebenenfalls
587 if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
588 {
589 *pCmp = aTmp; // nicht gefunden, eintragen
590 nFound++;
591 }
592 else if( pCmp->nStt > aTmp.nStt ) // erweitern ?
593 pCmp->nStt = aTmp.nStt;
594
595 bContinue = sal_True;
596 }
597 }
598 // wird Attribut gueltig ?
599 else if( CmpAttr( *pItem, *pTmpItem ))
600 {
601 pFndArr[ nWhch - nArrStart ] = aTmp;
602 ++nFound;
603 bContinue = sal_True;
604 }
605
606 // tja, dann muss es auf den Stack
607 if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
608 {
609 // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
610 if( pCmp->nStt < aTmp.nStt )
611 {
612 ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
613 "Stack-Platz ist noch belegt" );
614
615 // ---------
616 // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
617 // pCmp->nEnd = aTmp.nStt;
618 if( aTmp.nEnd <= pCmp->nEnd )
619 pCmp->nEnd = aTmp.nStt;
620 else
621 pCmp->nStt = aTmp.nEnd;
622 // ---------
623
624 pStackArr[ nWhch - nArrStart ] = *pCmp;
625 nStackCnt++;
626 }
627 pCmp->nWhich = 0;
628 nFound--;
629 }
630 }
631 if( pIter )
632 {
633 nWhch = pIter->NextWhich();
634 while( nWhch &&
635 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
636 nWhch = pIter->NextWhich();
637 if( !nWhch )
638 break;
639 }
640 else
641 break;
642 }
643 delete pIter;
644 return Found();
645 }
646
647
Start() const648 xub_StrLen SwAttrCheckArr::Start() const
649 {
650 xub_StrLen nStart = nNdStt;
651 _SwSrchChrAttr* pArrPtr = pFndArr;
652 for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
653 if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
654 nStart = pArrPtr->nStt;
655
656 return nStart;
657 }
658
659
End() const660 xub_StrLen SwAttrCheckArr::End() const
661 {
662 _SwSrchChrAttr* pArrPtr = pFndArr;
663 xub_StrLen nEnd = nNdEnd;
664 for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
665 if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
666 nEnd = pArrPtr->nEnd;
667
668 return nEnd;
669 }
670
671
CheckStack()672 int SwAttrCheckArr::CheckStack()
673 {
674 if( !nStackCnt )
675 return sal_False;
676
677 sal_uInt16 n;
678 xub_StrLen nSttPos = Start(), nEndPos = End();
679 _SwSrchChrAttr* pArrPtr;
680 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
681 {
682 if( !pArrPtr->nWhich )
683 continue;
684
685 if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
686 {
687 pArrPtr->nWhich = 0; // geloescht
688 if( !--nStackCnt )
689 return nFound == aCmpSet.Count();
690 }
691 else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
692 {
693 // alle die "offen" sind, heisst ueber die Start Position ragen,
694 // im FndSet setzen
695 ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
696 pFndArr[ n ] = *pArrPtr;
697 pArrPtr->nWhich = 0;
698 nFound++;
699 if( !--nStackCnt )
700 return nFound == aCmpSet.Count();
701 }
702 }
703 return nFound == aCmpSet.Count();
704 }
705
706
707
lcl_SearchForward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)708 int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
709 SwPaM& rPam )
710 {
711 xub_StrLen nEndPos, nSttPos;
712 rCmpArr.SetNewSet( rTxtNd, rPam );
713 if( !rTxtNd.HasHints() )
714 {
715 if( !rCmpArr.Found() )
716 return sal_False;
717 nEndPos = rCmpArr.GetNdEnd();
718 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
719 return sal_True;
720 }
721
722 // dann gehe mal durch das nach "Start" sortierte Array
723 const SwpHints& rHtArr = rTxtNd.GetSwpHints();
724 const SwTxtAttr* pAttr;
725 sal_uInt16 nPos = 0;
726
727 // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
728 // das wieder beendet wird.
729 if( rCmpArr.Found() )
730 {
731 for( ; nPos < rHtArr.Count(); ++nPos )
732 if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
733 {
734 if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
735 {
736 // dann haben wir unser Ende:
737 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
738 pAttr->GetStart(), sal_True );
739 return sal_True;
740 }
741 // ansonsten muessen wir weiter suchen
742 break;
743 }
744
745 if( nPos == rHtArr.Count() && rCmpArr.Found() )
746 {
747 // dann haben wir unseren Bereich
748 nEndPos = rCmpArr.GetNdEnd();
749 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
750 return sal_True;
751 }
752 }
753
754 for( ; nPos < rHtArr.Count(); ++nPos )
755 if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
756 {
757 // sollten noch mehr auf der gleichen Position anfangen ??
758 // auch die noch mit testen !!
759 nSttPos = *pAttr->GetStart();
760 while( ++nPos < rHtArr.Count() && nSttPos ==
761 *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
762 rCmpArr.SetAttrFwd( *pAttr ) )
763 ;
764 if( !rCmpArr.Found() )
765 continue;
766
767 // dann haben wir den Bereich zusammen
768 if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
769 return sal_False;
770 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
771 return sal_True;
772 }
773
774 if( !rCmpArr.CheckStack() ||
775 (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
776 return sal_False;
777 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
778 return sal_True;
779 }
780
781
lcl_SearchBackward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)782 int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
783 SwPaM& rPam )
784 {
785 xub_StrLen nEndPos, nSttPos;
786 rCmpArr.SetNewSet( rTxtNd, rPam );
787 if( !rTxtNd.HasHints() )
788 {
789 if( !rCmpArr.Found() )
790 return sal_False;
791 nEndPos = rCmpArr.GetNdEnd();
792 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
793 return sal_True;
794 }
795
796 // dann gehe mal durch das nach "Start" sortierte Array
797 const SwpHints& rHtArr = rTxtNd.GetSwpHints();
798 const SwTxtAttr* pAttr;
799 sal_uInt16 nPos = rHtArr.Count();
800
801 // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
802 // das wieder beendet wird.
803 if( rCmpArr.Found() )
804 {
805 while( nPos )
806 if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
807 {
808 nSttPos = *pAttr->GetAnyEnd();
809 if( nSttPos < rCmpArr.GetNdEnd() )
810 {
811 // dann haben wir unser Ende:
812 nEndPos = rCmpArr.GetNdEnd();
813 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
814 return sal_True;
815 }
816
817 // ansonsten muessen wir weiter suchen
818 break;
819 }
820
821 if( !nPos && rCmpArr.Found() )
822 {
823 // dann haben wir unseren Bereich
824 nEndPos = rCmpArr.GetNdEnd();
825 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
826 return sal_True;
827 }
828 }
829
830 while( nPos )
831 if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
832 {
833 // sollten noch mehr auf der gleichen Position anfangen ??
834 // auch die noch mit testen !!
835 if( nPos )
836 {
837 nEndPos = *pAttr->GetAnyEnd();
838 while( --nPos && nEndPos ==
839 *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
840 rCmpArr.SetAttrBwd( *pAttr ) )
841 ;
842 }
843 if( !rCmpArr.Found() )
844 continue;
845
846
847 // dann haben wir den Bereich zusammen
848 if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
849 return sal_False;
850 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
851 return sal_True;
852 }
853
854 if( !rCmpArr.CheckStack() ||
855 (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
856 return sal_False;
857 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
858 return sal_True;
859 }
860
861
lcl_Search(const SwCntntNode & rCNd,const SfxItemSet & rCmpSet,sal_Bool bNoColls)862 int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
863 {
864 // nur die harte Attributierung suchen ?
865 if( bNoColls && !rCNd.HasSwAttrSet() )
866 return sal_False;
867
868 const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
869 SfxItemIter aIter( rCmpSet );
870 const SfxPoolItem* pItem = aIter.GetCurItem();
871 const SfxPoolItem* pNdItem;
872 sal_uInt16 nWhich;
873
874 while( sal_True )
875 {
876 // nur testen, ob vorhanden ist ?
877 if( IsInvalidItem( pItem ))
878 {
879 nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
880 if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
881 || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
882 return sal_False;
883 }
884 else
885 {
886 nWhich = pItem->Which();
887 //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
888 // runter
889 // if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
890 // || *pNdItem != *pItem )
891 if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
892 return sal_False;
893 }
894
895 if( aIter.IsAtEnd() )
896 break;
897 pItem = aIter.NextItem();
898 }
899 return sal_True; // wurde gefunden
900 }
901
902
Find(const SfxPoolItem & rAttr,sal_Bool bValue,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)903 sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
904 const SwPaM *pRegion, sal_Bool bInReadOnly )
905 {
906 // stelle fest welches Attribut gesucht wird:
907 const sal_uInt16 nWhich = rAttr.Which();
908 int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
909
910 SwPaM* pPam = MakeRegion( fnMove, pRegion );
911
912 sal_Bool bFound = sal_False;
913 sal_Bool bFirst = sal_True;
914 sal_Bool bSrchForward = fnMove == fnMoveForward;
915 SwCntntNode * pNode;
916 const SfxPoolItem* pItem;
917 SwpFmts aFmtArr;
918
919 // Wenn am Anfang/Ende, aus dem Node moven
920 if( bSrchForward
921 ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
922 : !pPam->GetPoint()->nContent.GetIndex() )
923 {
924 if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
925 {
926 delete pPam;
927 return sal_False;
928 }
929 SwCntntNode *pNd = pPam->GetCntntNode();
930 xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
931 pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
932 }
933
934 while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
935 {
936 if( bCharAttr )
937 {
938 if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
939 continue;
940
941 if( ((SwTxtNode*)pNode)->HasHints() &&
942 lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue ))
943 {
944 // setze auf die Werte vom Attribut
945 SetMark();
946 *GetPoint() = *pPam->GetPoint();
947 *GetMark() = *pPam->GetMark();
948 bFound = sal_True;
949 break;
950 }
951 else if (isTXTATR(nWhich))
952 continue; // --> also weiter
953 }
954
955 // keine harte Attributierung, dann pruefe, ob die Vorlage schon
956 // mal nach dem Attribut befragt wurde
957 if( !pNode->HasSwAttrSet() )
958 {
959 const SwFmt* pTmpFmt = pNode->GetFmtColl();
960 if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
961 continue; // die Collection wurde schon mal befragt
962 aFmtArr.Insert( pTmpFmt );
963 }
964
965 if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
966 sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
967 {
968 // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
969 // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
970 // und immer nach der Logik: inkl. Start, exkl. End !!!
971 *GetPoint() = *pPam->GetPoint();
972 SetMark();
973 pNode->MakeEndIndex( &GetPoint()->nContent );
974 bFound = sal_True;
975 break;
976 }
977 }
978
979 // beim rueckwaerts Suchen noch Point und Mark vertauschen
980 if( bFound && !bSrchForward )
981 Exchange();
982
983 delete pPam;
984 return bFound;
985 }
986
987
988 typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
989
Find(const SfxItemSet & rSet,sal_Bool bNoColls,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly,sal_Bool bMoveFirst)990 sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
991 const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
992 {
993 SwPaM* pPam = MakeRegion( fnMove, pRegion );
994
995 sal_Bool bFound = sal_False;
996 sal_Bool bFirst = sal_True;
997 sal_Bool bSrchForward = fnMove == fnMoveForward;
998 SwCntntNode * pNode;
999 SwpFmts aFmtArr;
1000
1001 // teste doch mal welche Text/Char-Attribute gesucht werden
1002 SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
1003 SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
1004 RES_PARATR_BEGIN, RES_GRFATR_END-1 );
1005 aOtherSet.Put( rSet, sal_False ); // alle Invalid-Items erhalten!
1006
1007 FnSearchAttr fnSearch = bSrchForward
1008 ? (&::lcl_SearchForward)
1009 : (&::lcl_SearchBackward);
1010
1011 // Wenn am Anfang/Ende, aus dem Node moven
1012 // Wenn am Anfang/Ende, aus dem Node moven
1013 if( bMoveFirst &&
1014 ( bSrchForward
1015 ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
1016 : !pPam->GetPoint()->nContent.GetIndex() ) )
1017 {
1018 if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
1019 {
1020 delete pPam;
1021 return sal_False;
1022 }
1023 SwCntntNode *pNd = pPam->GetCntntNode();
1024 xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
1025 pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
1026 }
1027
1028
1029 while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
1030 {
1031 if( aCmpArr.Count() )
1032 {
1033 if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
1034 continue;
1035
1036 if( (!aOtherSet.Count() ||
1037 lcl_Search( *pNode, aOtherSet, bNoColls )) &&
1038 (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
1039 {
1040 // setze auf die Werte vom Attribut
1041 SetMark();
1042 *GetPoint() = *pPam->GetPoint();
1043 *GetMark() = *pPam->GetMark();
1044 bFound = sal_True;
1045 break;
1046 }
1047 continue; // TextAttribute
1048 }
1049
1050 if( !aOtherSet.Count() )
1051 continue;
1052
1053 // keine harte Attributierung, dann pruefe, ob die Vorlage schon
1054 // mal nach dem Attribut befragt wurde
1055 if( !pNode->HasSwAttrSet() )
1056 {
1057 const SwFmt* pTmpFmt = pNode->GetFmtColl();
1058 if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
1059 continue; // die Collection wurde schon mal befragt
1060 aFmtArr.Insert( pTmpFmt );
1061 }
1062
1063 if( lcl_Search( *pNode, aOtherSet, bNoColls ))
1064 {
1065 // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
1066 // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
1067 // und immer nach der Logik: inkl. Start, exkl. End !!!
1068 *GetPoint() = *pPam->GetPoint();
1069 SetMark();
1070 pNode->MakeEndIndex( &GetPoint()->nContent );
1071 bFound = sal_True;
1072 break;
1073 }
1074 }
1075
1076 // beim rueckwaerts Suchen noch Point und Mark vertauschen
1077 if( bFound && !bSrchForward )
1078 Exchange();
1079
1080 delete pPam;
1081 return bFound;
1082 }
1083
1084 //------------------ Methoden vom SwCursor ---------------------------
1085
1086 // Parameter fuer das Suchen vom Attributen
1087 struct SwFindParaAttr : public SwFindParas
1088 {
1089 sal_Bool bValue;
1090 const SfxItemSet *pSet, *pReplSet;
1091 const SearchOptions *pSearchOpt;
1092 SwCursor& rCursor;
1093 utl::TextSearch* pSTxt;
1094
SwFindParaAttrSwFindParaAttr1095 SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
1096 const SearchOptions* pOpt, const SfxItemSet* pRSet,
1097 SwCursor& rCrsr )
1098 : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
1099 pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
1100
~SwFindParaAttrSwFindParaAttr1101 virtual ~SwFindParaAttr() { delete pSTxt; }
1102
1103 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
1104 virtual int IsReplaceMode() const;
1105 };
1106
1107
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)1108 int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
1109 sal_Bool bInReadOnly )
1110 {
1111 // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
1112 // gesucht wird)
1113 sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1114 !pSet->Count() );
1115 sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
1116 sal_Bool bMoveFirst = !bReplaceAttr;
1117 if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
1118 bInReadOnly = sal_False;
1119
1120 // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
1121 {
1122 SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
1123 SwPaM* pTextRegion = &aRegion;
1124 SwPaM aSrchPam( *pCrsr->GetPoint() );
1125
1126 while( sal_True )
1127 {
1128 if( pSet->Count() ) // gibts ueberhaupt Attributierung?
1129 {
1130 // zuerst die Attributierung
1131 if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
1132 //JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
1133 // || *pCrsr->GetMark() == *pCrsr->GetPoint() ) // kein Bereich ??
1134 return FIND_NOT_FOUND;
1135 bMoveFirst = sal_True;
1136
1137 if( !pSearchOpt )
1138 break; // ok, nur Attribute, also gefunden
1139
1140 pTextRegion = &aSrchPam;
1141 }
1142 else if( !pSearchOpt )
1143 return FIND_NOT_FOUND;
1144
1145 // dann darin den Text
1146 if( !pSTxt )
1147 {
1148 SearchOptions aTmp( *pSearchOpt );
1149
1150 // search in selection
1151 aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
1152 SearchFlags::REG_NOT_ENDOFLINE);
1153
1154 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
1155
1156 pSTxt = new utl::TextSearch( aTmp );
1157 }
1158
1159 // todo/mba: searching for attributes in Outliner text?!
1160 sal_Bool bSearchInNotes = sal_False;
1161
1162 // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
1163 if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
1164 *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) // gefunden ?
1165 break; // also raus
1166 else if( !pSet->Count() )
1167 return FIND_NOT_FOUND; // nur Text und nicht gefunden
1168
1169 /* // --> FME 2007-4-12 #i74765 # Why should we move the position?
1170 Moving the position results in bugs when there are two adjacent
1171 portions which both have the requested attributes set. I suspect this
1172 should be only be an optimization. Therefore I boldly remove it now!
1173
1174 // JP: und wieder neu aufsetzen, aber eine Position weiter
1175 //JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit
1176 // weiterbewegt werden kann!
1177 {
1178 sal_Bool bCheckRegion = sal_True;
1179 SwPosition* pPos = aSrchPam.GetPoint();
1180 if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(),
1181 &pPos->nContent, CRSR_SKIP_CHARS ))
1182 {
1183 if( (*fnMove->fnNds)( &pPos->nNode, sal_False ))
1184 {
1185 SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode();
1186 xub_StrLen nCPos;
1187 if( fnMove == fnMoveForward )
1188 nCPos = 0;
1189 else
1190 nCPos = pNd->Len();
1191 pPos->nContent.Assign( pNd, nCPos );
1192 }
1193 else
1194 bCheckRegion = sal_False;
1195 }
1196 if( !bCheckRegion || *aRegion.GetPoint() <= *pPos )
1197 return FIND_NOT_FOUND; // nicht gefunden
1198 }*/
1199 *aRegion.GetMark() = *aSrchPam.GetPoint();
1200 }
1201
1202 *pCrsr->GetPoint() = *aSrchPam.GetPoint();
1203 pCrsr->SetMark();
1204 *pCrsr->GetMark() = *aSrchPam.GetMark();
1205 }
1206
1207 if( bReplaceTxt )
1208 {
1209 const bool bRegExp(
1210 SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
1211 SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
1212 xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
1213
1214 // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
1215 // mit aufnehmen !!
1216 Ring *pPrevRing = 0;
1217 if( bRegExp )
1218 {
1219 pPrevRing = pRegion->GetPrev();
1220 ((Ring*)pRegion)->MoveRingTo( &rCursor );
1221 }
1222
1223 ::std::auto_ptr<String> pRepl( (bRegExp) ?
1224 ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
1225 rCursor.GetDoc()->ReplaceRange( *pCrsr,
1226 (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
1227 bRegExp );
1228 rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
1229
1230 if( bRegExp )
1231 {
1232 // und die Region wieder herausnehmen:
1233 Ring *p, *pNext = (Ring*)pRegion;
1234 do {
1235 p = pNext;
1236 pNext = p->GetNext();
1237 p->MoveTo( (Ring*)pRegion );
1238 } while( p != pPrevRing );
1239 }
1240 rSttCntIdx = nSttCnt;
1241 }
1242
1243 if( bReplaceAttr )
1244 {
1245 // --- Ist die Selection noch da ??????
1246
1247 // und noch die Attribute setzen
1248 #ifdef OLD
1249 pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 );
1250 #else
1251 //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
1252 // ReplaceSet angegeben, auf Default zurueck gesetzt
1253
1254 if( !pSet->Count() )
1255 {
1256 pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
1257 }
1258 else
1259 {
1260 SfxItemPool* pPool = pReplSet->GetPool();
1261 SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
1262
1263 SfxItemIter aIter( *pSet );
1264 const SfxPoolItem* pItem = aIter.GetCurItem();
1265 while( sal_True )
1266 {
1267 // alle die nicht gesetzt sind mit Pool-Defaults aufuellen
1268 if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
1269 pReplSet->GetItemState( pItem->Which(), sal_False ))
1270 aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
1271
1272 if( aIter.IsAtEnd() )
1273 break;
1274 pItem = aIter.NextItem();
1275 }
1276 aSet.Put( *pReplSet );
1277 pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
1278 }
1279 #endif
1280 return FIND_NO_RING;
1281 }
1282
1283 else
1284 return FIND_FOUND;
1285 }
1286
1287
IsReplaceMode() const1288 int SwFindParaAttr::IsReplaceMode() const
1289 {
1290 return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
1291 ( pReplSet && pReplSet->Count() );
1292 }
1293
1294 // Suchen nach Attributen
1295
1296
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,const SearchOptions * pSearchOpt,const SfxItemSet * pReplSet)1297 sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
1298 SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
1299 FindRanges eFndRngs,
1300 const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
1301 {
1302 // OLE-Benachrichtigung abschalten !!
1303 SwDoc* pDoc = GetDoc();
1304 Link aLnk( pDoc->GetOle2Link() );
1305 pDoc->SetOle2Link( Link() );
1306
1307 sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1308 !rSet.Count() ) ) ||
1309 (pReplSet && pReplSet->Count());
1310 bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
1311 if (bStartUndo)
1312 {
1313 pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
1314 }
1315
1316 SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
1317 pReplSet, *this );
1318
1319 sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
1320 pDoc->SetOle2Link( aLnk );
1321 if( nRet && bReplace )
1322 pDoc->SetModified();
1323
1324 if (bStartUndo)
1325 {
1326 pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
1327 }
1328
1329 return nRet;
1330 }
1331
1332
1333
1334