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 return Found();
484 }
485
486
SetAttrBwd(const SwTxtAttr & rAttr)487 int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
488 {
489 _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
490
491 // ignore all attributes not in search range
492 if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
493 {
494 return Found();
495 }
496
497 const SfxPoolItem* pItem;
498 // --------------------------------------------------------------
499 // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
500 // --------------------------------------------------------------
501 sal_uInt16 nWhch = rAttr.Which();
502 SfxWhichIter* pIter = NULL;
503 const SfxPoolItem* pTmpItem = NULL;
504 const SfxItemSet* pSet = NULL;
505 if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
506 {
507 if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
508 return Found();
509
510 pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
511 if ( pSet )
512 {
513 pIter = new SfxWhichIter( *pSet );
514 nWhch = pIter->FirstWhich();
515 while( nWhch &&
516 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
517 nWhch = pIter->NextWhich();
518 if( !nWhch )
519 pTmpItem = NULL;
520 }
521 }
522 else
523 pTmpItem = &rAttr.GetAttr();
524 while( pTmpItem )
525 {
526 SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
527 if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
528 {
529 sal_uInt16 n;
530 _SwSrchChrAttr* pCmp;
531
532 // loesche erstmal alle, die bis zu der Start Position schon wieder
533 // ungueltig sind:
534
535 _SwSrchChrAttr* pArrPtr;
536 if( nFound )
537 for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
538 if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
539 {
540 pArrPtr->nWhich = 0; // geloescht
541 nFound--;
542 }
543
544 // loesche erstmal alle, die bis zu der Start Position schon wieder
545 // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
546 // die Start Position ragen, vom Stack in den FndSet
547
548 if( nStackCnt )
549 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
550 {
551 if( !pArrPtr->nWhich )
552 continue;
553
554 if( pArrPtr->nStt >= aTmp.nEnd )
555 {
556 pArrPtr->nWhich = 0; // geloescht
557 if( !--nStackCnt )
558 break;
559 }
560 else if( pArrPtr->nEnd >= aTmp.nEnd )
561 {
562 if( ( pCmp = &pFndArr[ n ])->nWhich )
563 {
564 if( pCmp->nStt > pArrPtr->nStt ) // erweitern
565 pCmp->nStt = pArrPtr->nStt;
566 }
567 else
568 {
569 *pCmp = *pArrPtr;
570 nFound++;
571 }
572 pArrPtr->nWhich = 0;
573 if( !--nStackCnt )
574 break;
575 }
576 }
577
578 sal_Bool bContinue = sal_False;
579 if( SFX_ITEM_DONTCARE == eState )
580 {
581 // wird Attribut gueltig ?
582 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
583 *pTmpItem ) )
584 {
585 // suche das Attribut und erweiter es gegebenenfalls
586 if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
587 {
588 *pCmp = aTmp; // nicht gefunden, eintragen
589 nFound++;
590 }
591 else if( pCmp->nStt > aTmp.nStt ) // erweitern ?
592 pCmp->nStt = aTmp.nStt;
593
594 bContinue = sal_True;
595 }
596 }
597 // wird Attribut gueltig ?
598 else if( CmpAttr( *pItem, *pTmpItem ))
599 {
600 pFndArr[ nWhch - nArrStart ] = aTmp;
601 ++nFound;
602 bContinue = sal_True;
603 }
604
605 // tja, dann muss es auf den Stack
606 if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
607 {
608 // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
609 if( pCmp->nStt < aTmp.nStt )
610 {
611 ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
612 "Stack-Platz ist noch belegt" );
613
614 // ---------
615 // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
616 // pCmp->nEnd = aTmp.nStt;
617 if( aTmp.nEnd <= pCmp->nEnd )
618 pCmp->nEnd = aTmp.nStt;
619 else
620 pCmp->nStt = aTmp.nEnd;
621 // ---------
622
623 pStackArr[ nWhch - nArrStart ] = *pCmp;
624 nStackCnt++;
625 }
626 pCmp->nWhich = 0;
627 nFound--;
628 }
629 }
630 if( pIter )
631 {
632 nWhch = pIter->NextWhich();
633 while( nWhch &&
634 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
635 nWhch = pIter->NextWhich();
636 if( !nWhch )
637 break;
638 }
639 else
640 break;
641 }
642 return Found();
643 }
644
645
Start() const646 xub_StrLen SwAttrCheckArr::Start() const
647 {
648 xub_StrLen nStart = nNdStt;
649 _SwSrchChrAttr* pArrPtr = pFndArr;
650 for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
651 if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
652 nStart = pArrPtr->nStt;
653
654 return nStart;
655 }
656
657
End() const658 xub_StrLen SwAttrCheckArr::End() const
659 {
660 _SwSrchChrAttr* pArrPtr = pFndArr;
661 xub_StrLen nEnd = nNdEnd;
662 for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
663 if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
664 nEnd = pArrPtr->nEnd;
665
666 return nEnd;
667 }
668
669
CheckStack()670 int SwAttrCheckArr::CheckStack()
671 {
672 if( !nStackCnt )
673 return sal_False;
674
675 sal_uInt16 n;
676 xub_StrLen nSttPos = Start(), nEndPos = End();
677 _SwSrchChrAttr* pArrPtr;
678 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
679 {
680 if( !pArrPtr->nWhich )
681 continue;
682
683 if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
684 {
685 pArrPtr->nWhich = 0; // geloescht
686 if( !--nStackCnt )
687 return nFound == aCmpSet.Count();
688 }
689 else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
690 {
691 // alle die "offen" sind, heisst ueber die Start Position ragen,
692 // im FndSet setzen
693 ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
694 pFndArr[ n ] = *pArrPtr;
695 pArrPtr->nWhich = 0;
696 nFound++;
697 if( !--nStackCnt )
698 return nFound == aCmpSet.Count();
699 }
700 }
701 return nFound == aCmpSet.Count();
702 }
703
704
705
lcl_SearchForward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)706 int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
707 SwPaM& rPam )
708 {
709 xub_StrLen nEndPos, nSttPos;
710 rCmpArr.SetNewSet( rTxtNd, rPam );
711 if( !rTxtNd.HasHints() )
712 {
713 if( !rCmpArr.Found() )
714 return sal_False;
715 nEndPos = rCmpArr.GetNdEnd();
716 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
717 return sal_True;
718 }
719
720 // dann gehe mal durch das nach "Start" sortierte Array
721 const SwpHints& rHtArr = rTxtNd.GetSwpHints();
722 const SwTxtAttr* pAttr;
723 sal_uInt16 nPos = 0;
724
725 // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
726 // das wieder beendet wird.
727 if( rCmpArr.Found() )
728 {
729 for( ; nPos < rHtArr.Count(); ++nPos )
730 if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
731 {
732 if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
733 {
734 // dann haben wir unser Ende:
735 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
736 pAttr->GetStart(), sal_True );
737 return sal_True;
738 }
739 // ansonsten muessen wir weiter suchen
740 break;
741 }
742
743 if( nPos == rHtArr.Count() && rCmpArr.Found() )
744 {
745 // dann haben wir unseren Bereich
746 nEndPos = rCmpArr.GetNdEnd();
747 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
748 return sal_True;
749 }
750 }
751
752 for( ; nPos < rHtArr.Count(); ++nPos )
753 if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
754 {
755 // sollten noch mehr auf der gleichen Position anfangen ??
756 // auch die noch mit testen !!
757 nSttPos = *pAttr->GetStart();
758 while( ++nPos < rHtArr.Count() && nSttPos ==
759 *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
760 rCmpArr.SetAttrFwd( *pAttr ) )
761 ;
762 if( !rCmpArr.Found() )
763 continue;
764
765 // dann haben wir den Bereich zusammen
766 if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
767 return sal_False;
768 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
769 return sal_True;
770 }
771
772 if( !rCmpArr.CheckStack() ||
773 (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
774 return sal_False;
775 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
776 return sal_True;
777 }
778
779
lcl_SearchBackward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)780 int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
781 SwPaM& rPam )
782 {
783 xub_StrLen nEndPos, nSttPos;
784 rCmpArr.SetNewSet( rTxtNd, rPam );
785 if( !rTxtNd.HasHints() )
786 {
787 if( !rCmpArr.Found() )
788 return sal_False;
789 nEndPos = rCmpArr.GetNdEnd();
790 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
791 return sal_True;
792 }
793
794 // dann gehe mal durch das nach "Start" sortierte Array
795 const SwpHints& rHtArr = rTxtNd.GetSwpHints();
796 const SwTxtAttr* pAttr;
797 sal_uInt16 nPos = rHtArr.Count();
798
799 // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
800 // das wieder beendet wird.
801 if( rCmpArr.Found() )
802 {
803 while( nPos )
804 if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
805 {
806 nSttPos = *pAttr->GetAnyEnd();
807 if( nSttPos < rCmpArr.GetNdEnd() )
808 {
809 // dann haben wir unser Ende:
810 nEndPos = rCmpArr.GetNdEnd();
811 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
812 return sal_True;
813 }
814
815 // ansonsten muessen wir weiter suchen
816 break;
817 }
818
819 if( !nPos && rCmpArr.Found() )
820 {
821 // dann haben wir unseren Bereich
822 nEndPos = rCmpArr.GetNdEnd();
823 lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
824 return sal_True;
825 }
826 }
827
828 while( nPos )
829 if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
830 {
831 // sollten noch mehr auf der gleichen Position anfangen ??
832 // auch die noch mit testen !!
833 if( nPos )
834 {
835 nEndPos = *pAttr->GetAnyEnd();
836 while( --nPos && nEndPos ==
837 *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
838 rCmpArr.SetAttrBwd( *pAttr ) )
839 ;
840 }
841 if( !rCmpArr.Found() )
842 continue;
843
844
845 // dann haben wir den Bereich zusammen
846 if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
847 return sal_False;
848 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
849 return sal_True;
850 }
851
852 if( !rCmpArr.CheckStack() ||
853 (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
854 return sal_False;
855 lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
856 return sal_True;
857 }
858
859
lcl_Search(const SwCntntNode & rCNd,const SfxItemSet & rCmpSet,sal_Bool bNoColls)860 int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
861 {
862 // nur die harte Attributierung suchen ?
863 if( bNoColls && !rCNd.HasSwAttrSet() )
864 return sal_False;
865
866 const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
867 SfxItemIter aIter( rCmpSet );
868 const SfxPoolItem* pItem = aIter.GetCurItem();
869 const SfxPoolItem* pNdItem;
870 sal_uInt16 nWhich;
871
872 while( sal_True )
873 {
874 // nur testen, ob vorhanden ist ?
875 if( IsInvalidItem( pItem ))
876 {
877 nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
878 if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
879 || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
880 return sal_False;
881 }
882 else
883 {
884 nWhich = pItem->Which();
885 //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
886 // runter
887 // if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
888 // || *pNdItem != *pItem )
889 if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
890 return sal_False;
891 }
892
893 if( aIter.IsAtEnd() )
894 break;
895 pItem = aIter.NextItem();
896 }
897 return sal_True; // wurde gefunden
898 }
899
900
Find(const SfxPoolItem & rAttr,sal_Bool bValue,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)901 sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
902 const SwPaM *pRegion, sal_Bool bInReadOnly )
903 {
904 // stelle fest welches Attribut gesucht wird:
905 const sal_uInt16 nWhich = rAttr.Which();
906 int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
907
908 SwPaM* pPam = MakeRegion( fnMove, pRegion );
909
910 sal_Bool bFound = sal_False;
911 sal_Bool bFirst = sal_True;
912 sal_Bool bSrchForward = fnMove == fnMoveForward;
913 SwCntntNode * pNode;
914 const SfxPoolItem* pItem;
915 SwpFmts aFmtArr;
916
917 // Wenn am Anfang/Ende, aus dem Node moven
918 if( bSrchForward
919 ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
920 : !pPam->GetPoint()->nContent.GetIndex() )
921 {
922 if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
923 {
924 delete pPam;
925 return sal_False;
926 }
927 SwCntntNode *pNd = pPam->GetCntntNode();
928 xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
929 pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
930 }
931
932 while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
933 {
934 if( bCharAttr )
935 {
936 if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
937 continue;
938
939 if( ((SwTxtNode*)pNode)->HasHints() &&
940 lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue ))
941 {
942 // setze auf die Werte vom Attribut
943 SetMark();
944 *GetPoint() = *pPam->GetPoint();
945 *GetMark() = *pPam->GetMark();
946 bFound = sal_True;
947 break;
948 }
949 else if (isTXTATR(nWhich))
950 continue; // --> also weiter
951 }
952
953 // keine harte Attributierung, dann pruefe, ob die Vorlage schon
954 // mal nach dem Attribut befragt wurde
955 if( !pNode->HasSwAttrSet() )
956 {
957 const SwFmt* pTmpFmt = pNode->GetFmtColl();
958 if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
959 continue; // die Collection wurde schon mal befragt
960 aFmtArr.Insert( pTmpFmt );
961 }
962
963 if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
964 sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
965 {
966 // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
967 // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
968 // und immer nach der Logik: inkl. Start, exkl. End !!!
969 *GetPoint() = *pPam->GetPoint();
970 SetMark();
971 pNode->MakeEndIndex( &GetPoint()->nContent );
972 bFound = sal_True;
973 break;
974 }
975 }
976
977 // beim rueckwaerts Suchen noch Point und Mark vertauschen
978 if( bFound && !bSrchForward )
979 Exchange();
980
981 delete pPam;
982 return bFound;
983 }
984
985
986 typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
987
Find(const SfxItemSet & rSet,sal_Bool bNoColls,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly,sal_Bool bMoveFirst)988 sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
989 const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
990 {
991 SwPaM* pPam = MakeRegion( fnMove, pRegion );
992
993 sal_Bool bFound = sal_False;
994 sal_Bool bFirst = sal_True;
995 sal_Bool bSrchForward = fnMove == fnMoveForward;
996 SwCntntNode * pNode;
997 SwpFmts aFmtArr;
998
999 // teste doch mal welche Text/Char-Attribute gesucht werden
1000 SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
1001 SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
1002 RES_PARATR_BEGIN, RES_GRFATR_END-1 );
1003 aOtherSet.Put( rSet, sal_False ); // alle Invalid-Items erhalten!
1004
1005 FnSearchAttr fnSearch = bSrchForward
1006 ? (&::lcl_SearchForward)
1007 : (&::lcl_SearchBackward);
1008
1009 // Wenn am Anfang/Ende, aus dem Node moven
1010 // Wenn am Anfang/Ende, aus dem Node moven
1011 if( bMoveFirst &&
1012 ( bSrchForward
1013 ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
1014 : !pPam->GetPoint()->nContent.GetIndex() ) )
1015 {
1016 if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
1017 {
1018 delete pPam;
1019 return sal_False;
1020 }
1021 SwCntntNode *pNd = pPam->GetCntntNode();
1022 xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
1023 pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
1024 }
1025
1026
1027 while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
1028 {
1029 if( aCmpArr.Count() )
1030 {
1031 if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
1032 continue;
1033
1034 if( (!aOtherSet.Count() ||
1035 lcl_Search( *pNode, aOtherSet, bNoColls )) &&
1036 (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
1037 {
1038 // setze auf die Werte vom Attribut
1039 SetMark();
1040 *GetPoint() = *pPam->GetPoint();
1041 *GetMark() = *pPam->GetMark();
1042 bFound = sal_True;
1043 break;
1044 }
1045 continue; // TextAttribute
1046 }
1047
1048 if( !aOtherSet.Count() )
1049 continue;
1050
1051 // keine harte Attributierung, dann pruefe, ob die Vorlage schon
1052 // mal nach dem Attribut befragt wurde
1053 if( !pNode->HasSwAttrSet() )
1054 {
1055 const SwFmt* pTmpFmt = pNode->GetFmtColl();
1056 if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
1057 continue; // die Collection wurde schon mal befragt
1058 aFmtArr.Insert( pTmpFmt );
1059 }
1060
1061 if( lcl_Search( *pNode, aOtherSet, bNoColls ))
1062 {
1063 // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
1064 // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
1065 // und immer nach der Logik: inkl. Start, exkl. End !!!
1066 *GetPoint() = *pPam->GetPoint();
1067 SetMark();
1068 pNode->MakeEndIndex( &GetPoint()->nContent );
1069 bFound = sal_True;
1070 break;
1071 }
1072 }
1073
1074 // beim rueckwaerts Suchen noch Point und Mark vertauschen
1075 if( bFound && !bSrchForward )
1076 Exchange();
1077
1078 delete pPam;
1079 return bFound;
1080 }
1081
1082 //------------------ Methoden vom SwCursor ---------------------------
1083
1084 // Parameter fuer das Suchen vom Attributen
1085 struct SwFindParaAttr : public SwFindParas
1086 {
1087 sal_Bool bValue;
1088 const SfxItemSet *pSet, *pReplSet;
1089 const SearchOptions *pSearchOpt;
1090 SwCursor& rCursor;
1091 utl::TextSearch* pSTxt;
1092
SwFindParaAttrSwFindParaAttr1093 SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
1094 const SearchOptions* pOpt, const SfxItemSet* pRSet,
1095 SwCursor& rCrsr )
1096 : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
1097 pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
1098
~SwFindParaAttrSwFindParaAttr1099 virtual ~SwFindParaAttr() { delete pSTxt; }
1100
1101 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
1102 virtual int IsReplaceMode() const;
1103 };
1104
1105
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)1106 int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
1107 sal_Bool bInReadOnly )
1108 {
1109 // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
1110 // gesucht wird)
1111 sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1112 !pSet->Count() );
1113 sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
1114 sal_Bool bMoveFirst = !bReplaceAttr;
1115 if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
1116 bInReadOnly = sal_False;
1117
1118 // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
1119 {
1120 SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
1121 SwPaM* pTextRegion = &aRegion;
1122 SwPaM aSrchPam( *pCrsr->GetPoint() );
1123
1124 while( sal_True )
1125 {
1126 if( pSet->Count() ) // gibts ueberhaupt Attributierung?
1127 {
1128 // zuerst die Attributierung
1129 if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
1130 //JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
1131 // || *pCrsr->GetMark() == *pCrsr->GetPoint() ) // kein Bereich ??
1132 return FIND_NOT_FOUND;
1133 bMoveFirst = sal_True;
1134
1135 if( !pSearchOpt )
1136 break; // ok, nur Attribute, also gefunden
1137
1138 pTextRegion = &aSrchPam;
1139 }
1140 else if( !pSearchOpt )
1141 return FIND_NOT_FOUND;
1142
1143 // dann darin den Text
1144 if( !pSTxt )
1145 {
1146 SearchOptions aTmp( *pSearchOpt );
1147
1148 // search in selection
1149 aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
1150 SearchFlags::REG_NOT_ENDOFLINE);
1151
1152 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
1153
1154 pSTxt = new utl::TextSearch( aTmp );
1155 }
1156
1157 // todo/mba: searching for attributes in Outliner text?!
1158 sal_Bool bSearchInNotes = sal_False;
1159
1160 // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
1161 if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
1162 *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) // gefunden ?
1163 break; // also raus
1164 else if( !pSet->Count() )
1165 return FIND_NOT_FOUND; // nur Text und nicht gefunden
1166
1167 /* // --> FME 2007-4-12 #i74765 # Why should we move the position?
1168 Moving the position results in bugs when there are two adjacent
1169 portions which both have the requested attributes set. I suspect this
1170 should be only be an optimization. Therefore I boldly remove it now!
1171
1172 // JP: und wieder neu aufsetzen, aber eine Position weiter
1173 //JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit
1174 // weiterbewegt werden kann!
1175 {
1176 sal_Bool bCheckRegion = sal_True;
1177 SwPosition* pPos = aSrchPam.GetPoint();
1178 if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(),
1179 &pPos->nContent, CRSR_SKIP_CHARS ))
1180 {
1181 if( (*fnMove->fnNds)( &pPos->nNode, sal_False ))
1182 {
1183 SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode();
1184 xub_StrLen nCPos;
1185 if( fnMove == fnMoveForward )
1186 nCPos = 0;
1187 else
1188 nCPos = pNd->Len();
1189 pPos->nContent.Assign( pNd, nCPos );
1190 }
1191 else
1192 bCheckRegion = sal_False;
1193 }
1194 if( !bCheckRegion || *aRegion.GetPoint() <= *pPos )
1195 return FIND_NOT_FOUND; // nicht gefunden
1196 }*/
1197 *aRegion.GetMark() = *aSrchPam.GetPoint();
1198 }
1199
1200 *pCrsr->GetPoint() = *aSrchPam.GetPoint();
1201 pCrsr->SetMark();
1202 *pCrsr->GetMark() = *aSrchPam.GetMark();
1203 }
1204
1205 if( bReplaceTxt )
1206 {
1207 const bool bRegExp(
1208 SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
1209 SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
1210 xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
1211
1212 // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
1213 // mit aufnehmen !!
1214 Ring *pPrevRing = 0;
1215 if( bRegExp )
1216 {
1217 pPrevRing = pRegion->GetPrev();
1218 ((Ring*)pRegion)->MoveRingTo( &rCursor );
1219 }
1220
1221 ::std::auto_ptr<String> pRepl( (bRegExp) ?
1222 ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
1223 rCursor.GetDoc()->ReplaceRange( *pCrsr,
1224 (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
1225 bRegExp );
1226 rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
1227
1228 if( bRegExp )
1229 {
1230 // und die Region wieder herausnehmen:
1231 Ring *p, *pNext = (Ring*)pRegion;
1232 do {
1233 p = pNext;
1234 pNext = p->GetNext();
1235 p->MoveTo( (Ring*)pRegion );
1236 } while( p != pPrevRing );
1237 }
1238 rSttCntIdx = nSttCnt;
1239 }
1240
1241 if( bReplaceAttr )
1242 {
1243 // --- Ist die Selection noch da ??????
1244
1245 // und noch die Attribute setzen
1246 #ifdef OLD
1247 pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 );
1248 #else
1249 //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
1250 // ReplaceSet angegeben, auf Default zurueck gesetzt
1251
1252 if( !pSet->Count() )
1253 {
1254 pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
1255 }
1256 else
1257 {
1258 SfxItemPool* pPool = pReplSet->GetPool();
1259 SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
1260
1261 SfxItemIter aIter( *pSet );
1262 const SfxPoolItem* pItem = aIter.GetCurItem();
1263 while( sal_True )
1264 {
1265 // alle die nicht gesetzt sind mit Pool-Defaults aufuellen
1266 if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
1267 pReplSet->GetItemState( pItem->Which(), sal_False ))
1268 aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
1269
1270 if( aIter.IsAtEnd() )
1271 break;
1272 pItem = aIter.NextItem();
1273 }
1274 aSet.Put( *pReplSet );
1275 pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
1276 }
1277 #endif
1278 return FIND_NO_RING;
1279 }
1280
1281 else
1282 return FIND_FOUND;
1283 }
1284
1285
IsReplaceMode() const1286 int SwFindParaAttr::IsReplaceMode() const
1287 {
1288 return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
1289 ( pReplSet && pReplSet->Count() );
1290 }
1291
1292 // Suchen nach Attributen
1293
1294
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,const SearchOptions * pSearchOpt,const SfxItemSet * pReplSet)1295 sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
1296 SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
1297 FindRanges eFndRngs,
1298 const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
1299 {
1300 // OLE-Benachrichtigung abschalten !!
1301 SwDoc* pDoc = GetDoc();
1302 Link aLnk( pDoc->GetOle2Link() );
1303 pDoc->SetOle2Link( Link() );
1304
1305 sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1306 !rSet.Count() ) ) ||
1307 (pReplSet && pReplSet->Count());
1308 bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
1309 if (bStartUndo)
1310 {
1311 pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
1312 }
1313
1314 SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
1315 pReplSet, *this );
1316
1317 sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
1318 pDoc->SetOle2Link( aLnk );
1319 if( nRet && bReplace )
1320 pDoc->SetModified();
1321
1322 if (bStartUndo)
1323 {
1324 pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
1325 }
1326
1327 return nRet;
1328 }
1329
1330
1331
1332