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