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