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