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