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 ) 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 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 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 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 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->GetEnd(), 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 171 _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 ?? 194 sal_uInt16 Count() const { return aCmpSet.Count(); } 195 int Found() const { return nFound == aCmpSet.Count(); } 196 int CheckStack(); 197 198 xub_StrLen Start() const; 199 xub_StrLen End() const; 200 201 xub_StrLen GetNdStt() const { return nNdStt; } 202 xub_StrLen GetNdEnd() const { return nNdEnd; } 203 204 int SetAttrFwd( const SwTxtAttr& rAttr ); 205 int SetAttrBwd( const SwTxtAttr& rAttr ); 206 }; 207 208 209 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 231 SwAttrCheckArr::~SwAttrCheckArr() 232 { 233 delete[] (char*)pFndArr; 234 delete[] (char*)pStackArr; 235 } 236 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 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 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 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 646 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 658 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 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 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 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 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 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 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 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 1093 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 1099 virtual ~SwFindParaAttr() { delete pSTxt; } 1100 1101 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ); 1102 virtual int IsReplaceMode() const; 1103 }; 1104 1105 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 1286 int SwFindParaAttr::IsReplaceMode() const 1287 { 1288 return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) || 1289 ( pReplSet && pReplSet->Count() ); 1290 } 1291 1292 // Suchen nach Attributen 1293 1294 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