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->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 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 delete pIter; 484 return Found(); 485 } 486 487 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 648 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 660 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 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 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 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 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 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 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 1095 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 1101 virtual ~SwFindParaAttr() { delete pSTxt; } 1102 1103 virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly ); 1104 virtual int IsReplaceMode() const; 1105 }; 1106 1107 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 1288 int SwFindParaAttr::IsReplaceMode() const 1289 { 1290 return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) || 1291 ( pReplSet && pReplSet->Count() ); 1292 } 1293 1294 // Suchen nach Attributen 1295 1296 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