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->GetFmtFld(); 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.GetField()->GetTyp()->Which() 1325 && static_cast<const SwTblField*>(rFld.GetField())->IsIntrnlName()) 1326 { 1327 // wandel die interne in eine externe Formel um 1328 const SwTableNode* const pDstTblNd = 1329 static_cast<const SwTxtFld*>(pHt)->GetTxtNode().FindTableNode(); 1330 if( pDstTblNd ) 1331 { 1332 SwTblField* const pTblFld = const_cast<SwTblField*>( 1333 static_cast<const SwTblField*>(pNewHt->GetFmtFld().GetField())); 1334 pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() ); 1335 } 1336 } 1337 } 1338 break; 1339 1340 case RES_TXTATR_TOXMARK : 1341 if( pOtherDoc && pDest && pDest->GetpSwpHints() 1342 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1343 { 1344 // Beim Kopieren von TOXMarks(Client) in andere Dokumente 1345 // muss der Verzeichnis (Modify) ausgetauscht werden 1346 static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc ); 1347 } 1348 break; 1349 1350 case RES_TXTATR_CHARFMT : 1351 // Wenn wir es mit einer Zeichenvorlage zu tun haben, 1352 // muessen wir natuerlich auch die Formate kopieren. 1353 if( pDest && pDest->GetpSwpHints() 1354 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1355 { 1356 SwCharFmt* pFmt = 1357 static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt()); 1358 1359 if( pFmt && pOtherDoc ) 1360 { 1361 pFmt = pOtherDoc->CopyCharFmt( *pFmt ); 1362 } 1363 const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>( 1364 pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt ); 1365 } 1366 break; 1367 case RES_TXTATR_INETFMT : 1368 { 1369 // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen 1370 // zu tun haben, muessen wir natuerlich auch die Formate kopieren. 1371 if( pOtherDoc && pDest && pDest->GetpSwpHints() 1372 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) ) 1373 { 1374 const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt) 1375 ->GetTxtNode().GetDoc(); 1376 if ( pDoc ) 1377 { 1378 const SwCharFmts* pCharFmts = pDoc->GetCharFmts(); 1379 const SwFmtINetFmt& rFmt = pHt->GetINetFmt(); 1380 SwCharFmt* pFmt; 1381 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() ); 1382 if( pFmt ) 1383 pOtherDoc->CopyCharFmt( *pFmt ); 1384 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() ); 1385 if( pFmt ) 1386 pOtherDoc->CopyCharFmt( *pFmt ); 1387 } 1388 } 1389 //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut 1390 // gesetzt sein, damit die Vorlagen erzeugt 1391 // werden koenne 1392 SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt); 1393 if ( !pINetHt->GetpTxtNode() ) 1394 { 1395 pINetHt->ChgTxtNode( pDest ); 1396 } 1397 1398 //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen 1399 pINetHt->GetCharFmt(); 1400 break; 1401 } 1402 case RES_TXTATR_META: 1403 case RES_TXTATR_METAFIELD: 1404 OSL_ENSURE(pNewHt, "copying Meta should not fail!"); 1405 OSL_ENSURE(pDest && (CH_TXTATR_INWORD == 1406 pDest->GetTxt().GetChar(*pNewHt->GetStart())), 1407 "missing CH_TXTATR?"); 1408 break; 1409 } 1410 } 1411 1412 /************************************************************************* 1413 |* SwTxtNode::CopyAttr() 1414 |* Beschreibung kopiert Attribute an der Position nStart in pDest. 1415 |* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx 1416 |* kopiert! CopyAttr wird vornehmlich dann gerufen, 1417 |* wenn Attribute fuer einen Node mit leerem String 1418 |* gesetzt werden sollen. 1419 *************************************************************************/ 1420 1421 void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx, 1422 const xub_StrLen nOldPos ) 1423 { 1424 if ( HasHints() ) // keine Attribute, keine Kekse 1425 { 1426 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? 1427 pDest->GetDoc() : 0; 1428 1429 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ ) 1430 { 1431 SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i); 1432 xub_StrLen const nAttrStartIdx = *pHt->GetStart(); 1433 if ( nTxtStartIdx < nAttrStartIdx ) 1434 break; // ueber das Textende, da nLen == 0 1435 1436 const xub_StrLen *const pEndIdx = pHt->GetEnd(); 1437 if ( pEndIdx && !pHt->HasDummyChar() ) 1438 { 1439 if( ( *pEndIdx > nTxtStartIdx || 1440 ( *pEndIdx == nTxtStartIdx && 1441 nAttrStartIdx == nTxtStartIdx ) ) ) 1442 { 1443 sal_uInt16 const nWhich = pHt->Which(); 1444 if ( RES_TXTATR_REFMARK != nWhich ) 1445 { 1446 // attribute in the area => copy 1447 SwTxtAttr *const pNewHt = pDest->InsertItem( 1448 pHt->GetAttr(), nOldPos, nOldPos, 1449 nsSetAttrMode::SETATTR_IS_COPY); 1450 if ( pNewHt ) 1451 { 1452 lcl_CopyHint( nWhich, pHt, pNewHt, 1453 pOtherDoc, pDest ); 1454 } 1455 } 1456 else if( !pOtherDoc ? GetDoc()->IsCopyIsMove() 1457 : 0 == pOtherDoc->GetRefMark( 1458 pHt->GetRefMark().GetRefName() ) ) 1459 { 1460 pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, 1461 nsSetAttrMode::SETATTR_IS_COPY); 1462 } 1463 } 1464 } 1465 } 1466 } 1467 1468 if( this != pDest ) 1469 { 1470 // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern 1471 SwUpdateAttr aHint( nOldPos, nOldPos, 0 ); 1472 pDest->ModifyNotification( 0, &aHint ); 1473 } 1474 } 1475 1476 /************************************************************************* 1477 |* SwTxtNode::Copy() 1478 |* Beschreibung kopiert Zeichen und Attibute in pDest, 1479 |* wird angehaengt 1480 *************************************************************************/ 1481 1482 // --> OD 2008-11-18 #i96213# 1483 // introduction of new optional parameter to control, if all attributes have to be copied. 1484 void SwTxtNode::CopyText( SwTxtNode *const pDest, 1485 const SwIndex &rStart, 1486 const xub_StrLen nLen, 1487 const bool bForceCopyOfAllAttrs ) 1488 { 1489 SwIndex aIdx( pDest, pDest->m_Text.Len() ); 1490 CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs ); 1491 } 1492 // <-- 1493 1494 // --> OD 2008-11-18 #i96213# 1495 // introduction of new optional parameter to control, if all attributes have to be copied. 1496 void SwTxtNode::CopyText( SwTxtNode *const pDest, 1497 const SwIndex &rDestStart, 1498 const SwIndex &rStart, 1499 xub_StrLen nLen, 1500 const bool bForceCopyOfAllAttrs ) 1501 // <-- 1502 { 1503 xub_StrLen nTxtStartIdx = rStart.GetIndex(); 1504 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken 1505 1506 if (pDest->GetDoc()->IsClipBoard() && this->GetNum()) 1507 { 1508 // #i111677# cache expansion of source (for clipboard) 1509 pDest->m_pNumStringCache.reset( 1510 new ::rtl::OUString(this->GetNumString())); 1511 } 1512 1513 if( !nLen ) 1514 { 1515 // wurde keine Laenge angegeben, dann Kopiere die Attribute 1516 // an der Position rStart. 1517 CopyAttr( pDest, nTxtStartIdx, nDestStart ); 1518 1519 // harte Absatz umspannende Attribute kopieren 1520 if( HasSwAttrSet() ) 1521 { 1522 // alle, oder nur die CharAttribute ? 1523 // --> OD 2008-11-18 #i96213# 1524 if ( !bForceCopyOfAllAttrs && 1525 ( nDestStart || 1526 pDest->HasSwAttrSet() || 1527 nLen != pDest->GetTxt().Len() ) ) 1528 // <-- 1529 { 1530 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 1531 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 1532 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 1533 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 1534 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 1535 0 ); 1536 aCharSet.Put( *GetpSwAttrSet() ); 1537 if( aCharSet.Count() ) 1538 { 1539 pDest->SetAttr( aCharSet, nDestStart, nDestStart ); 1540 } 1541 } 1542 else 1543 { 1544 GetpSwAttrSet()->CopyToModify( *pDest ); 1545 } 1546 } 1547 return; 1548 } 1549 1550 // 1. Text kopieren 1551 const xub_StrLen oldLen = pDest->m_Text.Len(); 1552 //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum 1553 // ueber die InsertMethode den Text einfuegen und nicht 1554 // selbst direkt 1555 pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart, 1556 IDocumentContentOperations::INS_EMPTYEXPAND ); 1557 1558 // um reale Groesse Updaten ! 1559 nLen = pDest->m_Text.Len() - oldLen; 1560 if ( !nLen ) // string not longer? 1561 return; 1562 1563 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? 1564 pDest->GetDoc() : 0; 1565 1566 // harte Absatz umspannende Attribute kopieren 1567 if( HasSwAttrSet() ) 1568 { 1569 // alle, oder nur die CharAttribute ? 1570 // --> OD 2008-11-18 #i96213# 1571 if ( !bForceCopyOfAllAttrs && 1572 ( nDestStart || 1573 pDest->HasSwAttrSet() || 1574 nLen != pDest->GetTxt().Len() ) ) 1575 // <-- 1576 { 1577 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 1578 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 1579 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 1580 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 1581 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 1582 0 ); 1583 aCharSet.Put( *GetpSwAttrSet() ); 1584 if( aCharSet.Count() ) 1585 { 1586 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); 1587 } 1588 } 1589 else 1590 { 1591 GetpSwAttrSet()->CopyToModify( *pDest ); 1592 } 1593 } 1594 1595 bool const bUndoNodes = !pOtherDoc 1596 && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 1597 1598 // Ende erst jetzt holen, weil beim Kopieren in sich selbst der 1599 // Start-Index und alle Attribute vorher aktualisiert werden. 1600 nTxtStartIdx = rStart.GetIndex(); 1601 const xub_StrLen nEnd = nTxtStartIdx + nLen; 1602 1603 // 2. Attribute kopieren 1604 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 1605 // des Attributs hinter dem zu kopierenden Bereich liegt 1606 const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0; 1607 1608 // wird in sich selbst kopiert, dann kann beim Einfuegen ein 1609 // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und 1610 // dann erst ins eigene uebertragen. 1611 SwpHts aArr( 5 ); 1612 1613 // Del-Array fuer alle RefMarks ohne Ausdehnung 1614 SwpHts aRefMrkArr; 1615 1616 sal_uInt16 nDeletedDummyChars(0); 1617 //Achtung: kann ungueltig sein!! 1618 for (sal_uInt16 n = 0; ( n < nSize ); ++n) 1619 { 1620 const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart(); 1621 if (!( nAttrStartIdx < nEnd)) 1622 break; 1623 1624 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n); 1625 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 1626 const sal_uInt16 nWhich = pHt->Which(); 1627 1628 // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber 1629 // keinen Bereich umspannt, so steht im Text ein 255 1630 // dieses muss entfernt werden. Trick: erst kopieren, 1631 // erkennen und sammeln, nach dem kopieren Loeschen. 1632 // Nimmt sein Zeichen mit ins Grab !! 1633 // JP 14.08.95: Duerfen RefMarks gemovt werden? 1634 int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes || 1635 (!pOtherDoc ? GetDoc()->IsCopyIsMove() 1636 : 0 == pOtherDoc->GetRefMark( 1637 pHt->GetRefMark().GetRefName() ))); 1638 1639 if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark ) 1640 { 1641 continue; 1642 } 1643 1644 xub_StrLen nAttrStt; 1645 xub_StrLen nAttrEnd; 1646 1647 if( nAttrStartIdx < nTxtStartIdx ) 1648 { 1649 // start is before selection 1650 // copy hints with end and CH_TXTATR only if dummy char is copied 1651 if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() ) 1652 { 1653 // attribute with extent and the end is in the selection 1654 nAttrStt = nDestStart; 1655 nAttrEnd = (*pEndIdx > nEnd) 1656 ? rDestStart.GetIndex() 1657 : nDestStart + (*pEndIdx) - nTxtStartIdx; 1658 } 1659 else 1660 { 1661 continue; 1662 } 1663 } 1664 else 1665 { 1666 // start is in the selection 1667 nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx ); 1668 if( pEndIdx ) 1669 { 1670 nAttrEnd = *pEndIdx > nEnd 1671 ? rDestStart.GetIndex() 1672 : nDestStart + ( *pEndIdx - nTxtStartIdx ); 1673 } 1674 else 1675 { 1676 nAttrEnd = nAttrStt; 1677 } 1678 } 1679 1680 SwTxtAttr * pNewHt = 0; 1681 1682 if( pDest == this ) 1683 { 1684 // copy the hint here, but insert it later 1685 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 1686 nAttrStt, nAttrEnd, COPY, pDest ); 1687 1688 lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest); 1689 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() ); 1690 } 1691 else 1692 { 1693 pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt - nDeletedDummyChars, 1694 nAttrEnd - nDeletedDummyChars, 1695 nsSetAttrMode::SETATTR_NOTXTATRCHR 1696 | nsSetAttrMode::SETATTR_IS_COPY); 1697 if (pNewHt) 1698 { 1699 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest ); 1700 } 1701 else if (pHt->HasDummyChar()) 1702 { 1703 // The attribute that has failed to be copied would insert 1704 // dummy char, so positions of the following attributes have 1705 // to be shifted by one to compensate for that missing char. 1706 ++nDeletedDummyChars; 1707 } 1708 } 1709 1710 if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark ) 1711 { 1712 aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() ); 1713 } 1714 } 1715 1716 // nur falls im Array Attribute stehen (kann nur beim Kopieren 1717 // sich selbst passieren!!) 1718 for ( sal_uInt16 i = 0; i < aArr.Count(); ++i ) 1719 { 1720 InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR ); 1721 } 1722 1723 if( pDest->GetpSwpHints() ) 1724 { 1725 for ( sal_uInt16 i = 0; i < aRefMrkArr.Count(); ++i ) 1726 { 1727 SwTxtAttr * const pNewHt = aRefMrkArr[i]; 1728 if( pNewHt->GetEnd() ) 1729 { 1730 pDest->GetpSwpHints()->Delete( pNewHt ); 1731 pDest->DestroyAttr( pNewHt ); 1732 } 1733 else 1734 { 1735 const SwIndex aIdx( pDest, *pNewHt->GetStart() ); 1736 pDest->EraseText( aIdx, 1 ); 1737 } 1738 } 1739 } 1740 1741 CHECK_SWPHINTS(this); 1742 } 1743 1744 1745 void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx, 1746 const IDocumentContentOperations::InsertFlags nMode ) 1747 { 1748 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." ); 1749 ASSERT( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN, 1750 "SwTxtNode::InsertText: node text with insertion > STRING_LEN." ); 1751 1752 xub_StrLen aPos = rIdx.GetIndex(); 1753 xub_StrLen nLen = m_Text.Len() - aPos; 1754 m_Text.Insert( rStr, aPos ); 1755 nLen = m_Text.Len() - aPos - nLen; 1756 1757 if ( !nLen ) return; 1758 1759 sal_Bool bOldExpFlg = IsIgnoreDontExpand(); 1760 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1761 { 1762 SetIgnoreDontExpand( sal_True ); 1763 } 1764 1765 Update( rIdx, nLen ); // text content changed! 1766 1767 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1768 { 1769 SetIgnoreDontExpand( bOldExpFlg ); 1770 } 1771 1772 // analog zu Insert(char) in txtedt.cxx: 1773 // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen 1774 // 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen 1775 1776 if ( HasHints() ) 1777 { 1778 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() && 1779 rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i ) 1780 { 1781 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i ); 1782 xub_StrLen * const pEndIdx = pHt->GetEnd(); 1783 if( !pEndIdx ) 1784 continue; 1785 1786 if( rIdx == *pEndIdx ) 1787 { 1788 if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) || 1789 (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND) 1790 && pHt->DontExpand()) ) 1791 { 1792 // bei leeren Attributen auch Start veraendern 1793 if( rIdx == *pHt->GetStart() ) 1794 *pHt->GetStart() = *pHt->GetStart() - nLen; 1795 *pEndIdx = *pEndIdx - nLen; 1796 m_pSwpHints->DeleteAtPos(i); 1797 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST ); 1798 } 1799 // empty hints at insert position? 1800 else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND) 1801 && (*pEndIdx == *pHt->GetStart()) ) 1802 { 1803 *pHt->GetStart() = *pHt->GetStart() - nLen; 1804 const sal_uInt16 nAktLen = m_pSwpHints->Count(); 1805 m_pSwpHints->DeleteAtPos(i); 1806 InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ ); 1807 if ( nAktLen > m_pSwpHints->Count() && i ) 1808 { 1809 --i; 1810 } 1811 continue; 1812 } 1813 else 1814 { 1815 continue; 1816 } 1817 } 1818 if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) && 1819 rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() && 1820 !pHt->IsDontExpandStartAttr() ) 1821 { 1822 // Kein Feld, am Absatzanfang, HintExpand 1823 m_pSwpHints->DeleteAtPos(i); 1824 *pHt->GetStart() = *pHt->GetStart() - nLen; 1825 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST ); 1826 } 1827 } 1828 TryDeleteSwpHints(); 1829 } 1830 1831 if ( GetDepends() ) 1832 { 1833 SwInsTxt aHint( aPos, nLen ); 1834 NotifyClients( 0, &aHint ); 1835 } 1836 1837 // By inserting a character, the hidden flags 1838 // at the TxtNode can become invalid: 1839 SetCalcHiddenCharFlags(); 1840 1841 CHECK_SWPHINTS(this); 1842 } 1843 1844 /************************************************************************* 1845 |* 1846 |* SwTxtNode::Cut() 1847 |* 1848 |* Beschreibung text.doc 1849 |* Ersterstellung VB 20.03.91 1850 |* Letzte Aenderung JP 11.08.94 1851 |* 1852 *************************************************************************/ 1853 1854 void SwTxtNode::CutText( SwTxtNode * const pDest, 1855 const SwIndex & rStart, const xub_StrLen nLen ) 1856 { 1857 if(pDest) 1858 { 1859 SwIndex aDestStt( pDest, pDest->GetTxt().Len() ); 1860 CutImpl( pDest, aDestStt, rStart, nLen, false ); 1861 } 1862 else 1863 { 1864 ASSERT(false, 1865 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1866 EraseText( rStart, nLen ); 1867 } 1868 } 1869 1870 1871 void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart, 1872 const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate ) 1873 { 1874 if(!pDest) 1875 { 1876 ASSERT(false, 1877 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1878 EraseText( rStart, nLen ); 1879 return; 1880 } 1881 1882 // nicht im Dokument verschieben ? 1883 if( GetDoc() != pDest->GetDoc() ) 1884 { 1885 ASSERT(false, 1886 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1887 CopyText( pDest, rDestStart, rStart, nLen); 1888 EraseText(rStart, nLen); 1889 return; 1890 } 1891 1892 if( !nLen ) 1893 { 1894 // wurde keine Laenge angegeben, dann Kopiere die Attribute 1895 // an der Position rStart. 1896 CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() ); 1897 return; 1898 } 1899 1900 xub_StrLen nTxtStartIdx = rStart.GetIndex(); 1901 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken 1902 const xub_StrLen nInitSize = pDest->m_Text.Len(); 1903 1904 // wird in sich selbst verschoben, muss es gesondert behandelt werden !! 1905 if( pDest == this ) 1906 { 1907 ASSERT(false, 1908 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 1909 m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart ); 1910 m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen ); 1911 1912 const xub_StrLen nEnd = rStart.GetIndex() + nLen; 1913 1914 // dann suche mal alle Attribute zusammen, die im verschobenen 1915 // Bereich liegen. Diese werden in das extra Array verschoben, 1916 // damit sich die Indizies beim Updaten nicht veraendern !!! 1917 SwpHts aArr( 5 ); 1918 1919 // 2. Attribute verschieben 1920 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 1921 // des Attributs hinter dem zu verschiebenden Bereich liegt 1922 sal_uInt16 nAttrCnt = 0; 1923 while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() ) 1924 { 1925 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 1926 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 1927 if (!( nAttrStartIdx < nEnd )) 1928 break; 1929 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 1930 const sal_uInt16 nWhich = pHt->Which(); 1931 SwTxtAttr *pNewHt = 0; 1932 1933 if(nAttrStartIdx < nTxtStartIdx) 1934 { 1935 // Anfang liegt vor dem Bereich 1936 if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() && 1937 pEndIdx && *pEndIdx > nTxtStartIdx ) 1938 { 1939 // Attribut mit einem Bereich 1940 // und das Ende des Attribut liegt im Bereich 1941 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0, 1942 *pEndIdx > nEnd 1943 ? nLen 1944 : *pEndIdx - nTxtStartIdx ); 1945 } 1946 } 1947 else 1948 { 1949 // der Anfang liegt vollstaendig im Bereich 1950 if( !pEndIdx || *pEndIdx < nEnd ) 1951 { 1952 // Attribut verschieben 1953 m_pSwpHints->Delete( pHt ); 1954 // die Start/End Indicies neu setzen 1955 *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx; 1956 if( pEndIdx ) 1957 *pHt->GetEnd() = *pEndIdx - nTxtStartIdx; 1958 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() ); 1959 continue; // while-Schleife weiter, ohne ++ ! 1960 } 1961 // das Ende liegt dahinter 1962 else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar()) 1963 { 1964 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 1965 nAttrStartIdx - nTxtStartIdx, 1966 !pEndIdx ? 0 1967 : ( *pEndIdx > nEnd 1968 ? nLen 1969 : *pEndIdx - nTxtStartIdx )); 1970 } 1971 } 1972 if( pNewHt ) 1973 { 1974 // die Daten kopieren 1975 lcl_CopyHint( nWhich, pHt, pNewHt, 0, this ); 1976 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() ); 1977 } 1978 ++nAttrCnt; 1979 } 1980 1981 if( bUpdate ) 1982 { 1983 // Update aller Indizies 1984 Update( rDestStart, nLen, sal_False, sal_True ); 1985 } 1986 #ifdef CUTNOEXPAND 1987 else 1988 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben 1989 if ( 0 < nLen && 0 < nInitSize && m_pSwpHints ) 1990 { 1991 // check if there was the end of an attribute at the insertion 1992 // position: if it is not a field, it must be expanded 1993 for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); n++ ) 1994 { 1995 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n); 1996 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 1997 if ( pEndIdx && (*pEndIdx == nInitSize) ) 1998 { 1999 *pEndIdx = *pEndIdx + nLen; 2000 } 2001 } 2002 } 2003 #endif 2004 CHECK_SWPHINTS(this); 2005 2006 Update( rStart, nLen, sal_True, sal_True ); 2007 2008 CHECK_SWPHINTS(this); 2009 2010 // dann setze die kopierten/geloeschten Attribute in den Node 2011 if( nDestStart <= nTxtStartIdx ) 2012 { 2013 nTxtStartIdx = nTxtStartIdx + nLen; 2014 } 2015 else 2016 { 2017 nDestStart = nDestStart - nLen; 2018 } 2019 2020 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n ) 2021 { 2022 SwTxtAttr *const pNewHt = aArr[n]; 2023 *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart(); 2024 xub_StrLen * const pEndIdx = pNewHt->GetEnd(); 2025 if ( pEndIdx ) 2026 { 2027 *pEndIdx = nDestStart + *pEndIdx; 2028 } 2029 InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR ); 2030 } 2031 } 2032 else 2033 { 2034 pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart ); 2035 m_Text.Erase( nTxtStartIdx, nLen ); 2036 nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size! 2037 if( !nLen ) // String nicht gewachsen ?? 2038 return; 2039 2040 if( bUpdate ) 2041 { 2042 // Update aller Indizies 2043 pDest->Update( rDestStart, nLen, sal_False, sal_True); 2044 } 2045 #ifdef CUTNOEXPAND 2046 else 2047 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben 2048 if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints ) 2049 { 2050 // check if there was the end of an attribute at the insertion 2051 // position: if it is not a field, it must be expanded 2052 for ( sal_uInt16 n = 0; n < pDest->m_pSwpHints->Count(); n++ ) 2053 { 2054 SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n); 2055 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2056 if ( pEndIdx && (*pEndIdx == nInitSize) ) 2057 { 2058 *pEndIdx = *pEndIdx + nLen; 2059 } 2060 } 2061 } 2062 #endif 2063 CHECK_SWPHINTS(pDest); 2064 2065 const xub_StrLen nEnd = rStart.GetIndex() + nLen; 2066 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) 2067 ? pDest->GetDoc() : 0; 2068 bool const bUndoNodes = !pOtherDoc 2069 && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 2070 2071 ASSERT(!pOtherDoc, 2072 "mst: entering dead and bitrotted code; fasten your seatbelts!"); 2073 2074 // harte Absatz umspannende Attribute kopieren 2075 if( HasSwAttrSet() ) 2076 { 2077 // alle, oder nur die CharAttribute ? 2078 if( nInitSize || pDest->HasSwAttrSet() || 2079 nLen != pDest->GetTxt().Len() ) 2080 { 2081 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(), 2082 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 2083 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 2084 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 2085 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 2086 0 ); 2087 aCharSet.Put( *GetpSwAttrSet() ); 2088 if( aCharSet.Count() ) 2089 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen ); 2090 } 2091 else 2092 { 2093 GetpSwAttrSet()->CopyToModify( *pDest ); 2094 } 2095 } 2096 2097 // 2. Attribute verschieben 2098 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches 2099 // des Attributs hinter dem zu verschiebenden Bereich liegt 2100 sal_uInt16 nAttrCnt = 0; 2101 while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) ) 2102 { 2103 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 2104 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 2105 if (!( nAttrStartIdx < nEnd )) 2106 break; 2107 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2108 const sal_uInt16 nWhich = pHt->Which(); 2109 SwTxtAttr *pNewHt = 0; 2110 2111 // if the hint has a dummy character, then it must not be split! 2112 if(nAttrStartIdx < nTxtStartIdx) 2113 { 2114 // Anfang liegt vor dem Bereich 2115 if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich 2116 || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx ) 2117 { 2118 // Attribut mit einem Bereich 2119 // und das Ende des Attribut liegt im Bereich 2120 pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(), 2121 nDestStart, 2122 nDestStart + ( 2123 *pEndIdx > nEnd 2124 ? nLen 2125 : *pEndIdx - nTxtStartIdx ) ); 2126 } 2127 } 2128 else 2129 { 2130 // der Anfang liegt vollstaendig im Bereich 2131 if( !pEndIdx || *pEndIdx < nEnd || 2132 (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich) 2133 || pHt->HasDummyChar() ) 2134 { 2135 // do not delete note and later add it -> sidebar flickering 2136 if ( GetDoc()->GetDocShell() ) 2137 { 2138 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04)); 2139 } 2140 // Attribut verschieben 2141 m_pSwpHints->Delete( pHt ); 2142 // die Start/End Indicies neu setzen 2143 *pHt->GetStart() = 2144 nDestStart + (nAttrStartIdx - nTxtStartIdx); 2145 if( pEndIdx ) 2146 { 2147 *pHt->GetEnd() = nDestStart + ( 2148 *pEndIdx > nEnd 2149 ? nLen 2150 : *pEndIdx - nTxtStartIdx ); 2151 } 2152 pDest->InsertHint( pHt, 2153 nsSetAttrMode::SETATTR_NOTXTATRCHR 2154 | nsSetAttrMode::SETATTR_DONTREPLACE ); 2155 if ( GetDoc()->GetDocShell() ) 2156 { 2157 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04)); 2158 } 2159 continue; // while-Schleife weiter, ohne ++ ! 2160 } 2161 // das Ende liegt dahinter 2162 else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes ) 2163 { 2164 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 2165 nDestStart + (nAttrStartIdx - nTxtStartIdx), 2166 !pEndIdx ? 0 2167 : nDestStart + ( *pEndIdx > nEnd 2168 ? nLen 2169 : *pEndIdx - nTxtStartIdx )); 2170 } 2171 } 2172 if ( pNewHt ) 2173 { 2174 const bool bSuccess( pDest->InsertHint( pNewHt, 2175 nsSetAttrMode::SETATTR_NOTXTATRCHR 2176 | nsSetAttrMode::SETATTR_DONTREPLACE 2177 | nsSetAttrMode::SETATTR_IS_COPY) ); 2178 if (bSuccess) 2179 { 2180 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest ); 2181 } 2182 } 2183 ++nAttrCnt; 2184 } 2185 // sollten jetzt noch leere Attribute rumstehen, dann haben diese 2186 // eine hoehere Praezedenz. Also herausholen und das Array updaten. 2187 // Die dabei entstehenden leeren Hints werden von den gesicherten 2188 // "uebergeplaettet". (Bug: 6977) 2189 if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() ) 2190 { 2191 SwpHts aArr( 5 ); 2192 while ( nAttrCnt < m_pSwpHints->Count() ) 2193 { 2194 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt); 2195 if ( nEnd != *pHt->GetStart() ) 2196 break; 2197 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2198 if ( pEndIdx && *pEndIdx == nEnd ) 2199 { 2200 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() ); 2201 m_pSwpHints->Delete( pHt ); 2202 } 2203 else 2204 { 2205 ++nAttrCnt; 2206 } 2207 } 2208 Update( rStart, nLen, sal_True, sal_True ); 2209 2210 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n ) 2211 { 2212 SwTxtAttr * const pHt = aArr[ n ]; 2213 *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex(); 2214 InsertHint( pHt ); 2215 } 2216 } 2217 else 2218 { 2219 Update( rStart, nLen, sal_True, sal_True ); 2220 } 2221 2222 CHECK_SWPHINTS(this); 2223 } 2224 2225 TryDeleteSwpHints(); 2226 2227 // Frames benachrichtigen; 2228 SwInsTxt aInsHint( nDestStart, nLen ); 2229 pDest->ModifyNotification( 0, &aInsHint ); 2230 SwDelTxt aDelHint( nTxtStartIdx, nLen ); 2231 ModifyNotification( 0, &aDelHint ); 2232 } 2233 2234 2235 void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount, 2236 const IDocumentContentOperations::InsertFlags nMode ) 2237 { 2238 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." ); 2239 2240 const xub_StrLen nStartIdx = rIdx.GetIndex(); 2241 const xub_StrLen nCnt = (STRING_LEN == nCount) 2242 ? m_Text.Len() - nStartIdx : nCount; 2243 const xub_StrLen nEndIdx = nStartIdx + nCnt; 2244 m_Text.Erase( nStartIdx, nCnt ); 2245 2246 /* GCAttr(); alle leeren weggwerfen ist zu brutal. 2247 * Es duerfen nur die wegggeworfen werden, 2248 * die im Bereich liegen und nicht am Ende des Bereiches liegen 2249 */ 2250 2251 for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) 2252 { 2253 SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i); 2254 2255 const xub_StrLen nHintStart = *pHt->GetStart(); 2256 2257 if ( nHintStart < nStartIdx ) 2258 continue; 2259 2260 if ( nHintStart > nEndIdx ) 2261 break; // hints are sorted by end, so break here 2262 2263 const xub_StrLen* pHtEndIdx = pHt->GetEnd(); 2264 const sal_uInt16 nWhich = pHt->Which(); 2265 2266 if( !pHtEndIdx ) 2267 { 2268 ASSERT(pHt->HasDummyChar(), 2269 "attribute with neither end nor CH_TXTATR?"); 2270 if (isTXTATR(nWhich) && 2271 (nHintStart >= nStartIdx) && (nHintStart < nEndIdx)) 2272 { 2273 m_pSwpHints->DeleteAtPos(i); 2274 DestroyAttr( pHt ); 2275 --i; 2276 } 2277 continue; 2278 } 2279 2280 ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx) 2281 && pHt->HasDummyChar() ) 2282 // next line: deleting exactly dummy char: DeleteAttributes 2283 || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)), 2284 "ERROR: deleting left-overlapped attribute with CH_TXTATR"); 2285 2286 // Delete the hint if: 2287 // 1. The hint ends before the deletion end position or 2288 // 2. The hint ends at the deletion end position and 2289 // we are not in empty expand mode and 2290 // the hint is a [toxmark|refmark|ruby] text attribute 2291 // 3. deleting exactly the dummy char of an hint with end and dummy 2292 // char deletes the hint 2293 if ( (*pHtEndIdx < nEndIdx) 2294 || ( (*pHtEndIdx == nEndIdx) && 2295 !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) && 2296 ( (RES_TXTATR_TOXMARK == nWhich) || 2297 (RES_TXTATR_REFMARK == nWhich) || 2298 // --> FME 2006-03-03 #i62668# Ruby text attribute must be 2299 // treated just like toxmark and refmarks 2300 (RES_TXTATR_CJK_RUBY == nWhich) ) ) 2301 // <-- 2302 #if 0 2303 || ( (nHintStart == nStartIdx) && 2304 (nHintStart + 1 == nEndIdx)&& 2305 #else // generalize this to left-overlapped dummy char hints (see ASSERT) 2306 || ( (nHintStart < nEndIdx) && 2307 #endif 2308 pHt->HasDummyChar() ) 2309 ) 2310 { 2311 m_pSwpHints->DeleteAtPos(i); 2312 DestroyAttr( pHt ); 2313 --i; 2314 } 2315 } 2316 2317 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?"); 2318 2319 TryDeleteSwpHints(); 2320 2321 Update( rIdx, nCnt, sal_True ); 2322 2323 if( 1 == nCnt ) 2324 { 2325 SwDelChr aHint( nStartIdx ); 2326 NotifyClients( 0, &aHint ); 2327 } 2328 else 2329 { 2330 SwDelTxt aHint( nStartIdx, nCnt ); 2331 NotifyClients( 0, &aHint ); 2332 } 2333 2334 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?"); 2335 2336 // By deleting a character, the hidden flags 2337 // at the TxtNode can become invalid: 2338 SetCalcHiddenCharFlags(); 2339 2340 CHECK_SWPHINTS(this); 2341 } 2342 2343 /*********************************************************************** 2344 #* Class : SwTxtNode 2345 #* Methode : GCAttr 2346 #* 2347 #* Beschreibung 2348 #* text.doc 2349 #* 2350 #* Datum : MS 28.11.90 2351 #* Update : VB 24.07.91 2352 #***********************************************************************/ 2353 2354 void SwTxtNode::GCAttr() 2355 { 2356 if ( !HasHints() ) 2357 return; 2358 2359 bool bChanged = false; 2360 sal_uInt16 nMin = m_Text.Len(), 2361 nMax = 0; 2362 sal_Bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die 2363 // INet-Formate entfernt. 2364 2365 for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i ) 2366 { 2367 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i); 2368 2369 // wenn Ende und Start gleich sind --> loeschen 2370 const xub_StrLen * const pEndIdx = pHt->GetEnd(); 2371 if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart()) 2372 && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) ) 2373 { 2374 bChanged = true; 2375 nMin = Min( nMin, *pHt->GetStart() ); 2376 nMax = Max( nMax, *pHt->GetEnd() ); 2377 DestroyAttr( m_pSwpHints->Cut(i) ); 2378 --i; 2379 } 2380 else 2381 { 2382 pHt->SetDontExpand( false ); 2383 } 2384 } 2385 TryDeleteSwpHints(); 2386 2387 if(bChanged) 2388 { 2389 //TxtFrm's reagieren auf aHint, andere auf aNew 2390 SwUpdateAttr aHint( nMin, nMax, 0 ); 2391 NotifyClients( 0, &aHint ); 2392 SwFmtChg aNew( GetTxtColl() ); 2393 NotifyClients( 0, &aNew ); 2394 } 2395 } 2396 2397 // #i23726# 2398 SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const 2399 { 2400 SwNumRule* pRet = 0; 2401 2402 const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent ); 2403 bool bNoNumRule = false; 2404 if ( pItem ) 2405 { 2406 String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue(); 2407 if (sNumRuleName.Len() > 0) 2408 { 2409 pRet = GetDoc()->FindNumRulePtr( sNumRuleName ); 2410 } 2411 else // numbering is turned off 2412 bNoNumRule = true; 2413 } 2414 2415 if ( !bNoNumRule ) 2416 { 2417 if ( pRet && pRet == GetDoc()->GetOutlineNumRule() && 2418 ( !HasSwAttrSet() || 2419 SFX_ITEM_SET != 2420 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) ) 2421 { 2422 SwTxtFmtColl* pColl = GetTxtColl(); 2423 if ( pColl ) 2424 { 2425 const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False ); 2426 if ( rDirectItem.GetValue().Len() == 0 ) 2427 { 2428 pRet = 0L; 2429 } 2430 } 2431 } 2432 2433 // --> OD 2006-11-20 #i71764# 2434 // Document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE has no influence 2435 // any more. 2436 // if ( !pRet && 2437 // GetDoc()->get(IDocumentSettingAccess::OUTLINE_LEVEL_YIELDS_OUTLINE_RULE) && 2438 // GetOutlineLevel() != NO_NUMBERING ) 2439 // { 2440 // pRet = GetDoc()->GetOutlineNumRule(); 2441 // } 2442 // <-- 2443 } 2444 // old code before tuning 2445 // // --> OD 2005-10-25 #126347# 2446 // // determine of numbering/bullet rule, which is set as a hard attribute 2447 // // at the text node 2448 // const SfxPoolItem* pItem( 0L ); 2449 // if ( HasSwAttrSet() ) // does text node has hard attributes ? 2450 // { 2451 // if ( SFX_ITEM_SET != 2452 // GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ) 2453 // { 2454 // pItem = 0L; 2455 // } 2456 // // else: <pItem> contains the numbering/bullet attribute, which is 2457 // // hard set at the paragraph. 2458 2459 // } 2460 // // <-- 2461 // bool bNoNumRule = false; 2462 // if (pItem) 2463 // { 2464 // String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue(); 2465 // if (sNumRuleName.Len() > 0) 2466 // { 2467 // pRet = GetDoc()->FindNumRulePtr(sNumRuleName); 2468 // } 2469 // else // numbering is turned off by hard attribute 2470 // bNoNumRule = true; 2471 // } 2472 2473 // if (! bNoNumRule) 2474 // { 2475 // if (! pRet && bInParent) 2476 // { 2477 // SwTxtFmtColl * pColl = GetTxtColl(); 2478 2479 // if (pColl) 2480 // { 2481 // const SwNumRuleItem & rItem = pColl->GetNumRule(sal_True); 2482 2483 // pRet = const_cast<SwDoc *>(GetDoc())-> 2484 // FindNumRulePtrWithPool(rItem.GetValue()); 2485 // // --> OD 2005-10-13 #125993# - The outline numbering rule 2486 // // isn't allowed to be derived from a parent paragraph style 2487 // // to a derived one. 2488 // // Thus check, if the found outline numbering rule is directly 2489 // // set at the paragraph style <pColl>. If not, don't return 2490 // // the outline numbering rule. 2491 // if ( pRet && pRet == GetDoc()->GetOutlineNumRule() ) 2492 // { 2493 // const SwNumRuleItem& rDirectItem = pColl->GetNumRule(sal_False); 2494 // SwNumRule* pNumRuleAtParaStyle = const_cast<SwDoc*>(GetDoc())-> 2495 // FindNumRulePtrWithPool(rDirectItem.GetValue()); 2496 // if ( !pNumRuleAtParaStyle ) 2497 // { 2498 // pRet = 0L; 2499 // } 2500 // } 2501 // // <-- 2502 // } 2503 // } 2504 2505 // if (!pRet && GetDoc()->IsOutlineLevelYieldsOutlineRule() && 2506 // GetOutlineLevel() != NO_NUMBERING) 2507 // pRet = GetDoc()->GetOutlineNumRule(); 2508 // } 2509 // <-- 2510 2511 return pRet; 2512 } 2513 2514 SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const 2515 { 2516 SwNumRule * pRet = _GetNumRule(bInParent); 2517 2518 return pRet; 2519 } 2520 2521 void SwTxtNode::NumRuleChgd() 2522 { 2523 // --> OD 2008-04-04 #refactorlists# 2524 if ( IsInList() ) 2525 { 2526 SwNumRule* pNumRule = GetNumRule(); 2527 if ( pNumRule && pNumRule != GetNum()->GetNumRule() ) 2528 { 2529 mpNodeNum->ChangeNumRule( *pNumRule ); 2530 } 2531 } 2532 // <-- 2533 2534 if( IsInCache() ) 2535 { 2536 SwFrm::GetCache().Delete( this ); 2537 SetInCache( sal_False ); 2538 } 2539 SetInSwFntCache( sal_False ); 2540 2541 // Sending "noop" modify in order to cause invalidations of registered 2542 // <SwTxtFrm> instances to get the list style change respectively the change 2543 // in the list tree reflected in the layout. 2544 // Important note: 2545 { 2546 SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace(); 2547 NotifyClients( &rLR, &rLR ); 2548 } 2549 } 2550 2551 // -> #i27615# 2552 sal_Bool SwTxtNode::IsNumbered() const 2553 { 2554 sal_Bool bResult = sal_False; 2555 2556 SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2557 if ( pRule && IsCountedInList() ) 2558 bResult = sal_True; 2559 2560 return bResult; 2561 } 2562 2563 // --> OD 2008-04-02 #refactorlists# 2564 bool SwTxtNode::HasMarkedLabel() const 2565 { 2566 bool bResult = false; 2567 2568 if ( IsInList() ) 2569 { 2570 bResult = 2571 GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() ); 2572 } 2573 2574 return bResult; 2575 } 2576 // <-- 2577 // <- #i27615# 2578 2579 SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext, 2580 sal_Bool bChgFollow ) 2581 { 2582 /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */ 2583 SwAttrSet* pNewAttrSet = 0; 2584 // --> OD 2007-07-10 #i75353# 2585 bool bClearHardSetNumRuleWhenFmtCollChanges( false ); 2586 // <-- 2587 if( HasSwAttrSet() ) 2588 { 2589 pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() ); 2590 const SfxItemSet* pTmpSet = GetpSwAttrSet(); 2591 2592 if( bNext ) // der naechste erbt keine Breaks! 2593 pTmpSet = pNewAttrSet; 2594 2595 // PageBreaks/PageDesc/ColBreak rausschmeissen. 2596 sal_Bool bRemoveFromCache = sal_False; 2597 std::vector<sal_uInt16> aClearWhichIds; 2598 if ( bNext ) 2599 bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) ); 2600 else 2601 aClearWhichIds.push_back( RES_PAGEDESC ); 2602 2603 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) ) 2604 { 2605 if ( bNext ) 2606 pNewAttrSet->ClearItem( RES_BREAK ); 2607 else 2608 aClearWhichIds.push_back( RES_BREAK ); 2609 bRemoveFromCache = sal_True; 2610 } 2611 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) ) 2612 { 2613 if ( bNext ) 2614 pNewAttrSet->ClearItem( RES_KEEP ); 2615 else 2616 aClearWhichIds.push_back( RES_KEEP ); 2617 bRemoveFromCache = sal_True; 2618 } 2619 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) ) 2620 { 2621 if ( bNext ) 2622 pNewAttrSet->ClearItem( RES_PARATR_SPLIT ); 2623 else 2624 aClearWhichIds.push_back( RES_PARATR_SPLIT ); 2625 bRemoveFromCache = sal_True; 2626 } 2627 if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False)) 2628 { 2629 SwNumRule * pRule = GetNumRule(); 2630 2631 if (pRule && IsOutline()) 2632 { 2633 if ( bNext ) 2634 pNewAttrSet->ClearItem(RES_PARATR_NUMRULE); 2635 else 2636 { 2637 // --> OD 2007-07-10 #i75353# 2638 // No clear of hard set numbering rule at an outline paragraph at this point. 2639 // Only if the paragraph style changes - see below. 2640 // aClearWhichIds.push_back( RES_PARATR_NUMRULE ); 2641 bClearHardSetNumRuleWhenFmtCollChanges = true; 2642 // <-- 2643 } 2644 bRemoveFromCache = sal_True; 2645 } 2646 } 2647 2648 if ( 0 != aClearWhichIds.size() ) 2649 bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds ); 2650 2651 if( !bNext && bRemoveFromCache && IsInCache() ) 2652 { 2653 SwFrm::GetCache().Delete( this ); 2654 SetInCache( sal_False ); 2655 } 2656 } 2657 SwNodes& rNds = GetNodes(); 2658 2659 SwTxtFmtColl* pColl = GetTxtColl(); 2660 2661 SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet ); 2662 2663 if( pNewAttrSet ) 2664 delete pNewAttrSet; 2665 2666 const SwNumRule* pRule = GetNumRule(); 2667 if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901# 2668 { 2669 // --> OD 2005-10-18 #i55459# 2670 // - correction: parameter <bNext> has to be checked, as it was in the 2671 // previous implementation. 2672 if ( !bNext && !IsCountedInList() ) 2673 SetCountedInList(true); 2674 // <-- 2675 } 2676 2677 // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine 2678 // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht 2679 // nochmal uebergeplaettet werden !! 2680 if( pColl != pNode->GetTxtColl() || 2681 ( bChgFollow && pColl != GetTxtColl() )) 2682 return pNode; // mehr duerfte nicht gemacht werden oder ???? 2683 2684 pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung 2685 if( bNext || !bChgFollow ) 2686 return pNode; 2687 2688 SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl(); 2689 // --> OD 2009-08-12 #i101870# 2690 // perform action on different paragraph styles before applying the new paragraph style 2691 if (pNextColl != pColl) 2692 { 2693 // --> OD 2007-07-10 #i75353# 2694 if ( bClearHardSetNumRuleWhenFmtCollChanges ) 2695 { 2696 std::vector<sal_uInt16> aClearWhichIds; 2697 aClearWhichIds.push_back( RES_PARATR_NUMRULE ); 2698 if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() ) 2699 { 2700 SwFrm::GetCache().Delete( this ); 2701 SetInCache( sal_False ); 2702 } 2703 } 2704 // <-- 2705 } 2706 // <-- 2707 ChgFmtColl( pNextColl ); 2708 2709 return pNode; 2710 } 2711 2712 SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos ) 2713 { 2714 // Position hinter dem eingefuegt wird 2715 SwNodeIndex aIdx( rPos.nNode, 1 ); 2716 SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True ); 2717 2718 // --> OD 2008-05-14 #refactorlists# 2719 // reset list attributes at appended text node 2720 pNew->ResetAttr( RES_PARATR_LIST_ISRESTART ); 2721 pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 2722 pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 2723 if ( pNew->GetNumRule() == 0 ) 2724 { 2725 pNew->ResetAttr( RES_PARATR_LIST_ID ); 2726 pNew->ResetAttr( RES_PARATR_LIST_LEVEL ); 2727 } 2728 // <-- 2729 // --> OD 2008-03-13 #refactorlists# 2730 // SyncNumberAndNumRule(); 2731 if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 ) 2732 { 2733 AddToList(); 2734 } 2735 // <-- 2736 2737 if( GetDepends() ) 2738 MakeFrms( *pNew ); 2739 return pNew; 2740 } 2741 2742 /************************************************************************* 2743 * SwTxtNode::GetTxtAttr 2744 *************************************************************************/ 2745 2746 SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex, 2747 const RES_TXTATR nWhich ) const 2748 { 2749 if ( HasHints() ) 2750 { 2751 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i ) 2752 { 2753 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i); 2754 const xub_StrLen nStartPos = *pHint->GetStart(); 2755 if ( nIndex < nStartPos ) 2756 { 2757 return 0; 2758 } 2759 if ( (nIndex == nStartPos) && pHint->HasDummyChar() ) 2760 { 2761 return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() ) 2762 ? pHint : 0; 2763 } 2764 } 2765 } 2766 return 0; 2767 } 2768 2769 // -> #i29560# 2770 sal_Bool SwTxtNode::HasNumber() const 2771 { 2772 sal_Bool bResult = sal_False; 2773 2774 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2775 if ( pRule ) 2776 { 2777 SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()))); 2778 2779 // #i40041# 2780 bResult = aFmt.IsEnumeration() && 2781 SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType(); 2782 } 2783 2784 return bResult; 2785 } 2786 2787 sal_Bool SwTxtNode::HasBullet() const 2788 { 2789 sal_Bool bResult = sal_False; 2790 2791 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2792 if ( pRule ) 2793 { 2794 SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()))); 2795 2796 bResult = aFmt.IsItemize(); 2797 } 2798 2799 return bResult; 2800 } 2801 // <- #i29560# 2802 2803 // --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings> 2804 //i53420 added max outline parameter 2805 XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const 2806 { 2807 if (GetDoc()->IsClipBoard() && m_pNumStringCache.get()) 2808 { 2809 // #i111677# do not expand number strings in clipboard documents 2810 return *m_pNumStringCache; 2811 } 2812 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2813 if ( pRule && 2814 IsCountedInList() ) 2815 { 2816 SvxNumberType const& rNumberType( 2817 pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) ); 2818 if (rNumberType.IsTxtFmt() || 2819 // #b6432095# 2820 (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType())) 2821 { 2822 return pRule->MakeNumString( GetNum()->GetNumberVector(), 2823 _bInclPrefixAndSuffixStrings ? sal_True : sal_False, 2824 sal_False, 2825 _nRestrictToThisLevel ); 2826 } 2827 } 2828 2829 return aEmptyStr; 2830 } 2831 2832 long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const 2833 { 2834 long nRet = 0; 2835 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2836 if( pRule ) 2837 { 2838 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2839 // --> OD 2008-01-16 #newlistlevelattrs# 2840 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2841 { 2842 nRet = rFmt.GetAbsLSpace(); 2843 2844 if( !bTxtLeft ) 2845 { 2846 if( 0 > rFmt.GetFirstLineOffset() && 2847 nRet > -rFmt.GetFirstLineOffset() ) 2848 nRet = nRet + rFmt.GetFirstLineOffset(); 2849 else 2850 nRet = 0; 2851 } 2852 2853 if( pRule->IsAbsSpaces() ) 2854 nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft(); 2855 } 2856 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2857 { 2858 if ( AreListLevelIndentsApplicable() ) 2859 { 2860 nRet = rFmt.GetIndentAt(); 2861 // --> OD 2008-06-06 #i90401# 2862 // Only negative first line indents have consider for the left margin 2863 if ( !bTxtLeft && 2864 rFmt.GetFirstLineIndent() < 0 ) 2865 { 2866 nRet = nRet + rFmt.GetFirstLineIndent(); 2867 } 2868 // <-- 2869 } 2870 } 2871 // <-- 2872 } 2873 2874 return nRet; 2875 } 2876 2877 sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const 2878 { 2879 sal_Bool bRet( sal_False ); 2880 // --> OD 2009-09-08 #i95907#, #b6879723# 2881 rFLOffset = 0; 2882 // <-- 2883 2884 // --> OD 2005-11-02 #i51089 - TUNING# 2885 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2886 if ( pRule ) 2887 { 2888 if ( IsCountedInList() ) 2889 { 2890 // --> OD 2008-01-16 #newlistlevelattrs# 2891 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2892 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2893 { 2894 rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset(); 2895 2896 if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2897 { 2898 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 2899 rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst(); 2900 } 2901 } 2902 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2903 { 2904 if ( AreListLevelIndentsApplicable() ) 2905 { 2906 rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent()); 2907 } 2908 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2909 { 2910 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 2911 rFLOffset = aItem.GetTxtFirstLineOfst(); 2912 } 2913 } 2914 // <-- 2915 } 2916 2917 bRet = sal_True; 2918 } 2919 else 2920 { 2921 rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2922 } 2923 2924 return bRet; 2925 } 2926 2927 // --> OD 2010-01-05 #b6884103# 2928 SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const 2929 { 2930 SwTwips nAdditionalIndent = 0; 2931 2932 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 2933 if ( pRule ) 2934 { 2935 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2936 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2937 { 2938 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2939 2940 if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2941 { 2942 nAdditionalIndent = nAdditionalIndent - 2943 GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2944 } 2945 } 2946 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2947 { 2948 if ( AreListLevelIndentsApplicable() ) 2949 { 2950 nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent(); 2951 } 2952 else 2953 { 2954 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2955 if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 2956 { 2957 nAdditionalIndent = nAdditionalIndent - 2958 GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst(); 2959 } 2960 } 2961 } 2962 } 2963 else 2964 { 2965 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft(); 2966 } 2967 2968 return nAdditionalIndent; 2969 } 2970 // <-- 2971 2972 // --> OD 2008-12-02 #i96772# 2973 void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const 2974 { 2975 if ( AreListLevelIndentsApplicable() ) 2976 { 2977 const SwNumRule* pRule = GetNumRule(); 2978 if ( pRule && GetActualListLevel() >= 0 ) 2979 { 2980 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 2981 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2982 { 2983 SvxLRSpaceItem aLR( RES_LR_SPACE ); 2984 o_rLRSpaceItem = aLR; 2985 } 2986 } 2987 } 2988 } 2989 // <-- 2990 2991 // --> OD 2008-07-01 #i91133# 2992 long SwTxtNode::GetLeftMarginForTabCalculation() const 2993 { 2994 long nLeftMarginForTabCalc = 0; 2995 2996 bool bLeftMarginForTabCalcSetToListLevelIndent( false ); 2997 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0; 2998 if( pRule ) 2999 { 3000 const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel())); 3001 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 3002 { 3003 if ( AreListLevelIndentsApplicable() ) 3004 { 3005 nLeftMarginForTabCalc = rFmt.GetIndentAt(); 3006 bLeftMarginForTabCalcSetToListLevelIndent = true; 3007 } 3008 } 3009 } 3010 if ( !bLeftMarginForTabCalcSetToListLevelIndent ) 3011 { 3012 nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft(); 3013 } 3014 3015 return nLeftMarginForTabCalc; 3016 } 3017 // <-- 3018 3019 void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt, 3020 xub_StrLen nEndPos, sal_Bool bExpandFlds ) const 3021 { 3022 if( GetpSwpHints() ) 3023 { 3024 sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD; 3025 for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter, 3026 cSrchChr = CH_TXTATR_INWORD ) 3027 { 3028 xub_StrLen nPos = rTxt.Search( cSrchChr ); 3029 while( STRING_NOTFOUND != nPos && nPos < nEndPos ) 3030 { 3031 const SwTxtAttr* const pAttr = 3032 GetTxtAttrForCharAt( rTxtStt + nPos ); 3033 if( pAttr ) 3034 { 3035 switch( pAttr->Which() ) 3036 { 3037 case RES_TXTATR_FIELD: 3038 rTxt.Erase( nPos, 1 ); 3039 if( bExpandFlds ) 3040 { 3041 const XubString aExpand( 3042 static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true)); 3043 rTxt.Insert( aExpand, nPos ); 3044 nPos = nPos + aExpand.Len(); 3045 nEndPos = nEndPos + aExpand.Len(); 3046 rTxtStt = rTxtStt - aExpand.Len(); 3047 } 3048 ++rTxtStt; 3049 break; 3050 case RES_TXTATR_FTN: 3051 rTxt.Erase( nPos, 1 ); 3052 if( bExpandFlds ) 3053 { 3054 const SwFmtFtn& rFtn = pAttr->GetFtn(); 3055 XubString sExpand; 3056 if( rFtn.GetNumStr().Len() ) 3057 sExpand = rFtn.GetNumStr(); 3058 else if( rFtn.IsEndNote() ) 3059 sExpand = GetDoc()->GetEndNoteInfo().aFmt. 3060 GetNumStr( rFtn.GetNumber() ); 3061 else 3062 sExpand = GetDoc()->GetFtnInfo().aFmt. 3063 GetNumStr( rFtn.GetNumber() ); 3064 rTxt.Insert( sExpand, nPos ); 3065 nPos = nPos + sExpand.Len(); 3066 nEndPos = nEndPos + sExpand.Len(); 3067 rTxtStt = rTxtStt - sExpand.Len(); 3068 } 3069 ++rTxtStt; 3070 break; 3071 default: 3072 rTxt.Erase( nPos, 1 ); 3073 ++rTxtStt; 3074 } 3075 } 3076 else 3077 ++nPos, ++nEndPos; 3078 nPos = rTxt.Search( cSrchChr, nPos ); 3079 } 3080 } 3081 } 3082 } 3083 3084 /************************************************************************* 3085 * SwTxtNode::GetExpandTxt 3086 * Expand fields 3087 *************************************************************************/ 3088 // --> OD 2007-11-15 #i83479# - handling of new parameters 3089 XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx, 3090 const xub_StrLen nLen, 3091 const bool bWithNum, 3092 const bool bAddSpaceAfterListLabelStr, 3093 const bool bWithSpacesForLevel ) const 3094 { 3095 XubString aTxt( GetTxt().Copy( nIdx, nLen ) ); 3096 xub_StrLen nTxtStt = nIdx; 3097 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True ); 3098 if( bWithNum ) 3099 { 3100 XubString aListLabelStr = GetNumString(); 3101 if ( aListLabelStr.Len() > 0 ) 3102 { 3103 if ( bAddSpaceAfterListLabelStr ) 3104 { 3105 const sal_Unicode aSpace = ' '; 3106 aTxt.Insert( aSpace, 0 ); 3107 } 3108 aTxt.Insert( GetNumString(), 0 ); 3109 } 3110 } 3111 3112 if ( bWithSpacesForLevel && GetActualListLevel() > 0 ) 3113 { 3114 int nLevel( GetActualListLevel() ); 3115 while ( nLevel > 0 ) 3116 { 3117 const sal_Unicode aSpace = ' '; 3118 aTxt.Insert( aSpace , 0 ); 3119 aTxt.Insert( aSpace , 0 ); 3120 --nLevel; 3121 } 3122 } 3123 3124 return aTxt; 3125 } 3126 // <-- 3127 3128 sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx, 3129 xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum, 3130 sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const 3131 { 3132 if( &rDestNd == this ) 3133 return sal_False; 3134 3135 SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() ); 3136 if( pDestIdx ) 3137 aDestIdx = *pDestIdx; 3138 xub_StrLen nDestStt = aDestIdx.GetIndex(); 3139 3140 // Text einfuegen 3141 String sTmpText = GetTxt(); 3142 if( bReplaceTabsWithSpaces ) 3143 sTmpText.SearchAndReplaceAll('\t', ' '); 3144 3145 // mask hidden characters 3146 const xub_Unicode cChar = CH_TXTATR_BREAKWORD; 3147 sal_uInt16 nHiddenChrs = 3148 SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar ); 3149 3150 sTmpText = sTmpText.Copy( nIdx, nLen ); 3151 rDestNd.InsertText( sTmpText, aDestIdx ); 3152 nLen = aDestIdx.GetIndex() - nDestStt; 3153 3154 // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen 3155 if ( HasHints() ) 3156 { 3157 xub_StrLen nInsPos = nDestStt - nIdx; 3158 for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ ) 3159 { 3160 const SwTxtAttr* pHt = (*m_pSwpHints)[i]; 3161 const xub_StrLen nAttrStartIdx = *pHt->GetStart(); 3162 const sal_uInt16 nWhich = pHt->Which(); 3163 if (nIdx + nLen <= nAttrStartIdx) 3164 break; // ueber das Textende 3165 3166 const xub_StrLen *pEndIdx = pHt->GetEnd(); 3167 if( pEndIdx && *pEndIdx > nIdx && 3168 ( RES_CHRATR_FONT == nWhich || 3169 RES_TXTATR_CHARFMT == nWhich || 3170 RES_TXTATR_AUTOFMT == nWhich )) 3171 { 3172 const SvxFontItem* const pFont = 3173 static_cast<const SvxFontItem*>( 3174 CharFmt::GetItem( *pHt, RES_CHRATR_FONT )); 3175 if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() ) 3176 { 3177 // attribute in area => copy 3178 rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont), 3179 nInsPos + nAttrStartIdx, nInsPos + *pEndIdx ); 3180 } 3181 } 3182 else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) ) 3183 { 3184 aDestIdx = nInsPos + nAttrStartIdx; 3185 switch( nWhich ) 3186 { 3187 case RES_TXTATR_FIELD: 3188 { 3189 XubString const aExpand( 3190 static_cast<SwTxtFld const*>(pHt)->GetFmtFld().GetField()->ExpandField(true) ); 3191 if( aExpand.Len() ) 3192 { 3193 aDestIdx++; // dahinter einfuegen; 3194 rDestNd.InsertText( aExpand, aDestIdx ); 3195 aDestIdx = nInsPos + nAttrStartIdx; 3196 nInsPos = nInsPos + aExpand.Len(); 3197 } 3198 rDestNd.EraseText( aDestIdx, 1 ); 3199 --nInsPos; 3200 } 3201 break; 3202 3203 case RES_TXTATR_FTN: 3204 { 3205 if ( bWithFtn ) 3206 { 3207 const SwFmtFtn& rFtn = pHt->GetFtn(); 3208 XubString sExpand; 3209 if( rFtn.GetNumStr().Len() ) 3210 sExpand = rFtn.GetNumStr(); 3211 else if( rFtn.IsEndNote() ) 3212 sExpand = GetDoc()->GetEndNoteInfo().aFmt. 3213 GetNumStr( rFtn.GetNumber() ); 3214 else 3215 sExpand = GetDoc()->GetFtnInfo().aFmt. 3216 GetNumStr( rFtn.GetNumber() ); 3217 if( sExpand.Len() ) 3218 { 3219 aDestIdx++; // insert behind 3220 SvxEscapementItem aItem( 3221 SVX_ESCAPEMENT_SUPERSCRIPT ); 3222 rDestNd.InsertItem(aItem, 3223 aDestIdx.GetIndex(), 3224 aDestIdx.GetIndex() ); 3225 rDestNd.InsertText( sExpand, aDestIdx, 3226 IDocumentContentOperations::INS_EMPTYEXPAND); 3227 aDestIdx = nInsPos + nAttrStartIdx; 3228 nInsPos = nInsPos + sExpand.Len(); 3229 } 3230 } 3231 rDestNd.EraseText( aDestIdx, 1 ); 3232 --nInsPos; 3233 } 3234 break; 3235 3236 default: 3237 rDestNd.EraseText( aDestIdx, 1 ); 3238 --nInsPos; 3239 } 3240 } 3241 } 3242 } 3243 3244 if( bWithNum ) 3245 { 3246 aDestIdx = nDestStt; 3247 rDestNd.InsertText( GetNumString(), aDestIdx ); 3248 } 3249 3250 if ( nHiddenChrs > 0 ) 3251 { 3252 aDestIdx = 0; 3253 while ( aDestIdx < rDestNd.GetTxt().Len() ) 3254 { 3255 if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) ) 3256 { 3257 xub_StrLen nIndex = aDestIdx.GetIndex(); 3258 while ( nIndex < rDestNd.GetTxt().Len() && 3259 cChar == rDestNd.GetTxt().GetChar( ++nIndex ) ) 3260 ; 3261 rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() ); 3262 } 3263 else 3264 ++aDestIdx; 3265 } 3266 } 3267 3268 return sal_True; 3269 } 3270 3271 const ModelToViewHelper::ConversionMap* 3272 SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const 3273 { 3274 const rtl::OUString& rNodeText = GetTxt(); 3275 rRetText = rNodeText; 3276 ModelToViewHelper::ConversionMap* pConversionMap = 0; 3277 3278 const SwpHints* pSwpHints2 = GetpSwpHints(); 3279 xub_StrLen nPos = 0; 3280 3281 for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i ) 3282 { 3283 const SwTxtAttr* pAttr = (*pSwpHints2)[i]; 3284 if ( RES_TXTATR_FIELD == pAttr->Which() ) 3285 { 3286 const XubString aExpand( 3287 static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true)); 3288 if ( aExpand.Len() > 0 ) 3289 { 3290 const xub_StrLen nFieldPos = *pAttr->GetStart(); 3291 rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand ); 3292 if ( !pConversionMap ) 3293 pConversionMap = new ModelToViewHelper::ConversionMap; 3294 pConversionMap->push_back( 3295 ModelToViewHelper::ConversionMapEntry( 3296 nFieldPos, nPos + nFieldPos ) ); 3297 nPos += ( aExpand.Len() - 1 ); 3298 } 3299 } 3300 } 3301 3302 if ( pConversionMap && pConversionMap->size() ) 3303 pConversionMap->push_back( 3304 ModelToViewHelper::ConversionMapEntry( 3305 rNodeText.getLength()+1, rRetText.getLength()+1 ) ); 3306 3307 return pConversionMap; 3308 } 3309 3310 XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen, 3311 sal_Bool bExpandFlds, sal_Bool bWithNum ) const 3312 { 3313 SvUShorts aRedlArr; 3314 const SwDoc* pDoc = GetDoc(); 3315 sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE ); 3316 if( USHRT_MAX != nRedlPos ) 3317 { 3318 // es existiert fuer den Node irgendein Redline-Delete-Object 3319 const sal_uLong nNdIdx = GetIndex(); 3320 for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos ) 3321 { 3322 const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ]; 3323 if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() ) 3324 { 3325 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End(); 3326 if( pRStt->nNode < nNdIdx ) 3327 { 3328 if( pREnd->nNode > nNdIdx ) 3329 // Absatz ist komplett geloescht 3330 return aEmptyStr; 3331 else if( pREnd->nNode == nNdIdx ) 3332 { 3333 // von 0 bis nContent ist alles geloescht 3334 aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() ); 3335 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() ); 3336 } 3337 } 3338 else if( pRStt->nNode == nNdIdx ) 3339 { 3340 aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() ); 3341 if( pREnd->nNode == nNdIdx ) 3342 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() ); 3343 else 3344 { 3345 aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() ); 3346 break; // mehr kann nicht kommen 3347 } 3348 } 3349 else 3350 break; // mehr kann nicht kommen 3351 } 3352 } 3353 } 3354 3355 XubString aTxt( GetTxt().Copy( nIdx, nLen ) ); 3356 3357 xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len(); 3358 for( sal_uInt16 n = 0; n < aRedlArr.Count(); n += 2 ) 3359 { 3360 xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ]; 3361 if( ( nIdx <= nStt && nStt <= nIdxEnd ) || 3362 ( nIdx <= nEnd && nEnd <= nIdxEnd )) 3363 { 3364 if( nStt < nIdx ) nStt = nIdx; 3365 if( nIdxEnd < nEnd ) nEnd = nIdxEnd; 3366 xub_StrLen nDelCnt = nEnd - nStt; 3367 aTxt.Erase( nStt - nTxtStt, nDelCnt ); 3368 Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds ); 3369 nTxtStt = nTxtStt + nDelCnt; 3370 } 3371 else if( nStt >= nIdxEnd ) 3372 break; 3373 } 3374 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds ); 3375 3376 if( bWithNum ) 3377 aTxt.Insert( GetNumString(), 0 ); 3378 return aTxt; 3379 } 3380 3381 /************************************************************************* 3382 * SwTxtNode::ReplaceText 3383 *************************************************************************/ 3384 3385 void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen, 3386 const XubString& rText ) 3387 { 3388 ASSERT( rStart.GetIndex() < m_Text.Len() && 3389 rStart.GetIndex() + nDelLen <= m_Text.Len(), 3390 "SwTxtNode::ReplaceText: index out of bounds" ); 3391 const xub_StrLen nStartPos = rStart.GetIndex(); 3392 xub_StrLen nEndPos = nStartPos + nDelLen; 3393 xub_StrLen nLen = nDelLen; 3394 for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos ) 3395 { 3396 if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) || 3397 ( CH_TXTATR_INWORD == m_Text.GetChar( nPos ) ) ) 3398 { 3399 SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos ); 3400 if (pHint) 3401 { 3402 ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar() 3403 && (*pHint->GetStart() < nEndPos) 3404 && (*pHint->GetEnd() > nEndPos) ), 3405 "ReplaceText: ERROR: " 3406 "deleting left-overlapped attribute with CH_TXTATR"); 3407 DeleteAttribute( pHint ); 3408 --nEndPos; 3409 --nLen; 3410 } 3411 } 3412 } 3413 3414 sal_Bool bOldExpFlg = IsIgnoreDontExpand(); 3415 SetIgnoreDontExpand( sal_True ); 3416 3417 if( nLen && rText.Len() ) 3418 { 3419 // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen 3420 // Dadurch wird die Attributierung des 1. Zeichen expandiert! 3421 m_Text.SetChar( nStartPos, rText.GetChar( 0 ) ); 3422 3423 ((SwIndex&)rStart)++; 3424 m_Text.Erase( rStart.GetIndex(), nLen - 1 ); 3425 Update( rStart, nLen - 1, true ); 3426 3427 XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 ); 3428 m_Text.Insert( aTmpTxt, rStart.GetIndex() ); 3429 Update( rStart, aTmpTxt.Len(), false ); 3430 } 3431 else 3432 { 3433 m_Text.Erase( nStartPos, nLen ); 3434 Update( rStart, nLen, true ); 3435 3436 m_Text.Insert( rText, nStartPos ); 3437 Update( rStart, rText.Len(), false ); 3438 } 3439 3440 SetIgnoreDontExpand( bOldExpFlg ); 3441 SwDelTxt aDelHint( nStartPos, nDelLen ); 3442 NotifyClients( 0, &aDelHint ); 3443 3444 SwInsTxt aHint( nStartPos, rText.Len() ); 3445 NotifyClients( 0, &aHint ); 3446 } 3447 3448 // --> OD 2008-03-27 #refactorlists# 3449 namespace { 3450 // Helper method for special handling of modified attributes at text node. 3451 // The following is handled: 3452 // (1) on changing the paragraph style - RES_FMT_CHG: 3453 // Check, if list style of the text node is changed. If yes, add respectively 3454 // remove the text node to the corresponding list. 3455 // (2) on changing the attributes - RES_ATTRSET_CHG: 3456 // Same as (1). 3457 // (3) on changing the list style - RES_PARATR_NUMRULE: 3458 // Same as (1). 3459 void HandleModifyAtTxtNode( SwTxtNode& rTxtNode, 3460 const SfxPoolItem* pOldValue, 3461 const SfxPoolItem* pNewValue ) 3462 { 3463 const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() : 3464 pNewValue ? pNewValue->Which() : 0 ; 3465 bool bNumRuleSet = false; 3466 bool bParagraphStyleChanged = false; 3467 String sNumRule; 3468 String sOldNumRule; 3469 switch ( nWhich ) 3470 { 3471 case RES_FMT_CHG: 3472 { 3473 bParagraphStyleChanged = true; 3474 if( rTxtNode.GetNodes().IsDocNodes() ) 3475 { 3476 // --> OD 2008-12-17 #i70748# 3477 // The former list style set at the paragraph can not be 3478 // retrieved from the change set. 3479 // sOldNumRule = 3480 // dynamic_cast<const SwFmtChg*>(pOldValue)->pChangedFmt->GetNumRule().GetValue(); 3481 const SwNumRule* pFormerNumRuleAtTxtNode = 3482 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3483 if ( pFormerNumRuleAtTxtNode ) 3484 { 3485 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3486 } 3487 // <-- 3488 // --> OD 2008-11-19 #i70748# 3489 if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() ) 3490 { 3491 const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule(); 3492 if ( rNumRuleItem.GetValue().Len() > 0 ) 3493 { 3494 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3495 } 3496 } 3497 // <-- 3498 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3499 if ( pNumRuleAtTxtNode ) 3500 { 3501 bNumRuleSet = true; 3502 sNumRule = pNumRuleAtTxtNode->GetName(); 3503 } 3504 } 3505 break; 3506 } 3507 case RES_ATTRSET_CHG: 3508 { 3509 const SfxPoolItem* pItem = 0; 3510 // --> OD 2008-12-19 #i70748# 3511 // The former list style set at the paragraph can not be 3512 // retrieved from the change set. 3513 // if ( dynamic_cast<const SwAttrSetChg*>(pOldValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == 3514 // SFX_ITEM_SET ) 3515 // { 3516 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue(); 3517 // } 3518 const SwNumRule* pFormerNumRuleAtTxtNode = 3519 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3520 if ( pFormerNumRuleAtTxtNode ) 3521 { 3522 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3523 } 3524 // <-- 3525 if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == 3526 SFX_ITEM_SET ) 3527 { 3528 // --> OD 2008-11-19 #i70748# 3529 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3530 // <-- 3531 bNumRuleSet = true; 3532 // The new list style set at the paragraph can not be 3533 // retrieved from the change set. 3534 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue(); 3535 // <-- 3536 } 3537 // --> OD 2008-12-17 #i70748# 3538 // The new list style set at the paragraph. 3539 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3540 if ( pNumRuleAtTxtNode ) 3541 { 3542 sNumRule = pNumRuleAtTxtNode->GetName(); 3543 } 3544 // <-- 3545 break; 3546 } 3547 case RES_PARATR_NUMRULE: 3548 { 3549 if ( rTxtNode.GetNodes().IsDocNodes() ) 3550 { 3551 // The former list style set at the paragraph can not be 3552 // retrieved from the change set. 3553 // if ( pOldValue ) 3554 // { 3555 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pOldValue)->GetValue(); 3556 // } 3557 const SwNumRule* pFormerNumRuleAtTxtNode = 3558 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0; 3559 if ( pFormerNumRuleAtTxtNode ) 3560 { 3561 sOldNumRule = pFormerNumRuleAtTxtNode->GetName(); 3562 } 3563 // <-- 3564 if ( pNewValue ) 3565 { 3566 // --> OD 2008-11-19 #i70748# 3567 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 3568 // <-- 3569 bNumRuleSet = true; 3570 // --> OD 2008-12-17 #i70748# 3571 // The new list style set at the paragraph can not be 3572 // retrieved from the change set. 3573 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pNewValue)->GetValue(); 3574 // <-- 3575 } 3576 // --> OD 2008-12-17 #i70748# 3577 // The new list style set at the paragraph. 3578 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule(); 3579 if ( pNumRuleAtTxtNode ) 3580 { 3581 sNumRule = pNumRuleAtTxtNode->GetName(); 3582 } 3583 // <-- 3584 } 3585 break; 3586 } 3587 } 3588 if ( sNumRule != sOldNumRule ) 3589 { 3590 if ( bNumRuleSet ) 3591 { 3592 if ( sNumRule.Len() == 0 ) 3593 { 3594 rTxtNode.RemoveFromList(); 3595 if ( bParagraphStyleChanged ) 3596 { 3597 SvUShortsSort aResetAttrsArray; 3598 aResetAttrsArray.Insert( RES_PARATR_LIST_ID ); 3599 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL ); 3600 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART ); 3601 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE ); 3602 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 3603 SwPaM aPam( rTxtNode ); 3604 // --> OD 2008-11-28 #i96644# 3605 // suppress side effect "send data changed events" 3606 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False, 3607 &aResetAttrsArray, 3608 false ); 3609 // <-- 3610 } 3611 } 3612 else 3613 { 3614 rTxtNode.RemoveFromList(); 3615 // If new list style is the outline style, apply outline 3616 // level as the list level. 3617 if ( sNumRule == 3618 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) ) 3619 { 3620 // --> OD 2008-09-10 #i70748# 3621 ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(), 3622 "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." ); 3623 int nNewListLevel = 3624 rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel(); 3625 // <-- 3626 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) 3627 { 3628 rTxtNode.SetAttrListLevel( nNewListLevel ); 3629 } 3630 } 3631 rTxtNode.AddToList(); 3632 } 3633 } 3634 else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0> 3635 { 3636 rTxtNode.RemoveFromList(); 3637 if ( bParagraphStyleChanged ) 3638 { 3639 SvUShortsSort aResetAttrsArray; 3640 aResetAttrsArray.Insert( RES_PARATR_LIST_ID ); 3641 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL ); 3642 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART ); 3643 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE ); 3644 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 3645 SwPaM aPam( rTxtNode ); 3646 // --> OD 2008-11-28 #i96644# 3647 // suppress side effect "send data changed events" 3648 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False, 3649 &aResetAttrsArray, 3650 false ); 3651 // <-- 3652 // --> OD 2008-11-19 #i70748# 3653 if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 ) 3654 { 3655 rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 3656 } 3657 // <-- 3658 } 3659 } 3660 } 3661 else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() ) 3662 { 3663 rTxtNode.AddToList(); 3664 } 3665 // <-- 3666 } 3667 // End of method <HandleModifyAtTxtNode> 3668 } 3669 // <-- 3670 3671 void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue ) 3672 { 3673 bool bWasNotifiable = m_bNotifiable; 3674 m_bNotifiable = false; 3675 3676 // Bug 24616/24617: 3677 // Modify ueberladen, damit beim Loeschen von Vorlagen diese 3678 // wieder richtig verwaltet werden (Outline-Numerierung!!) 3679 // Bug25481: 3680 // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen. 3681 if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() && 3682 GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt && 3683 GetNodes().IsDocNodes() ) 3684 { 3685 _ChgTxtCollUpdateNum( 3686 (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt, 3687 (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt ); 3688 } 3689 3690 // --> OD 2008-03-27 #refactorlists# 3691 if ( !mbInSetOrResetAttr ) 3692 { 3693 HandleModifyAtTxtNode( *this, pOldValue, pNewValue ); 3694 } 3695 // <-- 3696 3697 SwCntntNode::Modify( pOldValue, pNewValue ); 3698 3699 SwDoc * pDoc = GetDoc(); 3700 // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array 3701 if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() ) 3702 // <-- 3703 { 3704 pDoc->GetNodes().UpdateOutlineNode(*this); 3705 } 3706 3707 m_bNotifiable = bWasNotifiable; 3708 3709 if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which())) 3710 { // invalidate cached uno object 3711 SetXParagraph(::com::sun::star::uno::Reference< 3712 ::com::sun::star::text::XTextContent>(0)); 3713 } 3714 } 3715 3716 SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl ) 3717 { 3718 ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." ); 3719 ASSERT( HAS_BASE( SwTxtFmtColl, pNewColl ), 3720 "ChgFmtColl: ist kein Text-Collectionpointer." ); 3721 3722 SwTxtFmtColl *pOldColl = GetTxtColl(); 3723 if( pNewColl != pOldColl ) 3724 { 3725 SetCalcHiddenCharFlags(); 3726 SwCntntNode::ChgFmtColl( pNewColl ); 3727 // --> OD 2008-03-27 #refactorlists# 3728 // NumRuleChgd(); 3729 #if OSL_DEBUG_LEVEL > 1 3730 ASSERT( !mbInSetOrResetAttr, 3731 "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" ) 3732 #endif 3733 if ( !mbInSetOrResetAttr ) 3734 { 3735 SwFmtChg aTmp1( pOldColl ); 3736 SwFmtChg aTmp2( pNewColl ); 3737 HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 ); 3738 } 3739 // <-- 3740 } 3741 3742 // nur wenn im normalen Nodes-Array 3743 if( GetNodes().IsDocNodes() ) 3744 { 3745 _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) ); 3746 } 3747 3748 GetNodes().UpdateOutlineNode(*this); 3749 3750 return pOldColl; 3751 } 3752 3753 SwNodeNum* SwTxtNode::CreateNum() const 3754 { 3755 if ( !mpNodeNum ) 3756 { 3757 // --> OD 2008-02-19 #refactorlists# 3758 mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) ); 3759 // <-- 3760 } 3761 return mpNodeNum; 3762 } 3763 3764 SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const 3765 { 3766 if ( GetNum() ) 3767 { 3768 return GetNum()->GetNumberVector(); 3769 } 3770 else 3771 { 3772 SwNumberTree::tNumberVector aResult; 3773 return aResult; 3774 } 3775 } 3776 3777 bool SwTxtNode::IsOutline() const 3778 { 3779 bool bResult = false; 3780 3781 //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei 3782 if ( GetAttrOutlineLevel() > 0 ) //<-end,zhaojianwei 3783 { 3784 bResult = !IsInRedlines(); 3785 } 3786 else 3787 { 3788 const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L ); 3789 if ( pRule && pRule->IsOutlineRule() ) 3790 { 3791 bResult = !IsInRedlines(); 3792 } 3793 } 3794 3795 return bResult; 3796 } 3797 3798 bool SwTxtNode::IsOutlineStateChanged() const 3799 { 3800 return IsOutline() != m_bLastOutlineState; 3801 } 3802 3803 void SwTxtNode::UpdateOutlineState() 3804 { 3805 m_bLastOutlineState = IsOutline(); 3806 } 3807 3808 //#outline level, zhaojianwei 3809 int SwTxtNode::GetAttrOutlineLevel() const 3810 { 3811 return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue(); 3812 } 3813 void SwTxtNode::SetAttrOutlineLevel(int nLevel) 3814 { 3815 ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei 3816 if ( 0 <= nLevel && nLevel <= MAXLEVEL ) 3817 { 3818 SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 3819 static_cast<sal_uInt16>(nLevel) ) ); 3820 } 3821 } 3822 //<-end 3823 3824 // --> OD 2008-11-19 #i70748# 3825 bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr() 3826 { 3827 return mbEmptyListStyleSetDueToSetOutlineLevelAttr; 3828 } 3829 3830 void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr() 3831 { 3832 if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr ) 3833 { 3834 SetAttr( SwNumRuleItem() ); 3835 mbEmptyListStyleSetDueToSetOutlineLevelAttr = true; 3836 } 3837 } 3838 3839 void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr() 3840 { 3841 if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr ) 3842 { 3843 ResetAttr( RES_PARATR_NUMRULE ); 3844 mbEmptyListStyleSetDueToSetOutlineLevelAttr = false; 3845 } 3846 } 3847 // <-- 3848 3849 3850 // --> OD 2008-02-27 #refactorlists# 3851 void SwTxtNode::SetAttrListLevel( int nLevel ) 3852 { 3853 if ( nLevel < 0 || nLevel >= MAXLEVEL ) 3854 { 3855 ASSERT( false, 3856 "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" ); 3857 return; 3858 } 3859 3860 SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL, 3861 static_cast<sal_Int16>(nLevel) ); 3862 SetAttr( aNewListLevelItem ); 3863 } 3864 // <-- 3865 // --> OD 2008-02-27 #refactorlists# 3866 bool SwTxtNode::HasAttrListLevel() const 3867 { 3868 return GetpSwAttrSet() && 3869 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET; 3870 } 3871 // <-- 3872 // --> OD 2008-02-27 #refactorlists# 3873 int SwTxtNode::GetAttrListLevel() const 3874 { 3875 int nAttrListLevel = 0; 3876 3877 const SfxInt16Item& aListLevelItem = 3878 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL )); 3879 nAttrListLevel = static_cast<int>(aListLevelItem.GetValue()); 3880 3881 return nAttrListLevel; 3882 } 3883 // <-- 3884 3885 int SwTxtNode::GetActualListLevel() const 3886 { 3887 return GetNum() ? GetNum()->GetLevelInListTree() : -1; 3888 } 3889 3890 // --> OD 2008-02-25 #refactorlists# 3891 void SwTxtNode::SetListRestart( bool bRestart ) 3892 { 3893 // CreateNum()->SetRestart(bRestart); 3894 if ( !bRestart ) 3895 { 3896 // attribute not contained in paragraph style's attribute set. Thus, 3897 // it can be reset to the attribute pool default by resetting the attribute. 3898 ResetAttr( RES_PARATR_LIST_ISRESTART ); 3899 } 3900 else 3901 { 3902 SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART, 3903 sal_True ); 3904 SetAttr( aNewIsRestartItem ); 3905 } 3906 } 3907 3908 // --> OD 2008-02-25 #refactorlists# 3909 bool SwTxtNode::IsListRestart() const 3910 { 3911 // return GetNum() ? GetNum()->IsRestart() : false; 3912 const SfxBoolItem& aIsRestartItem = 3913 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART )); 3914 3915 return aIsRestartItem.GetValue() ? true : false; 3916 } 3917 // <-- 3918 3919 /** Returns if the paragraph has a visible numbering or bullet. 3920 This includes all kinds of numbering/bullet/outlines. 3921 OD 2008-02-28 #newlistlevelattrs# 3922 The concrete list label string has to be checked, too. 3923 */ 3924 bool SwTxtNode::HasVisibleNumberingOrBullet() const 3925 { 3926 bool bRet = false; 3927 3928 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L; 3929 if ( pRule && IsCountedInList()) 3930 { 3931 // --> OD 2008-03-19 #i87154# 3932 // Correction of #newlistlevelattrs#: 3933 // The numbering type has to be checked for bullet lists. 3934 const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )); 3935 if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() || 3936 pRule->MakeNumString( *(GetNum()) ).Len() > 0 ) 3937 { 3938 bRet = true; 3939 } 3940 // <-- 3941 } 3942 3943 return bRet; 3944 } 3945 3946 // --> OD 2008-02-25 #refactorlists# 3947 void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber ) 3948 { 3949 // CreateNum()->SetStart(nNumber); 3950 const bool bChanged( HasAttrListRestartValue() 3951 ? GetAttrListRestartValue() != nNumber 3952 : nNumber != USHRT_MAX ); 3953 3954 if ( bChanged || !HasAttrListRestartValue() ) 3955 { 3956 if ( nNumber == USHRT_MAX ) 3957 { 3958 ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 3959 } 3960 else 3961 { 3962 SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE, 3963 static_cast<sal_Int16>(nNumber) ); 3964 SetAttr( aNewListRestartValueItem ); 3965 } 3966 } 3967 } 3968 // <-- 3969 3970 // --> OD 2008-02-27 #refactorlists# 3971 bool SwTxtNode::HasAttrListRestartValue() const 3972 { 3973 return GetpSwAttrSet() && 3974 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET; 3975 } 3976 // <-- 3977 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const 3978 { 3979 ASSERT( HasAttrListRestartValue(), 3980 "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." ); 3981 3982 const SfxInt16Item& aListRestartValueItem = 3983 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE )); 3984 return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue()); 3985 } 3986 3987 // --> OD 2008-02-25 #refactorlists# 3988 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const 3989 { 3990 // return GetNum() ? GetNum()->GetStart() : 1; 3991 SwNumberTree::tSwNumTreeNumber nListRestartValue = 1; 3992 3993 if ( IsListRestart() && HasAttrListRestartValue() ) 3994 { 3995 nListRestartValue = GetAttrListRestartValue(); 3996 } 3997 else 3998 { 3999 SwNumRule* pRule = GetNumRule(); 4000 if ( pRule ) 4001 { 4002 const SwNumFmt* pFmt = 4003 pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) ); 4004 if ( pFmt ) 4005 { 4006 nListRestartValue = pFmt->GetStart(); 4007 } 4008 } 4009 } 4010 4011 return nListRestartValue; 4012 } 4013 // <-- 4014 4015 bool SwTxtNode::IsNotifiable() const 4016 { 4017 return m_bNotifiable && IsNotificationEnabled(); 4018 } 4019 4020 bool SwTxtNode::IsNotificationEnabled() const 4021 { 4022 bool bResult = false; 4023 const SwDoc * pDoc = GetDoc(); 4024 if( pDoc ) 4025 { 4026 bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true; 4027 } 4028 return bResult; 4029 } 4030 4031 // --> OD 2008-02-27 #refactorlists# 4032 void SwTxtNode::SetCountedInList( bool bCounted ) 4033 { 4034 if ( bCounted ) 4035 { 4036 // attribute not contained in paragraph style's attribute set. Thus, 4037 // it can be reset to the attribute pool default by resetting the attribute. 4038 ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 4039 } 4040 else 4041 { 4042 SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False ); 4043 SetAttr( aIsCountedInListItem ); 4044 } 4045 } 4046 // <-- 4047 4048 bool SwTxtNode::IsCountedInList() const 4049 { 4050 const SfxBoolItem& aIsCountedInListItem = 4051 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED )); 4052 4053 return aIsCountedInListItem.GetValue() ? true : false; 4054 } 4055 4056 // --> OD 2008-03-13 #refactorlists# 4057 void SwTxtNode::AddToList() 4058 { 4059 if ( IsInList() ) 4060 { 4061 ASSERT( false, 4062 "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" ); 4063 return; 4064 } 4065 4066 const String sListId = GetListId(); 4067 if ( sListId.Len() > 0 ) 4068 { 4069 SwList* pList = GetDoc()->getListByName( sListId ); 4070 if ( pList == 0 ) 4071 { 4072 // Create corresponding list. 4073 SwNumRule* pNumRule = GetNumRule(); 4074 if ( pNumRule ) 4075 { 4076 pList = GetDoc()->createList( sListId, GetNumRule()->GetName() ); 4077 } 4078 } 4079 ASSERT( pList != 0, 4080 "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" ); 4081 if ( pList ) 4082 { 4083 pList->InsertListItem( *CreateNum(), GetAttrListLevel() ); 4084 mpList = pList; 4085 } 4086 } 4087 } 4088 4089 void SwTxtNode::RemoveFromList() 4090 { 4091 if ( IsInList() ) 4092 { 4093 mpList->RemoveListItem( *mpNodeNum ); 4094 mpList = 0; 4095 delete mpNodeNum; 4096 mpNodeNum = 0L; 4097 } 4098 } 4099 4100 bool SwTxtNode::IsInList() const 4101 { 4102 return GetNum() != 0 && GetNum()->GetParent() != 0; 4103 } 4104 // <-- 4105 4106 bool SwTxtNode::IsFirstOfNumRule() const 4107 { 4108 bool bResult = false; 4109 4110 if ( GetNum() && GetNum()->GetNumRule()) 4111 bResult = GetNum()->IsFirst(); 4112 4113 return bResult; 4114 } 4115 4116 // --> OD 2008-02-20 #refactorlists# 4117 void SwTxtNode::SetListId( const String sListId ) 4118 { 4119 const SfxStringItem& rListIdItem = 4120 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); 4121 if ( rListIdItem.GetValue() != sListId ) 4122 { 4123 if ( sListId.Len() == 0 ) 4124 { 4125 ResetAttr( RES_PARATR_LIST_ID ); 4126 } 4127 else 4128 { 4129 SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId ); 4130 SetAttr( aNewListIdItem ); 4131 } 4132 } 4133 } 4134 4135 String SwTxtNode::GetListId() const 4136 { 4137 String sListId; 4138 4139 const SfxStringItem& rListIdItem = 4140 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID )); 4141 sListId = rListIdItem.GetValue(); 4142 4143 // As long as no explicit list id attribute is set, use the list id of 4144 // the list, which has been created for the applied list style. 4145 if ( sListId.Len() == 0 ) 4146 { 4147 SwNumRule* pRule = GetNumRule(); 4148 if ( pRule ) 4149 { 4150 sListId = pRule->GetDefaultListId(); 4151 //#if OSL_DEBUG_LEVEL > 1 4152 // ASSERT( false, 4153 // "DEBUG ASSERTION: default list id of list style is applied." ); 4154 //#endif 4155 // // setting list id directly using <SwCntntNode::SetAttr(..)>, 4156 // // because no handling of this attribute set is needed and to avoid 4157 // // recursive calls of <SwTxtNode::SetAttr(..)> 4158 // SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId ); 4159 // const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem ); 4160 } 4161 } 4162 4163 return sListId; 4164 } 4165 // <-- 4166 4167 /** Determines, if the list level indent attributes can be applied to the 4168 paragraph. 4169 4170 OD 2008-01-17 #newlistlevelattrs# 4171 The list level indents can be applied to the paragraph under the one 4172 of following conditions: 4173 - the list style is directly applied to the paragraph and the paragraph 4174 has no own indent attributes. 4175 - the list style is applied to the paragraph through one of its paragraph 4176 styles, the paragraph has no own indent attributes and on the paragraph 4177 style hierarchy from the paragraph to the paragraph style with the 4178 list style no indent attributes are found. 4179 4180 @author OD 4181 4182 @return boolean 4183 */ 4184 bool SwTxtNode::AreListLevelIndentsApplicable() const 4185 { 4186 bool bAreListLevelIndentsApplicable( true ); 4187 4188 if ( !GetNum() || !GetNum()->GetNumRule() ) 4189 { 4190 // no list style applied to paragraph 4191 bAreListLevelIndentsApplicable = false; 4192 } 4193 else if ( HasSwAttrSet() && 4194 GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET ) 4195 { 4196 // paragraph has hard-set indent attributes 4197 bAreListLevelIndentsApplicable = false; 4198 } 4199 else if ( HasSwAttrSet() && 4200 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET ) 4201 { 4202 // list style is directly applied to paragraph and paragraph has no 4203 // hard-set indent attributes 4204 bAreListLevelIndentsApplicable = true; 4205 } 4206 else 4207 { 4208 // list style is applied through one of the paragraph styles and 4209 // paragraph has no hard-set indent attributes 4210 4211 // check, paragraph's 4212 const SwTxtFmtColl* pColl = GetTxtColl(); 4213 while ( pColl ) 4214 { 4215 if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET ) 4216 { 4217 // indent attributes found in the paragraph style hierarchy. 4218 bAreListLevelIndentsApplicable = false; 4219 break; 4220 } 4221 4222 if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET ) 4223 { 4224 // paragraph style with the list style found and until now no 4225 // indent attributes are found in the paragraph style hierarchy. 4226 bAreListLevelIndentsApplicable = true; 4227 break; 4228 } 4229 4230 pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom()); 4231 ASSERT( pColl, 4232 "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." ); 4233 } 4234 } 4235 4236 return bAreListLevelIndentsApplicable; 4237 } 4238 4239 /** Retrieves the list tab stop position, if the paragraph's list level defines 4240 one and this list tab stop has to merged into the tap stops of the paragraph 4241 4242 OD 2008-01-17 #newlistlevelattrs# 4243 4244 @author OD 4245 4246 @param nListTabStopPosition 4247 output parameter - containing the list tab stop position 4248 4249 @return boolean - indicating, if a list tab stop position is provided 4250 */ 4251 bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const 4252 { 4253 bool bListTanStopPositionProvided( false ); 4254 4255 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0; 4256 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) 4257 { 4258 const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); 4259 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && 4260 rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB ) 4261 { 4262 bListTanStopPositionProvided = true; 4263 nListTabStopPosition = rFmt.GetListtabPos(); 4264 4265 if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) ) 4266 { 4267 // tab stop position are treated to be relative to the "before text" 4268 // indent value of the paragraph. Thus, adjust <nListTabStopPos>. 4269 if ( AreListLevelIndentsApplicable() ) 4270 { 4271 nListTabStopPosition -= rFmt.GetIndentAt(); 4272 } 4273 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING)) 4274 { 4275 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace(); 4276 nListTabStopPosition -= aItem.GetTxtLeft(); 4277 } 4278 } 4279 } 4280 } 4281 4282 return bListTanStopPositionProvided; 4283 } 4284 4285 /** Retrieves the character following the list label, if the paragraph's 4286 list level defines one. 4287 4288 OD 2008-01-17 #newlistlevelattrs# 4289 4290 @author OD 4291 4292 @return XubString - the list tab stop position 4293 */ 4294 XubString SwTxtNode::GetLabelFollowedBy() const 4295 { 4296 XubString aLabelFollowedBy; 4297 4298 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0; 4299 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 ) 4300 { 4301 const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ); 4302 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 4303 { 4304 switch ( rFmt.GetLabelFollowedBy() ) 4305 { 4306 case SvxNumberFormat::LISTTAB: 4307 { 4308 const sal_Unicode aTab = '\t'; 4309 aLabelFollowedBy.Insert( aTab, 0 ); 4310 } 4311 break; 4312 case SvxNumberFormat::SPACE: 4313 { 4314 const sal_Unicode aSpace = ' '; 4315 aLabelFollowedBy.Insert( aSpace, 0 ); 4316 } 4317 break; 4318 case SvxNumberFormat::NOTHING: 4319 { 4320 // intentionally left blank. 4321 } 4322 break; 4323 default: 4324 { 4325 ASSERT( false, 4326 "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" ); 4327 } 4328 } 4329 } 4330 } 4331 4332 return aLabelFollowedBy; 4333 } 4334 4335 void SwTxtNode::CalcHiddenCharFlags() const 4336 { 4337 xub_StrLen nStartPos; 4338 xub_StrLen nEndPos; 4339 // Update of the flags is done inside GetBoundsOfHiddenRange() 4340 SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos ); 4341 } 4342 4343 // --> FME 2004-06-08 #i12836# enhanced pdf export 4344 bool SwTxtNode::IsHidden() const 4345 { 4346 if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) ) 4347 return true; 4348 4349 const SwSectionNode* pSectNd = FindSectionNode(); 4350 if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() ) 4351 return true; 4352 4353 return false; 4354 } 4355 // <-- 4356 4357 // --> OD 2008-03-13 #refactorlists# 4358 namespace { 4359 // Helper class for special handling of setting attributes at text node: 4360 // In constructor an instance of the helper class recognize whose attributes 4361 // are set and perform corresponding actions before the intrinsic set of 4362 // attributes has been taken place. 4363 // In the destructor - after the attributes have been set at the text 4364 // node - corresponding actions are performed. 4365 // The following is handled: 4366 // (1) When the list style attribute - RES_PARATR_NUMRULE - is set, 4367 // (A) list style attribute is empty -> the text node is removed from 4368 // its list. 4369 // (B) list style attribute is not empty 4370 // (a) text node has no list style -> add text node to its list after 4371 // the attributes have been set. 4372 // (b) text node has list style -> change of list style is notified 4373 // after the attributes have been set. 4374 // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed, 4375 // the text node is removed from its current list before the attributes 4376 // are set and added to its new list after the attributes have been set. 4377 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set 4378 // and changed after the attributes have been set 4379 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set 4380 // and changed after the attributes have been set 4381 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - 4382 // is set and changed after the attributes have been set 4383 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set 4384 // and changed after the attributes have been set 4385 // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL. 4386 class HandleSetAttrAtTxtNode 4387 { 4388 public: 4389 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4390 const SfxPoolItem& pItem ); 4391 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4392 const SfxItemSet& rItemSet ); 4393 ~HandleSetAttrAtTxtNode(); 4394 4395 private: 4396 SwTxtNode& mrTxtNode; 4397 bool mbAddTxtNodeToList; 4398 bool mbUpdateListLevel; 4399 bool mbUpdateListRestart; 4400 bool mbUpdateListCount; 4401 // --> OD 2008-11-19 #i70748# 4402 bool mbOutlineLevelSet; 4403 // <-- 4404 }; 4405 4406 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4407 const SfxPoolItem& pItem ) 4408 : mrTxtNode( rTxtNode ), 4409 mbAddTxtNodeToList( false ), 4410 mbUpdateListLevel( false ), 4411 mbUpdateListRestart( false ), 4412 mbUpdateListCount( false ), 4413 // --> OD 2008-11-19 #i70748# 4414 mbOutlineLevelSet( false ) 4415 // <-- 4416 { 4417 switch ( pItem.Which() ) 4418 { 4419 // handle RES_PARATR_NUMRULE 4420 case RES_PARATR_NUMRULE: 4421 { 4422 mrTxtNode.RemoveFromList(); 4423 4424 const SwNumRuleItem& pNumRuleItem = 4425 dynamic_cast<const SwNumRuleItem&>(pItem); 4426 if ( pNumRuleItem.GetValue().Len() > 0 ) 4427 { 4428 mbAddTxtNodeToList = true; 4429 // --> OD 2010-05-12 #i105562# 4430 // 4431 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4432 // <-- 4433 } 4434 } 4435 break; 4436 4437 // handle RES_PARATR_LIST_ID 4438 case RES_PARATR_LIST_ID: 4439 { 4440 const SfxStringItem& pListIdItem = 4441 dynamic_cast<const SfxStringItem&>(pItem); 4442 ASSERT( pListIdItem.GetValue().Len() > 0, 4443 "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." ); 4444 const String sListIdOfTxtNode = rTxtNode.GetListId(); 4445 if ( pListIdItem.GetValue() != sListIdOfTxtNode ) 4446 { 4447 mbAddTxtNodeToList = true; 4448 if ( mrTxtNode.IsInList() ) 4449 { 4450 mrTxtNode.RemoveFromList(); 4451 } 4452 } 4453 } 4454 break; 4455 4456 // handle RES_PARATR_LIST_LEVEL 4457 case RES_PARATR_LIST_LEVEL: 4458 { 4459 const SfxInt16Item& aListLevelItem = 4460 dynamic_cast<const SfxInt16Item&>(pItem); 4461 if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() ) 4462 { 4463 mbUpdateListLevel = true; 4464 } 4465 } 4466 break; 4467 4468 // handle RES_PARATR_LIST_ISRESTART 4469 case RES_PARATR_LIST_ISRESTART: 4470 { 4471 const SfxBoolItem& aListIsRestartItem = 4472 dynamic_cast<const SfxBoolItem&>(pItem); 4473 if ( aListIsRestartItem.GetValue() != 4474 (mrTxtNode.IsListRestart() ? sal_True : sal_False) ) 4475 { 4476 mbUpdateListRestart = true; 4477 } 4478 } 4479 break; 4480 4481 // handle RES_PARATR_LIST_RESTARTVALUE 4482 case RES_PARATR_LIST_RESTARTVALUE: 4483 { 4484 const SfxInt16Item& aListRestartValueItem = 4485 dynamic_cast<const SfxInt16Item&>(pItem); 4486 if ( !mrTxtNode.HasAttrListRestartValue() || 4487 aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() ) 4488 { 4489 mbUpdateListRestart = true; 4490 } 4491 } 4492 break; 4493 4494 // handle RES_PARATR_LIST_ISCOUNTED 4495 case RES_PARATR_LIST_ISCOUNTED: 4496 { 4497 const SfxBoolItem& aIsCountedInListItem = 4498 dynamic_cast<const SfxBoolItem&>(pItem); 4499 if ( aIsCountedInListItem.GetValue() != 4500 (mrTxtNode.IsCountedInList() ? sal_True : sal_False) ) 4501 { 4502 mbUpdateListCount = true; 4503 } 4504 } 4505 break; 4506 4507 // --> OD 2008-11-19 #i70748# 4508 // handle RES_PARATR_OUTLINELEVEL 4509 case RES_PARATR_OUTLINELEVEL: 4510 { 4511 const SfxUInt16Item& aOutlineLevelItem = 4512 dynamic_cast<const SfxUInt16Item&>(pItem); 4513 if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() ) 4514 { 4515 mbOutlineLevelSet = true; 4516 } 4517 } 4518 break; 4519 // <-- 4520 } 4521 4522 } 4523 4524 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode, 4525 const SfxItemSet& rItemSet ) 4526 : mrTxtNode( rTxtNode ), 4527 mbAddTxtNodeToList( false ), 4528 mbUpdateListLevel( false ), 4529 mbUpdateListRestart( false ), 4530 mbUpdateListCount( false ), 4531 // --> OD 2008-11-19 #i70748# 4532 mbOutlineLevelSet( false ) 4533 // <-- 4534 { 4535 const SfxPoolItem* pItem = 0; 4536 // handle RES_PARATR_NUMRULE 4537 if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET ) 4538 { 4539 mrTxtNode.RemoveFromList(); 4540 4541 const SwNumRuleItem* pNumRuleItem = 4542 dynamic_cast<const SwNumRuleItem*>(pItem); 4543 if ( pNumRuleItem->GetValue().Len() > 0 ) 4544 { 4545 mbAddTxtNodeToList = true; 4546 // --> OD 2008-11-19 #i70748# 4547 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4548 // <-- 4549 } 4550 } 4551 4552 // handle RES_PARATR_LIST_ID 4553 if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET ) 4554 { 4555 const SfxStringItem* pListIdItem = 4556 dynamic_cast<const SfxStringItem*>(pItem); 4557 const String sListIdOfTxtNode = mrTxtNode.GetListId(); 4558 if ( pListIdItem && 4559 pListIdItem->GetValue() != sListIdOfTxtNode ) 4560 { 4561 mbAddTxtNodeToList = true; 4562 if ( mrTxtNode.IsInList() ) 4563 { 4564 mrTxtNode.RemoveFromList(); 4565 } 4566 } 4567 } 4568 4569 // handle RES_PARATR_LIST_LEVEL 4570 if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET ) 4571 { 4572 const SfxInt16Item* pListLevelItem = 4573 dynamic_cast<const SfxInt16Item*>(pItem); 4574 if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() ) 4575 { 4576 mbUpdateListLevel = true; 4577 } 4578 } 4579 4580 // handle RES_PARATR_LIST_ISRESTART 4581 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET ) 4582 { 4583 const SfxBoolItem* pListIsRestartItem = 4584 dynamic_cast<const SfxBoolItem*>(pItem); 4585 if ( pListIsRestartItem->GetValue() != 4586 (mrTxtNode.IsListRestart() ? sal_True : sal_False) ) 4587 { 4588 mbUpdateListRestart = true; 4589 } 4590 } 4591 4592 // handle RES_PARATR_LIST_RESTARTVALUE 4593 if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET ) 4594 { 4595 const SfxInt16Item* pListRestartValueItem = 4596 dynamic_cast<const SfxInt16Item*>(pItem); 4597 if ( !mrTxtNode.HasAttrListRestartValue() || 4598 pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() ) 4599 { 4600 mbUpdateListRestart = true; 4601 } 4602 } 4603 4604 // handle RES_PARATR_LIST_ISCOUNTED 4605 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET ) 4606 { 4607 const SfxBoolItem* pIsCountedInListItem = 4608 dynamic_cast<const SfxBoolItem*>(pItem); 4609 if ( pIsCountedInListItem->GetValue() != 4610 (mrTxtNode.IsCountedInList() ? sal_True : sal_False) ) 4611 { 4612 mbUpdateListCount = true; 4613 } 4614 } 4615 4616 // --> OD 2008-11-19 #i70748# 4617 // handle RES_PARATR_OUTLINELEVEL 4618 if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET ) 4619 { 4620 const SfxUInt16Item* pOutlineLevelItem = 4621 dynamic_cast<const SfxUInt16Item*>(pItem); 4622 if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() ) 4623 { 4624 mbOutlineLevelSet = true; 4625 } 4626 } 4627 // <-- 4628 } 4629 4630 HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode() 4631 { 4632 if ( mbAddTxtNodeToList ) 4633 { 4634 SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule(); 4635 if ( pNumRuleAtTxtNode ) 4636 { 4637 mrTxtNode.AddToList(); 4638 } 4639 } 4640 else 4641 { 4642 if ( mbUpdateListLevel && mrTxtNode.IsInList() ) 4643 { 4644 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree( 4645 mrTxtNode.GetAttrListLevel() ); 4646 } 4647 4648 if ( mbUpdateListRestart && mrTxtNode.IsInList() ) 4649 { 4650 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4651 pNodeNum->InvalidateMe(); 4652 pNodeNum->NotifyInvalidSiblings(); 4653 } 4654 4655 if ( mbUpdateListCount && mrTxtNode.IsInList() ) 4656 { 4657 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree(); 4658 } 4659 } 4660 4661 // --> OD 2008-11-19 #i70748# 4662 if ( mbOutlineLevelSet ) 4663 { 4664 if ( mrTxtNode.GetAttrOutlineLevel() == 0 ) 4665 { 4666 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4667 } 4668 else 4669 { 4670 const SfxPoolItem* pItem = 0; 4671 if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE, 4672 sal_True, &pItem ) 4673 != SFX_ITEM_SET ) 4674 { 4675 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 4676 } 4677 } 4678 } 4679 // <-- 4680 } 4681 // End of class <HandleSetAttrAtTxtNode> 4682 } 4683 4684 sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem ) 4685 { 4686 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 4687 mbInSetOrResetAttr = true; 4688 4689 HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem ); 4690 4691 sal_Bool bRet = SwCntntNode::SetAttr( pItem ); 4692 4693 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 4694 4695 return bRet; 4696 } 4697 4698 sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet ) 4699 { 4700 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 4701 mbInSetOrResetAttr = true; 4702 4703 HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet ); 4704 4705 sal_Bool bRet = SwCntntNode::SetAttr( rSet ); 4706 4707 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 4708 4709 return bRet; 4710 } 4711 4712 namespace { 4713 // Helper class for special handling of resetting attributes at text node: 4714 // In constructor an instance of the helper class recognize whose attributes 4715 // are reset and perform corresponding actions before the intrinsic reset of 4716 // attributes has been taken place. 4717 // In the destructor - after the attributes have been reset at the text 4718 // node - corresponding actions are performed. 4719 // The following is handled: 4720 // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset, 4721 // the text is removed from its list before the attributes have been reset. 4722 // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset, 4723 // the text is removed from its list before the attributes have been reset. 4724 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset. 4725 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset. 4726 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset. 4727 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset. 4728 // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset. 4729 class HandleResetAttrAtTxtNode 4730 { 4731 public: 4732 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4733 const sal_uInt16 nWhich1, 4734 const sal_uInt16 nWhich2 ); 4735 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4736 const SvUShorts& rWhichArr ); 4737 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode ); 4738 4739 ~HandleResetAttrAtTxtNode(); 4740 4741 private: 4742 SwTxtNode& mrTxtNode; 4743 bool mbListStyleOrIdReset; 4744 bool mbUpdateListLevel; 4745 bool mbUpdateListRestart; 4746 bool mbUpdateListCount; 4747 }; 4748 4749 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4750 const sal_uInt16 nWhich1, 4751 const sal_uInt16 nWhich2 ) 4752 : mrTxtNode( rTxtNode ), 4753 mbListStyleOrIdReset( false ), 4754 mbUpdateListLevel( false ), 4755 mbUpdateListRestart( false ), 4756 mbUpdateListCount( false ) 4757 { 4758 bool bRemoveFromList( false ); 4759 if ( nWhich2 != 0 && nWhich2 > nWhich1 ) 4760 { 4761 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4762 if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 ) 4763 { 4764 bRemoveFromList = mrTxtNode.GetNumRule() != 0; 4765 mbListStyleOrIdReset = true; 4766 } 4767 else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 ) 4768 { 4769 bRemoveFromList = mrTxtNode.GetpSwAttrSet() && 4770 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET; 4771 // --> OD 2008-10-20 #i92898# 4772 mbListStyleOrIdReset = true; 4773 // <-- 4774 } 4775 4776 if ( !bRemoveFromList ) 4777 { 4778 // RES_PARATR_LIST_LEVEL 4779 mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL && 4780 RES_PARATR_LIST_LEVEL <= nWhich2 && 4781 mrTxtNode.HasAttrListLevel() ); 4782 4783 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4784 mbUpdateListRestart = 4785 ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 && 4786 mrTxtNode.IsListRestart() ) || 4787 ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 && 4788 mrTxtNode.HasAttrListRestartValue() ); 4789 4790 // RES_PARATR_LIST_ISCOUNTED 4791 mbUpdateListCount = 4792 ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 && 4793 !mrTxtNode.IsCountedInList() ); 4794 } 4795 4796 // --> OD 2008-11-19 #i70748# 4797 // RES_PARATR_OUTLINELEVEL 4798 if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 ) 4799 { 4800 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4801 } 4802 // <-- 4803 } 4804 else 4805 { 4806 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4807 if ( nWhich1 == RES_PARATR_NUMRULE ) 4808 { 4809 bRemoveFromList = mrTxtNode.GetNumRule() != 0; 4810 mbListStyleOrIdReset = true; 4811 } 4812 else if ( nWhich1 == RES_PARATR_LIST_ID ) 4813 { 4814 bRemoveFromList = mrTxtNode.GetpSwAttrSet() && 4815 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET; 4816 // --> OD 2008-10-20 #i92898# 4817 mbListStyleOrIdReset = true; 4818 // <-- 4819 } 4820 // --> OD 2008-11-19 #i70748# 4821 // RES_PARATR_OUTLINELEVEL 4822 else if ( nWhich1 == RES_PARATR_OUTLINELEVEL ) 4823 { 4824 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4825 } 4826 // <-- 4827 4828 if ( !bRemoveFromList ) 4829 { 4830 // RES_PARATR_LIST_LEVEL 4831 mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL && 4832 mrTxtNode.HasAttrListLevel(); 4833 4834 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4835 mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART && 4836 mrTxtNode.IsListRestart() ) || 4837 ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE && 4838 mrTxtNode.HasAttrListRestartValue() ); 4839 4840 // RES_PARATR_LIST_ISCOUNTED 4841 mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED && 4842 !mrTxtNode.IsCountedInList(); 4843 } 4844 } 4845 4846 if ( bRemoveFromList && mrTxtNode.IsInList() ) 4847 { 4848 mrTxtNode.RemoveFromList(); 4849 } 4850 } 4851 4852 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode, 4853 const SvUShorts& rWhichArr ) 4854 : mrTxtNode( rTxtNode ), 4855 mbListStyleOrIdReset( false ), 4856 mbUpdateListLevel( false ), 4857 mbUpdateListRestart( false ), 4858 mbUpdateListCount( false ) 4859 { 4860 bool bRemoveFromList( false ); 4861 { 4862 const sal_uInt16 nEnd = rWhichArr.Count(); 4863 for ( sal_uInt16 n = 0; n < nEnd; ++n ) 4864 { 4865 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID 4866 if ( rWhichArr[ n ] == RES_PARATR_NUMRULE ) 4867 { 4868 bRemoveFromList = bRemoveFromList || 4869 mrTxtNode.GetNumRule() != 0; 4870 mbListStyleOrIdReset = true; 4871 } 4872 else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID ) 4873 { 4874 bRemoveFromList = bRemoveFromList || 4875 ( mrTxtNode.GetpSwAttrSet() && 4876 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET ); 4877 // --> OD 2008-10-20 #i92898# 4878 mbListStyleOrIdReset = true; 4879 // <-- 4880 } 4881 // --> OD 2008-11-19 #i70748# 4882 // RES_PARATR_OUTLINELEVEL 4883 else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL ) 4884 { 4885 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4886 } 4887 // <-- 4888 4889 if ( !bRemoveFromList ) 4890 { 4891 // RES_PARATR_LIST_LEVEL 4892 mbUpdateListLevel = mbUpdateListLevel || 4893 ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL && 4894 mrTxtNode.HasAttrListLevel() ); 4895 4896 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE 4897 mbUpdateListRestart = mbUpdateListRestart || 4898 ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART && 4899 mrTxtNode.IsListRestart() ) || 4900 ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE && 4901 mrTxtNode.HasAttrListRestartValue() ); 4902 4903 // RES_PARATR_LIST_ISCOUNTED 4904 mbUpdateListCount = mbUpdateListCount || 4905 ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED && 4906 !mrTxtNode.IsCountedInList() ); 4907 } 4908 } 4909 } 4910 4911 if ( bRemoveFromList && mrTxtNode.IsInList() ) 4912 { 4913 mrTxtNode.RemoveFromList(); 4914 } 4915 } 4916 4917 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode ) 4918 : mrTxtNode( rTxtNode ), 4919 mbListStyleOrIdReset( false ), 4920 mbUpdateListLevel( false ), 4921 mbUpdateListRestart( false ), 4922 mbUpdateListCount( false ) 4923 { 4924 mbListStyleOrIdReset = true; 4925 if ( rTxtNode.IsInList() ) 4926 { 4927 rTxtNode.RemoveFromList(); 4928 } 4929 // --> OD 2008-11-19 #i70748# 4930 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr(); 4931 // <-- 4932 } 4933 4934 HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode() 4935 { 4936 if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() ) 4937 { 4938 // check, if in spite of the reset of the list style or the list id 4939 // the paragraph still has to be added to a list. 4940 if ( mrTxtNode.GetNumRule() && 4941 mrTxtNode.GetListId().Len() > 0 ) 4942 { 4943 // --> OD 2009-01-14 #i96062# 4944 // If paragraph has no list level attribute set and list style 4945 // is the outline style, apply outline level as the list level. 4946 if ( !mrTxtNode.HasAttrListLevel() && 4947 mrTxtNode.GetNumRule()->GetName() == 4948 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) && 4949 mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() ) 4950 { 4951 int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel(); 4952 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL ) 4953 { 4954 mrTxtNode.SetAttrListLevel( nNewListLevel ); 4955 } 4956 } 4957 // <-- 4958 mrTxtNode.AddToList(); 4959 } 4960 // --> OD 2008-11-19 #i70748# 4961 // --> OD 2010-05-12 #i105562# 4962 else if ( mrTxtNode.GetpSwAttrSet() && 4963 dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 ) 4964 { 4965 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr(); 4966 } 4967 // <-- 4968 } 4969 4970 if ( mrTxtNode.IsInList() ) 4971 { 4972 if ( mbUpdateListLevel ) 4973 { 4974 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4975 pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() ); 4976 } 4977 4978 if ( mbUpdateListRestart ) 4979 { 4980 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4981 pNodeNum->InvalidateMe(); 4982 pNodeNum->NotifyInvalidSiblings(); 4983 } 4984 4985 if ( mbUpdateListCount ) 4986 { 4987 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum()); 4988 pNodeNum->InvalidateAndNotifyTree(); 4989 } 4990 } 4991 } 4992 // End of class <HandleResetAttrAtTxtNode> 4993 } 4994 4995 sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 ) 4996 { 4997 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 4998 mbInSetOrResetAttr = true; 4999 5000 HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 ); 5001 5002 sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 ); 5003 5004 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5005 5006 return bRet; 5007 } 5008 5009 sal_Bool SwTxtNode::ResetAttr( const SvUShorts& rWhichArr ) 5010 { 5011 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 5012 mbInSetOrResetAttr = true; 5013 5014 HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr ); 5015 5016 sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr ); 5017 5018 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5019 5020 return bRet; 5021 } 5022 5023 sal_uInt16 SwTxtNode::ResetAllAttr() 5024 { 5025 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr ); 5026 mbInSetOrResetAttr = true; 5027 5028 HandleResetAttrAtTxtNode aHandleResetAttr( *this ); 5029 5030 sal_uInt16 nRet = SwCntntNode::ResetAllAttr(); 5031 5032 mbInSetOrResetAttr = bOldIsSetOrResetAttr; 5033 5034 return nRet; 5035 } 5036 // <-- 5037 5038 // sw::Metadatable 5039 ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry() 5040 { 5041 return GetDoc()->GetXmlIdRegistry(); 5042 } 5043 5044 bool SwTxtNode::IsInClipboard() const 5045 { 5046 return GetDoc()->IsClipBoard(); 5047 } 5048 5049 bool SwTxtNode::IsInUndo() const 5050 { 5051 return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes()); 5052 } 5053 5054 bool SwTxtNode::IsInContent() const 5055 { 5056 return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) ); 5057 } 5058 5059 void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint ) 5060 { 5061 const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint); 5062 if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() ) 5063 ChkCondColl(); 5064 } 5065 5066 #include <unoparagraph.hxx> 5067 5068 uno::Reference< rdf::XMetadatable > 5069 SwTxtNode::MakeUnoObject() 5070 { 5071 const uno::Reference<rdf::XMetadatable> xMeta( 5072 SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY); 5073 return xMeta; 5074 } 5075 //Bug 120881:Modify here for Directly Page Numbering 5076 bool SwTxtNode::HasPageNumberField() 5077 { 5078 xub_StrLen nEnd = Len(); 5079 for(xub_StrLen nStart=0;nStart<nEnd;nStart++) 5080 { 5081 const SwTxtFld* pFld = GetTxtFld(nStart); 5082 const SwField* pSwField = pFld 5083 ? pFld->GetFmtFld().GetField() 5084 : NULL; 5085 const SwFieldType* pType = pSwField 5086 ? pSwField->GetTyp() 5087 : NULL; 5088 if ( pType && pType->Which() == RES_PAGENUMBERFLD ) 5089 { 5090 return true; 5091 } 5092 } 5093 return false; 5094 5095 } 5096 //Bug 120881(End) 5097 5098