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 #include <hintids.hxx> 31 #include <hints.hxx> 32 33 #include <editeng/fontitem.hxx> 34 #include <editeng/brkitem.hxx> 35 #include <editeng/escpitem.hxx> 36 #include <editeng/lrspitem.hxx> 37 #include <editeng/tstpitem.hxx> 38 #include <svl/urihelper.hxx> 39 #ifndef _SVSTDARR_HXX 40 #define _SVSTDARR_ULONGS 41 #include <svl/svstdarr.hxx> 42 #endif 43 #include <svl/ctloptions.hxx> 44 #include <swmodule.hxx> 45 #include <txtfld.hxx> 46 #include <txtinet.hxx> 47 #include <fmtinfmt.hxx> 48 #include <fmtpdsc.hxx> 49 #include <txtatr.hxx> 50 #include <fmtrfmrk.hxx> 51 #include <txttxmrk.hxx> 52 #include <fchrfmt.hxx> 53 #include <txtftn.hxx> 54 #include <fmtflcnt.hxx> 55 #include <fmtfld.hxx> 56 #include <frmatr.hxx> 57 #include <charatr.hxx> 58 #include <ftnidx.hxx> 59 #include <ftninfo.hxx> 60 #include <fmtftn.hxx> 61 #include <fmtmeta.hxx> 62 #include <charfmt.hxx> 63 #include <ndtxt.hxx> 64 #include <doc.hxx> 65 #include <IDocumentUndoRedo.hxx> 66 #include <docary.hxx> 67 #include <pam.hxx> // fuer SwPosition 68 #include <fldbas.hxx> 69 #include <errhdl.hxx> 70 #include <paratr.hxx> 71 #include <txtfrm.hxx> 72 #include <ftnfrm.hxx> 73 #include <ftnboss.hxx> 74 #include <rootfrm.hxx> 75 #include <pagedesc.hxx> // fuer SwPageDesc 76 #include <expfld.hxx> // fuer SwTblField 77 #include <section.hxx> // fuer SwSection 78 #include <mvsave.hxx> 79 #include <swcache.hxx> 80 #include <SwGrammarMarkUp.hxx> 81 #include <dcontact.hxx> 82 #include <redline.hxx> 83 #include <doctxm.hxx> 84 #include <IMark.hxx> 85 #include <scriptinfo.hxx> 86 #include <istyleaccess.hxx> 87 #include <SwStyleNameMapper.hxx> 88 #include <numrule.hxx> 89 #include <svl/intitem.hxx> 90 #include <swtable.hxx> 91 #include <docsh.hxx> 92 #include <SwNodeNum.hxx> 93 #include <svl/intitem.hxx> 94 #include <list.hxx> 95 #include <switerator.hxx> 96 #include <attrhint.hxx> 97 98 99 using namespace ::com::sun::star; 100 101 102 SV_DECL_PTRARR( TmpHints, SwTxtAttr*, 0, 4 ) 103 104 TYPEINIT1( SwTxtNode, SwCntntNode ) 105 106 SV_DECL_PTRARR(SwpHts,SwTxtAttr*,1,1) 107 108 // Leider ist das SwpHints nicht ganz wasserdicht: 109 // Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge 110 // und Verkettung sicherstellen zu muessen. 111 #ifdef DBG_UTIL 112 #define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \ 113 !pNd->GetDoc()->IsInReading() ) \ 114 pNd->GetpSwpHints()->Check(); } 115 #else 116 #define CHECK_SWPHINTS(pNd) 117 #endif 118 119 SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere, 120 SwTxtFmtColl *pColl, 121 SwAttrSet* pAutoAttr ) 122 { 123 ASSERT( pColl, "Collectionpointer ist 0." ); 124 125 SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr ); 126 127 SwNodeIndex aIdx( *pNode ); 128 129 // --> OD 2005-11-03 #125329# 130 // call method <UpdateOutlineNode(..)> only for the document nodes array 131 if ( IsDocNodes() ) 132 UpdateOutlineNode(*pNode); 133 134 //Wenn es noch kein Layout gibt oder in einer versteckten Section 135 // stehen, brauchen wir uns um das MakeFrms nicht bemuehen. 136 const SwSectionNode* pSectNd; 137 if( !GetDoc()->GetCurrentViewShell() || //swmod 071108//swmod 071225 138 ( 0 != (pSectNd = pNode->FindSectionNode()) && 139 pSectNd->GetSection().IsHiddenFlag() )) 140 return pNode; 141 142 SwNodeIndex aTmp( rWhere ); 143 do { 144 // max. 2 Durchlaeufe: 145 // 1. den Nachfolger nehmen 146 // 2. den Vorgaenger 147 148 SwNode * pNd = & aTmp.GetNode(); 149 switch (pNd->GetNodeType()) 150 { 151 case ND_TABLENODE: 152 ((SwTableNode*)pNd)->MakeFrms( aIdx ); 153 return pNode; 154 155 case ND_SECTIONNODE: 156 if( ((SwSectionNode*)pNd)->GetSection().IsHidden() || 157 ((SwSectionNode*)pNd)->IsCntntHidden() ) 158 { 159 SwNodeIndex aTmpIdx( *pNode ); 160 pNd = FindPrvNxtFrmNode( aTmpIdx, pNode ); 161 if( !pNd ) 162 return pNode; 163 aTmp = *pNd; 164 break; 165 } 166 ((SwSectionNode*)pNd)->MakeFrms( aIdx ); 167 return pNode; 168 169 case ND_TEXTNODE: 170 case ND_GRFNODE: 171 case ND_OLENODE: 172 ((SwCntntNode*)pNd)->MakeFrms( *pNode ); 173 return pNode; 174 175 case ND_ENDNODE: 176 if( pNd->StartOfSectionNode()->IsSectionNode() && 177 aTmp.GetIndex() < rWhere.GetIndex() ) 178 { 179 if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag()) 180 { 181 if( !GoPrevSection( &aTmp, sal_True, sal_False ) || 182 aTmp.GetNode().FindTableNode() != 183 pNode->FindTableNode() ) 184 return pNode; // schade, das wars 185 } 186 else 187 aTmp = *pNd->StartOfSectionNode(); 188 break; 189 } 190 else if( pNd->StartOfSectionNode()->IsTableNode() && 191 aTmp.GetIndex() < rWhere.GetIndex() ) 192 { 193 // wir stehen hinter einem TabellenNode 194 aTmp = *pNd->StartOfSectionNode(); 195 break; 196 } 197 // kein break !!! 198 default: 199 if( rWhere == aTmp ) 200 aTmp -= 2; 201 else 202 return pNode; 203 break; 204 } 205 } while( sal_True ); 206 } 207 208 // -------------------- 209 // SwTxtNode 210 // -------------------- 211 212 SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere, 213 SwTxtFmtColl *pTxtColl, 214 const SfxItemSet* pAutoAttr ) 215 : SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ), 216 m_pSwpHints( 0 ), 217 mpNodeNum( 0 ), 218 m_bLastOutlineState( false ), 219 m_bNotifiable( false ), 220 // --> OD 2008-11-19 #i70748# 221 mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ), 222 // <-- 223 // --> OD 2008-05-06 #refactorlists# 224 mbInSetOrResetAttr( false ), 225 mpList( 0 ) 226 // <-- 227 { 228 InitSwParaStatistics( true ); 229 230 // soll eine Harte-Attributierung gesetzt werden? 231 if( pAutoAttr ) 232 SetAttr( *pAutoAttr ); 233 234 // --> OD 2008-03-13 #refactorlists# - no longed needed 235 // SyncNumberAndNumRule(); 236 if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 ) 237 { 238 // --> OD 2009-08-27 #i101516# 239 // apply paragraph style's assigned outline style list level as 240 // list level of the paragraph, if it has none set already. 241 if ( !HasAttrListLevel() && 242 pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() ) 243 { 244 SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() ); 245 } 246 // <-- 247 AddToList(); 248 } 249 // <-- 250 GetNodes().UpdateOutlineNode(*this); 251 252 m_bNotifiable = true; 253 254 m_bContainsHiddenChars = m_bHiddenCharsHidePara = false; 255 m_bRecalcHiddenCharFlags = true; 256 } 257 258 SwTxtNode::~SwTxtNode() 259 { 260 // delete loescht nur die Pointer, nicht die Arrayelemente! 261 if ( m_pSwpHints ) 262 { 263 // damit Attribute die ihren Inhalt entfernen nicht doppelt 264 // geloescht werden. 265 SwpHints* pTmpHints = m_pSwpHints; 266 m_pSwpHints = 0; 267 268 for( sal_uInt16 j = pTmpHints->Count(); j; ) 269 // erst muss das Attribut aus dem Array entfernt werden, 270 // denn sonst wuerde es sich selbst loeschen (Felder) !!!! 271 DestroyAttr( pTmpHints->GetTextHint( --j ) ); 272 273 delete pTmpHints; 274 } 275 276 // --> OD 2008-03-13 #refactorlists# 277 // if ( mpNodeNum ) 278 // { 279 // mpNodeNum->RemoveMe(); 280 // delete mpNodeNum; 281 // mpNodeNum = 0L; 282 // } 283 RemoveFromList(); 284 // <-- 285 286 InitSwParaStatistics( false ); 287 } 288 289 SwCntntFrm *SwTxtNode::MakeFrm( SwFrm* pSib ) 290 { 291 SwCntntFrm *pFrm = new SwTxtFrm( this, pSib ); 292 return pFrm; 293 } 294 295 xub_StrLen SwTxtNode::Len() const 296 { 297 return m_Text.Len(); 298 } 299 300 /*--------------------------------------------------------------------------- 301 * lcl_ChangeFtnRef 302 * After a split node, it's necessary to actualize the ref-pointer of the 303 * ftnfrms. 304 * --------------------------------------------------------------------------*/ 305 306 void lcl_ChangeFtnRef( SwTxtNode &rNode ) 307 { 308 SwpHints *pSwpHints = rNode.GetpSwpHints(); 309 if( pSwpHints && rNode.GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225 310 { 311 SwTxtAttr* pHt; 312 SwCntntFrm* pFrm = NULL; 313 // OD 07.11.2002 #104840# - local variable to remember first footnote 314 // of node <rNode> in order to invalidate position of its first content. 315 // Thus, in its <MakeAll()> it will checked its position relative to its reference. 316 SwFtnFrm* pFirstFtnOfNode = 0; 317 for( sal_uInt16 j = pSwpHints->Count(); j; ) 318 { 319 pHt = pSwpHints->GetTextHint(--j); 320 if (RES_TXTATR_FTN == pHt->Which()) 321 { 322 if( !pFrm ) 323 { 324 pFrm = SwIterator<SwCntntFrm,SwTxtNode>::FirstElement( rNode ); 325 if( !pFrm ) 326 return; 327 } 328 SwTxtFtn *pAttr = (SwTxtFtn*)pHt; 329 ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." ); 330 SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); 331 SwCntntNode *pNd = aIdx.GetNode().GetCntntNode(); 332 if ( !pNd ) 333 pNd = pFrm->GetAttrSet()->GetDoc()-> 334 GetNodes().GoNextSection( &aIdx, sal_True, sal_False ); 335 if ( !pNd ) 336 continue; 337 338 SwIterator<SwCntntFrm,SwCntntNode> aIter( *pNd ); 339 SwCntntFrm* pCntnt = aIter.First(); 340 if( pCntnt ) 341 { 342 ASSERT( pCntnt->getRootFrm() == pFrm->getRootFrm(), 343 "lcl_ChangeFtnRef: Layout double?" ); 344 SwFtnFrm *pFtn = pCntnt->FindFtnFrm(); 345 if( pFtn && pFtn->GetAttr() == pAttr ) 346 { 347 while( pFtn->GetMaster() ) 348 pFtn = pFtn->GetMaster(); 349 // OD 07.11.2002 #104840# - remember footnote frame 350 pFirstFtnOfNode = pFtn; 351 while ( pFtn ) 352 { 353 pFtn->SetRef( pFrm ); 354 pFtn = pFtn->GetFollow(); 355 ((SwTxtFrm*)pFrm)->SetFtn( sal_True ); 356 } 357 } 358 #ifdef DBG_UTIL 359 while( 0 != (pCntnt = aIter.Next()) ) 360 { 361 SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm(); 362 ASSERT( !pDbgFtn || pDbgFtn->GetRef() == pFrm, 363 "lcl_ChangeFtnRef: Who's that guy?" ); 364 } 365 #endif 366 } 367 } 368 } // end of for-loop on <SwpHints> 369 // OD 08.11.2002 #104840# - invalidate 370 if ( pFirstFtnOfNode ) 371 { 372 SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt(); 373 if ( pCntnt ) 374 { 375 pCntnt->_InvalidatePos(); 376 } 377 } 378 } 379 } 380 381 SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos ) 382 { 383 // lege den Node "vor" mir an 384 const xub_StrLen nSplitPos = rPos.nContent.GetIndex(); 385 const xub_StrLen nTxtLen = m_Text.Len(); 386 SwTxtNode* const pNode = 387 _MakeNewTxtNode( rPos.nNode, sal_False, nSplitPos==nTxtLen ); 388 389 // the first paragraph gets the XmlId, 390 // _except_ if it is empty and the second is not empty 391 if (nSplitPos != 0) { 392 pNode->RegisterAsCopyOf(*this, true); 393 if (nSplitPos == nTxtLen) 394 { 395 this->RemoveMetadataReference(); 396 // NB: SwUndoSplitNode will call pNode->JoinNext, 397 // which is sufficient even in this case! 398 } 399 } 400 401 // --> OD 2008-03-27 #refactorlists# 402 // // --> OD 2007-07-09 #i77372# 403 // // reset numbering attribute at current node, only if it is numbered. 404 // if ( GetNumRule() != NULL ) 405 // { 406 // SetRestart(false); 407 // SetStart(1); 408 // SetCounted(true); 409 // } 410 ResetAttr( RES_PARATR_LIST_ISRESTART ); 411 ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 412 ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 413 if ( GetNumRule() == 0 ) 414 { 415 ResetAttr( RES_PARATR_LIST_ID ); 416 ResetAttr( RES_PARATR_LIST_LEVEL ); 417 } 418 // <-- 419 420 if ( GetDepends() && m_Text.Len() && (nTxtLen / 2) < nSplitPos ) 421 { 422 // JP 25.04.95: Optimierung fuer SplitNode: 423 // Wird am Ende vom Node gesplittet, dann verschiebe die 424 // Frames vom akt. auf den neuen und erzeuge fuer den akt. 425 // neue. Dadurch entfaellt das neu aufbauen vom Layout. 426 427 LockModify(); // Benachrichtigungen abschalten 428 429 // werden FlyFrames mit verschoben, so muessen diese nicht ihre 430 // Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt! 431 if ( HasHints() ) 432 { 433 pNode->GetOrCreateSwpHints().SetInSplitNode(true); 434 } 435 436 //Ersten Teil des Inhalts in den neuen Node uebertragen und 437 //im alten Node loeschen. 438 SwIndex aIdx( this ); 439 CutText( pNode, aIdx, nSplitPos ); 440 441 if( GetWrong() ) 442 { 443 pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) ); 444 } 445 SetWrongDirty( true ); 446 447 if( GetGrammarCheck() ) 448 { 449 pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) ); 450 } 451 SetGrammarCheckDirty( true ); 452 453 SetWordCountDirty( true ); 454 455 // SMARTTAGS 456 if( GetSmartTags() ) 457 { 458 pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) ); 459 } 460 SetSmartTagDirty( true ); 461 462 if ( pNode->HasHints() ) 463 { 464 if ( pNode->m_pSwpHints->CanBeDeleted() ) 465 { 466 delete pNode->m_pSwpHints; 467 pNode->m_pSwpHints = 0; 468 } 469 else 470 { 471 pNode->m_pSwpHints->SetInSplitNode(false); 472 } 473 474 // alle zeichengebundenen Rahmen, die im neuen Absatz laden 475 // muessen aus den alten Frame entfernt werden: 476 // JP 01.10.96: alle leeren und nicht zu expandierenden 477 // Attribute loeschen 478 if ( HasHints() ) 479 { 480 for ( sal_uInt16 j = m_pSwpHints->Count(); j; ) 481 { 482 SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j ); 483 if ( RES_TXTATR_FLYCNT == pHt ->Which() ) 484 { 485 pHt->GetFlyCnt().GetFrmFmt()->DelFrms(); 486 } 487 else if ( pHt->DontExpand() ) 488 { 489 const xub_StrLen* const pEnd = pHt->GetEnd(); 490 if (pEnd && *pHt->GetStart() == *pEnd ) 491 { 492 // delete it! 493 m_pSwpHints->DeleteAtPos( j ); 494 DestroyAttr( pHt ); 495 } 496 } 497 } 498 } 499 500 } 501 502 SwIterator<SwCntntFrm,SwTxtNode> aIter( *this ); 503 for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) 504 { 505 pFrm->RegisterToNode( *pNode ); 506 if( pFrm->IsTxtFrm() && !pFrm->IsFollow() && ((SwTxtFrm*)pFrm)->GetOfst() ) 507 ((SwTxtFrm*)pFrm)->SetOfst( 0 ); 508 } 509 510 if ( IsInCache() ) 511 { 512 SwFrm::GetCache().Delete( this ); 513 SetInCache( sal_False ); 514 } 515 516 UnlockModify(); // Benachrichtigungen wieder freischalten 517 518 // If there is an accessible layout we must call modify even 519 // with length zero, because we have to notify about the changed 520 // text node. 521 const SwRootFrm *pRootFrm; 522 if ( (nTxtLen != nSplitPos) || 523 ( (pRootFrm = pNode->GetDoc()->GetCurrentLayout()) != 0 && 524 pRootFrm->IsAnyShellAccessible() ) ) //swmod 080218 525 { 526 // dann sage den Frames noch, das am Ende etwas "geloescht" wurde 527 if( 1 == nTxtLen - nSplitPos ) 528 { 529 SwDelChr aHint( nSplitPos ); 530 pNode->NotifyClients( 0, &aHint ); 531 } 532 else 533 { 534 SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos ); 535 pNode->NotifyClients( 0, &aHint ); 536 } 537 } 538 if ( HasHints() ) 539 { 540 MoveTxtAttr_To_AttrSet(); 541 } 542 pNode->MakeFrms( *this ); // neue Frames anlegen. 543 lcl_ChangeFtnRef( *this ); 544 } 545 else 546 { 547 SwWrongList *pList = GetWrong(); 548 SetWrong( 0, false ); 549 SetWrongDirty( true ); 550 551 SwGrammarMarkUp *pList3 = GetGrammarCheck(); 552 SetGrammarCheck( 0, false ); 553 SetGrammarCheckDirty( true ); 554 555 SetWordCountDirty( true ); 556 557 // SMARTTAGS 558 SwWrongList *pList2 = GetSmartTags(); 559 SetSmartTags( 0, false ); 560 SetSmartTagDirty( true ); 561 562 SwIndex aIdx( this ); 563 CutText( pNode, aIdx, nSplitPos ); 564 565 // JP 01.10.96: alle leeren und nicht zu expandierenden 566 // Attribute loeschen 567 if ( HasHints() ) 568 { 569 for ( sal_uInt16 j = m_pSwpHints->Count(); j; ) 570 { 571 SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j ); 572 const xub_StrLen* const pEnd = pHt->GetEnd(); 573 if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) ) 574 { 575 // delete it! 576 m_pSwpHints->DeleteAtPos( j ); 577 DestroyAttr( pHt ); 578 } 579 } 580 MoveTxtAttr_To_AttrSet(); 581 } 582 583 if( pList ) 584 { 585 pNode->SetWrong( pList->SplitList( nSplitPos ) ); 586 SetWrong( pList, false ); 587 } 588 589 if( pList3 ) 590 { 591 pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) ); 592 SetGrammarCheck( pList3, false ); 593 } 594 595 // SMARTTAGS 596 if( pList2 ) 597 { 598 pNode->SetSmartTags( pList2->SplitList( nSplitPos ) ); 599 SetSmartTags( pList2, false ); 600 } 601 602 if ( GetDepends() ) 603 { 604 MakeFrms( *pNode ); // neue Frames anlegen. 605 } 606 lcl_ChangeFtnRef( *pNode ); 607 } 608 609 { 610 //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im 611 //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum 612 //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden 613 //muesten. #56977# #55001# #56135# 614 const SfxPoolItem *pItem; 615 if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet(). 616 GetItemState( RES_PAGEDESC, sal_True, &pItem ) ) 617 { 618 pNode->ModifyNotification( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem ); 619 } 620 } 621 return pNode; 622 } 623 624 void SwTxtNode::MoveTxtAttr_To_AttrSet() 625 { 626 ASSERT( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" ); 627 for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) 628 { 629 SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i); 630 631 if( *pHt->GetStart() ) 632 break; 633 634 const xub_StrLen* pHtEndIdx = pHt->GetEnd(); 635 636 if( !pHtEndIdx ) 637 continue; 638 639 if ( *pHtEndIdx < m_Text.Len() || pHt->IsCharFmtAttr() ) 640 break; 641 642 if( !pHt->IsDontMoveAttr() && 643 SetAttr( pHt->GetAttr() ) ) 644 { 645 m_pSwpHints->DeleteAtPos(i); 646 DestroyAttr( pHt ); 647 --i; 648 } 649 } 650 651 } 652 653 SwCntntNode *SwTxtNode::JoinNext() 654 { 655 SwNodes& rNds = GetNodes(); 656 SwNodeIndex aIdx( *this ); 657 if( SwCntntNode::CanJoinNext( &aIdx ) ) 658 { 659 SwDoc* pDoc = rNds.GetDoc(); 660 SvULongs aBkmkArr( 15, 15 ); 661 _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY ); 662 SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode(); 663 xub_StrLen nOldLen = m_Text.Len(); 664 665 // METADATA: merge 666 this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len()); 667 668 SwWrongList *pList = GetWrong(); 669 if( pList ) 670 { 671 pList->JoinList( pTxtNode->GetWrong(), nOldLen ); 672 SetWrongDirty( true ); 673 SetWrong( 0, false ); 674 } 675 else 676 { 677 pList = pTxtNode->GetWrong(); 678 if( pList ) 679 { 680 pList->Move( 0, nOldLen ); 681 SetWrongDirty( true ); 682 pTxtNode->SetWrong( 0, false ); 683 } 684 } 685 686 SwGrammarMarkUp *pList3 = GetGrammarCheck(); 687 if( pList3 ) 688 { 689 pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen ); 690 SetGrammarCheckDirty( true ); 691 SetGrammarCheck( 0, false ); 692 } 693 else 694 { 695 pList3 = pTxtNode->GetGrammarCheck(); 696 if( pList3 ) 697 { 698 pList3->MoveGrammar( 0, nOldLen ); 699 SetGrammarCheckDirty( true ); 700 pTxtNode->SetGrammarCheck( 0, false ); 701 } 702 } 703 704 // SMARTTAGS 705 SwWrongList *pList2 = GetSmartTags(); 706 if( pList2 ) 707 { 708 pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen ); 709 SetSmartTagDirty( true ); 710 SetSmartTags( 0, false ); 711 } 712 else 713 { 714 pList2 = pTxtNode->GetSmartTags(); 715 if( pList2 ) 716 { 717 pList2->Move( 0, nOldLen ); 718 SetSmartTagDirty( true ); 719 pTxtNode->SetSmartTags( 0, false ); 720 } 721 } 722 723 { // wg. SwIndex 724 pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() ); 725 } 726 // verschiebe noch alle Bookmarks/TOXMarks 727 if( aBkmkArr.Count() ) 728 _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen ); 729 730 if( pTxtNode->HasAnyIndex() ) 731 { 732 // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben 733 pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, sal_True ); 734 } 735 rNds.Delete(aIdx); 736 SetWrong( pList, false ); 737 SetGrammarCheck( pList3, false ); 738 SetSmartTags( pList2, false ); // SMARTTAGS 739 InvalidateNumRule(); 740 } 741 else { 742 ASSERT( sal_False, "kein TxtNode." ); 743 } 744 745 return this; 746 } 747 748 SwCntntNode *SwTxtNode::JoinPrev() 749 { 750 SwNodes& rNds = GetNodes(); 751 SwNodeIndex aIdx( *this ); 752 if( SwCntntNode::CanJoinPrev( &aIdx ) ) 753 { 754 SwDoc* pDoc = rNds.GetDoc(); 755 SvULongs aBkmkArr( 15, 15 ); 756 _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY ); 757 SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode(); 758 xub_StrLen nLen = pTxtNode->Len(); 759 760 SwWrongList *pList = pTxtNode->GetWrong(); 761 if( pList ) 762 { 763 pList->JoinList( GetWrong(), Len() ); 764 SetWrongDirty( true ); 765 pTxtNode->SetWrong( 0, false ); 766 SetWrong( NULL ); 767 } 768 else 769 { 770 pList = GetWrong(); 771 if( pList ) 772 { 773 pList->Move( 0, nLen ); 774 SetWrongDirty( true ); 775 SetWrong( 0, false ); 776 } 777 } 778 779 SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck(); 780 if( pList3 ) 781 { 782 pList3->JoinGrammarList( GetGrammarCheck(), Len() ); 783 SetGrammarCheckDirty( true ); 784 pTxtNode->SetGrammarCheck( 0, false ); 785 SetGrammarCheck( NULL ); 786 } 787 else 788 { 789 pList3 = GetGrammarCheck(); 790 if( pList3 ) 791 { 792 pList3->MoveGrammar( 0, nLen ); 793 SetGrammarCheckDirty( true ); 794 SetGrammarCheck( 0, false ); 795 } 796 } 797 798 // SMARTTAGS 799 SwWrongList *pList2 = pTxtNode->GetSmartTags(); 800 if( pList2 ) 801 { 802 pList2->JoinList( GetSmartTags(), Len() ); 803 SetSmartTagDirty( true ); 804 pTxtNode->SetSmartTags( 0, false ); 805 SetSmartTags( NULL ); 806 } 807 else 808 { 809 pList2 = GetSmartTags(); 810 if( pList2 ) 811 { 812 pList2->Move( 0, nLen ); 813 SetSmartTagDirty( true ); 814 SetSmartTags( 0, false ); 815 } 816 } 817 818 { // wg. SwIndex 819 pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen ); 820 } 821 // verschiebe noch alle Bookmarks/TOXMarks 822 if( aBkmkArr.Count() ) 823 _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() ); 824 825 if( pTxtNode->HasAnyIndex() ) 826 { 827 // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben 828 pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, sal_True ); 829 } 830 rNds.Delete(aIdx); 831 SetWrong( pList, false ); 832 SetGrammarCheck( pList3, false ); 833 SetSmartTags( pList2, false ); 834 InvalidateNumRule(); 835 } 836 else { 837 ASSERT( sal_False, "kein TxtNode." ); 838 } 839 840 return this; 841 } 842 843 // erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen 844 void SwTxtNode::NewAttrSet( SwAttrPool& rPool ) 845 { 846 ASSERT( !mpAttrSet.get(), "AttrSet ist doch gesetzt" ); 847 SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange ); 848 849 // put names of parent style and conditional style: 850 const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl(); 851 const SwFmtColl* pFmtColl = GetFmtColl(); 852 String sVal; 853 SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True ); 854 SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal ); 855 if ( pFmtColl != pAnyFmtColl ) 856 SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True ); 857 SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal ); 858 aNewAttrSet.Put( aAnyFmtColl ); 859 aNewAttrSet.Put( aFmtColl ); 860 861 aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() ); 862 mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA ); 863 } 864 865 866 // override SwIndexReg::Update => text hints do not need SwIndex for start/end! 867 void SwTxtNode::Update( SwIndex const & rPos, const xub_StrLen nChangeLen, 868 const bool bNegative, const bool bDelete ) 869 { 870 SetAutoCompleteWordDirty( sal_True ); 871 872 ::std::auto_ptr<TmpHints> pCollector; 873 const xub_StrLen nChangePos = rPos.GetIndex(); 874 875 if ( HasHints() ) 876 { 877 if ( bNegative ) 878 { 879 const xub_StrLen nChangeEnd = nChangePos + nChangeLen; 880 for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n ) 881 { 882 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n); 883 xub_StrLen * const pStart = pHint->GetStart(); 884 if ( *pStart > nChangePos ) 885 { 886 if ( *pStart > nChangeEnd ) 887 { 888 *pStart = *pStart - nChangeLen; 889 } 890 else 891 { 892 *pStart = nChangePos; 893 } 894 } 895 896 xub_StrLen * const pEnd = pHint->GetEnd(); 897 if (pEnd) 898 { 899 if ( *pEnd > nChangePos ) 900 { 901 if( *pEnd > nChangeEnd ) 902 { 903 *pEnd = *pEnd - nChangeLen; 904 } 905 else 906 { 907 *pEnd = nChangePos; 908 } 909 } 910 } 911 } 912 913 m_pSwpHints->MergePortions( *this ); 914 } 915 else 916 { 917 bool bNoExp = false; 918 bool bResort = false; 919 const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) - 920 static_cast<sal_uInt16>(RES_CHRATR_BEGIN); 921 922 sal_Bool aDontExp[ coArrSz ]; 923 memset( &aDontExp, 0, coArrSz * sizeof(sal_Bool) ); 924 925 for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n ) 926 { 927 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n); 928 xub_StrLen * const pStart = pHint->GetStart(); 929 xub_StrLen * const pEnd = pHint->GetEnd(); 930 if ( *pStart >= nChangePos ) 931 { 932 *pStart = *pStart + nChangeLen; 933 if ( pEnd ) 934 { 935 *pEnd = *pEnd + nChangeLen; 936 } 937 } 938 else if ( pEnd && (*pEnd >= nChangePos) ) 939 { 940 if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() ) 941 { 942 *pEnd = *pEnd + nChangeLen; 943 } 944 else // *pEnd == nChangePos 945 { 946 sal_uInt16 nWhPos; 947 const sal_uInt16 nWhich = pHint->Which(); 948 949 ASSERT(!isCHRATR(nWhich), "Update: char attr hint?"); 950 if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) 951 { 952 nWhPos = static_cast<sal_uInt16>(nWhich - 953 RES_CHRATR_BEGIN); 954 } 955 else 956 continue; 957 958 if( aDontExp[ nWhPos ] ) 959 continue; 960 961 if ( pHint->DontExpand() ) 962 { 963 pHint->SetDontExpand( false ); 964 bResort = true; 965 if ( pHint->IsCharFmtAttr() ) 966 { 967 bNoExp = true; 968 aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_CHARFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ] 969 = sal_True; 970 aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_INETFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ] 971 = sal_True; 972 } 973 else 974 aDontExp[ nWhPos ] = sal_True; 975 } 976 else if( bNoExp ) 977 { 978 if ( !pCollector.get() ) 979 { 980 pCollector.reset( new TmpHints ); 981 } 982 sal_uInt16 nCollCnt = pCollector->Count(); 983 for( sal_uInt16 i = 0; i < nCollCnt; ++i ) 984 { 985 SwTxtAttr *pTmp = (*pCollector)[ i ]; 986 if( nWhich == pTmp->Which() ) 987 { 988 pCollector->Remove( i ); 989 SwTxtAttr::Destroy( pTmp, 990 GetDoc()->GetAttrPool() ); 991 break; 992 } 993 } 994 SwTxtAttr * const pTmp = MakeTxtAttr( *GetDoc(), 995 pHint->GetAttr(), 996 nChangePos, nChangePos + nChangeLen); 997 pCollector->C40_INSERT( SwTxtAttr, pTmp, pCollector->Count() ); 998 } 999 else 1000 { 1001 *pEnd = *pEnd + nChangeLen; 1002 } 1003 } 1004 } 1005 } 1006 if ( bResort ) 1007 { 1008 m_pSwpHints->Resort(); 1009 } 1010 } 1011 } 1012 1013 SwIndexReg aTmpIdxReg; 1014 if ( !bNegative && !bDelete ) 1015 { 1016 const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl(); 1017 for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 1018 { 1019 SwRedline *const pRedl = rTbl[ i ]; 1020 if ( pRedl->HasMark() ) 1021 { 1022 SwPosition* const pEnd = pRedl->End(); 1023 if ( this == &pEnd->nNode.GetNode() && 1024 *pRedl->GetPoint() != *pRedl->GetMark() ) 1025 { 1026 SwIndex & rIdx = pEnd->nContent; 1027 if (nChangePos == rIdx.GetIndex()) 1028 { 1029 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() ); 1030 } 1031 } 1032 } 1033 else if ( this == &pRedl->GetPoint()->nNode.GetNode() ) 1034 { 1035 SwIndex & rIdx = pRedl->GetPoint()->nContent; 1036 if (nChangePos == rIdx.GetIndex()) 1037 { 1038 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() ); 1039 // mst: FIXME: why does this adjust the unused position??? 1040 SwIndex * pIdx; 1041 if ( &pRedl->GetBound( true ) == pRedl->GetPoint() ) 1042 { 1043 pRedl->GetBound( false ) = pRedl->GetBound( true ); 1044 pIdx = &pRedl->GetBound( false ).nContent; 1045 } 1046 else 1047 { 1048 pRedl->GetBound( true ) = pRedl->GetBound( false ); 1049 pIdx = &pRedl->GetBound( true ).nContent; 1050 } 1051 pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() ); 1052 } 1053 } 1054 } 1055 1056 const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess(); 1057 for(IDocumentMarkAccess::const_iterator_t ppMark = 1058 pMarkAccess->getMarksBegin(); 1059 ppMark != pMarkAccess->getMarksEnd(); 1060 ppMark++) 1061 { 1062 // Bookmarks must never grow to either side, when 1063 // editing (directly) to the left or right (#i29942#)! 1064 // And a bookmark with same start and end must remain 1065 // to the left of the inserted text (used in XML import). 1066 const ::sw::mark::IMark* const pMark = ppMark->get(); 1067 const SwPosition* pEnd = &pMark->GetMarkEnd(); 1068 SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent); 1069 if( this == &pEnd->nNode.GetNode() && 1070 rPos.GetIndex() == rIdx.GetIndex() ) 1071 { 1072 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() ); 1073 } 1074 } 1075 } 1076 1077 // base class 1078 SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete ); 1079 1080 if ( pCollector.get() ) 1081 { 1082 const sal_uInt16 nCount = pCollector->Count(); 1083 for ( sal_uInt16 i = 0; i < nCount; ++i ) 1084 { 1085 m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this ); 1086 } 1087 } 1088 1089 aTmpIdxReg.MoveTo( *this ); 1090 } 1091 1092 void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl, 1093 const SwTxtFmtColl *pNewColl) 1094 { 1095 SwDoc* pDoc = GetDoc(); 1096 ASSERT( pDoc, "Kein Doc?" ); 1097 // erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array, 1098 // falls sich die Level geaendert haben ! 1099 //const sal_uInt8 nOldLevel = pOldColl ? pOldColl->GetOutlineLevel():NO_NUMBERING;//#outline level,removed by zhaojianwei 1100 //const sal_uInt8 nNewLevel = pNewColl ? pNewColl->GetOutlineLevel():NO_NUMBERING;//<-end,zhaojianwei 1101 const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ? 1102 pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL; 1103 const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ? 1104 pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL; 1105 1106 // if ( NO_NUMBERING != nNewLevel ) //#outline level,zhaojianwei 1107 if ( MAXLEVEL != nNewLevel ) //<-end,zhaojianwei 1108 { 1109 SetAttrListLevel(nNewLevel); 1110 } 1111 1112 { 1113 if (pDoc) 1114 pDoc->GetNodes().UpdateOutlineNode(*this); 1115 } 1116 1117 1118 SwNodes& rNds = GetNodes(); 1119 // Update beim Level 0 noch die Fussnoten !! 1120 if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() && 1121 FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum && 1122 rNds.IsDocNodes() ) 1123 { 1124 SwNodeIndex aTmpIndex( rNds, GetIndex()); 1125 1126 pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex); 1127 } 1128 1129 //FEATURE::CONDCOLL 1130 if( /*pOldColl != pNewColl && pNewColl && */ 1131 RES_CONDTXTFMTCOLL == pNewColl->Which() ) 1132 { 1133 // Erfrage die akt. Condition des TextNodes: 1134 ChkCondColl(); 1135 } 1136 //FEATURE::CONDCOLL 1137 } 1138 1139 // Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet, 1140 // bekommt diese das DontExpand-Flag verpasst 1141 1142 sal_Bool SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag, 1143 sal_Bool bFmtToTxtAttributes ) 1144 { 1145 const xub_StrLen nIdx = rIdx.GetIndex(); 1146 if ( bFmtToTxtAttributes && nIdx == m_Text.Len() ) 1147 { 1148 FmtToTxtAttr( this ); 1149 } 1150 1151 sal_Bool bRet = sal_False; 1152 if ( HasHints() ) 1153 { 1154 const sal_uInt16 nEndCnt = m_pSwpHints->GetEndCount(); 1155 sal_uInt16 nPos = nEndCnt; 1156 while( nPos ) 1157 { 1158 SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos ); 1159 xub_StrLen *pEnd = pTmp->GetEnd(); 1160 if( !pEnd || *pEnd > nIdx ) 1161 continue; 1162 if( nIdx != *pEnd ) 1163 nPos = 0; 1164 else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag() 1165 && *pEnd > *pTmp->GetStart()) 1166 { 1167 bRet = sal_True; 1168 m_pSwpHints->NoteInHistory( pTmp ); 1169 pTmp->SetDontExpand( bFlag ); 1170 } 1171 } 1172 } 1173 return bRet; 1174 } 1175 1176 static bool lcl_GetTxtAttrDefault(xub_StrLen const nIndex, 1177 xub_StrLen const nHintStart, xub_StrLen const nHintEnd) 1178 { 1179 return ((nHintStart <= nIndex) && (nIndex < nHintEnd)); 1180 } 1181 static bool lcl_GetTxtAttrExpand(xub_StrLen const nIndex, 1182 xub_StrLen const nHintStart, xub_StrLen const nHintEnd) 1183 { 1184 return ((nHintStart < nIndex) && (nIndex <= nHintEnd)); 1185 } 1186 static bool lcl_GetTxtAttrParent(xub_StrLen const nIndex, 1187 xub_StrLen const nHintStart, xub_StrLen const nHintEnd) 1188 { 1189 return ((nHintStart < nIndex) && (nIndex < nHintEnd)); 1190 } 1191 1192 static void 1193 lcl_GetTxtAttrs( 1194 ::std::vector<SwTxtAttr *> *const pVector, SwTxtAttr **const ppTxtAttr, 1195 SwpHints *const pSwpHints, 1196 xub_StrLen const nIndex, RES_TXTATR const nWhich, 1197 enum SwTxtNode::GetTxtAttrMode const eMode) 1198 { 1199 sal_uInt16 const nSize = (pSwpHints) ? pSwpHints->Count() : 0; 1200 xub_StrLen nPreviousIndex(0); // index of last hint with nWhich 1201 bool (*pMatchFunc)(xub_StrLen const, xub_StrLen const, xub_StrLen const)=0; 1202 switch (eMode) 1203 { 1204 case SwTxtNode::DEFAULT: pMatchFunc = &lcl_GetTxtAttrDefault; break; 1205 case SwTxtNode::EXPAND: pMatchFunc = &lcl_GetTxtAttrExpand; break; 1206 case SwTxtNode::PARENT: pMatchFunc = &lcl_GetTxtAttrParent; break; 1207 default: OSL_ASSERT(false); 1208 } 1209 1210 for( sal_uInt16 i = 0; i < nSize; ++i ) 1211 { 1212 SwTxtAttr *const pHint = pSwpHints->GetTextHint(i); 1213 xub_StrLen const nHintStart( *(pHint->GetStart()) ); 1214 if (nIndex < nHintStart) 1215 { 1216 return; // hints are sorted by start, so we are done... 1217 } 1218 1219 if (pHint->Which() != nWhich) 1220 { 1221 continue; 1222 } 1223 1224 xub_StrLen const*const pEndIdx = pHint->GetEnd(); 1225 ASSERT(pEndIdx || pHint->HasDummyChar(), 1226 "hint with no end and no dummy char?"); 1227 // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe 1228 // simuliert, d.h. der Start wuede verschoben, das Ende expandiert, 1229 bool const bContained( (pEndIdx) 1230 ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx) 1231 : (nHintStart == nIndex) ); 1232 if (bContained) 1233 { 1234 if (pVector) 1235 { 1236 if (nPreviousIndex < nHintStart) 1237 { 1238 pVector->clear(); // clear hints that are outside pHint 1239 nPreviousIndex = nHintStart; 1240 } 1241 pVector->push_back(pHint); 1242 } 1243 else 1244 { 1245 *ppTxtAttr = pHint; // and possibly overwrite outer hint 1246 } 1247 if (!pEndIdx) 1248 { 1249 break; 1250 } 1251 } 1252 } 1253 } 1254 1255 ::std::vector<SwTxtAttr *> 1256 SwTxtNode::GetTxtAttrsAt(xub_StrLen const nIndex, RES_TXTATR const nWhich, 1257 enum GetTxtAttrMode const eMode) const 1258 { 1259 ::std::vector<SwTxtAttr *> ret; 1260 lcl_GetTxtAttrs(& ret, 0, m_pSwpHints, nIndex, nWhich, eMode); 1261 return ret; 1262 } 1263 1264 SwTxtAttr * 1265 SwTxtNode::GetTxtAttrAt(xub_StrLen const nIndex, RES_TXTATR const nWhich, 1266 enum GetTxtAttrMode const eMode) const 1267 { 1268 ASSERT( (nWhich == RES_TXTATR_META) 1269 || (nWhich == RES_TXTATR_METAFIELD) 1270 || (nWhich == RES_TXTATR_AUTOFMT) 1271 || (nWhich == RES_TXTATR_INETFMT) 1272 || (nWhich == RES_TXTATR_CJK_RUBY) 1273 || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER), 1274 "GetTxtAttrAt() will give wrong result for this hint!"); 1275 1276 SwTxtAttr * pRet(0); 1277 lcl_GetTxtAttrs(0, & pRet, m_pSwpHints, nIndex, nWhich, eMode); 1278 return pRet; 1279 } 1280 1281 /************************************************************************* 1282 * CopyHint() 1283 *************************************************************************/ 1284 1285 SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName ) 1286 { 1287 if( rName.Len() ) 1288 { 1289 SwCharFmt* pFmt; 1290 sal_uInt16 nArrLen = pCharFmts->Count(); 1291 for( sal_uInt16 i = 1; i < nArrLen; i++ ) 1292 { 1293 pFmt = (*pCharFmts)[ i ]; 1294 if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL ) 1295 return pFmt; 1296 } 1297 } 1298 return NULL; 1299 } 1300 1301 void lcl_CopyHint( const sal_uInt16 nWhich, const SwTxtAttr * const pHt, 1302 SwTxtAttr *const pNewHt, SwDoc *const pOtherDoc, SwTxtNode *const pDest ) 1303 { 1304 ASSERT( nWhich == pHt->Which(), "Falsche Hint-Id" ); 1305 switch( nWhich ) 1306 { 1307 // copy nodesarray section with footnote content 1308 case RES_TXTATR_FTN : 1309 ASSERT(pDest, "lcl_CopyHint: no destination text node?"); 1310 static_cast<const SwTxtFtn*>(pHt)->CopyFtn( 1311 *static_cast<SwTxtFtn*>(pNewHt), *pDest); 1312 break; 1313 1314 // Beim Kopieren von Feldern in andere Dokumente 1315 // muessen die Felder bei ihren neuen Feldtypen angemeldet werden. 1316 1317 // TabellenFormel muessen relativ kopiert werden. 1318 case RES_TXTATR_FIELD : 1319 { 1320 const SwFmtFld& rFld = pHt->GetFld(); 1321 if( pOtherDoc ) 1322 { 1323 static_cast<const SwTxtFld*>(pHt)->CopyFld( 1324 static_cast<SwTxtFld*>(pNewHt) ); 1325 } 1326 1327 // Tabellenformel ?? 1328 if( RES_TABLEFLD == rFld.GetFld()->GetTyp()->Which() 1329 && static_cast<const SwTblField*>(rFld.GetFld())->IsIntrnlName()) 1330 { 1331 // wandel die interne in eine externe Formel um 1332 const SwTableNode* const pDstTblNd = 1333 static_cast<const SwTxtFld*>(pHt)-> 1334 GetTxtNode().FindTableNode(); 1335 if( pDstTblNd ) 1336 { 1337 SwTblField* const pTblFld = const_cast<SwTblField*>( 1338 static_cast<const SwTblField*>( 1339 pNewHt->GetFld().GetFld())); 1340 pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() ); 1341 } 1342 } 1343 } 1344 break; 1345 1346 case RES_TXTATR_TOXMARK : 1347 if( pOtherDoc && pDest && pDest->GetpSwpHints() 1348 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1349 { 1350 // Beim Kopieren von TOXMarks(Client) in andere Dokumente 1351 // muss der Verzeichnis (Modify) ausgetauscht werden 1352 static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc ); 1353 } 1354 break; 1355 1356 case RES_TXTATR_CHARFMT : 1357 // Wenn wir es mit einer Zeichenvorlage zu tun haben, 1358 // muessen wir natuerlich auch die Formate kopieren. 1359 if( pDest && pDest->GetpSwpHints() 1360 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1361 { 1362 SwCharFmt* pFmt = 1363 static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt()); 1364 1365 if( pFmt && pOtherDoc ) 1366 { 1367 pFmt = pOtherDoc->CopyCharFmt( *pFmt ); 1368 } 1369 const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>( 1370 pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt ); 1371 } 1372 break; 1373 case RES_TXTATR_INETFMT : 1374 { 1375 // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen 1376 // zu tun haben, muessen wir natuerlich auch die Formate kopieren. 1377 if( pOtherDoc && pDest && pDest->GetpSwpHints() 1378 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1379 { 1380 const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt) 1381 ->GetTxtNode().GetDoc(); 1382 if ( pDoc ) 1383 { 1384 const SwCharFmts* pCharFmts = pDoc->GetCharFmts(); 1385 const SwFmtINetFmt& rFmt = pHt->GetINetFmt(); 1386 SwCharFmt* pFmt; 1387 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() ); 1388 if( pFmt ) 1389 pOtherDoc->CopyCharFmt( *pFmt ); 1390 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() ); 1391 if( pFmt ) 1392 pOtherDoc->CopyCharFmt( *pFmt ); 1393 } 1394 } 1395 //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut 1396 // gesetzt sein, damit die Vorlagen erzeugt 1397 // werden koenne 1398 SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt); 1399 if ( !pINetHt->GetpTxtNode() ) 1400 { 1401 pINetHt->ChgTxtNode( pDest ); 1402 } 1403 1404 //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen 1405 pINetHt->GetCharFmt(); 1406 break; 1407 } 1408 case RES_TXTATR_META: 1409 case RES_TXTATR_METAFIELD: 1410 OSL_ENSURE(pNewHt, "copying Meta should not fail!"); 1411 OSL_ENSURE(pDest && (CH_TXTATR_INWORD == 1412 pDest->GetTxt().GetChar(*pNewHt->GetStart())), 1413 "missing CH_TXTATR?"); 1414 break; 1415 } 1416 } 1417 1418 /************************************************************************* 1419 |* SwTxtNode::CopyAttr() 1420 |* Beschreibung kopiert Attribute an der Position nStart in pDest. 1421 |* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx 1422 |* kopiert! CopyAttr wird vornehmlich dann gerufen, 1423 |* wenn Attribute fuer einen Node mit leerem String 1424 |* gesetzt werden sollen. 1425 *************************************************************************/ 1426 1427 void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx, 1428 const xub_StrLen nOldPos ) 1429 { 1430 if ( HasHints() ) // keine Attribute, keine Kekse 1431 { 1432 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? 1433 pDest->GetDoc() : 0; 1434 1435 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ ) 1436 { 1437 SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i); 1438 xub_StrLen const nAttrStartIdx = *pHt->GetStart(); 1439 if ( nTxtStartIdx < nAttrStartIdx ) 1440 break; // ueber das Textende, da nLen == 0 1441 1442 const xub_StrLen *const pEndIdx = pHt->GetEnd(); 1443 if ( pEndIdx && !pHt->HasDummyChar() ) 1444 { 1445 if( ( *pEndIdx > nTxtStartIdx || 1446 ( *pEndIdx == nTxtStartIdx && 1447 nAttrStartIdx == nTxtStartIdx ) ) ) 1448 { 1449 sal_uInt16 const nWhich = pHt->Which(); 1450 if ( RES_TXTATR_REFMARK != nWhich ) 1451 { 1452 // attribute in the area => copy 1453 SwTxtAttr *const pNewHt = pDest->InsertItem( 1454 pHt->GetAttr(), nOldPos, nOldPos, 1455 nsSetAttrMode::SETATTR_IS_COPY); 1456 if ( pNewHt ) 1457 { 1458 lcl_CopyHint( nWhich, pHt, pNewHt, 1459 pOtherDoc, pDest ); 1460 } 1461 } 1462 else if( !pOtherDoc ? GetDoc()->IsCopyIsMove() 1463 : 0 == pOtherDoc->GetRefMark( 1464 pHt->GetRefMark().GetRefName() ) ) 1465 { 1466 pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, 1467 nsSetAttrMode::SETATTR_IS_COPY); 1468 } 1469 } 1470 } 1471 } 1472 } 1473 1474 if( this != pDest ) 1475 { 1476 // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern 1477 SwUpdateAttr aHint( nOldPos, nOldPos, 0 ); 1478 pDest->ModifyNotification( 0, &aHint ); 1479 } 1480 } 1481 1482 /************************************************************************* 1483 |* SwTxtNode::Copy() 1484 |* Beschreibung kopiert Zeichen und Attibute in pDest, 1485 |* wird angehaengt 1486 *************************************************************************/ 1487 1488 // --> OD 2008-11-18 #i96213# 1489 // introduction of new optional parameter to control, if all attributes have to be copied. 1490 void SwTxtNode::CopyText( SwTxtNode *const pDest, 1491 const SwIndex &rStart, 1492 const xub_StrLen nLen, 1493 const bool bForceCopyOfAllAttrs ) 1494 { 1495 SwIndex aIdx( pDest, pDest->m_Text.Len() ); 1496 CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs ); 1497 } 1498 // <-- 1499 1500 // --> OD 2008-11-18 #i96213# 1501 // introduction of new optional parameter to control, if all attributes have to be copied. 1502 void SwTxtNode::CopyText( SwTxtNode *const pDest, 1503 const SwIndex &rDestStart, 1504 const SwIndex &rStart, 1505 xub_StrLen nLen, 1506 const bool bForceCopyOfAllAttrs ) 1507 // <-- 1508 { 1509 xub_StrLen nTxtStartIdx = rStart.GetIndex(); 1510 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken 1511 1512 if (pDest->GetDoc()->IsClipBoard() && this->GetNum()) 1513 { 1514 // #i111677# cache expansion of source (for clipboard) 1515 pDest->m_pNumStringCache.reset( 1516 new ::rtl::OUString(this->GetNumString())); 1517 } 1518 1519 if( !nLen ) 1520 { 1521 // wurde keine Laenge angegeben, dann Kopiere die Attribute 1522 // an der Position rStart. 1523 CopyAttr( pDest, nTxtStartIdx, nDestStart ); 1524 1525 // harte Absatz umspannende Attribute kopieren 1526 if( HasSwAttrSet() ) 1527 { 1528 // alle, oder nur die CharAttribute ? 1529 // --> OD 2008-11-18 #i96213# 1530 if ( !bForceCopyOfAllAttrs && 1531 ( nDestStart || 1532 pDest->HasSwAttrSet() || 1533 nLen != pDest->GetTxt().Len() ) ) 1534 // <-- 1535 { 1536 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 1537 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 1538 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 1539 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 1540 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 1541 0 ); 1542 aCharSet.Put( *GetpSwAttrSet() ); 1543 if( aCharSet.Count() ) 1544 { 1545 pDest->SetAttr( aCharSet, nDestStart, nDestStart ); 1546 } 1547 } 1548 else 1549 { 1550 GetpSwAttrSet()->CopyToModify( *pDest ); 1551 } 1552 } 1553 return; 1554 } 1555 1556 // 1. Text kopieren 1557 const xub_StrLen oldLen = pDest->m_Text.Len(); 1558 //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum 1559 // ueber die InsertMethode den Text einfuegen und nicht 1560 // selbst direkt 1561 pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart, 1562 IDocumentContentOperations::INS_EMPTYEXPAND ); 1563 1564 // um reale Groesse Updaten ! 1565 nLen = pDest->m_Text.Len() - oldLen; 1566 if ( !nLen ) // string not longer? 1567 return; 1568 1569 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? 1570 pDest->GetDoc() : 0; 1571 1572 // harte Absatz umspannende Attribute kopieren 1573 if( HasSwAttrSet() ) 1574 { 1575 // alle, oder nur die CharAttribute ? 1576 // --> OD 2008-11-18 #i96213# 1577 if ( !bForceCopyOfAllAttrs && 1578 ( nDestStart || 1579 pDest->HasSwAttrSet() || 1580 nLen != pDest->GetTxt().Len() ) ) 1581 // <-- 1582 { 1583 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 1584 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 1585 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 1586 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 1587 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 1588 0 ); 1589 aCharSet.Put( *GetpSwAttrSet() ); 1590 if( aCharSet.Count() ) 1591 { 1592 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); 1593 } 1594 } 1595 else 1596 { 1597 GetpSwAttrSet()->CopyToModify( *pDest ); 1598 } 1599 } 1600 1601 bool const bUndoNodes = !pOtherDoc 1602 && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 1603 1604 // Ende erst jetzt holen, weil beim Kopieren in sich selbst der 1605 // Start-Index und alle Attribute vorher aktualisiert werden. 1606 nTxtStartIdx = rStart.GetIndex(); 1607 const xub_StrLen nEnd = nTxtStartIdx + nLen; 1608 1609 // 2. Attribute kopieren 1610 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 1611 // des Attributs hinter dem zu kopierenden Bereich liegt 1612 const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0; 1613 1614 // wird in sich selbst kopiert, dann kann beim Einfuegen ein 1615 // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und 1616 // dann erst ins eigene uebertragen. 1617 SwpHts aArr( 5 ); 1618 1619 // Del-Array fuer alle RefMarks ohne Ausdehnung 1620 SwpHts aRefMrkArr; 1621 1622 sal_uInt16 nDeletedDummyChars(0); 1623 //Achtung: kann ungueltig sein!! 1624 for (sal_uInt16 n = 0; ( n < nSize ); ++n) 1625 { 1626 const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart(); 1627 if (!( nAttrStartIdx < nEnd)) 1628 break; 1629 1630 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n); 1631 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 1632 const sal_uInt16 nWhich = pHt->Which(); 1633 1634 // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber 1635 // keinen Bereich umspannt, so steht im Text ein 255 1636 // dieses muss entfernt werden. Trick: erst kopieren, 1637 // erkennen und sammeln, nach dem kopieren Loeschen. 1638 // Nimmt sein Zeichen mit ins Grab !! 1639 // JP 14.08.95: Duerfen RefMarks gemovt werden? 1640 int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes || 1641 (!pOtherDoc ? GetDoc()->IsCopyIsMove() 1642 : 0 == pOtherDoc->GetRefMark( 1643 pHt->GetRefMark().GetRefName() ))); 1644 1645 if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark ) 1646 { 1647 continue; 1648 } 1649 1650 xub_StrLen nAttrStt; 1651 xub_StrLen nAttrEnd; 1652 1653 if( nAttrStartIdx < nTxtStartIdx ) 1654 { 1655 // start is before selection 1656 // copy hints with end and CH_TXTATR only if dummy char is copied 1657 if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() ) 1658 { 1659 // attribute with extent and the end is in the selection 1660 nAttrStt = nDestStart; 1661 nAttrEnd = (*pEndIdx > nEnd) 1662 ? rDestStart.GetIndex() 1663 : nDestStart + (*pEndIdx) - nTxtStartIdx; 1664 } 1665 else 1666 { 1667 continue; 1668 } 1669 } 1670 else 1671 { 1672 // start is in the selection 1673 nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx ); 1674 if( pEndIdx ) 1675 { 1676 nAttrEnd = *pEndIdx > nEnd 1677 ? rDestStart.GetIndex() 1678 : nDestStart + ( *pEndIdx - nTxtStartIdx ); 1679 } 1680 else 1681 { 1682 nAttrEnd = nAttrStt; 1683 } 1684 } 1685 1686 SwTxtAttr * pNewHt = 0; 1687 1688 if( pDest == this ) 1689 { 1690 // copy the hint here, but insert it later 1691 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 1692 nAttrStt, nAttrEnd, COPY, pDest ); 1693 1694 lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest); 1695 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() ); 1696 } 1697 else 1698 { 1699 pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt - nDeletedDummyChars, 1700 nAttrEnd - nDeletedDummyChars, 1701 nsSetAttrMode::SETATTR_NOTXTATRCHR 1702 | nsSetAttrMode::SETATTR_IS_COPY); 1703 if (pNewHt) 1704 { 1705 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest ); 1706 } 1707 else if (pHt->HasDummyChar()) 1708 { 1709 // The attribute that has failed to be copied would insert 1710 // dummy char, so positions of the following attributes have 1711 // to be shifted by one to compensate for that missing char. 1712 ++nDeletedDummyChars; 1713 } 1714 } 1715 1716 if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark ) 1717 { 1718 aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() ); 1719 } 1720 } 1721 1722 // nur falls im Array Attribute stehen (kann nur beim Kopieren 1723 // sich selbst passieren!!) 1724 for ( sal_uInt16 i = 0; i < aArr.Count(); ++i ) 1725 { 1726 InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR ); 1727 } 1728 1729 if( pDest->GetpSwpHints() ) 1730 { 1731 for ( sal_uInt16 i = 0; i < aRefMrkArr.Count(); ++i ) 1732 { 1733 SwTxtAttr * const pNewHt = aRefMrkArr[i]; 1734 if( pNewHt->GetEnd() ) 1735 { 1736 pDest->GetpSwpHints()->Delete( pNewHt ); 1737 pDest->DestroyAttr( pNewHt ); 1738 } 1739 else 1740 { 1741 const SwIndex aIdx( pDest, *pNewHt->GetStart() ); 1742 pDest->EraseText( aIdx, 1 ); 1743 } 1744 } 1745 } 1746 1747 CHECK_SWPHINTS(this); 1748 } 1749 1750 1751 void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx, 1752 const IDocumentContentOperations::InsertFlags nMode ) 1753 { 1754 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." ); 1755 ASSERT( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN, 1756 "SwTxtNode::InsertText: node text with insertion > STRING_LEN." ); 1757 1758 xub_StrLen aPos = rIdx.GetIndex(); 1759 xub_StrLen nLen = m_Text.Len() - aPos; 1760 m_Text.Insert( rStr, aPos ); 1761 nLen = m_Text.Len() - aPos - nLen; 1762 1763 if ( !nLen ) return; 1764 1765 sal_Bool bOldExpFlg = IsIgnoreDontExpand(); 1766 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1767 { 1768 SetIgnoreDontExpand( sal_True ); 1769 } 1770 1771 Update( rIdx, nLen ); // text content changed! 1772 1773 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1774 { 1775 SetIgnoreDontExpand( bOldExpFlg ); 1776 } 1777 1778 // analog zu Insert(char) in txtedt.cxx: 1779 // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen 1780 // 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen 1781 1782 if ( HasHints() ) 1783 { 1784 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() && 1785 rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i ) 1786 { 1787 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i ); 1788 xub_StrLen * const pEndIdx = pHt->GetEnd(); 1789 if( !pEndIdx ) 1790 continue; 1791 1792 if( rIdx == *pEndIdx ) 1793 { 1794 if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) || 1795 (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1796 && pHt->DontExpand()) ) 1797 { 1798 // bei leeren Attributen auch Start veraendern 1799 if( rIdx == *pHt->GetStart() ) 1800 *pHt->GetStart() = *pHt->GetStart() - nLen; 1801 *pEndIdx = *pEndIdx - nLen; 1802 m_pSwpHints->DeleteAtPos(i); 1803 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST ); 1804 } 1805 // empty hints at insert position? 1806 else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND) 1807 && (*pEndIdx == *pHt->GetStart()) ) 1808 { 1809 *pHt->GetStart() = *pHt->GetStart() - nLen; 1810 const sal_uInt16 nAktLen = m_pSwpHints->Count(); 1811 m_pSwpHints->DeleteAtPos(i); 1812 InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ ); 1813 if ( nAktLen > m_pSwpHints->Count() && i ) 1814 { 1815 --i; 1816 } 1817 continue; 1818 } 1819 else 1820 { 1821 continue; 1822 } 1823 } 1824 if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) && 1825 rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() && 1826 !pHt->IsDontExpandStartAttr() ) 1827 { 1828 // Kein Feld, am Absatzanfang, HintExpand 1829 m_pSwpHints->DeleteAtPos(i); 1830 *pHt->GetStart() = *pHt->GetStart() - nLen; 1831 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST ); 1832 } 1833 } 1834 TryDeleteSwpHints(); 1835 } 1836 1837 if ( GetDepends() ) 1838 { 1839 SwInsTxt aHint( aPos, nLen ); 1840 NotifyClients( 0, &aHint ); 1841 } 1842 1843 // By inserting a character, the hidden flags 1844 // at the TxtNode can become invalid: 1845 SetCalcHiddenCharFlags(); 1846 1847 CHECK_SWPHINTS(this); 1848 } 1849 1850 /************************************************************************* 1851 |* 1852 |* SwTxtNode::Cut() 1853 |* 1854 |* Beschreibung text.doc 1855 |* Ersterstellung VB 20.03.91 1856 |* Letzte Aenderung JP 11.08.94 1857 |* 1858 *************************************************************************/ 1859 1860 void SwTxtNode::CutText( SwTxtNode * const pDest, 1861 const SwIndex & rStart, const xub_StrLen nLen ) 1862 { 1863 if(pDest) 1864 { 1865 SwIndex aDestStt( pDest, pDest->GetTxt().Len() ); 1866 CutImpl( pDest, aDestStt, rStart, nLen, false ); 1867 } 1868 else 1869 { 1870 ASSERT(false, 1871 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1872 EraseText( rStart, nLen ); 1873 } 1874 } 1875 1876 1877 void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart, 1878 const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate ) 1879 { 1880 if(!pDest) 1881 { 1882 ASSERT(false, 1883 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1884 EraseText( rStart, nLen ); 1885 return; 1886 } 1887 1888 // nicht im Dokument verschieben ? 1889 if( GetDoc() != pDest->GetDoc() ) 1890 { 1891 ASSERT(false, 1892 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1893 CopyText( pDest, rDestStart, rStart, nLen); 1894 EraseText(rStart, nLen); 1895 return; 1896 } 1897 1898 if( !nLen ) 1899 { 1900 // wurde keine Laenge angegeben, dann Kopiere die Attribute 1901 // an der Position rStart. 1902 CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() ); 1903 return; 1904 } 1905 1906 xub_StrLen nTxtStartIdx = rStart.GetIndex(); 1907 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken 1908 const xub_StrLen nInitSize = pDest->m_Text.Len(); 1909 1910 // wird in sich selbst verschoben, muss es gesondert behandelt werden !! 1911 if( pDest == this ) 1912 { 1913 ASSERT(false, 1914 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1915 m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart ); 1916 m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen ); 1917 1918 const xub_StrLen nEnd = rStart.GetIndex() + nLen; 1919 1920 // dann suche mal alle Attribute zusammen, die im verschobenen 1921 // Bereich liegen. Diese werden in das extra Array verschoben, 1922 // damit sich die Indizies beim Updaten nicht veraendern !!! 1923 SwpHts aArr( 5 ); 1924 1925 // 2. Attribute verschieben 1926 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 1927 // des Attributs hinter dem zu verschiebenden Bereich liegt 1928 sal_uInt16 nAttrCnt = 0; 1929 while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() ) 1930 { 1931 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 1932 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 1933 if (!( nAttrStartIdx < nEnd )) 1934 break; 1935 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 1936 const sal_uInt16 nWhich = pHt->Which(); 1937 SwTxtAttr *pNewHt = 0; 1938 1939 if(nAttrStartIdx < nTxtStartIdx) 1940 { 1941 // Anfang liegt vor dem Bereich 1942 if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() && 1943 pEndIdx && *pEndIdx > nTxtStartIdx ) 1944 { 1945 // Attribut mit einem Bereich 1946 // und das Ende des Attribut liegt im Bereich 1947 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0, 1948 *pEndIdx > nEnd 1949 ? nLen 1950 : *pEndIdx - nTxtStartIdx ); 1951 } 1952 } 1953 else 1954 { 1955 // der Anfang liegt vollstaendig im Bereich 1956 if( !pEndIdx || *pEndIdx < nEnd ) 1957 { 1958 // Attribut verschieben 1959 m_pSwpHints->Delete( pHt ); 1960 // die Start/End Indicies neu setzen 1961 *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx; 1962 if( pEndIdx ) 1963 *pHt->GetEnd() = *pEndIdx - nTxtStartIdx; 1964 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() ); 1965 continue; // while-Schleife weiter, ohne ++ ! 1966 } 1967 // das Ende liegt dahinter 1968 else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar()) 1969 { 1970 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 1971 nAttrStartIdx - nTxtStartIdx, 1972 !pEndIdx ? 0 1973 : ( *pEndIdx > nEnd 1974 ? nLen 1975 : *pEndIdx - nTxtStartIdx )); 1976 } 1977 } 1978 if( pNewHt ) 1979 { 1980 // die Daten kopieren 1981 lcl_CopyHint( nWhich, pHt, pNewHt, 0, this ); 1982 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() ); 1983 } 1984 ++nAttrCnt; 1985 } 1986 1987 if( bUpdate ) 1988 { 1989 // Update aller Indizies 1990 Update( rDestStart, nLen, sal_False, sal_True ); 1991 } 1992 #ifdef CUTNOEXPAND 1993 else 1994 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben 1995 if ( 0 < nLen && 0 < nInitSize && m_pSwpHints ) 1996 { 1997 // check if there was the end of an attribute at the insertion 1998 // position: if it is not a field, it must be expanded 1999 for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); n++ ) 2000 { 2001 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n); 2002 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2003 if ( pEndIdx && (*pEndIdx == nInitSize) ) 2004 { 2005 *pEndIdx = *pEndIdx + nLen; 2006 } 2007 } 2008 } 2009 #endif 2010 CHECK_SWPHINTS(this); 2011 2012 Update( rStart, nLen, sal_True, sal_True ); 2013 2014 CHECK_SWPHINTS(this); 2015 2016 // dann setze die kopierten/geloeschten Attribute in den Node 2017 if( nDestStart <= nTxtStartIdx ) 2018 { 2019 nTxtStartIdx = nTxtStartIdx + nLen; 2020 } 2021 else 2022 { 2023 nDestStart = nDestStart - nLen; 2024 } 2025 2026 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n ) 2027 { 2028 SwTxtAttr *const pNewHt = aArr[n]; 2029 *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart(); 2030 xub_StrLen * const pEndIdx = pNewHt->GetEnd(); 2031 if ( pEndIdx ) 2032 { 2033 *pEndIdx = nDestStart + *pEndIdx; 2034 } 2035 InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR ); 2036 } 2037 } 2038 else 2039 { 2040 pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart ); 2041 m_Text.Erase( nTxtStartIdx, nLen ); 2042 nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size! 2043 if( !nLen ) // String nicht gewachsen ?? 2044 return; 2045 2046 if( bUpdate ) 2047 { 2048 // Update aller Indizies 2049 pDest->Update( rDestStart, nLen, sal_False, sal_True); 2050 } 2051 #ifdef CUTNOEXPAND 2052 else 2053 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben 2054 if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints ) 2055 { 2056 // check if there was the end of an attribute at the insertion 2057 // position: if it is not a field, it must be expanded 2058 for ( sal_uInt16 n = 0; n < pDest->m_pSwpHints->Count(); n++ ) 2059 { 2060 SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n); 2061 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2062 if ( pEndIdx && (*pEndIdx == nInitSize) ) 2063 { 2064 *pEndIdx = *pEndIdx + nLen; 2065 } 2066 } 2067 } 2068 #endif 2069 CHECK_SWPHINTS(pDest); 2070 2071 const xub_StrLen nEnd = rStart.GetIndex() + nLen; 2072 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) 2073 ? pDest->GetDoc() : 0; 2074 bool const bUndoNodes = !pOtherDoc 2075 && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 2076 2077 ASSERT(!pOtherDoc, 2078 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 2079 2080 // harte Absatz umspannende Attribute kopieren 2081 if( HasSwAttrSet() ) 2082 { 2083 // alle, oder nur die CharAttribute ? 2084 if( nInitSize || pDest->HasSwAttrSet() || 2085 nLen != pDest->GetTxt().Len() ) 2086 { 2087 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 2088 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 2089 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 2090 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 2091 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 2092 0 ); 2093 aCharSet.Put( *GetpSwAttrSet() ); 2094 if( aCharSet.Count() ) 2095 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); 2096 } 2097 else 2098 { 2099 GetpSwAttrSet()->CopyToModify( *pDest ); 2100 } 2101 } 2102 2103 // 2. Attribute verschieben 2104 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 2105 // des Attributs hinter dem zu verschiebenden Bereich liegt 2106 sal_uInt16 nAttrCnt = 0; 2107 while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) ) 2108 { 2109 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 2110 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 2111 if (!( nAttrStartIdx < nEnd )) 2112 break; 2113 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2114 const sal_uInt16 nWhich = pHt->Which(); 2115 SwTxtAttr *pNewHt = 0; 2116 2117 // if the hint has a dummy character, then it must not be split! 2118 if(nAttrStartIdx < nTxtStartIdx) 2119 { 2120 // Anfang liegt vor dem Bereich 2121 if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich 2122 || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx ) 2123 { 2124 // Attribut mit einem Bereich 2125 // und das Ende des Attribut liegt im Bereich 2126 pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(), 2127 nDestStart, 2128 nDestStart + ( 2129 *pEndIdx > nEnd 2130 ? nLen 2131 : *pEndIdx - nTxtStartIdx ) ); 2132 } 2133 } 2134 else 2135 { 2136 // der Anfang liegt vollstaendig im Bereich 2137 if( !pEndIdx || *pEndIdx < nEnd || 2138 (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich) 2139 || pHt->HasDummyChar() ) 2140 { 2141 // do not delete note and later add it -> sidebar flickering 2142 if ( GetDoc()->GetDocShell() ) 2143 { 2144 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04)); 2145 } 2146 // Attribut verschieben 2147 m_pSwpHints->Delete( pHt ); 2148 // die Start/End Indicies neu setzen 2149 *pHt->GetStart() = 2150 nDestStart + (nAttrStartIdx - nTxtStartIdx); 2151 if( pEndIdx ) 2152 { 2153 *pHt->GetEnd() = nDestStart + ( 2154 *pEndIdx > nEnd 2155 ? nLen 2156 : *pEndIdx - nTxtStartIdx ); 2157 } 2158 pDest->InsertHint( pHt, 2159 nsSetAttrMode::SETATTR_NOTXTATRCHR 2160 | nsSetAttrMode::SETATTR_DONTREPLACE ); 2161 if ( GetDoc()->GetDocShell() ) 2162 { 2163 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04)); 2164 } 2165 continue; // while-Schleife weiter, ohne ++ ! 2166 } 2167 // das Ende liegt dahinter 2168 else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes ) 2169 { 2170 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 2171 nDestStart + (nAttrStartIdx - nTxtStartIdx), 2172 !pEndIdx ? 0 2173 : nDestStart + ( *pEndIdx > nEnd 2174 ? nLen 2175 : *pEndIdx - nTxtStartIdx )); 2176 } 2177 } 2178 if ( pNewHt ) 2179 { 2180 const bool bSuccess( pDest->InsertHint( pNewHt, 2181 nsSetAttrMode::SETATTR_NOTXTATRCHR 2182 | nsSetAttrMode::SETATTR_DONTREPLACE 2183 | nsSetAttrMode::SETATTR_IS_COPY) ); 2184 if (bSuccess) 2185 { 2186 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest ); 2187 } 2188 } 2189 ++nAttrCnt; 2190 } 2191 // sollten jetzt noch leere Attribute rumstehen, dann haben diese 2192 // eine hoehere Praezedenz. Also herausholen und das Array updaten. 2193 // Die dabei entstehenden leeren Hints werden von den gesicherten 2194 // "uebergeplaettet". (Bug: 6977) 2195 if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() ) 2196 { 2197 SwpHts aArr( 5 ); 2198 while ( nAttrCnt < m_pSwpHints->Count() ) 2199 { 2200 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 2201 if ( nEnd != *pHt->GetStart() ) 2202 break; 2203 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2204 if ( pEndIdx && *pEndIdx == nEnd ) 2205 { 2206 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() ); 2207 m_pSwpHints->Delete( pHt ); 2208 } 2209 else 2210 { 2211 ++nAttrCnt; 2212 } 2213 } 2214 Update( rStart, nLen, sal_True, sal_True ); 2215 2216 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n ) 2217 { 2218 SwTxtAttr * const pHt = aArr[ n ]; 2219 *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex(); 2220 InsertHint( pHt ); 2221 } 2222 } 2223 else 2224 { 2225 Update( rStart, nLen, sal_True, sal_True ); 2226 } 2227 2228 CHECK_SWPHINTS(this); 2229 } 2230 2231 TryDeleteSwpHints(); 2232 2233 // Frames benachrichtigen; 2234 SwInsTxt aInsHint( nDestStart, nLen ); 2235 pDest->ModifyNotification( 0, &aInsHint ); 2236 SwDelTxt aDelHint( nTxtStartIdx, nLen ); 2237 ModifyNotification( 0, &aDelHint ); 2238 } 2239 2240 2241 void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount, 2242 const IDocumentContentOperations::InsertFlags nMode ) 2243 { 2244 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." ); 2245 2246 const xub_StrLen nStartIdx = rIdx.GetIndex(); 2247 const xub_StrLen nCnt = (STRING_LEN == nCount) 2248 ? m_Text.Len() - nStartIdx : nCount; 2249 const xub_StrLen nEndIdx = nStartIdx + nCnt; 2250 m_Text.Erase( nStartIdx, nCnt ); 2251 2252 /* GCAttr(); alle leeren weggwerfen ist zu brutal. 2253 * Es duerfen nur die wegggeworfen werden, 2254 * die im Bereich liegen und nicht am Ende des Bereiches liegen 2255 */ 2256 2257 for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) 2258 { 2259 SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i); 2260 2261 const xub_StrLen nHintStart = *pHt->GetStart(); 2262 2263 if ( nHintStart < nStartIdx ) 2264 continue; 2265 2266 if ( nHintStart > nEndIdx ) 2267 break; // hints are sorted by end, so break here 2268 2269 const xub_StrLen* pHtEndIdx = pHt->GetEnd(); 2270 const sal_uInt16 nWhich = pHt->Which(); 2271 2272 if( !pHtEndIdx ) 2273 { 2274 ASSERT(pHt->HasDummyChar(), 2275 "attribute with neither end nor CH_TXTATR?"); 2276 if (isTXTATR(nWhich) && 2277 (nHintStart >= nStartIdx) && (nHintStart < nEndIdx)) 2278 { 2279 m_pSwpHints->DeleteAtPos(i); 2280 DestroyAttr( pHt ); 2281 --i; 2282 } 2283 continue; 2284 } 2285 2286 ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) 2287 && pHt->HasDummyChar() ) 2288 // next line: deleting exactly dummy char: DeleteAttributes 2289 || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)), 2290 "ERROR: deleting left-overlapped attribute with CH_TXTATR"); 2291 2292 // Delete the hint if: 2293 // 1. The hint ends before the deletion end position or 2294 // 2. The hint ends at the deletion end position and 2295 // we are not in empty expand mode and 2296 // the hint is a [toxmark|refmark|ruby] text attribute 2297 // 3. deleting exactly the dummy char of an hint with end and dummy 2298 // char deletes the hint 2299 if ( (*pHtEndIdx < nEndIdx) 2300 || ( (*pHtEndIdx == nEndIdx) && 2301 !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) && 2302 ( (RES_TXTATR_TOXMARK == nWhich) || 2303 (RES_TXTATR_REFMARK == nWhich) || 2304 // --> FME 2006-03-03 #i62668# Ruby text attribute must be 2305 // treated just like toxmark and refmarks 2306 (RES_TXTATR_CJK_RUBY == nWhich) ) ) 2307 // <-- 2308 #if 0 2309 || ( (nHintStart == nStartIdx) && 2310 (nHintStart + 1 == nEndIdx)&& 2311 #else // generalize this to left-overlapped dummy char hints (see ASSERT) 2312 || ( (nHintStart < nEndIdx) && 2313 #endif 2314 pHt->HasDummyChar() ) 2315 ) 2316 { 2317 m_pSwpHints->DeleteAtPos(i); 2318 DestroyAttr( pHt ); 2319 --i; 2320 } 2321 } 2322 2323 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?"); 2324 2325 TryDeleteSwpHints(); 2326 2327 Update( rIdx, nCnt, sal_True ); 2328 2329 if( 1 == nCnt ) 2330 { 2331 SwDelChr aHint( nStartIdx ); 2332 NotifyClients( 0, &aHint ); 2333 } 2334 else 2335 { 2336 SwDelTxt aHint( nStartIdx, nCnt ); 2337 NotifyClients( 0, &aHint ); 2338 } 2339 2340 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?"); 2341 2342 // By deleting a character, the hidden flags 2343 // at the TxtNode can become invalid: 2344 SetCalcHiddenCharFlags(); 2345 2346 CHECK_SWPHINTS(this); 2347 } 2348 2349 /*********************************************************************** 2350 #* Class : SwTxtNode 2351 #* Methode : GCAttr 2352 #* 2353 #* Beschreibung 2354 #* text.doc 2355 #* 2356 #* Datum : MS 28.11.90 2357 #* Update : VB 24.07.91 2358 #***********************************************************************/ 2359 2360 void SwTxtNode::GCAttr() 2361 { 2362 if ( !HasHints() ) 2363 return; 2364 2365 bool bChanged = false; 2366 sal_uInt16 nMin = m_Text.Len(), 2367 nMax = 0; 2368 sal_Bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die 2369 // INet-Formate entfernt. 2370 2371 for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) 2372 { 2373 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i); 2374 2375 // wenn Ende und Start gleich sind --> loeschen 2376 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2377 if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart()) 2378 && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) ) 2379 { 2380 bChanged = true; 2381 nMin = Min( nMin, *pHt->GetStart() ); 2382 nMax = Max( nMax, *pHt->GetEnd() ); 2383 DestroyAttr( m_pSwpHints->Cut(i) ); 2384 --i; 2385 } 2386 else 2387 { 2388 pHt->SetDontExpand( false ); 2389 } 2390 } 2391 TryDeleteSwpHints(); 2392 2393 if(bChanged) 2394 { 2395 //TxtFrm's reagieren auf aHint, andere auf aNew 2396 SwUpdateAttr aHint( nMin, nMax, 0 ); 2397 NotifyClients( 0, &aHint ); 2398 SwFmtChg aNew( GetTxtColl() ); 2399 NotifyClients( 0, &aNew ); 2400 } 2401 } 2402 2403 // #i23726# 2404 SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const 2405 { 2406 SwNumRule* pRet = 0; 2407 2408 const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent ); 2409 bool bNoNumRule = false; 2410 if ( pItem ) 2411 { 2412 String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue(); 2413 if (sNumRuleName.Len() > 0) 2414 { 2415 pRet = GetDoc()->FindNumRulePtr( sNumRuleName ); 2416 } 2417 else // numbering is turned off 2418 bNoNumRule = true; 2419 } 2420 2421 if ( !bNoNumRule ) 2422 { 2423 if ( pRet && pRet == GetDoc()->GetOutlineNumRule() && 2424 ( !HasSwAttrSet() || 2425 SFX_ITEM_SET != 2426 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) ) 2427 { 2428 SwTxtFmtColl* pColl = GetTxtColl(); 2429 if ( pColl ) 2430 { 2431 const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False ); 2432 if ( rDirectItem.GetValue().Len() == 0 ) 2433 { 2434 pRet = 0L; 2435 } 2436 } 2437 } 2438 2439 // --> OD 2006-11-20 #i71764# 2440 // Document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE has no influence 2441 // any more. 2442 // if ( !pRet && 2443 // GetDoc()->get(IDocumentSettingAccess::OUTLINE_LEVEL_YIELDS_OUTLINE_RULE) && 2444 // GetOutlineLevel() != NO_NUMBERING ) 2445 // { 2446 // pRet = GetDoc()->GetOutlineNumRule(); 2447 // } 2448 // <-- 2449 } 2450 // old code before tuning 2451 // // --> OD 2005-10-25 #126347# 2452 // // determine of numbering/bullet rule, which is set as a hard attribute 2453 // // at the text node 2454 // const SfxPoolItem* pItem( 0L ); 2455 // if ( HasSwAttrSet() ) // does text node has hard attributes ? 2456 // { 2457 // if ( SFX_ITEM_SET != 2458 // GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ) 2459 // { 2460 // pItem = 0L; 2461 // } 2462 // // else: <pItem> contains the numbering/bullet attribute, which is 2463 // // hard set at the paragraph. 2464 2465 // } 2466 // // <-- 2467 // bool bNoNumRule = false; 2468 // if (pItem) 2469 // { 2470 // String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue(); 2471 // if (sNumRuleName.Len() > 0) 2472 // { 2473 // pRet = GetDoc()->FindNumRulePtr(sNumRuleName); 2474 // } 2475 // else // numbering is turned off by hard attribute 2476 // bNoNumRule = true; 2477 // } 2478 2479 // if (! bNoNumRule) 2480 // { 2481 // if (! pRet && bInParent) 2482 // { 2483 // SwTxtFmtColl * pColl = GetTxtColl(); 2484 2485 // if (pColl) 2486 // { 2487 // const SwNumRuleItem & rItem = pColl->GetNumRule(sal_True); 2488 2489 // pRet = const_cast<SwDoc *>(GetDoc())-> 2490 // FindNumRulePtrWithPool(rItem.GetValue()); 2491 // // --> OD 2005-10-13 #125993# - The outline numbering rule 2492 // // isn't allowed to be derived from a parent paragraph style 2493 // // to a derived one. 2494 // // Thus check, if the found outline numbering rule is directly 2495 // // set at the paragraph style <pColl>. If not, don't return 2496 // // the outline numbering rule. 2497 // if ( pRet && pRet == GetDoc()->GetOutlineNumRule() ) 2498 // { 2499 // const SwNumRuleItem& rDirectItem = pColl->GetNumRule(sal_False); 2500 // SwNumRule* pNumRuleAtParaStyle = const_cast<SwDoc*>(GetDoc())-> 2501 // FindNumRulePtrWithPool(rDirectItem.GetValue()); 2502 // if ( !pNumRuleAtParaStyle ) 2503 // { 2504 // pRet = 0L; 2505 // } 2506 // } 2507 // // <-- 2508 // } 2509 // } 2510 2511 // if (!pRet && GetDoc()->IsOutlineLevelYieldsOutlineRule() && 2512 // GetOutlineLevel() != NO_NUMBERING) 2513 // pRet = GetDoc()->GetOutlineNumRule(); 2514 // } 2515 // <-- 2516 2517 return pRet; 2518 } 2519 2520 SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const 2521 { 2522 SwNumRule * pRet = _GetNumRule(bInParent); 2523 2524 return pRet; 2525 } 2526 2527 void SwTxtNode::NumRuleChgd() 2528 { 2529 // --> OD 2008-04-04 #refactorlists# 2530 if ( IsInList() ) 2531 { 2532 SwNumRule* pNumRule = GetNumRule(); 2533 if ( pNumRule && pNumRule != GetNum()->GetNumRule() ) 2534 { 2535 mpNodeNum->ChangeNumRule( *pNumRule ); 2536 } 2537 } 2538 // <-- 2539 2540 if( IsInCache() ) 2541 { 2542 SwFrm::GetCache().Delete( this ); 2543 SetInCache( sal_False ); 2544 } 2545 SetInSwFntCache( sal_False ); 2546 2547 // Sending "noop" modify in order to cause invalidations of registered 2548 // <SwTxtFrm> instances to get the list style change respectively the change 2549 // in the list tree reflected in the layout. 2550 // Important note: 2551 { 2552 SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace(); 2553 NotifyClients( &rLR, &rLR ); 2554 } 2555 } 2556 2557 // -> #i27615# 2558 sal_Bool SwTxtNode::IsNumbered() const 2559 { 2560 sal_Bool bResult = sal_False; 2561 2562 SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2563 if ( pRule && IsCountedInList() ) 2564 bResult = sal_True; 2565 2566 return bResult; 2567 } 2568 2569 // --> OD 2008-04-02 #refactorlists# 2570 bool SwTxtNode::HasMarkedLabel() const 2571 { 2572 bool bResult = false; 2573 2574 if ( IsInList() ) 2575 { 2576 bResult = 2577 GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() ); 2578 } 2579 2580 return bResult; 2581 } 2582 // <-- 2583 // <- #i27615# 2584 2585 SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext, 2586 sal_Bool bChgFollow ) 2587 { 2588 /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */ 2589 SwAttrSet* pNewAttrSet = 0; 2590 // --> OD 2007-07-10 #i75353# 2591 bool bClearHardSetNumRuleWhenFmtCollChanges( false ); 2592 // <-- 2593 if( HasSwAttrSet() ) 2594 { 2595 pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() ); 2596 const SfxItemSet* pTmpSet = GetpSwAttrSet(); 2597 2598 if( bNext ) // der naechste erbt keine Breaks! 2599 pTmpSet = pNewAttrSet; 2600 2601 // PageBreaks/PageDesc/ColBreak rausschmeissen. 2602 sal_Bool bRemoveFromCache = sal_False; 2603 std::vector<sal_uInt16> aClearWhichIds; 2604 if ( bNext ) 2605 bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) ); 2606 else 2607 aClearWhichIds.push_back( RES_PAGEDESC ); 2608 2609 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) ) 2610 { 2611 if ( bNext ) 2612 pNewAttrSet->ClearItem( RES_BREAK ); 2613 else 2614 aClearWhichIds.push_back( RES_BREAK ); 2615 bRemoveFromCache = sal_True; 2616 } 2617 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) ) 2618 { 2619 if ( bNext ) 2620 pNewAttrSet->ClearItem( RES_KEEP ); 2621 else 2622 aClearWhichIds.push_back( RES_KEEP ); 2623 bRemoveFromCache = sal_True; 2624 } 2625 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) ) 2626 { 2627 if ( bNext ) 2628 pNewAttrSet->ClearItem( RES_PARATR_SPLIT ); 2629 else 2630 aClearWhichIds.push_back( RES_PARATR_SPLIT ); 2631 bRemoveFromCache = sal_True; 2632 } 2633 if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False)) 2634 { 2635 SwNumRule * pRule = GetNumRule(); 2636 2637 if (pRule && IsOutline()) 2638 { 2639 if ( bNext ) 2640 pNewAttrSet->ClearItem(RES_PARATR_NUMRULE); 2641 else 2642 { 2643 // --> OD 2007-07-10 #i75353# 2644 // No clear of hard set numbering rule at an outline paragraph at this point. 2645 // Only if the paragraph style changes - see below. 2646 // aClearWhichIds.push_back( RES_PARATR_NUMRULE ); 2647 bClearHardSetNumRuleWhenFmtCollChanges = true; 2648 // <-- 2649 } 2650 bRemoveFromCache = sal_True; 2651 } 2652 } 2653 2654 if ( 0 != aClearWhichIds.size() ) 2655 bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds ); 2656 2657 if( !bNext && bRemoveFromCache && IsInCache() ) 2658 { 2659 SwFrm::GetCache().Delete( this ); 2660 SetInCache( sal_False ); 2661 } 2662 } 2663 SwNodes& rNds = GetNodes(); 2664 2665 SwTxtFmtColl* pColl = GetTxtColl(); 2666 2667 SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet ); 2668 2669 if( pNewAttrSet ) 2670 delete pNewAttrSet; 2671 2672 const SwNumRule* pRule = GetNumRule(); 2673 if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901# 2674 { 2675 // --> OD 2005-10-18 #i55459# 2676 // - correction: parameter <bNext> has to be checked, as it was in the 2677 // previous implementation. 2678 if ( !bNext && !IsCountedInList() ) 2679 SetCountedInList(true); 2680 // <-- 2681 } 2682 2683 // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine 2684 // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht 2685 // nochmal uebergeplaettet werden !! 2686 if( pColl != pNode->GetTxtColl() || 2687 ( bChgFollow && pColl != GetTxtColl() )) 2688 return pNode; // mehr duerfte nicht gemacht werden oder ???? 2689 2690 pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung 2691 if( bNext || !bChgFollow ) 2692 return pNode; 2693 2694 SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl(); 2695 // --> OD 2009-08-12 #i101870# 2696 // perform action on different paragraph styles before applying the new paragraph style 2697 if (pNextColl != pColl) 2698 { 2699 // --> OD 2007-07-10 #i75353# 2700 if ( bClearHardSetNumRuleWhenFmtCollChanges ) 2701 { 2702 std::vector<sal_uInt16> aClearWhichIds; 2703 aClearWhichIds.push_back( RES_PARATR_NUMRULE ); 2704 if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() ) 2705 { 2706 SwFrm::GetCache().Delete( this ); 2707 SetInCache( sal_False ); 2708 } 2709 } 2710 // <-- 2711 } 2712 // <-- 2713 ChgFmtColl( pNextColl ); 2714 2715 return pNode; 2716 } 2717 2718 SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos ) 2719 { 2720 // Position hinter dem eingefuegt wird 2721 SwNodeIndex aIdx( rPos.nNode, 1 ); 2722 SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True ); 2723 2724 // --> OD 2008-05-14 #refactorlists# 2725 // reset list attributes at appended text node 2726 pNew->ResetAttr( RES_PARATR_LIST_ISRESTART ); 2727 pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 2728 pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 2729 if ( pNew->GetNumRule() == 0 ) 2730 { 2731 pNew->ResetAttr( RES_PARATR_LIST_ID ); 2732 pNew->ResetAttr( RES_PARATR_LIST_LEVEL ); 2733 } 2734 // <-- 2735 // --> OD 2008-03-13 #refactorlists# 2736 // SyncNumberAndNumRule(); 2737 if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 ) 2738 { 2739 AddToList(); 2740 } 2741 // <-- 2742 2743 if( GetDepends() ) 2744 MakeFrms( *pNew ); 2745 return pNew; 2746 } 2747 2748 /************************************************************************* 2749 * SwTxtNode::GetTxtAttr 2750 *************************************************************************/ 2751 2752 SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex, 2753 const RES_TXTATR nWhich ) const 2754 { 2755 if ( HasHints() ) 2756 { 2757 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i ) 2758 { 2759 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i); 2760 const xub_StrLen nStartPos = *pHint->GetStart(); 2761 if ( nIndex < nStartPos ) 2762 { 2763 return 0; 2764 } 2765 if ( (nIndex == nStartPos) && pHint->HasDummyChar() ) 2766 { 2767 return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() ) 2768 ? pHint : 0; 2769 } 2770 } 2771 } 2772 return 0; 2773 } 2774 2775 // -> #i29560# 2776 sal_Bool SwTxtNode::HasNumber() const 2777 { 2778 sal_Bool bResult = sal_False; 2779 2780 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2781 if ( pRule ) 2782 { 2783 SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()))); 2784 2785 // #i40041# 2786 bResult = aFmt.IsEnumeration() && 2787 SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType(); 2788 } 2789 2790 return bResult; 2791 } 2792 2793 sal_Bool SwTxtNode::HasBullet() const 2794 { 2795 sal_Bool bResult = sal_False; 2796 2797 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2798 if ( pRule ) 2799 { 2800 SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()))); 2801 2802 bResult = aFmt.IsItemize(); 2803 } 2804 2805 return bResult; 2806 } 2807 // <- #i29560# 2808 2809 // --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings> 2810 //i53420 added max outline parameter 2811 XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const 2812 { 2813 if (GetDoc()->IsClipBoard() && m_pNumStringCache.get()) 2814 { 2815 // #i111677# do not expand number strings in clipboard documents 2816 return *m_pNumStringCache; 2817 } 2818 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2819 if ( pRule && 2820 IsCountedInList() ) 2821 { 2822 SvxNumberType const& rNumberType( 2823 pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) ); 2824 if (rNumberType.IsTxtFmt() || 2825 // #b6432095# 2826 (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType())) 2827 { 2828 return pRule->MakeNumString( GetNum()->GetNumberVector(), 2829 _bInclPrefixAndSuffixStrings ? sal_True : sal_False, 2830 sal_False, 2831 _nRestrictToThisLevel ); 2832 } 2833 } 2834 2835 return aEmptyStr; 2836 } 2837 2838 long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const 2839 { 2840 long nRet = 0; 2841 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2842 if( pRule ) 2843 { 2844 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2845 // --> OD 2008-01-16 #newlistlevelattrs# 2846 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2847 { 2848 nRet = rFmt.GetAbsLSpace(); 2849 2850 if( !bTxtLeft ) 2851 { 2852 if( 0 > rFmt.GetFirstLineOffset() && 2853 nRet > -rFmt.GetFirstLineOffset() ) 2854 nRet = nRet + rFmt.GetFirstLineOffset(); 2855 else 2856 nRet = 0; 2857 } 2858 2859 if( pRule->IsAbsSpaces() ) 2860 nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft(); 2861 } 2862 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2863 { 2864 if ( AreListLevelIndentsApplicable() ) 2865 { 2866 nRet = rFmt.GetIndentAt(); 2867 // --> OD 2008-06-06 #i90401# 2868 // Only negative first line indents have consider for the left margin 2869 if ( !bTxtLeft && 2870 rFmt.GetFirstLineIndent() < 0 ) 2871 { 2872 nRet = nRet + rFmt.GetFirstLineIndent(); 2873 } 2874 // <-- 2875 } 2876 } 2877 // <-- 2878 } 2879 2880 return nRet; 2881 } 2882 2883 sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const 2884 { 2885 sal_Bool bRet( sal_False ); 2886 // --> OD 2009-09-08 #i95907#, #b6879723# 2887 rFLOffset = 0; 2888 // <-- 2889 2890 // --> OD 2005-11-02 #i51089 - TUNING# 2891 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2892 if ( pRule ) 2893 { 2894 if ( IsCountedInList() ) 2895 { 2896 // --> OD 2008-01-16 #newlistlevelattrs# 2897 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2898 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2899 { 2900 rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset(); 2901 2902 if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2903 { 2904 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 2905 rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst(); 2906 } 2907 } 2908 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2909 { 2910 if ( AreListLevelIndentsApplicable() ) 2911 { 2912 rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent()); 2913 } 2914 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2915 { 2916 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 2917 rFLOffset = aItem.GetTxtFirstLineOfst(); 2918 } 2919 } 2920 // <-- 2921 } 2922 2923 bRet = sal_True; 2924 } 2925 else 2926 { 2927 rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2928 } 2929 2930 return bRet; 2931 } 2932 2933 // --> OD 2010-01-05 #b6884103# 2934 SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const 2935 { 2936 SwTwips nAdditionalIndent = 0; 2937 2938 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2939 if ( pRule ) 2940 { 2941 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2942 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2943 { 2944 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2945 2946 if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2947 { 2948 nAdditionalIndent = nAdditionalIndent - 2949 GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2950 } 2951 } 2952 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2953 { 2954 if ( AreListLevelIndentsApplicable() ) 2955 { 2956 nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent(); 2957 } 2958 else 2959 { 2960 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2961 if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2962 { 2963 nAdditionalIndent = nAdditionalIndent - 2964 GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2965 } 2966 } 2967 } 2968 } 2969 else 2970 { 2971 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2972 } 2973 2974 return nAdditionalIndent; 2975 } 2976 // <-- 2977 2978 // --> OD 2008-12-02 #i96772# 2979 void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const 2980 { 2981 if ( AreListLevelIndentsApplicable() ) 2982 { 2983 const SwNumRule* pRule = GetNumRule(); 2984 if ( pRule && GetActualListLevel() >= 0 ) 2985 { 2986 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2987 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2988 { 2989 SvxLRSpaceItem aLR( RES_LR_SPACE ); 2990 o_rLRSpaceItem = aLR; 2991 } 2992 } 2993 } 2994 } 2995 // <-- 2996 2997 // --> OD 2008-07-01 #i91133# 2998 long SwTxtNode::GetLeftMarginForTabCalculation() const 2999 { 3000 long nLeftMarginForTabCalc = 0; 3001 3002 bool bLeftMarginForTabCalcSetToListLevelIndent( false ); 3003 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0; 3004 if( pRule ) 3005 { 3006 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 3007 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 3008 { 3009 if ( AreListLevelIndentsApplicable() ) 3010 { 3011 nLeftMarginForTabCalc = rFmt.GetIndentAt(); 3012 bLeftMarginForTabCalcSetToListLevelIndent = true; 3013 } 3014 } 3015 } 3016 if ( !bLeftMarginForTabCalcSetToListLevelIndent ) 3017 { 3018 nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft(); 3019 } 3020 3021 return nLeftMarginForTabCalc; 3022 } 3023 // <-- 3024 3025 void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt, 3026 xub_StrLen nEndPos, sal_Bool bExpandFlds ) const 3027 { 3028 if( GetpSwpHints() ) 3029 { 3030 sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD; 3031 for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter, 3032 cSrchChr = CH_TXTATR_INWORD ) 3033 { 3034 xub_StrLen nPos = rTxt.Search( cSrchChr ); 3035 while( STRING_NOTFOUND != nPos && nPos < nEndPos ) 3036 { 3037 const SwTxtAttr* const pAttr = 3038 GetTxtAttrForCharAt( rTxtStt + nPos ); 3039 if( pAttr ) 3040 { 3041 switch( pAttr->Which() ) 3042 { 3043 case RES_TXTATR_FIELD: 3044 rTxt.Erase( nPos, 1 ); 3045 if( bExpandFlds ) 3046 { 3047 const XubString aExpand( 3048 static_cast<SwTxtFld const*>(pAttr)->GetFld() 3049 .GetFld()->ExpandField(true)); 3050 rTxt.Insert( aExpand, nPos ); 3051 nPos = nPos + aExpand.Len(); 3052 nEndPos = nEndPos + aExpand.Len(); 3053 rTxtStt = rTxtStt - aExpand.Len(); 3054 } 3055 ++rTxtStt; 3056 break; 3057 case RES_TXTATR_FTN: 3058 rTxt.Erase( nPos, 1 ); 3059 if( bExpandFlds ) 3060 { 3061 const SwFmtFtn& rFtn = pAttr->GetFtn(); 3062 XubString sExpand; 3063 if( rFtn.GetNumStr().Len() ) 3064 sExpand = rFtn.GetNumStr(); 3065 else if( rFtn.IsEndNote() ) 3066 sExpand = GetDoc()->GetEndNoteInfo().aFmt. 3067 GetNumStr( rFtn.GetNumber() ); 3068 else 3069 sExpand = GetDoc()->GetFtnInfo().aFmt. 3070 GetNumStr( rFtn.GetNumber() ); 3071 rTxt.Insert( sExpand, nPos ); 3072 nPos = nPos + sExpand.Len(); 3073 nEndPos = nEndPos + sExpand.Len(); 3074 rTxtStt = rTxtStt - sExpand.Len(); 3075 } 3076 ++rTxtStt; 3077 break; 3078 default: 3079 rTxt.Erase( nPos, 1 ); 3080 ++rTxtStt; 3081 } 3082 } 3083 else 3084 ++nPos, ++nEndPos; 3085 nPos = rTxt.Search( cSrchChr, nPos ); 3086 } 3087 } 3088 } 3089 } 3090 3091 /************************************************************************* 3092 * SwTxtNode::GetExpandTxt 3093 * Expand fields 3094 *************************************************************************/ 3095 // --> OD 2007-11-15 #i83479# - handling of new parameters 3096 XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx, 3097 const xub_StrLen nLen, 3098 const bool bWithNum, 3099 const bool bAddSpaceAfterListLabelStr, 3100 const bool bWithSpacesForLevel ) const 3101 { 3102 XubString aTxt( GetTxt().Copy( nIdx, nLen ) ); 3103 xub_StrLen nTxtStt = nIdx; 3104 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True ); 3105 if( bWithNum ) 3106 { 3107 XubString aListLabelStr = GetNumString(); 3108 if ( aListLabelStr.Len() > 0 ) 3109 { 3110 if ( bAddSpaceAfterListLabelStr ) 3111 { 3112 const sal_Unicode aSpace = ' '; 3113 aTxt.Insert( aSpace, 0 ); 3114 } 3115 aTxt.Insert( GetNumString(), 0 ); 3116 } 3117 } 3118 3119 if ( bWithSpacesForLevel && GetActualListLevel() > 0 ) 3120 { 3121 int nLevel( GetActualListLevel() ); 3122 while ( nLevel > 0 ) 3123 { 3124 const sal_Unicode aSpace = ' '; 3125 aTxt.Insert( aSpace , 0 ); 3126 aTxt.Insert( aSpace , 0 ); 3127 --nLevel; 3128 } 3129 } 3130 3131 return aTxt; 3132 } 3133 // <-- 3134 3135 sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx, 3136 xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum, 3137 sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const 3138 { 3139 if( &rDestNd == this ) 3140 return sal_False; 3141 3142 SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() ); 3143 if( pDestIdx ) 3144 aDestIdx = *pDestIdx; 3145 xub_StrLen nDestStt = aDestIdx.GetIndex(); 3146 3147 // Text einfuegen 3148 String sTmpText = GetTxt(); 3149 if( bReplaceTabsWithSpaces ) 3150 sTmpText.SearchAndReplaceAll('\t', ' '); 3151 3152 // mask hidden characters 3153 const xub_Unicode cChar = CH_TXTATR_BREAKWORD; 3154 sal_uInt16 nHiddenChrs = 3155 SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar ); 3156 3157 sTmpText = sTmpText.Copy( nIdx, nLen ); 3158 rDestNd.InsertText( sTmpText, aDestIdx ); 3159 nLen = aDestIdx.GetIndex() - nDestStt; 3160 3161 // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen 3162 if ( HasHints() ) 3163 { 3164 xub_StrLen nInsPos = nDestStt - nIdx; 3165 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ ) 3166 { 3167 const SwTxtAttr* pHt = (*m_pSwpHints)[i]; 3168 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 3169 const sal_uInt16 nWhich = pHt->Which(); 3170 if (nIdx + nLen <= nAttrStartIdx) 3171 break; // ueber das Textende 3172 3173 const xub_StrLen *pEndIdx = pHt->GetEnd(); 3174 if( pEndIdx && *pEndIdx > nIdx && 3175 ( RES_CHRATR_FONT == nWhich || 3176 RES_TXTATR_CHARFMT == nWhich || 3177 RES_TXTATR_AUTOFMT == nWhich )) 3178 { 3179 const SvxFontItem* const pFont = 3180 static_cast<const SvxFontItem*>( 3181 CharFmt::GetItem( *pHt, RES_CHRATR_FONT )); 3182 if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() ) 3183 { 3184 // attribute in area => copy 3185 rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont), 3186 nInsPos + nAttrStartIdx, nInsPos + *pEndIdx ); 3187 } 3188 } 3189 else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) ) 3190 { 3191 aDestIdx = nInsPos + nAttrStartIdx; 3192 switch( nWhich ) 3193 { 3194 case RES_TXTATR_FIELD: 3195 { 3196 XubString const aExpand( 3197 static_cast<SwTxtFld const*>(pHt)->GetFld().GetFld() 3198 ->ExpandField(true)); 3199 if( aExpand.Len() ) 3200 { 3201 aDestIdx++; // dahinter einfuegen; 3202 rDestNd.InsertText( aExpand, aDestIdx ); 3203 aDestIdx = nInsPos + nAttrStartIdx; 3204 nInsPos = nInsPos + aExpand.Len(); 3205 } 3206 rDestNd.EraseText( aDestIdx, 1 ); 3207 --nInsPos; 3208 } 3209 break; 3210 3211 case RES_TXTATR_FTN: 3212 { 3213 if ( bWithFtn ) 3214 { 3215 const SwFmtFtn& rFtn = pHt->GetFtn(); 3216 XubString sExpand; 3217 if( rFtn.GetNumStr().Len() ) 3218 sExpand = rFtn.GetNumStr(); 3219 else if( rFtn.IsEndNote() ) 3220 sExpand = GetDoc()->GetEndNoteInfo().aFmt. 3221 GetNumStr( rFtn.GetNumber() ); 3222 else 3223 sExpand = GetDoc()->GetFtnInfo().aFmt. 3224 GetNumStr( rFtn.GetNumber() ); 3225 if( sExpand.Len() ) 3226 { 3227 aDestIdx++; // insert behind 3228 SvxEscapementItem aItem( 3229 SVX_ESCAPEMENT_SUPERSCRIPT ); 3230 rDestNd.InsertItem(aItem, 3231 aDestIdx.GetIndex(), 3232 aDestIdx.GetIndex() ); 3233 rDestNd.InsertText( sExpand, aDestIdx, 3234 IDocumentContentOperations::INS_EMPTYEXPAND); 3235 aDestIdx = nInsPos + nAttrStartIdx; 3236 nInsPos = nInsPos + sExpand.Len(); 3237 } 3238 } 3239 rDestNd.EraseText( aDestIdx, 1 ); 3240 --nInsPos; 3241 } 3242 break; 3243 3244 default: 3245 rDestNd.EraseText( aDestIdx, 1 ); 3246 --nInsPos; 3247 } 3248 } 3249 } 3250 } 3251 3252 if( bWithNum ) 3253 { 3254 aDestIdx = nDestStt; 3255 rDestNd.InsertText( GetNumString(), aDestIdx ); 3256 } 3257 3258 if ( nHiddenChrs > 0 ) 3259 { 3260 aDestIdx = 0; 3261 while ( aDestIdx < rDestNd.GetTxt().Len() ) 3262 { 3263 if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) ) 3264 { 3265 xub_StrLen nIndex = aDestIdx.GetIndex(); 3266 while ( nIndex < rDestNd.GetTxt().Len() && 3267 cChar == rDestNd.GetTxt().GetChar( ++nIndex ) ) 3268 ; 3269 rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() ); 3270 } 3271 else 3272 ++aDestIdx; 3273 } 3274 } 3275 3276 return sal_True; 3277 } 3278 3279 const ModelToViewHelper::ConversionMap* 3280 SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const 3281 { 3282 const rtl::OUString& rNodeText = GetTxt(); 3283 rRetText = rNodeText; 3284 ModelToViewHelper::ConversionMap* pConversionMap = 0; 3285 3286 const SwpHints* pSwpHints2 = GetpSwpHints(); 3287 xub_StrLen nPos = 0; 3288 3289 for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i ) 3290 { 3291 const SwTxtAttr* pAttr = (*pSwpHints2)[i]; 3292 if ( RES_TXTATR_FIELD == pAttr->Which() ) 3293 { 3294 const XubString aExpand( 3295 static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld() 3296 ->ExpandField(true)); 3297 if ( aExpand.Len() > 0 ) 3298 { 3299 const xub_StrLen nFieldPos = *pAttr->GetStart(); 3300 rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand ); 3301 if ( !pConversionMap ) 3302 pConversionMap = new ModelToViewHelper::ConversionMap; 3303 pConversionMap->push_back( 3304 ModelToViewHelper::ConversionMapEntry( 3305 nFieldPos, nPos + nFieldPos ) ); 3306 nPos += ( aExpand.Len() - 1 ); 3307 } 3308 } 3309 } 3310 3311 if ( pConversionMap && pConversionMap->size() ) 3312 pConversionMap->push_back( 3313 ModelToViewHelper::ConversionMapEntry( 3314 rNodeText.getLength()+1, rRetText.getLength()+1 ) ); 3315 3316 return pConversionMap; 3317 } 3318 3319 XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen, 3320 sal_Bool bExpandFlds, sal_Bool bWithNum ) const 3321 { 3322 SvUShorts aRedlArr; 3323 const SwDoc* pDoc = GetDoc(); 3324 sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE ); 3325 if( USHRT_MAX != nRedlPos ) 3326 { 3327 // es existiert fuer den Node irgendein Redline-Delete-Object 3328 const sal_uLong nNdIdx = GetIndex(); 3329 for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos ) 3330 { 3331 const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ]; 3332 if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() ) 3333 { 3334 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End(); 3335 if( pRStt->nNode < nNdIdx ) 3336 { 3337 if( pREnd->nNode > nNdIdx ) 3338 // Absatz ist komplett geloescht 3339 return aEmptyStr; 3340 else if( pREnd->nNode == nNdIdx ) 3341 { 3342 // von 0 bis nContent ist alles geloescht 3343 aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() ); 3344 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() ); 3345 } 3346 } 3347 else if( pRStt->nNode == nNdIdx ) 3348 { 3349 aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() ); 3350 if( pREnd->nNode == nNdIdx ) 3351 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() ); 3352 else 3353 { 3354 aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() ); 3355 break; // mehr kann nicht kommen 3356 } 3357 } 3358 else 3359 break; // mehr kann nicht kommen 3360 } 3361 } 3362 } 3363 3364 XubString aTxt( GetTxt().Copy( nIdx, nLen ) ); 3365 3366 xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len(); 3367 for( sal_uInt16 n = 0; n < aRedlArr.Count(); n += 2 ) 3368 { 3369 xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ]; 3370 if( ( nIdx <= nStt && nStt <= nIdxEnd ) || 3371 ( nIdx <= nEnd && nEnd <= nIdxEnd )) 3372 { 3373 if( nStt < nIdx ) nStt = nIdx; 3374 if( nIdxEnd < nEnd ) nEnd = nIdxEnd; 3375 xub_StrLen nDelCnt = nEnd - nStt; 3376 aTxt.Erase( nStt - nTxtStt, nDelCnt ); 3377 Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds ); 3378 nTxtStt = nTxtStt + nDelCnt; 3379 } 3380 else if( nStt >= nIdxEnd ) 3381 break; 3382 } 3383 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds ); 3384 3385 if( bWithNum ) 3386 aTxt.Insert( GetNumString(), 0 ); 3387 return aTxt; 3388 } 3389 3390 /************************************************************************* 3391 * SwTxtNode::ReplaceText 3392 *************************************************************************/ 3393 3394 void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen, 3395 const XubString& rText ) 3396 { 3397 ASSERT( rStart.GetIndex() < m_Text.Len() && 3398 rStart.GetIndex() + nDelLen <= m_Text.Len(), 3399 "SwTxtNode::ReplaceText: index out of bounds" ); 3400 const xub_StrLen nStartPos = rStart.GetIndex(); 3401 xub_StrLen nEndPos = nStartPos + nDelLen; 3402 xub_StrLen nLen = nDelLen; 3403 for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos ) 3404 { 3405 if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) || 3406 ( CH_TXTATR_INWORD == m_Text.GetChar( nPos ) ) ) 3407 { 3408 SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos ); 3409 if (pHint) 3410 { 3411 ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar() 3412 && (*pHint->GetStart() < nEndPos) 3413 && (*pHint->GetEnd() > nEndPos) ), 3414 "ReplaceText: ERROR: " 3415 "deleting left-overlapped attribute with CH_TXTATR"); 3416 DeleteAttribute( pHint ); 3417 --nEndPos; 3418 --nLen; 3419 } 3420 } 3421 } 3422 3423 sal_Bool bOldExpFlg = IsIgnoreDontExpand(); 3424 SetIgnoreDontExpand( sal_True ); 3425 3426 if( nLen && rText.Len() ) 3427 { 3428 // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen 3429 // Dadurch wird die Attributierung des 1. Zeichen expandiert! 3430 m_Text.SetChar( nStartPos, rText.GetChar( 0 ) ); 3431 3432 ((SwIndex&)rStart)++; 3433 m_Text.Erase( rStart.GetIndex(), nLen - 1 ); 3434 Update( rStart, nLen - 1, true ); 3435 3436 XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 ); 3437 m_Text.Insert( aTmpTxt, rStart.GetIndex() ); 3438 Update( rStart, aTmpTxt.Len(), false ); 3439 } 3440 else 3441 { 3442 m_Text.Erase( nStartPos, nLen ); 3443 Update( rStart, nLen, true ); 3444 3445 m_Text.Insert( rText, nStartPos ); 3446 Update( rStart, rText.Len(), false ); 3447 } 3448 3449 SetIgnoreDontExpand( bOldExpFlg ); 3450 SwDelTxt aDelHint( nStartPos, nDelLen ); 3451 NotifyClients( 0, &aDelHint ); 3452 3453 SwInsTxt aHint( nStartPos, rText.Len() ); 3454 NotifyClients( 0, &aHint ); 3455 } 3456 3457 // --> OD 2008-03-27 #refactorlists# 3458 namespace { 3459 // Helper method for special handling of modified attributes at text node. 3460 // The following is handled: 3461 // (1) on changing the paragraph style - RES_FMT_CHG: 3462 // Check, if list style of the text node is changed. If yes, add respectively 3463 // remove the text node to the corresponding list. 3464 // (2) on changing the attributes - RES_ATTRSET_CHG: 3465 // Same as (1). 3466 // (3) on changing the list style - RES_PARATR_NUMRULE: 3467 // Same as (1). 3468 void HandleModifyAtTxtNode( SwTxtNode& rTxtNode, 3469 const SfxPoolItem* pOldValue, 3470 const SfxPoolItem* pNewValue ) 3471 { 3472 const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() : 3473 pNewValue ? pNewValue->Which() : 0 ; 3474 bool bNumRuleSet = false; 3475 bool bParagraphStyleChanged = false; 3476 String sNumRule; 3477 String sOldNumRule; 3478 switch ( nWhich ) 3479 { 3480 case RES_FMT_CHG: 3481 { 3482 bParagraphStyleChanged = true; 3483 if( rTxtNode.GetNodes().IsDocNodes() ) 3484 { 3485 // --> OD 2008-12-17 #i70748# 3486 // The former list style set at the paragraph can not be 3487 // retrieved from the change set. 3488 // sOldNumRule = 3489 // dynamic_cast<const SwFmtChg*>(pOldValue)->pChangedFmt->GetNumRule().GetValue(); 3490 const SwNumRule* pFormerNumRuleAtTxtNode = 3491 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3492 if ( pFormerNumRuleAtTxtNode ) 3493 { 3494 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3495 } 3496 // <-- 3497 // --> OD 2008-11-19 #i70748# 3498 if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() ) 3499 { 3500 const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule(); 3501 if ( rNumRuleItem.GetValue().Len() > 0 ) 3502 { 3503 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3504 } 3505 } 3506 // <-- 3507 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3508 if ( pNumRuleAtTxtNode ) 3509 { 3510 bNumRuleSet = true; 3511 sNumRule = pNumRuleAtTxtNode->GetName(); 3512 } 3513 } 3514 break; 3515 } 3516 case RES_ATTRSET_CHG: 3517 { 3518 const SfxPoolItem* pItem = 0; 3519 // --> OD 2008-12-19 #i70748# 3520 // The former list style set at the paragraph can not be 3521 // retrieved from the change set. 3522 // if ( dynamic_cast<const SwAttrSetChg*>(pOldValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == 3523 // SFX_ITEM_SET ) 3524 // { 3525 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue(); 3526 // } 3527 const SwNumRule* pFormerNumRuleAtTxtNode = 3528 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3529 if ( pFormerNumRuleAtTxtNode ) 3530 { 3531 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3532 } 3533 // <-- 3534 if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == 3535 SFX_ITEM_SET ) 3536 { 3537 // --> OD 2008-11-19 #i70748# 3538 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3539 // <-- 3540 bNumRuleSet = true; 3541 // The new list style set at the paragraph can not be 3542 // retrieved from the change set. 3543 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue(); 3544 // <-- 3545 } 3546 // --> OD 2008-12-17 #i70748# 3547 // The new list style set at the paragraph. 3548 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3549 if ( pNumRuleAtTxtNode ) 3550 { 3551 sNumRule = pNumRuleAtTxtNode->GetName(); 3552 } 3553 // <-- 3554 break; 3555 } 3556 case RES_PARATR_NUMRULE: 3557 { 3558 if ( rTxtNode.GetNodes().IsDocNodes() ) 3559 { 3560 // The former list style set at the paragraph can not be 3561 // retrieved from the change set. 3562 // if ( pOldValue ) 3563 // { 3564 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pOldValue)->GetValue(); 3565 // } 3566 const SwNumRule* pFormerNumRuleAtTxtNode = 3567 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3568 if ( pFormerNumRuleAtTxtNode ) 3569 { 3570 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3571 } 3572 // <-- 3573 if ( pNewValue ) 3574 { 3575 // --> OD 2008-11-19 #i70748# 3576 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3577 // <-- 3578 bNumRuleSet = true; 3579 // --> OD 2008-12-17 #i70748# 3580 // The new list style set at the paragraph can not be 3581 // retrieved from the change set. 3582 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pNewValue)->GetValue(); 3583 // <-- 3584 } 3585 // --> OD 2008-12-17 #i70748# 3586 // The new list style set at the paragraph. 3587 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3588 if ( pNumRuleAtTxtNode ) 3589 { 3590 sNumRule = pNumRuleAtTxtNode->GetName(); 3591 } 3592 // <-- 3593 } 3594 break; 3595 } 3596 } 3597 if ( sNumRule != sOldNumRule ) 3598 { 3599 if ( bNumRuleSet ) 3600 { 3601 if ( sNumRule.Len() == 0 ) 3602 { 3603 rTxtNode.RemoveFromList(); 3604 if ( bParagraphStyleChanged ) 3605 { 3606 SvUShortsSort aResetAttrsArray; 3607 aResetAttrsArray.Insert( RES_PARATR_LIST_ID ); 3608 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL ); 3609 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART ); 3610 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE ); 3611 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 3612 SwPaM aPam( rTxtNode ); 3613 // --> OD 2008-11-28 #i96644# 3614 // suppress side effect "send data changed events" 3615 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False, 3616 &aResetAttrsArray, 3617 false ); 3618 // <-- 3619 } 3620 } 3621 else 3622 { 3623 rTxtNode.RemoveFromList(); 3624 // If new list style is the outline style, apply outline 3625 // level as the list level. 3626 if ( sNumRule == 3627 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) ) 3628 { 3629 // --> OD 2008-09-10 #i70748# 3630 ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(), 3631 "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." ); 3632 int nNewListLevel = 3633 rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel(); 3634 // <-- 3635 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) 3636 { 3637 rTxtNode.SetAttrListLevel( nNewListLevel ); 3638 } 3639 } 3640 rTxtNode.AddToList(); 3641 } 3642 } 3643 else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0> 3644 { 3645 rTxtNode.RemoveFromList(); 3646 if ( bParagraphStyleChanged ) 3647 { 3648 SvUShortsSort aResetAttrsArray; 3649 aResetAttrsArray.Insert( RES_PARATR_LIST_ID ); 3650 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL ); 3651 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART ); 3652 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE ); 3653 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 3654 SwPaM aPam( rTxtNode ); 3655 // --> OD 2008-11-28 #i96644# 3656 // suppress side effect "send data changed events" 3657 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False, 3658 &aResetAttrsArray, 3659 false ); 3660 // <-- 3661 // --> OD 2008-11-19 #i70748# 3662 if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 ) 3663 { 3664 rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 3665 } 3666 // <-- 3667 } 3668 } 3669 } 3670 else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() ) 3671 { 3672 rTxtNode.AddToList(); 3673 } 3674 // <-- 3675 } 3676 // End of method <HandleModifyAtTxtNode> 3677 } 3678 // <-- 3679 3680 void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue ) 3681 { 3682 bool bWasNotifiable = m_bNotifiable; 3683 m_bNotifiable = false; 3684 3685 // Bug 24616/24617: 3686 // Modify ueberladen, damit beim Loeschen von Vorlagen diese 3687 // wieder richtig verwaltet werden (Outline-Numerierung!!) 3688 // Bug25481: 3689 // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen. 3690 if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() && 3691 GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt && 3692 GetNodes().IsDocNodes() ) 3693 { 3694 _ChgTxtCollUpdateNum( 3695 (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt, 3696 (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt ); 3697 } 3698 3699 // --> OD 2008-03-27 #refactorlists# 3700 if ( !mbInSetOrResetAttr ) 3701 { 3702 HandleModifyAtTxtNode( *this, pOldValue, pNewValue ); 3703 } 3704 // <-- 3705 3706 SwCntntNode::Modify( pOldValue, pNewValue ); 3707 3708 SwDoc * pDoc = GetDoc(); 3709 // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array 3710 if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() ) 3711 // <-- 3712 { 3713 pDoc->GetNodes().UpdateOutlineNode(*this); 3714 } 3715 3716 m_bNotifiable = bWasNotifiable; 3717 3718 if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which())) 3719 { // invalidate cached uno object 3720 SetXParagraph(::com::sun::star::uno::Reference< 3721 ::com::sun::star::text::XTextContent>(0)); 3722 } 3723 } 3724 3725 SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl ) 3726 { 3727 ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." ); 3728 ASSERT( HAS_BASE( SwTxtFmtColl, pNewColl ), 3729 "ChgFmtColl: ist kein Text-Collectionpointer." ); 3730 3731 SwTxtFmtColl *pOldColl = GetTxtColl(); 3732 if( pNewColl != pOldColl ) 3733 { 3734 SetCalcHiddenCharFlags(); 3735 SwCntntNode::ChgFmtColl( pNewColl ); 3736 // --> OD 2008-03-27 #refactorlists# 3737 // NumRuleChgd(); 3738 #if OSL_DEBUG_LEVEL > 1 3739 ASSERT( !mbInSetOrResetAttr, 3740 "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" ) 3741 #endif 3742 if ( !mbInSetOrResetAttr ) 3743 { 3744 SwFmtChg aTmp1( pOldColl ); 3745 SwFmtChg aTmp2( pNewColl ); 3746 HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 ); 3747 } 3748 // <-- 3749 } 3750 3751 // nur wenn im normalen Nodes-Array 3752 if( GetNodes().IsDocNodes() ) 3753 { 3754 _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) ); 3755 } 3756 3757 GetNodes().UpdateOutlineNode(*this); 3758 3759 return pOldColl; 3760 } 3761 3762 SwNodeNum* SwTxtNode::CreateNum() const 3763 { 3764 if ( !mpNodeNum ) 3765 { 3766 // --> OD 2008-02-19 #refactorlists# 3767 mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) ); 3768 // <-- 3769 } 3770 return mpNodeNum; 3771 } 3772 3773 SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const 3774 { 3775 if ( GetNum() ) 3776 { 3777 return GetNum()->GetNumberVector(); 3778 } 3779 else 3780 { 3781 SwNumberTree::tNumberVector aResult; 3782 return aResult; 3783 } 3784 } 3785 3786 bool SwTxtNode::IsOutline() const 3787 { 3788 bool bResult = false; 3789 3790 //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei 3791 if ( GetAttrOutlineLevel() > 0 ) //<-end,zhaojianwei 3792 { 3793 bResult = !IsInRedlines(); 3794 } 3795 else 3796 { 3797 const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L ); 3798 if ( pRule && pRule->IsOutlineRule() ) 3799 { 3800 bResult = !IsInRedlines(); 3801 } 3802 } 3803 3804 return bResult; 3805 } 3806 3807 bool SwTxtNode::IsOutlineStateChanged() const 3808 { 3809 return IsOutline() != m_bLastOutlineState; 3810 } 3811 3812 void SwTxtNode::UpdateOutlineState() 3813 { 3814 m_bLastOutlineState = IsOutline(); 3815 } 3816 3817 //#outline level, zhaojianwei 3818 int SwTxtNode::GetAttrOutlineLevel() const 3819 { 3820 return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue(); 3821 } 3822 void SwTxtNode::SetAttrOutlineLevel(int nLevel) 3823 { 3824 ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei 3825 if ( 0 <= nLevel && nLevel <= MAXLEVEL ) 3826 { 3827 SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 3828 static_cast<sal_uInt16>(nLevel) ) ); 3829 } 3830 } 3831 //<-end 3832 3833 // --> OD 2008-11-19 #i70748# 3834 bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr() 3835 { 3836 return mbEmptyListStyleSetDueToSetOutlineLevelAttr; 3837 } 3838 3839 void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr() 3840 { 3841 if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr ) 3842 { 3843 SetAttr( SwNumRuleItem() ); 3844 mbEmptyListStyleSetDueToSetOutlineLevelAttr = true; 3845 } 3846 } 3847 3848 void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr() 3849 { 3850 if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr ) 3851 { 3852 ResetAttr( RES_PARATR_NUMRULE ); 3853 mbEmptyListStyleSetDueToSetOutlineLevelAttr = false; 3854 } 3855 } 3856 // <-- 3857 3858 3859 // --> OD 2008-02-27 #refactorlists# 3860 void SwTxtNode::SetAttrListLevel( int nLevel ) 3861 { 3862 if ( nLevel < 0 || nLevel >= MAXLEVEL ) 3863 { 3864 ASSERT( false, 3865 "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" ); 3866 return; 3867 } 3868 3869 SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL, 3870 static_cast<sal_Int16>(nLevel) ); 3871 SetAttr( aNewListLevelItem ); 3872 } 3873 // <-- 3874 // --> OD 2008-02-27 #refactorlists# 3875 bool SwTxtNode::HasAttrListLevel() const 3876 { 3877 return GetpSwAttrSet() && 3878 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET; 3879 } 3880 // <-- 3881 // --> OD 2008-02-27 #refactorlists# 3882 int SwTxtNode::GetAttrListLevel() const 3883 { 3884 int nAttrListLevel = 0; 3885 3886 const SfxInt16Item& aListLevelItem = 3887 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL )); 3888 nAttrListLevel = static_cast<int>(aListLevelItem.GetValue()); 3889 3890 return nAttrListLevel; 3891 } 3892 // <-- 3893 3894 int SwTxtNode::GetActualListLevel() const 3895 { 3896 return GetNum() ? GetNum()->GetLevelInListTree() : -1; 3897 } 3898 3899 // --> OD 2008-02-25 #refactorlists# 3900 void SwTxtNode::SetListRestart( bool bRestart ) 3901 { 3902 // CreateNum()->SetRestart(bRestart); 3903 if ( !bRestart ) 3904 { 3905 // attribute not contained in paragraph style's attribute set. Thus, 3906 // it can be reset to the attribute pool default by resetting the attribute. 3907 ResetAttr( RES_PARATR_LIST_ISRESTART ); 3908 } 3909 else 3910 { 3911 SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART, 3912 sal_True ); 3913 SetAttr( aNewIsRestartItem ); 3914 } 3915 } 3916 3917 // --> OD 2008-02-25 #refactorlists# 3918 bool SwTxtNode::IsListRestart() const 3919 { 3920 // return GetNum() ? GetNum()->IsRestart() : false; 3921 const SfxBoolItem& aIsRestartItem = 3922 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART )); 3923 3924 return aIsRestartItem.GetValue() ? true : false; 3925 } 3926 // <-- 3927 3928 /** Returns if the paragraph has a visible numbering or bullet. 3929 This includes all kinds of numbering/bullet/outlines. 3930 OD 2008-02-28 #newlistlevelattrs# 3931 The concrete list label string has to be checked, too. 3932 */ 3933 bool SwTxtNode::HasVisibleNumberingOrBullet() const 3934 { 3935 bool bRet = false; 3936 3937 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 3938 if ( pRule && IsCountedInList()) 3939 { 3940 // --> OD 2008-03-19 #i87154# 3941 // Correction of #newlistlevelattrs#: 3942 // The numbering type has to be checked for bullet lists. 3943 const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )); 3944 if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() || 3945 pRule->MakeNumString( *(GetNum()) ).Len() > 0 ) 3946 { 3947 bRet = true; 3948 } 3949 // <-- 3950 } 3951 3952 return bRet; 3953 } 3954 3955 // --> OD 2008-02-25 #refactorlists# 3956 void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber ) 3957 { 3958 // CreateNum()->SetStart(nNumber); 3959 const bool bChanged( HasAttrListRestartValue() 3960 ? GetAttrListRestartValue() != nNumber 3961 : nNumber != USHRT_MAX ); 3962 3963 if ( bChanged || !HasAttrListRestartValue() ) 3964 { 3965 if ( nNumber == USHRT_MAX ) 3966 { 3967 ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 3968 } 3969 else 3970 { 3971 SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE, 3972 static_cast<sal_Int16>(nNumber) ); 3973 SetAttr( aNewListRestartValueItem ); 3974 } 3975 } 3976 } 3977 // <-- 3978 3979 // --> OD 2008-02-27 #refactorlists# 3980 bool SwTxtNode::HasAttrListRestartValue() const 3981 { 3982 return GetpSwAttrSet() && 3983 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET; 3984 } 3985 // <-- 3986 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const 3987 { 3988 ASSERT( HasAttrListRestartValue(), 3989 "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." ); 3990 3991 const SfxInt16Item& aListRestartValueItem = 3992 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE )); 3993 return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue()); 3994 } 3995 3996 // --> OD 2008-02-25 #refactorlists# 3997 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const 3998 { 3999 // return GetNum() ? GetNum()->GetStart() : 1; 4000 SwNumberTree::tSwNumTreeNumber nListRestartValue = 1; 4001 4002 if ( IsListRestart() && HasAttrListRestartValue() ) 4003 { 4004 nListRestartValue = GetAttrListRestartValue(); 4005 } 4006 else 4007 { 4008 SwNumRule* pRule = GetNumRule(); 4009 if ( pRule ) 4010 { 4011 const SwNumFmt* pFmt = 4012 pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) ); 4013 if ( pFmt ) 4014 { 4015 nListRestartValue = pFmt->GetStart(); 4016 } 4017 } 4018 } 4019 4020 return nListRestartValue; 4021 } 4022 // <-- 4023 4024 bool SwTxtNode::IsNotifiable() const 4025 { 4026 return m_bNotifiable && IsNotificationEnabled(); 4027 } 4028 4029 bool SwTxtNode::IsNotificationEnabled() const 4030 { 4031 bool bResult = false; 4032 const SwDoc * pDoc = GetDoc(); 4033 if( pDoc ) 4034 { 4035 bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true; 4036 } 4037 return bResult; 4038 } 4039 4040 // --> OD 2008-02-27 #refactorlists# 4041 void SwTxtNode::SetCountedInList( bool bCounted ) 4042 { 4043 if ( bCounted ) 4044 { 4045 // attribute not contained in paragraph style's attribute set. Thus, 4046 // it can be reset to the attribute pool default by resetting the attribute. 4047 ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 4048 } 4049 else 4050 { 4051 SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False ); 4052 SetAttr( aIsCountedInListItem ); 4053 } 4054 } 4055 // <-- 4056 4057 bool SwTxtNode::IsCountedInList() const 4058 { 4059 const SfxBoolItem& aIsCountedInListItem = 4060 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED )); 4061 4062 return aIsCountedInListItem.GetValue() ? true : false; 4063 } 4064 4065 // --> OD 2008-03-13 #refactorlists# 4066 void SwTxtNode::AddToList() 4067 { 4068 if ( IsInList() ) 4069 { 4070 ASSERT( false, 4071 "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" ); 4072 return; 4073 } 4074 4075 const String sListId = GetListId(); 4076 if ( sListId.Len() > 0 ) 4077 { 4078 SwList* pList = GetDoc()->getListByName( sListId ); 4079 if ( pList == 0 ) 4080 { 4081 // Create corresponding list. 4082 SwNumRule* pNumRule = GetNumRule(); 4083 if ( pNumRule ) 4084 { 4085 pList = GetDoc()->createList( sListId, GetNumRule()->GetName() ); 4086 } 4087 } 4088 ASSERT( pList != 0, 4089 "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" ); 4090 if ( pList ) 4091 { 4092 pList->InsertListItem( *CreateNum(), GetAttrListLevel() ); 4093 mpList = pList; 4094 } 4095 } 4096 } 4097 4098 void SwTxtNode::RemoveFromList() 4099 { 4100 if ( IsInList() ) 4101 { 4102 mpList->RemoveListItem( *mpNodeNum ); 4103 mpList = 0; 4104 delete mpNodeNum; 4105 mpNodeNum = 0L; 4106 } 4107 } 4108 4109 bool SwTxtNode::IsInList() const 4110 { 4111 return GetNum() != 0 && GetNum()->GetParent() != 0; 4112 } 4113 // <-- 4114 4115 bool SwTxtNode::IsFirstOfNumRule() const 4116 { 4117 bool bResult = false; 4118 4119 if ( GetNum() && GetNum()->GetNumRule()) 4120 bResult = GetNum()->IsFirst(); 4121 4122 return bResult; 4123 } 4124 4125 // --> OD 2008-02-20 #refactorlists# 4126 void SwTxtNode::SetListId( const String sListId ) 4127 { 4128 const SfxStringItem& rListIdItem = 4129 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); 4130 if ( rListIdItem.GetValue() != sListId ) 4131 { 4132 if ( sListId.Len() == 0 ) 4133 { 4134 ResetAttr( RES_PARATR_LIST_ID ); 4135 } 4136 else 4137 { 4138 SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId ); 4139 SetAttr( aNewListIdItem ); 4140 } 4141 } 4142 } 4143 4144 String SwTxtNode::GetListId() const 4145 { 4146 String sListId; 4147 4148 const SfxStringItem& rListIdItem = 4149 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); 4150 sListId = rListIdItem.GetValue(); 4151 4152 // As long as no explicit list id attribute is set, use the list id of 4153 // the list, which has been created for the applied list style. 4154 if ( sListId.Len() == 0 ) 4155 { 4156 SwNumRule* pRule = GetNumRule(); 4157 if ( pRule ) 4158 { 4159 sListId = pRule->GetDefaultListId(); 4160 //#if OSL_DEBUG_LEVEL > 1 4161 // ASSERT( false, 4162 // "DEBUG ASSERTION: default list id of list style is applied." ); 4163 //#endif 4164 // // setting list id directly using <SwCntntNode::SetAttr(..)>, 4165 // // because no handling of this attribute set is needed and to avoid 4166 // // recursive calls of <SwTxtNode::SetAttr(..)> 4167 // SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId ); 4168 // const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem ); 4169 } 4170 } 4171 4172 return sListId; 4173 } 4174 // <-- 4175 4176 /** Determines, if the list level indent attributes can be applied to the 4177 paragraph. 4178 4179 OD 2008-01-17 #newlistlevelattrs# 4180 The list level indents can be applied to the paragraph under the one 4181 of following conditions: 4182 - the list style is directly applied to the paragraph and the paragraph 4183 has no own indent attributes. 4184 - the list style is applied to the paragraph through one of its paragraph 4185 styles, the paragraph has no own indent attributes and on the paragraph 4186 style hierarchy from the paragraph to the paragraph style with the 4187 list style no indent attributes are found. 4188 4189 @author OD 4190 4191 @return boolean 4192 */ 4193 bool SwTxtNode::AreListLevelIndentsApplicable() const 4194 { 4195 bool bAreListLevelIndentsApplicable( true ); 4196 4197 if ( !GetNum() || !GetNum()->GetNumRule() ) 4198 { 4199 // no list style applied to paragraph 4200 bAreListLevelIndentsApplicable = false; 4201 } 4202 else if ( HasSwAttrSet() && 4203 GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET ) 4204 { 4205 // paragraph has hard-set indent attributes 4206 bAreListLevelIndentsApplicable = false; 4207 } 4208 else if ( HasSwAttrSet() && 4209 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET ) 4210 { 4211 // list style is directly applied to paragraph and paragraph has no 4212 // hard-set indent attributes 4213 bAreListLevelIndentsApplicable = true; 4214 } 4215 else 4216 { 4217 // list style is applied through one of the paragraph styles and 4218 // paragraph has no hard-set indent attributes 4219 4220 // check, paragraph's 4221 const SwTxtFmtColl* pColl = GetTxtColl(); 4222 while ( pColl ) 4223 { 4224 if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET ) 4225 { 4226 // indent attributes found in the paragraph style hierarchy. 4227 bAreListLevelIndentsApplicable = false; 4228 break; 4229 } 4230 4231 if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET ) 4232 { 4233 // paragraph style with the list style found and until now no 4234 // indent attributes are found in the paragraph style hierarchy. 4235 bAreListLevelIndentsApplicable = true; 4236 break; 4237 } 4238 4239 pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom()); 4240 ASSERT( pColl, 4241 "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." ); 4242 } 4243 } 4244 4245 return bAreListLevelIndentsApplicable; 4246 } 4247 4248 /** Retrieves the list tab stop position, if the paragraph's list level defines 4249 one and this list tab stop has to merged into the tap stops of the paragraph 4250 4251 OD 2008-01-17 #newlistlevelattrs# 4252 4253 @author OD 4254 4255 @param nListTabStopPosition 4256 output parameter - containing the list tab stop position 4257 4258 @return boolean - indicating, if a list tab stop position is provided 4259 */ 4260 bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const 4261 { 4262 bool bListTanStopPositionProvided( false ); 4263 4264 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0; 4265 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) 4266 { 4267 const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); 4268 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && 4269 rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB ) 4270 { 4271 bListTanStopPositionProvided = true; 4272 nListTabStopPosition = rFmt.GetListtabPos(); 4273 4274 if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) ) 4275 { 4276 // tab stop position are treated to be relative to the "before text" 4277 // indent value of the paragraph. Thus, adjust <nListTabStopPos>. 4278 if ( AreListLevelIndentsApplicable() ) 4279 { 4280 nListTabStopPosition -= rFmt.GetIndentAt(); 4281 } 4282 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 4283 { 4284 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 4285 nListTabStopPosition -= aItem.GetTxtLeft(); 4286 } 4287 } 4288 } 4289 } 4290 4291 return bListTanStopPositionProvided; 4292 } 4293 4294 /** Retrieves the character following the list label, if the paragraph's 4295 list level defines one. 4296 4297 OD 2008-01-17 #newlistlevelattrs# 4298 4299 @author OD 4300 4301 @return XubString - the list tab stop position 4302 */ 4303 XubString SwTxtNode::GetLabelFollowedBy() const 4304 { 4305 XubString aLabelFollowedBy; 4306 4307 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0; 4308 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) 4309 { 4310 const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); 4311 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 4312 { 4313 switch ( rFmt.GetLabelFollowedBy() ) 4314 { 4315 case SvxNumberFormat::LISTTAB: 4316 { 4317 const sal_Unicode aTab = '\t'; 4318 aLabelFollowedBy.Insert( aTab, 0 ); 4319 } 4320 break; 4321 case SvxNumberFormat::SPACE: 4322 { 4323 const sal_Unicode aSpace = ' '; 4324 aLabelFollowedBy.Insert( aSpace, 0 ); 4325 } 4326 break; 4327 case SvxNumberFormat::NOTHING: 4328 { 4329 // intentionally left blank. 4330 } 4331 break; 4332 default: 4333 { 4334 ASSERT( false, 4335 "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" ); 4336 } 4337 } 4338 } 4339 } 4340 4341 return aLabelFollowedBy; 4342 } 4343 4344 void SwTxtNode::CalcHiddenCharFlags() const 4345 { 4346 xub_StrLen nStartPos; 4347 xub_StrLen nEndPos; 4348 // Update of the flags is done inside GetBoundsOfHiddenRange() 4349 SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos ); 4350 } 4351 4352 // --> FME 2004-06-08 #i12836# enhanced pdf export 4353 bool SwTxtNode::IsHidden() const 4354 { 4355 if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) ) 4356 return true; 4357 4358 const SwSectionNode* pSectNd = FindSectionNode(); 4359 if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() ) 4360 return true; 4361 4362 return false; 4363 } 4364 // <-- 4365 4366 // --> OD 2008-03-13 #refactorlists# 4367 namespace { 4368 // Helper class for special handling of setting attributes at text node: 4369 // In constructor an instance of the helper class recognize whose attributes 4370 // are set and perform corresponding actions before the intrinsic set of 4371 // attributes has been taken place. 4372 // In the destructor - after the attributes have been set at the text 4373 // node - corresponding actions are performed. 4374 // The following is handled: 4375 // (1) When the list style attribute - RES_PARATR_NUMRULE - is set, 4376 // (A) list style attribute is empty -> the text node is removed from 4377 // its list. 4378 // (B) list style attribute is not empty 4379 // (a) text node has no list style -> add text node to its list after 4380 // the attributes have been set. 4381 // (b) text node has list style -> change of list style is notified 4382 // after the attributes have been set. 4383 // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed, 4384 // the text node is removed from its current list before the attributes 4385 // are set and added to its new list after the attributes have been set. 4386 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set 4387 // and changed after the attributes have been set 4388 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set 4389 // and changed after the attributes have been set 4390 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - 4391 // is set and changed after the attributes have been set 4392 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set 4393 // and changed after the attributes have been set 4394 // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL. 4395 class HandleSetAttrAtTxtNode 4396 { 4397 public: 4398 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4399 const SfxPoolItem& pItem ); 4400 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4401 const SfxItemSet& rItemSet ); 4402 ~HandleSetAttrAtTxtNode(); 4403 4404 private: 4405 SwTxtNode& mrTxtNode; 4406 bool mbAddTxtNodeToList; 4407 bool mbUpdateListLevel; 4408 bool mbUpdateListRestart; 4409 bool mbUpdateListCount; 4410 // --> OD 2008-11-19 #i70748# 4411 bool mbOutlineLevelSet; 4412 // <-- 4413 }; 4414 4415 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4416 const SfxPoolItem& pItem ) 4417 : mrTxtNode( rTxtNode ), 4418 mbAddTxtNodeToList( false ), 4419 mbUpdateListLevel( false ), 4420 mbUpdateListRestart( false ), 4421 mbUpdateListCount( false ), 4422 // --> OD 2008-11-19 #i70748# 4423 mbOutlineLevelSet( false ) 4424 // <-- 4425 { 4426 switch ( pItem.Which() ) 4427 { 4428 // handle RES_PARATR_NUMRULE 4429 case RES_PARATR_NUMRULE: 4430 { 4431 mrTxtNode.RemoveFromList(); 4432 4433 const SwNumRuleItem& pNumRuleItem = 4434 dynamic_cast<const SwNumRuleItem&>(pItem); 4435 if ( pNumRuleItem.GetValue().Len() > 0 ) 4436 { 4437 mbAddTxtNodeToList = true; 4438 // --> OD 2010-05-12 #i105562# 4439 // 4440 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4441 // <-- 4442 } 4443 } 4444 break; 4445 4446 // handle RES_PARATR_LIST_ID 4447 case RES_PARATR_LIST_ID: 4448 { 4449 const SfxStringItem& pListIdItem = 4450 dynamic_cast<const SfxStringItem&>(pItem); 4451 ASSERT( pListIdItem.GetValue().Len() > 0, 4452 "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." ); 4453 const String sListIdOfTxtNode = rTxtNode.GetListId(); 4454 if ( pListIdItem.GetValue() != sListIdOfTxtNode ) 4455 { 4456 mbAddTxtNodeToList = true; 4457 if ( mrTxtNode.IsInList() ) 4458 { 4459 mrTxtNode.RemoveFromList(); 4460 } 4461 } 4462 } 4463 break; 4464 4465 // handle RES_PARATR_LIST_LEVEL 4466 case RES_PARATR_LIST_LEVEL: 4467 { 4468 const SfxInt16Item& aListLevelItem = 4469 dynamic_cast<const SfxInt16Item&>(pItem); 4470 if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() ) 4471 { 4472 mbUpdateListLevel = true; 4473 } 4474 } 4475 break; 4476 4477 // handle RES_PARATR_LIST_ISRESTART 4478 case RES_PARATR_LIST_ISRESTART: 4479 { 4480 const SfxBoolItem& aListIsRestartItem = 4481 dynamic_cast<const SfxBoolItem&>(pItem); 4482 if ( aListIsRestartItem.GetValue() != 4483 (mrTxtNode.IsListRestart() ? sal_True : sal_False) ) 4484 { 4485 mbUpdateListRestart = true; 4486 } 4487 } 4488 break; 4489 4490 // handle RES_PARATR_LIST_RESTARTVALUE 4491 case RES_PARATR_LIST_RESTARTVALUE: 4492 { 4493 const SfxInt16Item& aListRestartValueItem = 4494 dynamic_cast<const SfxInt16Item&>(pItem); 4495 if ( !mrTxtNode.HasAttrListRestartValue() || 4496 aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() ) 4497 { 4498 mbUpdateListRestart = true; 4499 } 4500 } 4501 break; 4502 4503 // handle RES_PARATR_LIST_ISCOUNTED 4504 case RES_PARATR_LIST_ISCOUNTED: 4505 { 4506 const SfxBoolItem& aIsCountedInListItem = 4507 dynamic_cast<const SfxBoolItem&>(pItem); 4508 if ( aIsCountedInListItem.GetValue() != 4509 (mrTxtNode.IsCountedInList() ? sal_True : sal_False) ) 4510 { 4511 mbUpdateListCount = true; 4512 } 4513 } 4514 break; 4515 4516 // --> OD 2008-11-19 #i70748# 4517 // handle RES_PARATR_OUTLINELEVEL 4518 case RES_PARATR_OUTLINELEVEL: 4519 { 4520 const SfxUInt16Item& aOutlineLevelItem = 4521 dynamic_cast<const SfxUInt16Item&>(pItem); 4522 if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() ) 4523 { 4524 mbOutlineLevelSet = true; 4525 } 4526 } 4527 break; 4528 // <-- 4529 } 4530 4531 } 4532 4533 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4534 const SfxItemSet& rItemSet ) 4535 : mrTxtNode( rTxtNode ), 4536 mbAddTxtNodeToList( false ), 4537 mbUpdateListLevel( false ), 4538 mbUpdateListRestart( false ), 4539 mbUpdateListCount( false ), 4540 // --> OD 2008-11-19 #i70748# 4541 mbOutlineLevelSet( false ) 4542 // <-- 4543 { 4544 const SfxPoolItem* pItem = 0; 4545 // handle RES_PARATR_NUMRULE 4546 if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET ) 4547 { 4548 mrTxtNode.RemoveFromList(); 4549 4550 const SwNumRuleItem* pNumRuleItem = 4551 dynamic_cast<const SwNumRuleItem*>(pItem); 4552 if ( pNumRuleItem->GetValue().Len() > 0 ) 4553 { 4554 mbAddTxtNodeToList = true; 4555 // --> OD 2008-11-19 #i70748# 4556 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4557 // <-- 4558 } 4559 } 4560 4561 // handle RES_PARATR_LIST_ID 4562 if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET ) 4563 { 4564 const SfxStringItem* pListIdItem = 4565 dynamic_cast<const SfxStringItem*>(pItem); 4566 const String sListIdOfTxtNode = mrTxtNode.GetListId(); 4567 if ( pListIdItem && 4568 pListIdItem->GetValue() != sListIdOfTxtNode ) 4569 { 4570 mbAddTxtNodeToList = true; 4571 if ( mrTxtNode.IsInList() ) 4572 { 4573 mrTxtNode.RemoveFromList(); 4574 } 4575 } 4576 } 4577 4578 // handle RES_PARATR_LIST_LEVEL 4579 if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET ) 4580 { 4581 const SfxInt16Item* pListLevelItem = 4582 dynamic_cast<const SfxInt16Item*>(pItem); 4583 if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() ) 4584 { 4585 mbUpdateListLevel = true; 4586 } 4587 } 4588 4589 // handle RES_PARATR_LIST_ISRESTART 4590 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET ) 4591 { 4592 const SfxBoolItem* pListIsRestartItem = 4593 dynamic_cast<const SfxBoolItem*>(pItem); 4594 if ( pListIsRestartItem->GetValue() != 4595 (mrTxtNode.IsListRestart() ? sal_True : sal_False) ) 4596 { 4597 mbUpdateListRestart = true; 4598 } 4599 } 4600 4601 // handle RES_PARATR_LIST_RESTARTVALUE 4602 if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET ) 4603 { 4604 const SfxInt16Item* pListRestartValueItem = 4605 dynamic_cast<const SfxInt16Item*>(pItem); 4606 if ( !mrTxtNode.HasAttrListRestartValue() || 4607 pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() ) 4608 { 4609 mbUpdateListRestart = true; 4610 } 4611 } 4612 4613 // handle RES_PARATR_LIST_ISCOUNTED 4614 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET ) 4615 { 4616 const SfxBoolItem* pIsCountedInListItem = 4617 dynamic_cast<const SfxBoolItem*>(pItem); 4618 if ( pIsCountedInListItem->GetValue() != 4619 (mrTxtNode.IsCountedInList() ? sal_True : sal_False) ) 4620 { 4621 mbUpdateListCount = true; 4622 } 4623 } 4624 4625 // --> OD 2008-11-19 #i70748# 4626 // handle RES_PARATR_OUTLINELEVEL 4627 if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET ) 4628 { 4629 const SfxUInt16Item* pOutlineLevelItem = 4630 dynamic_cast<const SfxUInt16Item*>(pItem); 4631 if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() ) 4632 { 4633 mbOutlineLevelSet = true; 4634 } 4635 } 4636 // <-- 4637 } 4638 4639 HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode() 4640 { 4641 if ( mbAddTxtNodeToList ) 4642 { 4643 SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule(); 4644 if ( pNumRuleAtTxtNode ) 4645 { 4646 mrTxtNode.AddToList(); 4647 } 4648 } 4649 else 4650 { 4651 if ( mbUpdateListLevel && mrTxtNode.IsInList() ) 4652 { 4653 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree( 4654 mrTxtNode.GetAttrListLevel() ); 4655 } 4656 4657 if ( mbUpdateListRestart && mrTxtNode.IsInList() ) 4658 { 4659 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4660 pNodeNum->InvalidateMe(); 4661 pNodeNum->NotifyInvalidSiblings(); 4662 } 4663 4664 if ( mbUpdateListCount && mrTxtNode.IsInList() ) 4665 { 4666 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree(); 4667 } 4668 } 4669 4670 // --> OD 2008-11-19 #i70748# 4671 if ( mbOutlineLevelSet ) 4672 { 4673 if ( mrTxtNode.GetAttrOutlineLevel() == 0 ) 4674 { 4675 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4676 } 4677 else 4678 { 4679 const SfxPoolItem* pItem = 0; 4680 if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE, 4681 sal_True, &pItem ) 4682 != SFX_ITEM_SET ) 4683 { 4684 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 4685 } 4686 } 4687 } 4688 // <-- 4689 } 4690 // End of class <HandleSetAttrAtTxtNode> 4691 } 4692 4693 sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem ) 4694 { 4695 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 4696 mbInSetOrResetAttr = true; 4697 4698 HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem ); 4699 4700 sal_Bool bRet = SwCntntNode::SetAttr( pItem ); 4701 4702 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 4703 4704 return bRet; 4705 } 4706 4707 sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet ) 4708 { 4709 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 4710 mbInSetOrResetAttr = true; 4711 4712 HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet ); 4713 4714 sal_Bool bRet = SwCntntNode::SetAttr( rSet ); 4715 4716 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 4717 4718 return bRet; 4719 } 4720 4721 namespace { 4722 // Helper class for special handling of resetting attributes at text node: 4723 // In constructor an instance of the helper class recognize whose attributes 4724 // are reset and perform corresponding actions before the intrinsic reset of 4725 // attributes has been taken place. 4726 // In the destructor - after the attributes have been reset at the text 4727 // node - corresponding actions are performed. 4728 // The following is handled: 4729 // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset, 4730 // the text is removed from its list before the attributes have been reset. 4731 // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset, 4732 // the text is removed from its list before the attributes have been reset. 4733 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset. 4734 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset. 4735 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset. 4736 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset. 4737 // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset. 4738 class HandleResetAttrAtTxtNode 4739 { 4740 public: 4741 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4742 const sal_uInt16 nWhich1, 4743 const sal_uInt16 nWhich2 ); 4744 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4745 const SvUShorts& rWhichArr ); 4746 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode ); 4747 4748 ~HandleResetAttrAtTxtNode(); 4749 4750 private: 4751 SwTxtNode& mrTxtNode; 4752 bool mbListStyleOrIdReset; 4753 bool mbUpdateListLevel; 4754 bool mbUpdateListRestart; 4755 bool mbUpdateListCount; 4756 }; 4757 4758 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4759 const sal_uInt16 nWhich1, 4760 const sal_uInt16 nWhich2 ) 4761 : mrTxtNode( rTxtNode ), 4762 mbListStyleOrIdReset( false ), 4763 mbUpdateListLevel( false ), 4764 mbUpdateListRestart( false ), 4765 mbUpdateListCount( false ) 4766 { 4767 bool bRemoveFromList( false ); 4768 if ( nWhich2 != 0 && nWhich2 > nWhich1 ) 4769 { 4770 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4771 if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 ) 4772 { 4773 bRemoveFromList = mrTxtNode.GetNumRule() != 0; 4774 mbListStyleOrIdReset = true; 4775 } 4776 else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 ) 4777 { 4778 bRemoveFromList = mrTxtNode.GetpSwAttrSet() && 4779 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET; 4780 // --> OD 2008-10-20 #i92898# 4781 mbListStyleOrIdReset = true; 4782 // <-- 4783 } 4784 4785 if ( !bRemoveFromList ) 4786 { 4787 // RES_PARATR_LIST_LEVEL 4788 mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL && 4789 RES_PARATR_LIST_LEVEL <= nWhich2 && 4790 mrTxtNode.HasAttrListLevel() ); 4791 4792 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4793 mbUpdateListRestart = 4794 ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 && 4795 mrTxtNode.IsListRestart() ) || 4796 ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 && 4797 mrTxtNode.HasAttrListRestartValue() ); 4798 4799 // RES_PARATR_LIST_ISCOUNTED 4800 mbUpdateListCount = 4801 ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 && 4802 !mrTxtNode.IsCountedInList() ); 4803 } 4804 4805 // --> OD 2008-11-19 #i70748# 4806 // RES_PARATR_OUTLINELEVEL 4807 if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 ) 4808 { 4809 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4810 } 4811 // <-- 4812 } 4813 else 4814 { 4815 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4816 if ( nWhich1 == RES_PARATR_NUMRULE ) 4817 { 4818 bRemoveFromList = mrTxtNode.GetNumRule() != 0; 4819 mbListStyleOrIdReset = true; 4820 } 4821 else if ( nWhich1 == RES_PARATR_LIST_ID ) 4822 { 4823 bRemoveFromList = mrTxtNode.GetpSwAttrSet() && 4824 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET; 4825 // --> OD 2008-10-20 #i92898# 4826 mbListStyleOrIdReset = true; 4827 // <-- 4828 } 4829 // --> OD 2008-11-19 #i70748# 4830 // RES_PARATR_OUTLINELEVEL 4831 else if ( nWhich1 == RES_PARATR_OUTLINELEVEL ) 4832 { 4833 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4834 } 4835 // <-- 4836 4837 if ( !bRemoveFromList ) 4838 { 4839 // RES_PARATR_LIST_LEVEL 4840 mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL && 4841 mrTxtNode.HasAttrListLevel(); 4842 4843 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4844 mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART && 4845 mrTxtNode.IsListRestart() ) || 4846 ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE && 4847 mrTxtNode.HasAttrListRestartValue() ); 4848 4849 // RES_PARATR_LIST_ISCOUNTED 4850 mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED && 4851 !mrTxtNode.IsCountedInList(); 4852 } 4853 } 4854 4855 if ( bRemoveFromList && mrTxtNode.IsInList() ) 4856 { 4857 mrTxtNode.RemoveFromList(); 4858 } 4859 } 4860 4861 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4862 const SvUShorts& rWhichArr ) 4863 : mrTxtNode( rTxtNode ), 4864 mbListStyleOrIdReset( false ), 4865 mbUpdateListLevel( false ), 4866 mbUpdateListRestart( false ), 4867 mbUpdateListCount( false ) 4868 { 4869 bool bRemoveFromList( false ); 4870 { 4871 const sal_uInt16 nEnd = rWhichArr.Count(); 4872 for ( sal_uInt16 n = 0; n < nEnd; ++n ) 4873 { 4874 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4875 if ( rWhichArr[ n ] == RES_PARATR_NUMRULE ) 4876 { 4877 bRemoveFromList = bRemoveFromList || 4878 mrTxtNode.GetNumRule() != 0; 4879 mbListStyleOrIdReset = true; 4880 } 4881 else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID ) 4882 { 4883 bRemoveFromList = bRemoveFromList || 4884 ( mrTxtNode.GetpSwAttrSet() && 4885 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET ); 4886 // --> OD 2008-10-20 #i92898# 4887 mbListStyleOrIdReset = true; 4888 // <-- 4889 } 4890 // --> OD 2008-11-19 #i70748# 4891 // RES_PARATR_OUTLINELEVEL 4892 else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL ) 4893 { 4894 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4895 } 4896 // <-- 4897 4898 if ( !bRemoveFromList ) 4899 { 4900 // RES_PARATR_LIST_LEVEL 4901 mbUpdateListLevel = mbUpdateListLevel || 4902 ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL && 4903 mrTxtNode.HasAttrListLevel() ); 4904 4905 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4906 mbUpdateListRestart = mbUpdateListRestart || 4907 ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART && 4908 mrTxtNode.IsListRestart() ) || 4909 ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE && 4910 mrTxtNode.HasAttrListRestartValue() ); 4911 4912 // RES_PARATR_LIST_ISCOUNTED 4913 mbUpdateListCount = mbUpdateListCount || 4914 ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED && 4915 !mrTxtNode.IsCountedInList() ); 4916 } 4917 } 4918 } 4919 4920 if ( bRemoveFromList && mrTxtNode.IsInList() ) 4921 { 4922 mrTxtNode.RemoveFromList(); 4923 } 4924 } 4925 4926 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode ) 4927 : mrTxtNode( rTxtNode ), 4928 mbListStyleOrIdReset( false ), 4929 mbUpdateListLevel( false ), 4930 mbUpdateListRestart( false ), 4931 mbUpdateListCount( false ) 4932 { 4933 mbListStyleOrIdReset = true; 4934 if ( rTxtNode.IsInList() ) 4935 { 4936 rTxtNode.RemoveFromList(); 4937 } 4938 // --> OD 2008-11-19 #i70748# 4939 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4940 // <-- 4941 } 4942 4943 HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode() 4944 { 4945 if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() ) 4946 { 4947 // check, if in spite of the reset of the list style or the list id 4948 // the paragraph still has to be added to a list. 4949 if ( mrTxtNode.GetNumRule() && 4950 mrTxtNode.GetListId().Len() > 0 ) 4951 { 4952 // --> OD 2009-01-14 #i96062# 4953 // If paragraph has no list level attribute set and list style 4954 // is the outline style, apply outline level as the list level. 4955 if ( !mrTxtNode.HasAttrListLevel() && 4956 mrTxtNode.GetNumRule()->GetName() == 4957 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) && 4958 mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() ) 4959 { 4960 int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel(); 4961 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) 4962 { 4963 mrTxtNode.SetAttrListLevel( nNewListLevel ); 4964 } 4965 } 4966 // <-- 4967 mrTxtNode.AddToList(); 4968 } 4969 // --> OD 2008-11-19 #i70748# 4970 // --> OD 2010-05-12 #i105562# 4971 else if ( mrTxtNode.GetpSwAttrSet() && 4972 dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 ) 4973 { 4974 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 4975 } 4976 // <-- 4977 } 4978 4979 if ( mrTxtNode.IsInList() ) 4980 { 4981 if ( mbUpdateListLevel ) 4982 { 4983 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4984 pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() ); 4985 } 4986 4987 if ( mbUpdateListRestart ) 4988 { 4989 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4990 pNodeNum->InvalidateMe(); 4991 pNodeNum->NotifyInvalidSiblings(); 4992 } 4993 4994 if ( mbUpdateListCount ) 4995 { 4996 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4997 pNodeNum->InvalidateAndNotifyTree(); 4998 } 4999 } 5000 } 5001 // End of class <HandleResetAttrAtTxtNode> 5002 } 5003 5004 sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 ) 5005 { 5006 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 5007 mbInSetOrResetAttr = true; 5008 5009 HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 ); 5010 5011 sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 ); 5012 5013 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5014 5015 return bRet; 5016 } 5017 5018 sal_Bool SwTxtNode::ResetAttr( const SvUShorts& rWhichArr ) 5019 { 5020 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 5021 mbInSetOrResetAttr = true; 5022 5023 HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr ); 5024 5025 sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr ); 5026 5027 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5028 5029 return bRet; 5030 } 5031 5032 sal_uInt16 SwTxtNode::ResetAllAttr() 5033 { 5034 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 5035 mbInSetOrResetAttr = true; 5036 5037 HandleResetAttrAtTxtNode aHandleResetAttr( *this ); 5038 5039 sal_uInt16 nRet = SwCntntNode::ResetAllAttr(); 5040 5041 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5042 5043 return nRet; 5044 } 5045 // <-- 5046 5047 // sw::Metadatable 5048 ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry() 5049 { 5050 return GetDoc()->GetXmlIdRegistry(); 5051 } 5052 5053 bool SwTxtNode::IsInClipboard() const 5054 { 5055 return GetDoc()->IsClipBoard(); 5056 } 5057 5058 bool SwTxtNode::IsInUndo() const 5059 { 5060 return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 5061 } 5062 5063 bool SwTxtNode::IsInContent() const 5064 { 5065 return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) ); 5066 } 5067 5068 void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint ) 5069 { 5070 const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint); 5071 if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() ) 5072 ChkCondColl(); 5073 } 5074 5075 #include <unoparagraph.hxx> 5076 5077 uno::Reference< rdf::XMetadatable > 5078 SwTxtNode::MakeUnoObject() 5079 { 5080 const uno::Reference<rdf::XMetadatable> xMeta( 5081 SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY); 5082 return xMeta; 5083 } 5084 5085