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