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