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