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