Update ooo320-m1
[ooovba.git] / sw / source / core / txtnode / ndtxt.cxx
bloba0740a35b0c495eb1d29b26a373f8bad6c61c1c2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndtxt.cxx,v $
10 * $Revision: 1.86.66.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
34 #include <hints.hxx>
36 #include <svx/fontitem.hxx>
37 #include <svx/brkitem.hxx>
38 #include <svx/escpitem.hxx>
39 #include <svx/lrspitem.hxx>
40 // --> OD 2008-01-17 #newlistlevelattrs#
41 #include <svx/tstpitem.hxx>
42 // <--
43 #include <svtools/urihelper.hxx>
44 #ifndef _SVSTDARR_HXX
45 #define _SVSTDARR_ULONGS
46 #include <svtools/svstdarr.hxx>
47 #endif
48 #include <svtools/ctloptions.hxx>
49 #include <swmodule.hxx>
50 #include <txtfld.hxx>
51 #include <txtinet.hxx>
52 #include <fmtinfmt.hxx>
53 #include <fmtpdsc.hxx>
54 #include <txtatr.hxx>
55 #include <fmtrfmrk.hxx>
56 #include <txttxmrk.hxx>
57 #include <fchrfmt.hxx>
58 #include <txtftn.hxx>
59 #include <fmtflcnt.hxx>
60 #include <fmtfld.hxx>
61 #include <frmatr.hxx>
62 #include <charatr.hxx>
63 #include <ftnidx.hxx>
64 #include <ftninfo.hxx>
65 #include <fmtftn.hxx>
66 #include <fmtmeta.hxx>
67 #include <charfmt.hxx>
68 #include <ndtxt.hxx>
69 #include <doc.hxx>
70 #include <docary.hxx>
71 #include <pam.hxx> // fuer SwPosition
72 #include <fldbas.hxx>
73 #include <errhdl.hxx>
74 #include <paratr.hxx>
75 #include <txtfrm.hxx>
76 #include <ftnfrm.hxx>
77 #include <ftnboss.hxx>
78 #include <rootfrm.hxx>
79 #include <pagedesc.hxx> // fuer SwPageDesc
80 #include <expfld.hxx> // fuer SwTblField
81 #include <section.hxx> // fuer SwSection
82 #include <mvsave.hxx>
83 #include <swcache.hxx>
84 #include <SwGrammarMarkUp.hxx>
85 #include <dcontact.hxx>
86 #include <redline.hxx>
87 #include <doctxm.hxx>
88 #include <IMark.hxx>
89 #include <scriptinfo.hxx>
90 #include <istyleaccess.hxx>
91 #include <SwStyleNameMapper.hxx>
92 #include <numrule.hxx>
94 //--> #outlinelevel added by zhaojianwei
95 #include <svtools/intitem.hxx>
96 //<--end
97 #include <swtable.hxx>
98 #include <docsh.hxx>
99 #include <SwNodeNum.hxx>
100 // --> OD 2008-02-25 #refactorlists#
101 #include <svtools/intitem.hxx>
102 #include <list.hxx>
103 // <--
105 SV_DECL_PTRARR( TmpHints, SwTxtAttr*, 0, 4 )
107 TYPEINIT1( SwTxtNode, SwCntntNode )
109 SV_DECL_PTRARR(SwpHts,SwTxtAttr*,1,1)
111 // Leider ist das SwpHints nicht ganz wasserdicht:
112 // Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge
113 // und Verkettung sicherstellen zu muessen.
114 #ifndef PRODUCT
115 #define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \
116 !pNd->GetDoc()->IsInReading() ) \
117 pNd->GetpSwpHints()->Check(); }
118 #else
119 #define CHECK_SWPHINTS(pNd)
120 #endif
122 SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere,
123 SwTxtFmtColl *pColl,
124 SwAttrSet* pAutoAttr )
126 ASSERT( pColl, "Collectionpointer ist 0." );
128 SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr );
130 SwNodeIndex aIdx( *pNode );
132 // --> OD 2005-11-03 #125329#
133 // call method <UpdateOutlineNode(..)> only for the document nodes array
134 if ( IsDocNodes() )
136 //if ( pColl && NO_NUMBERING != pColl->GetOutlineLevel() ) //#outline level,removed by zhaojianwei
138 // UpdateOutlineNode( *pNode, NO_NUMBERING, pColl->GetOutlineLevel() );
140 // if ( pColl && 0 != pColl->GetAttrOutlineLevel() )//#outline level,added by zhaojianwei
141 // {
142 // UpdateOutlineNode( *pNode, 0, pColl->GetAttrOutlineLevel() );
143 // }//<--end
144 // else
146 UpdateOutlineNode(*pNode);
149 // <--
151 //Wenn es noch kein Layout gibt oder in einer versteckten Section
152 // stehen, brauchen wir uns um das MakeFrms nicht bemuehen.
153 const SwSectionNode* pSectNd;
154 if( !GetDoc()->GetRootFrm() ||
155 ( 0 != (pSectNd = pNode->FindSectionNode()) &&
156 pSectNd->GetSection().IsHiddenFlag() ))
157 return pNode;
159 SwNodeIndex aTmp( rWhere );
160 do {
161 // max. 2 Durchlaeufe:
162 // 1. den Nachfolger nehmen
163 // 2. den Vorgaenger
165 SwNode *pNd;
166 switch( ( pNd = (*this)[aTmp] )->GetNodeType() )
168 case ND_TABLENODE:
169 ((SwTableNode*)pNd)->MakeFrms( aIdx );
170 return pNode;
172 case ND_SECTIONNODE:
173 if( ((SwSectionNode*)pNd)->GetSection().IsHidden() ||
174 ((SwSectionNode*)pNd)->IsCntntHidden() )
176 SwNodeIndex aTmpIdx( *pNode );
177 pNd = FindPrvNxtFrmNode( aTmpIdx, pNode );
178 if( !pNd )
179 return pNode;
180 aTmp = *pNd;
181 break;
183 ((SwSectionNode*)pNd)->MakeFrms( aIdx );
184 return pNode;
186 case ND_TEXTNODE:
187 case ND_GRFNODE:
188 case ND_OLENODE:
189 ((SwCntntNode*)pNd)->MakeFrms( *pNode );
190 return pNode;
192 case ND_ENDNODE:
193 if( pNd->StartOfSectionNode()->IsSectionNode() &&
194 aTmp.GetIndex() < rWhere.GetIndex() )
196 if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag())
198 if( !GoPrevSection( &aTmp, TRUE, FALSE ) ||
199 aTmp.GetNode().FindTableNode() !=
200 pNode->FindTableNode() )
201 return pNode; // schade, das wars
203 else
204 aTmp = *pNd->StartOfSectionNode();
205 break;
207 else if( pNd->StartOfSectionNode()->IsTableNode() &&
208 aTmp.GetIndex() < rWhere.GetIndex() )
210 // wir stehen hinter einem TabellenNode
211 aTmp = *pNd->StartOfSectionNode();
212 break;
214 // kein break !!!
215 default:
216 if( rWhere == aTmp )
217 aTmp -= 2;
218 else
219 return pNode;
220 break;
222 } while( TRUE );
225 // --------------------
226 // SwTxtNode
227 // --------------------
229 SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere,
230 SwTxtFmtColl *pTxtColl,
231 const SfxItemSet* pAutoAttr )
232 : SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ),
233 m_pSwpHints( 0 ),
234 mpNodeNum( 0 ),
235 m_bLastOutlineState( false ),
236 m_bNotifiable( false ),
237 // --> OD 2008-11-19 #i70748#
238 mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
239 // <--
240 // --> OD 2008-05-06 #refactorlists#
241 mbInSetOrResetAttr( false ),
242 mpList( 0 )
243 // <--
245 InitSwParaStatistics( true );
247 // soll eine Harte-Attributierung gesetzt werden?
248 if( pAutoAttr )
249 SetAttr( *pAutoAttr );
251 // --> OD 2008-03-13 #refactorlists# - no longed needed
252 // SyncNumberAndNumRule();
253 if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
255 // --> OD 2009-08-27 #i101516#
256 // apply paragraph style's assigned outline style list level as
257 // list level of the paragraph, if it has none set already.
258 if ( !HasAttrListLevel() &&
259 pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() )
261 SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() );
263 // <--
264 AddToList();
266 // <--
267 GetNodes().UpdateOutlineNode(*this);
269 m_bNotifiable = true;
271 m_bContainsHiddenChars = m_bHiddenCharsHidePara = false;
272 m_bRecalcHiddenCharFlags = true;
275 SwTxtNode::~SwTxtNode()
277 // delete loescht nur die Pointer, nicht die Arrayelemente!
278 if ( m_pSwpHints )
280 // damit Attribute die ihren Inhalt entfernen nicht doppelt
281 // geloescht werden.
282 SwpHints* pTmpHints = m_pSwpHints;
283 m_pSwpHints = 0;
285 for( USHORT j = pTmpHints->Count(); j; )
286 // erst muss das Attribut aus dem Array entfernt werden,
287 // denn sonst wuerde es sich selbst loeschen (Felder) !!!!
288 DestroyAttr( pTmpHints->GetTextHint( --j ) );
290 delete pTmpHints;
293 // --> OD 2008-03-13 #refactorlists#
294 // if ( mpNodeNum )
295 // {
296 // mpNodeNum->RemoveMe();
297 // delete mpNodeNum;
298 // mpNodeNum = 0L;
299 // }
300 RemoveFromList();
301 // <--
303 InitSwParaStatistics( false );
306 SwCntntFrm *SwTxtNode::MakeFrm()
308 SwCntntFrm *pFrm = new SwTxtFrm(this);
309 return pFrm;
312 xub_StrLen SwTxtNode::Len() const
314 return m_Text.Len();
317 /*---------------------------------------------------------------------------
318 * lcl_ChangeFtnRef
319 * After a split node, it's necessary to actualize the ref-pointer of the
320 * ftnfrms.
321 * --------------------------------------------------------------------------*/
323 void lcl_ChangeFtnRef( SwTxtNode &rNode )
325 SwpHints *pSwpHints = rNode.GetpSwpHints();
326 if( pSwpHints && rNode.GetDoc()->GetRootFrm() )
328 SwTxtAttr* pHt;
329 SwCntntFrm* pFrm = NULL;
330 // OD 07.11.2002 #104840# - local variable to remember first footnote
331 // of node <rNode> in order to invalidate position of its first content.
332 // Thus, in its <MakeAll()> it will checked its position relative to its reference.
333 SwFtnFrm* pFirstFtnOfNode = 0;
334 for( USHORT j = pSwpHints->Count(); j; )
336 pHt = pSwpHints->GetTextHint(--j);
337 if (RES_TXTATR_FTN == pHt->Which())
339 if( !pFrm )
341 SwClientIter aNew( rNode );
342 pFrm = (SwCntntFrm*)aNew.First( TYPE(SwCntntFrm) );
343 if( !pFrm )
344 return;
346 SwTxtFtn *pAttr = (SwTxtFtn*)pHt;
347 ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
348 SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
349 SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
350 if ( !pNd )
351 pNd = pFrm->GetAttrSet()->GetDoc()->
352 GetNodes().GoNextSection( &aIdx, TRUE, FALSE );
353 if ( !pNd )
354 continue;
355 SwClientIter aIter( *pNd );
356 SwCntntFrm* pCntnt = (SwCntntFrm*)aIter.First(TYPE(SwCntntFrm));
357 if( pCntnt )
359 ASSERT( pCntnt->FindRootFrm() == pFrm->FindRootFrm(),
360 "lcl_ChangeFtnRef: Layout double?" );
361 SwFtnFrm *pFtn = pCntnt->FindFtnFrm();
362 if( pFtn && pFtn->GetAttr() == pAttr )
364 while( pFtn->GetMaster() )
365 pFtn = pFtn->GetMaster();
366 // OD 07.11.2002 #104840# - remember footnote frame
367 pFirstFtnOfNode = pFtn;
368 while ( pFtn )
370 pFtn->SetRef( pFrm );
371 pFtn = pFtn->GetFollow();
372 ((SwTxtFrm*)pFrm)->SetFtn( TRUE );
375 #ifndef PRODUCT
376 while( 0 != (pCntnt = (SwCntntFrm*)aIter.Next()) )
378 SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm();
379 ASSERT( !pDbgFtn || pDbgFtn->GetRef() == pFrm,
380 "lcl_ChangeFtnRef: Who's that guy?" );
382 #endif
385 } // end of for-loop on <SwpHints>
386 // OD 08.11.2002 #104840# - invalidate
387 if ( pFirstFtnOfNode )
389 SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt();
390 if ( pCntnt )
392 pCntnt->_InvalidatePos();
398 SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos )
400 // lege den Node "vor" mir an
401 const xub_StrLen nSplitPos = rPos.nContent.GetIndex();
402 const xub_StrLen nTxtLen = m_Text.Len();
403 SwTxtNode* const pNode =
404 _MakeNewTxtNode( rPos.nNode, FALSE, nSplitPos==nTxtLen );
406 // the first paragraph gets the XmlId,
407 // _except_ if it is empty and the second is not empty
408 if (nSplitPos != 0) {
409 pNode->RegisterAsCopyOf(*this, true);
410 if (nSplitPos == nTxtLen)
412 this->RemoveMetadataReference();
413 // NB: SwUndoSplitNode will call pNode->JoinNext,
414 // which is sufficient even in this case!
418 // --> OD 2008-03-27 #refactorlists#
419 // // --> OD 2007-07-09 #i77372#
420 // // reset numbering attribute at current node, only if it is numbered.
421 // if ( GetNumRule() != NULL )
422 // {
423 // SetRestart(false);
424 // SetStart(1);
425 // SetCounted(true);
426 // }
427 ResetAttr( RES_PARATR_LIST_ISRESTART );
428 ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
429 ResetAttr( RES_PARATR_LIST_ISCOUNTED );
430 if ( GetNumRule() == 0 )
432 ResetAttr( RES_PARATR_LIST_ID );
433 ResetAttr( RES_PARATR_LIST_LEVEL );
435 // <--
437 if ( GetDepends() && m_Text.Len() && (nTxtLen / 2) < nSplitPos )
439 // JP 25.04.95: Optimierung fuer SplitNode:
440 // Wird am Ende vom Node gesplittet, dann verschiebe die
441 // Frames vom akt. auf den neuen und erzeuge fuer den akt.
442 // neue. Dadurch entfaellt das neu aufbauen vom Layout.
444 LockModify(); // Benachrichtigungen abschalten
446 // werden FlyFrames mit verschoben, so muessen diese nicht ihre
447 // Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt!
448 if ( HasHints() )
450 pNode->GetOrCreateSwpHints().SetInSplitNode(true);
453 //Ersten Teil des Inhalts in den neuen Node uebertragen und
454 //im alten Node loeschen.
455 SwIndex aIdx( this );
456 CutText( pNode, aIdx, nSplitPos );
458 if( GetWrong() )
460 pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
462 SetWrongDirty( true );
464 if( GetGrammarCheck() )
466 pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
468 SetGrammarCheckDirty( true );
470 SetWordCountDirty( true );
472 // SMARTTAGS
473 if( GetSmartTags() )
475 pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
477 SetSmartTagDirty( true );
479 if ( pNode->HasHints() )
481 if ( pNode->m_pSwpHints->CanBeDeleted() )
483 delete pNode->m_pSwpHints;
484 pNode->m_pSwpHints = 0;
486 else
488 pNode->m_pSwpHints->SetInSplitNode(false);
491 // alle zeichengebundenen Rahmen, die im neuen Absatz laden
492 // muessen aus den alten Frame entfernt werden:
493 // JP 01.10.96: alle leeren und nicht zu expandierenden
494 // Attribute loeschen
495 if ( HasHints() )
497 for ( USHORT j = m_pSwpHints->Count(); j; )
499 SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
500 if ( RES_TXTATR_FLYCNT == pHt ->Which() )
502 pHt->GetFlyCnt().GetFrmFmt()->DelFrms();
504 else if ( pHt->DontExpand() )
506 const xub_StrLen* const pEnd = pHt->GetEnd();
507 if (pEnd && *pHt->GetStart() == *pEnd )
509 // delete it!
510 m_pSwpHints->DeleteAtPos( j );
511 DestroyAttr( pHt );
519 SwClientIter aIter( *this );
520 SwClient* pLastFrm = aIter.GoStart();
521 if( pLastFrm )
524 { SwCntntFrm *pFrm = PTR_CAST( SwCntntFrm, pLastFrm );
525 if ( pFrm )
527 pNode->Add( pFrm );
528 if( pFrm->IsTxtFrm() && !pFrm->IsFollow() &&
529 ((SwTxtFrm*)pFrm)->GetOfst() )
530 ((SwTxtFrm*)pFrm)->SetOfst( 0 );
532 pLastFrm = aIter++;
533 } while ( pLastFrm );
536 if ( IsInCache() )
538 SwFrm::GetCache().Delete( this );
539 SetInCache( FALSE );
542 UnlockModify(); // Benachrichtigungen wieder freischalten
544 const SwRootFrm * const pRootFrm = pNode->GetDoc()->GetRootFrm();
545 // If there is an accessible layout we must call modify even
546 // with length zero, because we have to notify about the changed
547 // text node.
548 if ( (nTxtLen != nSplitPos) ||
549 ( pRootFrm && pRootFrm->IsAnyShellAccessible() ) )
552 // dann sage den Frames noch, das am Ende etwas "geloescht" wurde
553 if( 1 == nTxtLen - nSplitPos )
555 SwDelChr aHint( nSplitPos );
556 pNode->SwModify::Modify( 0, &aHint );
558 else
560 SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos );
561 pNode->SwModify::Modify( 0, &aHint );
564 if ( HasHints() )
566 MoveTxtAttr_To_AttrSet();
568 pNode->MakeFrms( *this ); // neue Frames anlegen.
569 lcl_ChangeFtnRef( *this );
571 else
573 SwWrongList *pList = GetWrong();
574 SetWrong( 0, false );
575 SetWrongDirty( true );
577 SwGrammarMarkUp *pList3 = GetGrammarCheck();
578 SetGrammarCheck( 0, false );
579 SetGrammarCheckDirty( true );
581 SetWordCountDirty( true );
583 // SMARTTAGS
584 SwWrongList *pList2 = GetSmartTags();
585 SetSmartTags( 0, false );
586 SetSmartTagDirty( true );
588 SwIndex aIdx( this );
589 CutText( pNode, aIdx, nSplitPos );
591 // JP 01.10.96: alle leeren und nicht zu expandierenden
592 // Attribute loeschen
593 if ( HasHints() )
595 for ( USHORT j = m_pSwpHints->Count(); j; )
597 SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
598 const xub_StrLen* const pEnd = pHt->GetEnd();
599 if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) )
601 // delete it!
602 m_pSwpHints->DeleteAtPos( j );
603 DestroyAttr( pHt );
606 MoveTxtAttr_To_AttrSet();
609 if( pList )
611 pNode->SetWrong( pList->SplitList( nSplitPos ) );
612 SetWrong( pList, false );
615 if( pList3 )
617 pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
618 SetGrammarCheck( pList3, false );
621 // SMARTTAGS
622 if( pList2 )
624 pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
625 SetSmartTags( pList2, false );
628 if ( GetDepends() )
630 MakeFrms( *pNode ); // neue Frames anlegen.
632 lcl_ChangeFtnRef( *pNode );
636 //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
637 //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
638 //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
639 //muesten. #56977# #55001# #56135#
640 const SfxPoolItem *pItem;
641 if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet().
642 GetItemState( RES_PAGEDESC, TRUE, &pItem ) )
644 pNode->Modify( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
647 return pNode;
650 void SwTxtNode::MoveTxtAttr_To_AttrSet()
652 ASSERT( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" );
653 for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
655 SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
657 if( *pHt->GetStart() )
658 break;
660 const xub_StrLen* pHtEndIdx = pHt->GetEnd();
662 if( !pHtEndIdx )
663 continue;
665 if ( *pHtEndIdx < m_Text.Len() || pHt->IsCharFmtAttr() )
666 break;
668 if( !pHt->IsDontMoveAttr() &&
669 SetAttr( pHt->GetAttr() ) )
671 m_pSwpHints->DeleteAtPos(i);
672 DestroyAttr( pHt );
673 --i;
679 SwCntntNode *SwTxtNode::JoinNext()
681 SwNodes& rNds = GetNodes();
682 SwNodeIndex aIdx( *this );
683 if( SwCntntNode::CanJoinNext( &aIdx ) )
685 SwDoc* pDoc = rNds.GetDoc();
686 SvULongs aBkmkArr( 15, 15 );
687 _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
688 SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
689 xub_StrLen nOldLen = m_Text.Len();
691 // METADATA: merge
692 this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len());
694 SwWrongList *pList = GetWrong();
695 if( pList )
697 pList->JoinList( pTxtNode->GetWrong(), nOldLen );
698 SetWrongDirty( true );
699 SetWrong( 0, false );
701 else
703 pList = pTxtNode->GetWrong();
704 if( pList )
706 pList->Move( 0, nOldLen );
707 SetWrongDirty( true );
708 pTxtNode->SetWrong( 0, false );
712 SwGrammarMarkUp *pList3 = GetGrammarCheck();
713 if( pList3 )
715 pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen );
716 SetGrammarCheckDirty( true );
717 SetGrammarCheck( 0, false );
719 else
721 pList3 = pTxtNode->GetGrammarCheck();
722 if( pList3 )
724 pList3->MoveGrammar( 0, nOldLen );
725 SetGrammarCheckDirty( true );
726 pTxtNode->SetGrammarCheck( 0, false );
730 // SMARTTAGS
731 SwWrongList *pList2 = GetSmartTags();
732 if( pList2 )
734 pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen );
735 SetSmartTagDirty( true );
736 SetSmartTags( 0, false );
738 else
740 pList2 = pTxtNode->GetSmartTags();
741 if( pList2 )
743 pList2->Move( 0, nOldLen );
744 SetSmartTagDirty( true );
745 pTxtNode->SetSmartTags( 0, false );
749 { // wg. SwIndex
750 pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() );
752 // verschiebe noch alle Bookmarks/TOXMarks
753 if( aBkmkArr.Count() )
754 _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen );
756 if( pTxtNode->HasAnyIndex() )
758 // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
759 pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, TRUE );
761 rNds.Delete(aIdx);
762 SetWrong( pList, false );
763 SetGrammarCheck( pList3, false );
764 SetSmartTags( pList2, false ); // SMARTTAGS
765 InvalidateNumRule();
767 else {
768 ASSERT( FALSE, "kein TxtNode." );
771 return this;
774 SwCntntNode *SwTxtNode::JoinPrev()
776 SwNodes& rNds = GetNodes();
777 SwNodeIndex aIdx( *this );
778 if( SwCntntNode::CanJoinPrev( &aIdx ) )
780 SwDoc* pDoc = rNds.GetDoc();
781 SvULongs aBkmkArr( 15, 15 );
782 _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
783 SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
784 xub_StrLen nLen = pTxtNode->Len();
786 SwWrongList *pList = pTxtNode->GetWrong();
787 if( pList )
789 pList->JoinList( GetWrong(), Len() );
790 SetWrongDirty( true );
791 pTxtNode->SetWrong( 0, false );
792 SetWrong( NULL );
794 else
796 pList = GetWrong();
797 if( pList )
799 pList->Move( 0, nLen );
800 SetWrongDirty( true );
801 SetWrong( 0, false );
805 SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck();
806 if( pList3 )
808 pList3->JoinGrammarList( GetGrammarCheck(), Len() );
809 SetGrammarCheckDirty( true );
810 pTxtNode->SetGrammarCheck( 0, false );
811 SetGrammarCheck( NULL );
813 else
815 pList3 = GetGrammarCheck();
816 if( pList3 )
818 pList3->MoveGrammar( 0, nLen );
819 SetGrammarCheckDirty( true );
820 SetGrammarCheck( 0, false );
824 // SMARTTAGS
825 SwWrongList *pList2 = pTxtNode->GetSmartTags();
826 if( pList2 )
828 pList2->JoinList( GetSmartTags(), Len() );
829 SetSmartTagDirty( true );
830 pTxtNode->SetSmartTags( 0, false );
831 SetSmartTags( NULL );
833 else
835 pList2 = GetSmartTags();
836 if( pList2 )
838 pList2->Move( 0, nLen );
839 SetSmartTagDirty( true );
840 SetSmartTags( 0, false );
844 { // wg. SwIndex
845 pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen );
847 // verschiebe noch alle Bookmarks/TOXMarks
848 if( aBkmkArr.Count() )
849 _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() );
851 if( pTxtNode->HasAnyIndex() )
853 // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
854 pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, TRUE );
856 rNds.Delete(aIdx);
857 SetWrong( pList, false );
858 SetGrammarCheck( pList3, false );
859 SetSmartTags( pList2, false );
860 InvalidateNumRule();
862 else {
863 ASSERT( FALSE, "kein TxtNode." );
866 return this;
869 // erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen
870 void SwTxtNode::NewAttrSet( SwAttrPool& rPool )
872 ASSERT( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
873 SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange );
875 // put names of parent style and conditional style:
876 const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl();
877 const SwFmtColl* pFmtColl = GetFmtColl();
878 String sVal;
879 SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
880 SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
881 if ( pFmtColl != pAnyFmtColl )
882 SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
883 SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
884 aNewAttrSet.Put( aAnyFmtColl );
885 aNewAttrSet.Put( aFmtColl );
887 aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() );
888 mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA );
892 // override SwIndexReg::Update => text hints do not need SwIndex for start/end!
893 void SwTxtNode::Update( SwIndex const & rPos, const xub_StrLen nChangeLen,
894 const bool bNegative, const bool bDelete )
896 SetAutoCompleteWordDirty( TRUE );
898 ::std::auto_ptr<TmpHints> pCollector;
899 const xub_StrLen nChangePos = rPos.GetIndex();
901 if ( HasHints() )
903 if ( bNegative )
905 const xub_StrLen nChangeEnd = nChangePos + nChangeLen;
906 for ( USHORT n = 0; n < m_pSwpHints->Count(); ++n )
908 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
909 xub_StrLen * const pStart = pHint->GetStart();
910 if ( *pStart > nChangePos )
912 if ( *pStart > nChangeEnd )
914 *pStart = *pStart - nChangeLen;
916 else
918 *pStart = nChangePos;
922 xub_StrLen * const pEnd = pHint->GetEnd();
923 if (pEnd)
925 if ( *pEnd > nChangePos )
927 if( *pEnd > nChangeEnd )
929 *pEnd = *pEnd - nChangeLen;
931 else
933 *pEnd = nChangePos;
939 m_pSwpHints->MergePortions( *this );
941 else
943 bool bNoExp = false;
944 bool bResort = false;
945 const USHORT coArrSz = static_cast<USHORT>(RES_TXTATR_WITHEND_END) -
946 static_cast<USHORT>(RES_CHRATR_BEGIN) +
947 static_cast<USHORT>(RES_UNKNOWNATR_END) -
948 static_cast<USHORT>(RES_UNKNOWNATR_BEGIN);
950 BOOL aDontExp[ coArrSz ];
951 memset( &aDontExp, 0, coArrSz * sizeof(BOOL) );
953 for ( USHORT n = 0; n < m_pSwpHints->Count(); ++n )
955 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
956 xub_StrLen * const pStart = pHint->GetStart();
957 xub_StrLen * const pEnd = pHint->GetEnd();
958 if ( *pStart >= nChangePos )
960 *pStart = *pStart + nChangeLen;
961 if ( pEnd )
963 *pEnd = *pEnd + nChangeLen;
966 else if ( pEnd && (*pEnd >= nChangePos) )
968 if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
970 *pEnd = *pEnd + nChangeLen;
972 else // *pEnd == nChangePos
974 USHORT nWhPos;
975 const USHORT nWhich = pHint->Which();
977 ASSERT(!isCHRATR(nWhich), "Update: char attr hint?");
978 if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))
980 nWhPos = static_cast<USHORT>(nWhich -
981 RES_CHRATR_BEGIN);
983 else if (isUNKNOWNATR(nWhich))
985 nWhPos = static_cast<USHORT>(
986 nWhich -
987 static_cast<USHORT>(RES_UNKNOWNATR_BEGIN) +
988 static_cast<USHORT>(RES_TXTATR_WITHEND_END) -
989 static_cast<USHORT>(RES_CHRATR_BEGIN) );
991 else
992 continue;
994 if( aDontExp[ nWhPos ] )
995 continue;
997 if ( pHint->DontExpand() )
999 pHint->SetDontExpand( false );
1000 bResort = true;
1001 if ( pHint->IsCharFmtAttr() )
1003 bNoExp = true;
1004 aDontExp[ static_cast<USHORT>(RES_TXTATR_CHARFMT) - static_cast<USHORT>(RES_CHRATR_BEGIN) ]
1005 = TRUE;
1006 aDontExp[ static_cast<USHORT>(RES_TXTATR_INETFMT) - static_cast<USHORT>(RES_CHRATR_BEGIN) ]
1007 = TRUE;
1009 else
1010 aDontExp[ nWhPos ] = TRUE;
1012 else if( bNoExp )
1014 if ( !pCollector.get() )
1016 pCollector.reset( new TmpHints );
1018 USHORT nCollCnt = pCollector->Count();
1019 for( USHORT i = 0; i < nCollCnt; ++i )
1021 SwTxtAttr *pTmp = (*pCollector)[ i ];
1022 if( nWhich == pTmp->Which() )
1024 pCollector->Remove( i );
1025 SwTxtAttr::Destroy( pTmp,
1026 GetDoc()->GetAttrPool() );
1027 break;
1030 SwTxtAttr * const pTmp = MakeTxtAttr( *GetDoc(),
1031 pHint->GetAttr(),
1032 nChangePos, nChangePos + nChangeLen);
1033 pCollector->C40_INSERT( SwTxtAttr, pTmp, pCollector->Count() );
1035 else
1037 *pEnd = *pEnd + nChangeLen;
1042 if ( bResort )
1044 m_pSwpHints->Resort();
1049 SwIndexReg aTmpIdxReg;
1050 if ( !bNegative && !bDelete )
1052 const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
1053 for ( USHORT i = 0; i < rTbl.Count(); ++i )
1055 SwRedline *const pRedl = rTbl[ i ];
1056 if ( pRedl->HasMark() )
1058 SwPosition* const pEnd = pRedl->End();
1059 if ( this == &pEnd->nNode.GetNode() &&
1060 *pRedl->GetPoint() != *pRedl->GetMark() )
1062 SwIndex & rIdx = pEnd->nContent;
1063 if (nChangePos == rIdx.GetIndex())
1065 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1069 else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
1071 SwIndex & rIdx = pRedl->GetPoint()->nContent;
1072 if (nChangePos == rIdx.GetIndex())
1074 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1075 // mst: FIXME: why does this adjust the unused position???
1076 SwIndex * pIdx;
1077 if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
1079 pRedl->GetBound( false ) = pRedl->GetBound( true );
1080 pIdx = &pRedl->GetBound( false ).nContent;
1082 else
1084 pRedl->GetBound( true ) = pRedl->GetBound( false );
1085 pIdx = &pRedl->GetBound( true ).nContent;
1087 pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
1092 const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
1093 for(IDocumentMarkAccess::const_iterator_t ppMark =
1094 pMarkAccess->getMarksBegin();
1095 ppMark != pMarkAccess->getMarksEnd();
1096 ppMark++)
1098 // Bookmarks must never grow to either side, when
1099 // editing (directly) to the left or right (#i29942#)!
1100 // And a bookmark with same start and end must remain
1101 // to the left of the inserted text (used in XML import).
1102 const ::sw::mark::IMark* const pMark = ppMark->get();
1103 const SwPosition* pEnd = &pMark->GetMarkEnd();
1104 SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent);
1105 if( this == &pEnd->nNode.GetNode() &&
1106 rPos.GetIndex() == rIdx.GetIndex() )
1108 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1113 // base class
1114 SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );
1116 if ( pCollector.get() )
1118 const USHORT nCount = pCollector->Count();
1119 for ( USHORT i = 0; i < nCount; ++i )
1121 m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
1125 aTmpIdxReg.MoveTo( *this );
1128 void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
1129 const SwTxtFmtColl *pNewColl)
1131 SwDoc* pDoc = GetDoc();
1132 ASSERT( pDoc, "Kein Doc?" );
1133 // erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
1134 // falls sich die Level geaendert haben !
1135 //const BYTE nOldLevel = pOldColl ? pOldColl->GetOutlineLevel():NO_NUMBERING;//#outline level,removed by zhaojianwei
1136 //const BYTE nNewLevel = pNewColl ? pNewColl->GetOutlineLevel():NO_NUMBERING;//<-end,zhaojianwei
1137 const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
1138 pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1139 const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
1140 pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1142 // if ( NO_NUMBERING != nNewLevel ) //#outline level,zhaojianwei
1143 if ( MAXLEVEL != nNewLevel ) //<-end,zhaojianwei
1145 SetAttrListLevel(nNewLevel);
1149 if (pDoc)
1150 pDoc->GetNodes().UpdateOutlineNode(*this);
1154 SwNodes& rNds = GetNodes();
1155 // Update beim Level 0 noch die Fussnoten !!
1156 if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() &&
1157 FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
1158 rNds.IsDocNodes() )
1160 SwNodeIndex aTmpIndex( rNds, GetIndex());
1162 pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
1165 //FEATURE::CONDCOLL
1166 if( /*pOldColl != pNewColl && pNewColl && */
1167 RES_CONDTXTFMTCOLL == pNewColl->Which() )
1169 // Erfrage die akt. Condition des TextNodes:
1170 ChkCondColl();
1172 //FEATURE::CONDCOLL
1175 // Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
1176 // bekommt diese das DontExpand-Flag verpasst
1178 BOOL SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
1179 BOOL bFmtToTxtAttributes )
1181 const xub_StrLen nIdx = rIdx.GetIndex();
1182 if ( bFmtToTxtAttributes && nIdx == m_Text.Len() )
1184 FmtToTxtAttr( this );
1187 BOOL bRet = FALSE;
1188 if ( HasHints() )
1190 const USHORT nEndCnt = m_pSwpHints->GetEndCount();
1191 USHORT nPos = nEndCnt;
1192 while( nPos )
1194 SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
1195 xub_StrLen *pEnd = pTmp->GetEnd();
1196 if( !pEnd || *pEnd > nIdx )
1197 continue;
1198 if( nIdx != *pEnd )
1199 nPos = 0;
1200 else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
1201 && *pEnd > *pTmp->GetStart())
1203 bRet = TRUE;
1204 m_pSwpHints->NoteInHistory( pTmp );
1205 pTmp->SetDontExpand( bFlag );
1209 return bRet;
1213 // gebe das vorgegebene Attribut, welches an der TextPosition (rIdx)
1214 // gesetzt ist, zurueck. Gibt es keines, returne 0-Pointer.
1215 // (gesetzt heisst, je nach bExpand ?
1216 // Start < rIdx <= End
1217 // : Start <= rIdx < End )
1219 SwTxtAttr* SwTxtNode::GetTxtAttr( const SwIndex& rIdx, USHORT nWhichHt,
1220 BOOL bExpand ) const
1222 const SwTxtAttr* pRet = 0;
1223 const SwTxtAttr* pHt = 0;
1224 const xub_StrLen *pEndIdx = 0;
1225 const xub_StrLen nIdx = rIdx.GetIndex();
1226 const USHORT nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
1228 for( USHORT i = 0; i < nSize; ++i )
1230 // ist der Attribut-Anfang schon groesser als der Idx ?
1231 pHt = (*m_pSwpHints)[i];
1232 if ( nIdx < *(pHt->GetStart()) )
1233 break; // beenden, kein gueltiges Attribut
1235 // ist es das gewuenschte Attribut ?
1236 if( pHt->Which() != nWhichHt )
1237 continue; // nein, weiter
1239 pEndIdx = pHt->GetEnd();
1240 // liegt innerhalb des Bereiches ??
1241 if( !pEndIdx )
1243 if( *pHt->GetStart() == nIdx )
1245 pRet = pHt;
1246 break;
1249 else if( *pHt->GetStart() <= nIdx && nIdx <= *pEndIdx )
1251 // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
1252 // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
1253 if( bExpand )
1255 if( *pHt->GetStart() < nIdx )
1256 pRet = pHt;
1258 else
1260 if( nIdx < *pEndIdx )
1261 pRet = pHt; // den am dichtesten liegenden
1265 return (SwTxtAttr*)pRet; // kein gueltiges Attribut gefunden !!
1268 /*************************************************************************
1269 * CopyHint()
1270 *************************************************************************/
1272 SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
1274 if( rName.Len() )
1276 SwCharFmt* pFmt;
1277 USHORT nArrLen = pCharFmts->Count();
1278 for( USHORT i = 1; i < nArrLen; i++ )
1280 pFmt = (*pCharFmts)[ i ];
1281 if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
1282 return pFmt;
1285 return NULL;
1288 void lcl_CopyHint( const USHORT nWhich, const SwTxtAttr * const pHt,
1289 SwTxtAttr *const pNewHt, SwDoc *const pOtherDoc, SwTxtNode *const pDest )
1291 ASSERT( nWhich == pHt->Which(), "Falsche Hint-Id" );
1292 switch( nWhich )
1294 // Wenn wir es mit einem Fussnoten-Attribut zu tun haben,
1295 // muessen wir natuerlich auch den Fussnotenbereich kopieren.
1296 case RES_TXTATR_FTN :
1297 static_cast<const SwTxtFtn*>(pHt)->CopyFtn(
1298 static_cast<SwTxtFtn*>(pNewHt));
1299 break;
1301 // Beim Kopieren von Feldern in andere Dokumente
1302 // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.
1304 // TabellenFormel muessen relativ kopiert werden.
1305 case RES_TXTATR_FIELD :
1307 const SwFmtFld& rFld = pHt->GetFld();
1308 if( pOtherDoc )
1310 static_cast<const SwTxtFld*>(pHt)->CopyFld(
1311 static_cast<SwTxtFld*>(pNewHt) );
1314 // Tabellenformel ??
1315 if( RES_TABLEFLD == rFld.GetFld()->GetTyp()->Which()
1316 && static_cast<const SwTblField*>(rFld.GetFld())->IsIntrnlName())
1318 // wandel die interne in eine externe Formel um
1319 const SwTableNode* const pDstTblNd =
1320 static_cast<const SwTxtFld*>(pHt)->
1321 GetTxtNode().FindTableNode();
1322 if( pDstTblNd )
1324 SwTblField* const pTblFld = const_cast<SwTblField*>(
1325 static_cast<const SwTblField*>(
1326 pNewHt->GetFld().GetFld()));
1327 pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
1331 break;
1333 case RES_TXTATR_TOXMARK :
1334 if( pOtherDoc && pDest && pDest->GetpSwpHints()
1335 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1337 // Beim Kopieren von TOXMarks(Client) in andere Dokumente
1338 // muss der Verzeichnis (Modify) ausgetauscht werden
1339 static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
1341 break;
1343 case RES_TXTATR_CHARFMT :
1344 // Wenn wir es mit einer Zeichenvorlage zu tun haben,
1345 // muessen wir natuerlich auch die Formate kopieren.
1346 if( pDest && pDest->GetpSwpHints()
1347 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1349 SwCharFmt* pFmt =
1350 static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());
1352 if( pFmt && pOtherDoc )
1354 pFmt = pOtherDoc->CopyCharFmt( *pFmt );
1356 const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
1357 pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
1359 break;
1360 case RES_TXTATR_INETFMT :
1362 // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
1363 // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
1364 if( pOtherDoc && pDest && pDest->GetpSwpHints()
1365 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1367 const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
1368 ->GetTxtNode().GetDoc();
1369 if ( pDoc )
1371 const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
1372 const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
1373 SwCharFmt* pFmt;
1374 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
1375 if( pFmt )
1376 pOtherDoc->CopyCharFmt( *pFmt );
1377 pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
1378 if( pFmt )
1379 pOtherDoc->CopyCharFmt( *pFmt );
1382 //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
1383 // gesetzt sein, damit die Vorlagen erzeugt
1384 // werden koenne
1385 SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
1386 if ( !pINetHt->GetpTxtNode() )
1388 pINetHt->ChgTxtNode( pDest );
1391 //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
1392 pINetHt->GetCharFmt();
1393 break;
1395 case RES_TXTATR_META:
1396 case RES_TXTATR_METAFIELD:
1397 ASSERT(pNewHt, "copying META should not fail! cannot call DoCopy");
1398 ASSERT(pDest && (CH_TXTATR_INWORD ==
1399 pDest->GetTxt().GetChar(*pNewHt->GetStart())),
1400 "missing CH_TXTATR?");
1401 if (pNewHt)
1403 SwFmtMeta & rMeta(static_cast<SwFmtMeta&>(pNewHt->GetAttr()));
1404 rMeta.DoCopy( const_cast<SwFmtMeta&>(pHt->GetMeta()) );
1406 break;
1410 /*************************************************************************
1411 |* SwTxtNode::CopyAttr()
1412 |* Beschreibung kopiert Attribute an der Position nStart in pDest.
1413 |* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx
1414 |* kopiert! CopyAttr wird vornehmlich dann gerufen,
1415 |* wenn Attribute fuer einen Node mit leerem String
1416 |* gesetzt werden sollen.
1417 *************************************************************************/
1419 void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
1420 const xub_StrLen nOldPos )
1422 if ( HasHints() ) // keine Attribute, keine Kekse
1424 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
1425 pDest->GetDoc() : 0;
1427 for ( USHORT i = 0; i < m_pSwpHints->Count(); i++ )
1429 SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
1430 xub_StrLen const nAttrStartIdx = *pHt->GetStart();
1431 if ( nTxtStartIdx < nAttrStartIdx )
1432 break; // ueber das Textende, da nLen == 0
1434 const xub_StrLen *const pEndIdx = pHt->GetEnd();
1435 if ( pEndIdx && !pHt->HasDummyChar() )
1437 if( ( *pEndIdx > nTxtStartIdx ||
1438 ( *pEndIdx == nTxtStartIdx &&
1439 nAttrStartIdx == nTxtStartIdx ) ) )
1441 USHORT const nWhich = pHt->Which();
1442 if ( RES_TXTATR_REFMARK != nWhich )
1444 // attribute in the area => copy
1445 SwTxtAttr *const pNewHt = pDest->InsertItem(
1446 pHt->GetAttr(), nOldPos, nOldPos );
1447 if ( pNewHt )
1449 lcl_CopyHint( nWhich, pHt, pNewHt,
1450 pOtherDoc, pDest );
1453 else if( !pOtherDoc ? GetDoc()->IsCopyIsMove()
1454 : 0 == pOtherDoc->GetRefMark(
1455 pHt->GetRefMark().GetRefName() ) )
1457 pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos );
1464 if( this != pDest )
1466 // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
1467 SwUpdateAttr aHint( nOldPos, nOldPos, 0 );
1468 pDest->Modify( 0, &aHint );
1472 /*************************************************************************
1473 |* SwTxtNode::Copy()
1474 |* Beschreibung kopiert Zeichen und Attibute in pDest,
1475 |* wird angehaengt
1476 *************************************************************************/
1478 // --> OD 2008-11-18 #i96213#
1479 // introduction of new optional parameter to control, if all attributes have to be copied.
1480 void SwTxtNode::CopyText( SwTxtNode *const pDest,
1481 const SwIndex &rStart,
1482 const xub_StrLen nLen,
1483 const bool bForceCopyOfAllAttrs )
1485 SwIndex aIdx( pDest, pDest->m_Text.Len() );
1486 CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
1488 // <--
1490 // --> OD 2008-11-18 #i96213#
1491 // introduction of new optional parameter to control, if all attributes have to be copied.
1492 void SwTxtNode::CopyText( SwTxtNode *const pDest,
1493 const SwIndex &rDestStart,
1494 const SwIndex &rStart,
1495 xub_StrLen nLen,
1496 const bool bForceCopyOfAllAttrs )
1497 // <--
1499 xub_StrLen nTxtStartIdx = rStart.GetIndex();
1500 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
1502 if( !nLen )
1504 // wurde keine Laenge angegeben, dann Kopiere die Attribute
1505 // an der Position rStart.
1506 CopyAttr( pDest, nTxtStartIdx, nDestStart );
1508 // harte Absatz umspannende Attribute kopieren
1509 if( HasSwAttrSet() )
1511 // alle, oder nur die CharAttribute ?
1512 // --> OD 2008-11-18 #i96213#
1513 if ( !bForceCopyOfAllAttrs &&
1514 ( nDestStart ||
1515 pDest->HasSwAttrSet() ||
1516 nLen != pDest->GetTxt().Len() ) )
1517 // <--
1519 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1520 RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1521 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1522 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1523 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1524 0 );
1525 aCharSet.Put( *GetpSwAttrSet() );
1526 if( aCharSet.Count() )
1528 pDest->SetAttr( aCharSet, nDestStart, nDestStart );
1531 else
1533 GetpSwAttrSet()->CopyToModify( *pDest );
1536 return;
1539 // 1. Text kopieren
1540 const xub_StrLen oldLen = pDest->m_Text.Len();
1541 //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
1542 // ueber die InsertMethode den Text einfuegen und nicht
1543 // selbst direkt
1544 pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart,
1545 IDocumentContentOperations::INS_EMPTYEXPAND );
1547 // um reale Groesse Updaten !
1548 nLen = pDest->m_Text.Len() - oldLen;
1549 if ( !nLen ) // string not longer?
1550 return;
1552 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
1553 pDest->GetDoc() : 0;
1555 // harte Absatz umspannende Attribute kopieren
1556 if( HasSwAttrSet() )
1558 // alle, oder nur die CharAttribute ?
1559 // --> OD 2008-11-18 #i96213#
1560 if ( !bForceCopyOfAllAttrs &&
1561 ( nDestStart ||
1562 pDest->HasSwAttrSet() ||
1563 nLen != pDest->GetTxt().Len() ) )
1564 // <--
1566 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1567 RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1568 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1569 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1570 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1571 0 );
1572 aCharSet.Put( *GetpSwAttrSet() );
1573 if( aCharSet.Count() )
1575 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
1578 else
1580 GetpSwAttrSet()->CopyToModify( *pDest );
1584 const bool bUndoNodes = !pOtherDoc && GetDoc()->GetUndoNds() == &GetNodes();
1586 // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
1587 // Start-Index und alle Attribute vorher aktualisiert werden.
1588 nTxtStartIdx = rStart.GetIndex();
1589 const xub_StrLen nEnd = nTxtStartIdx + nLen;
1591 // 2. Attribute kopieren
1592 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1593 // des Attributs hinter dem zu kopierenden Bereich liegt
1594 const USHORT nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
1596 // wird in sich selbst kopiert, dann kann beim Einfuegen ein
1597 // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
1598 // dann erst ins eigene uebertragen.
1599 SwpHts aArr( 5 );
1601 // Del-Array fuer alle RefMarks ohne Ausdehnung
1602 SwpHts aRefMrkArr;
1604 //Achtung: kann ungueltig sein!!
1605 for (USHORT n = 0; ( n < nSize ); ++n)
1607 const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
1608 if (!( nAttrStartIdx < nEnd))
1609 break;
1611 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
1612 const xub_StrLen * const pEndIdx = pHt->GetEnd();
1613 const USHORT nWhich = pHt->Which();
1615 // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
1616 // keinen Bereich umspannt, so steht im Text ein 255
1617 // dieses muss entfernt werden. Trick: erst kopieren,
1618 // erkennen und sammeln, nach dem kopieren Loeschen.
1619 // Nimmt sein Zeichen mit ins Grab !!
1620 // JP 14.08.95: Duerfen RefMarks gemovt werden?
1621 int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes ||
1622 (!pOtherDoc ? GetDoc()->IsCopyIsMove()
1623 : 0 == pOtherDoc->GetRefMark(
1624 pHt->GetRefMark().GetRefName() )));
1626 if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark )
1628 continue;
1631 xub_StrLen nAttrStt;
1632 xub_StrLen nAttrEnd;
1634 if( nAttrStartIdx < nTxtStartIdx )
1636 // start is before selection
1637 // copy hints with end and CH_TXTATR only if dummy char is copied
1638 if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
1640 // attribute with extent and the end is in the selection
1641 nAttrStt = nDestStart;
1642 nAttrEnd = (*pEndIdx > nEnd)
1643 ? rDestStart.GetIndex()
1644 : nDestStart + (*pEndIdx) - nTxtStartIdx;
1646 else
1648 continue;
1651 else
1653 // start is in the selection
1654 nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
1655 if( pEndIdx )
1657 nAttrEnd = *pEndIdx > nEnd
1658 ? rDestStart.GetIndex()
1659 : nDestStart + ( *pEndIdx - nTxtStartIdx );
1661 else
1663 nAttrEnd = nAttrStt;
1667 SwTxtAttr * pNewHt = 0;
1669 if( pDest == this )
1671 // die Daten kopieren
1672 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
1673 nAttrStt, nAttrEnd );
1675 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1676 //JP 23.04.95: erstmal so gesondert hier behandeln. Am Besten ist es
1677 // aber im CopyFtn wenn die pDestFtn keinen StartNode hat,
1678 // sich diesen dann anlegt.
1679 // Aber so kurz vor der BETA besser nicht anfassen.
1680 if( RES_TXTATR_FTN == nWhich )
1682 SwTxtFtn* pFtn = (SwTxtFtn*)pNewHt;
1683 pFtn->ChgTxtNode( this );
1684 pFtn->MakeNewTextSection( GetNodes() );
1685 lcl_CopyHint( nWhich, pHt, pFtn, 0, 0 );
1686 pFtn->ChgTxtNode( 0 );
1688 else
1689 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1691 lcl_CopyHint( nWhich, pHt, pNewHt, 0, pDest );
1693 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
1695 else
1697 pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt,
1698 nAttrEnd, nsSetAttrMode::SETATTR_NOTXTATRCHR );
1699 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
1702 if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
1704 aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() );
1708 // nur falls im Array Attribute stehen (kann nur beim Kopieren
1709 // sich selbst passieren!!)
1710 for ( USHORT i = 0; i < aArr.Count(); ++i )
1712 InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
1715 if( pDest->GetpSwpHints() )
1717 for ( USHORT i = 0; i < aRefMrkArr.Count(); ++i )
1719 SwTxtAttr * const pNewHt = aRefMrkArr[i];
1720 if( pNewHt->GetEnd() )
1722 pDest->GetpSwpHints()->Delete( pNewHt );
1723 pDest->DestroyAttr( pNewHt );
1725 else
1727 const SwIndex aIdx( pDest, *pNewHt->GetStart() );
1728 pDest->EraseText( aIdx, 1 );
1733 CHECK_SWPHINTS(this);
1737 void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
1738 const IDocumentContentOperations::InsertFlags nMode )
1740 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
1741 ASSERT( (ULONG)m_Text.Len() + (ULONG)rStr.Len() <= STRING_LEN,
1742 "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );
1744 xub_StrLen aPos = rIdx.GetIndex();
1745 xub_StrLen nLen = m_Text.Len() - aPos;
1746 m_Text.Insert( rStr, aPos );
1747 nLen = m_Text.Len() - aPos - nLen;
1749 if ( !nLen ) return;
1751 BOOL bOldExpFlg = IsIgnoreDontExpand();
1752 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1754 SetIgnoreDontExpand( TRUE );
1757 Update( rIdx, nLen ); // text content changed!
1759 if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1761 SetIgnoreDontExpand( bOldExpFlg );
1764 // analog zu Insert(char) in txtedt.cxx:
1765 // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
1766 // 2) bei bHintExp == FALSE mitgezogene Feldattribute zuruecksetzen
1768 if ( HasHints() )
1770 for ( USHORT i = 0; i < m_pSwpHints->Count() &&
1771 rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
1773 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
1774 xub_StrLen * const pEndIdx = pHt->GetEnd();
1775 if( !pEndIdx )
1776 continue;
1778 if( rIdx == *pEndIdx )
1780 if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
1781 (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1782 && pHt->DontExpand()) )
1784 // bei leeren Attributen auch Start veraendern
1785 if( rIdx == *pHt->GetStart() )
1786 *pHt->GetStart() = *pHt->GetStart() - nLen;
1787 *pEndIdx = *pEndIdx - nLen;
1788 m_pSwpHints->DeleteAtPos(i);
1789 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1791 // empty hints at insert position?
1792 else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
1793 && (*pEndIdx == *pHt->GetStart()) )
1795 *pHt->GetStart() = *pHt->GetStart() - nLen;
1796 const USHORT nAktLen = m_pSwpHints->Count();
1797 m_pSwpHints->DeleteAtPos(i);
1798 InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
1799 if ( nAktLen > m_pSwpHints->Count() && i )
1801 --i;
1803 continue;
1805 else
1807 continue;
1810 if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
1811 rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
1812 !pHt->IsDontExpandStartAttr() )
1814 // Kein Feld, am Absatzanfang, HintExpand
1815 m_pSwpHints->DeleteAtPos(i);
1816 *pHt->GetStart() = *pHt->GetStart() - nLen;
1817 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1820 TryDeleteSwpHints();
1823 if ( GetDepends() )
1825 SwInsTxt aHint( aPos, nLen );
1826 SwModify::Modify( 0, &aHint );
1829 // By inserting a character, the hidden flags
1830 // at the TxtNode can become invalid:
1831 SetCalcHiddenCharFlags();
1833 CHECK_SWPHINTS(this);
1836 /*************************************************************************
1838 |* SwTxtNode::Cut()
1840 |* Beschreibung text.doc
1841 |* Ersterstellung VB 20.03.91
1842 |* Letzte Aenderung JP 11.08.94
1844 *************************************************************************/
1846 void SwTxtNode::CutText( SwTxtNode * const pDest,
1847 const SwIndex & rStart, const xub_StrLen nLen )
1849 if(pDest)
1851 SwIndex aDestStt( pDest, pDest->GetTxt().Len() );
1852 CutImpl( pDest, aDestStt, rStart, nLen, false );
1854 else
1856 ASSERT(false,
1857 "mst: entering dead and bitrotted code; fasten your seatbelts!");
1858 EraseText( rStart, nLen );
1863 void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
1864 const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate )
1866 if(!pDest)
1868 ASSERT(false,
1869 "mst: entering dead and bitrotted code; fasten your seatbelts!");
1870 EraseText( rStart, nLen );
1871 return;
1874 // nicht im Dokument verschieben ?
1875 if( GetDoc() != pDest->GetDoc() )
1877 ASSERT(false,
1878 "mst: entering dead and bitrotted code; fasten your seatbelts!");
1879 CopyText( pDest, rDestStart, rStart, nLen);
1880 EraseText(rStart, nLen);
1881 return;
1884 if( !nLen )
1886 // wurde keine Laenge angegeben, dann Kopiere die Attribute
1887 // an der Position rStart.
1888 CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
1889 return;
1892 xub_StrLen nTxtStartIdx = rStart.GetIndex();
1893 xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
1894 const xub_StrLen nInitSize = pDest->m_Text.Len();
1896 // wird in sich selbst verschoben, muss es gesondert behandelt werden !!
1897 if( pDest == this )
1899 ASSERT(false,
1900 "mst: entering dead and bitrotted code; fasten your seatbelts!");
1901 m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
1902 m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen );
1904 const xub_StrLen nEnd = rStart.GetIndex() + nLen;
1906 // dann suche mal alle Attribute zusammen, die im verschobenen
1907 // Bereich liegen. Diese werden in das extra Array verschoben,
1908 // damit sich die Indizies beim Updaten nicht veraendern !!!
1909 SwpHts aArr( 5 );
1911 // 2. Attribute verschieben
1912 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1913 // des Attributs hinter dem zu verschiebenden Bereich liegt
1914 USHORT nAttrCnt = 0;
1915 while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
1917 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
1918 const xub_StrLen nAttrStartIdx = *pHt->GetStart();
1919 if (!( nAttrStartIdx < nEnd ))
1920 break;
1921 const xub_StrLen * const pEndIdx = pHt->GetEnd();
1922 const USHORT nWhich = pHt->Which();
1923 SwTxtAttr *pNewHt = 0;
1925 if(nAttrStartIdx < nTxtStartIdx)
1927 // Anfang liegt vor dem Bereich
1928 if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
1929 pEndIdx && *pEndIdx > nTxtStartIdx )
1931 // Attribut mit einem Bereich
1932 // und das Ende des Attribut liegt im Bereich
1933 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
1934 *pEndIdx > nEnd
1935 ? nLen
1936 : *pEndIdx - nTxtStartIdx );
1939 else
1941 // der Anfang liegt vollstaendig im Bereich
1942 if( !pEndIdx || *pEndIdx < nEnd )
1944 // Attribut verschieben
1945 m_pSwpHints->Delete( pHt );
1946 // die Start/End Indicies neu setzen
1947 *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
1948 if( pEndIdx )
1949 *pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
1950 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
1951 continue; // while-Schleife weiter, ohne ++ !
1953 // das Ende liegt dahinter
1954 else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
1956 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
1957 nAttrStartIdx - nTxtStartIdx,
1958 !pEndIdx ? 0
1959 : ( *pEndIdx > nEnd
1960 ? nLen
1961 : *pEndIdx - nTxtStartIdx ));
1964 if( pNewHt )
1966 // die Daten kopieren
1967 lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
1968 aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
1970 ++nAttrCnt;
1973 if( bUpdate )
1975 // Update aller Indizies
1976 Update( rDestStart, nLen, FALSE, TRUE );
1978 #ifdef CUTNOEXPAND
1979 else
1980 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
1981 if ( 0 < nLen && 0 < nInitSize && m_pSwpHints )
1983 // check if there was the end of an attribute at the insertion
1984 // position: if it is not a field, it must be expanded
1985 for ( USHORT n = 0; n < m_pSwpHints->Count(); n++ )
1987 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
1988 const xub_StrLen * const pEndIdx = pHt->GetEnd();
1989 if ( pEndIdx && (*pEndIdx == nInitSize) )
1991 *pEndIdx = *pEndIdx + nLen;
1995 #endif
1996 CHECK_SWPHINTS(this);
1998 Update( rStart, nLen, TRUE, TRUE );
2000 CHECK_SWPHINTS(this);
2002 // dann setze die kopierten/geloeschten Attribute in den Node
2003 if( nDestStart <= nTxtStartIdx )
2005 nTxtStartIdx = nTxtStartIdx + nLen;
2007 else
2009 nDestStart = nDestStart - nLen;
2012 for ( USHORT n = 0; n < aArr.Count(); ++n )
2014 SwTxtAttr *const pNewHt = aArr[n];
2015 *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
2016 xub_StrLen * const pEndIdx = pNewHt->GetEnd();
2017 if ( pEndIdx )
2019 *pEndIdx = nDestStart + *pEndIdx;
2021 InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
2024 else
2026 pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
2027 m_Text.Erase( nTxtStartIdx, nLen );
2028 nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size!
2029 if( !nLen ) // String nicht gewachsen ??
2030 return;
2032 if( bUpdate )
2034 // Update aller Indizies
2035 pDest->Update( rDestStart, nLen, FALSE, TRUE);
2037 #ifdef CUTNOEXPAND
2038 else
2039 // wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
2040 if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints )
2042 // check if there was the end of an attribute at the insertion
2043 // position: if it is not a field, it must be expanded
2044 for ( USHORT n = 0; n < pDest->m_pSwpHints->Count(); n++ )
2046 SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n);
2047 const xub_StrLen * const pEndIdx = pHt->GetEnd();
2048 if ( pEndIdx && (*pEndIdx == nInitSize) )
2050 *pEndIdx = *pEndIdx + nLen;
2054 #endif
2055 CHECK_SWPHINTS(pDest);
2057 const xub_StrLen nEnd = rStart.GetIndex() + nLen;
2058 SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
2059 ? pDest->GetDoc() : 0;
2060 const bool bUndoNodes =
2061 !pOtherDoc && GetDoc()->GetUndoNds() == &GetNodes();
2063 ASSERT(!pOtherDoc,
2064 "mst: entering dead and bitrotted code; fasten your seatbelts!");
2066 // harte Absatz umspannende Attribute kopieren
2067 if( HasSwAttrSet() )
2069 // alle, oder nur die CharAttribute ?
2070 if( nInitSize || pDest->HasSwAttrSet() ||
2071 nLen != pDest->GetTxt().Len() )
2073 SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
2074 RES_CHRATR_BEGIN, RES_CHRATR_END-1,
2075 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
2076 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
2077 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
2078 0 );
2079 aCharSet.Put( *GetpSwAttrSet() );
2080 if( aCharSet.Count() )
2081 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
2083 else
2085 GetpSwAttrSet()->CopyToModify( *pDest );
2089 // 2. Attribute verschieben
2090 // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
2091 // des Attributs hinter dem zu verschiebenden Bereich liegt
2092 USHORT nAttrCnt = 0;
2093 while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
2095 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2096 const xub_StrLen nAttrStartIdx = *pHt->GetStart();
2097 if (!( nAttrStartIdx < nEnd ))
2098 break;
2099 const xub_StrLen * const pEndIdx = pHt->GetEnd();
2100 const USHORT nWhich = pHt->Which();
2101 SwTxtAttr *pNewHt = 0;
2103 // if the hint has a dummy character, then it must not be split!
2104 if(nAttrStartIdx < nTxtStartIdx)
2106 // Anfang liegt vor dem Bereich
2107 if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
2108 || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
2110 // Attribut mit einem Bereich
2111 // und das Ende des Attribut liegt im Bereich
2112 pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
2113 nDestStart,
2114 nDestStart + (
2115 *pEndIdx > nEnd
2116 ? nLen
2117 : *pEndIdx - nTxtStartIdx ) );
2120 else
2122 // der Anfang liegt vollstaendig im Bereich
2123 if( !pEndIdx || *pEndIdx < nEnd ||
2124 (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
2125 || pHt->HasDummyChar() )
2127 // do not delete note and later add it -> sidebar flickering
2128 if ( GetDoc()->GetDocShell() )
2130 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2132 // Attribut verschieben
2133 m_pSwpHints->Delete( pHt );
2134 // die Start/End Indicies neu setzen
2135 *pHt->GetStart() =
2136 nDestStart + (nAttrStartIdx - nTxtStartIdx);
2137 if( pEndIdx )
2139 *pHt->GetEnd() = nDestStart + (
2140 *pEndIdx > nEnd
2141 ? nLen
2142 : *pEndIdx - nTxtStartIdx );
2144 pDest->InsertHint( pHt,
2145 nsSetAttrMode::SETATTR_NOTXTATRCHR
2146 | nsSetAttrMode::SETATTR_DONTREPLACE );
2147 if ( GetDoc()->GetDocShell() )
2149 GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2151 continue; // while-Schleife weiter, ohne ++ !
2153 // das Ende liegt dahinter
2154 else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
2156 pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
2157 nDestStart + (nAttrStartIdx - nTxtStartIdx),
2158 !pEndIdx ? 0
2159 : nDestStart + ( *pEndIdx > nEnd
2160 ? nLen
2161 : *pEndIdx - nTxtStartIdx ));
2164 if ( pNewHt )
2166 const bool bSuccess( pDest->InsertHint( pNewHt,
2167 nsSetAttrMode::SETATTR_NOTXTATRCHR
2168 | nsSetAttrMode::SETATTR_DONTREPLACE ) );
2169 if (bSuccess)
2171 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
2174 ++nAttrCnt;
2176 // sollten jetzt noch leere Attribute rumstehen, dann haben diese
2177 // eine hoehere Praezedenz. Also herausholen und das Array updaten.
2178 // Die dabei entstehenden leeren Hints werden von den gesicherten
2179 // "uebergeplaettet". (Bug: 6977)
2180 if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
2182 SwpHts aArr( 5 );
2183 while ( nAttrCnt < m_pSwpHints->Count() )
2185 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2186 if ( nEnd != *pHt->GetStart() )
2187 break;
2188 const xub_StrLen * const pEndIdx = pHt->GetEnd();
2189 if ( pEndIdx && *pEndIdx == nEnd )
2191 aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
2192 m_pSwpHints->Delete( pHt );
2194 else
2196 ++nAttrCnt;
2199 Update( rStart, nLen, TRUE, TRUE );
2201 for ( USHORT n = 0; n < aArr.Count(); ++n )
2203 SwTxtAttr * const pHt = aArr[ n ];
2204 *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
2205 InsertHint( pHt );
2208 else
2210 Update( rStart, nLen, TRUE, TRUE );
2213 CHECK_SWPHINTS(this);
2216 TryDeleteSwpHints();
2218 // Frames benachrichtigen;
2219 SwInsTxt aInsHint( nDestStart, nLen );
2220 pDest->Modify( 0, &aInsHint );
2221 SwDelTxt aDelHint( nTxtStartIdx, nLen );
2222 Modify( 0, &aDelHint );
2226 void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
2227 const IDocumentContentOperations::InsertFlags nMode )
2229 ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." );
2231 const xub_StrLen nStartIdx = rIdx.GetIndex();
2232 const xub_StrLen nCnt = (STRING_LEN == nCount)
2233 ? m_Text.Len() - nStartIdx : nCount;
2234 const xub_StrLen nEndIdx = nStartIdx + nCnt;
2235 m_Text.Erase( nStartIdx, nCnt );
2237 /* GCAttr(); alle leeren weggwerfen ist zu brutal.
2238 * Es duerfen nur die wegggeworfen werden,
2239 * die im Bereich liegen und nicht am Ende des Bereiches liegen
2242 for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2244 SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
2246 const xub_StrLen nHintStart = *pHt->GetStart();
2248 if ( nHintStart < nStartIdx )
2249 continue;
2251 if ( nHintStart > nEndIdx )
2252 break; // hints are sorted by end, so break here
2254 const xub_StrLen* pHtEndIdx = pHt->GetEnd();
2255 const USHORT nWhich = pHt->Which();
2257 if( !pHtEndIdx )
2259 ASSERT(pHt->HasDummyChar(),
2260 "attribute with neither end nor CH_TXTATR?");
2261 if (isTXTATR(nWhich) &&
2262 (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
2264 m_pSwpHints->DeleteAtPos(i);
2265 DestroyAttr( pHt );
2266 --i;
2268 continue;
2271 ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
2272 && pHt->HasDummyChar() )
2273 // next line: deleting exactly dummy char: DeleteAttributes
2274 || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)),
2275 "ERROR: deleting left-overlapped attribute with CH_TXTATR");
2277 // Delete the hint if:
2278 // 1. The hint ends before the deletion end position or
2279 // 2. The hint ends at the deletion end position and
2280 // we are not in empty expand mode and
2281 // the hint is a [toxmark|refmark|ruby] text attribute
2282 // 3. deleting exactly the dummy char of an hint with end and dummy
2283 // char deletes the hint
2284 if ( (*pHtEndIdx < nEndIdx)
2285 || ( (*pHtEndIdx == nEndIdx) &&
2286 !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) &&
2287 ( (RES_TXTATR_TOXMARK == nWhich) ||
2288 (RES_TXTATR_REFMARK == nWhich) ||
2289 // --> FME 2006-03-03 #i62668# Ruby text attribute must be
2290 // treated just like toxmark and refmarks
2291 (RES_TXTATR_CJK_RUBY == nWhich) ) )
2292 // <--
2293 #if 0
2294 || ( (nHintStart == nStartIdx) &&
2295 (nHintStart + 1 == nEndIdx)&&
2296 #else // generalize this to left-overlapped dummy char hints (see ASSERT)
2297 || ( (nHintStart < nEndIdx) &&
2298 #endif
2299 pHt->HasDummyChar() )
2302 m_pSwpHints->DeleteAtPos(i);
2303 DestroyAttr( pHt );
2304 --i;
2308 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2310 TryDeleteSwpHints();
2312 Update( rIdx, nCnt, TRUE );
2314 if( 1 == nCnt )
2316 SwDelChr aHint( nStartIdx );
2317 SwModify::Modify( 0, &aHint );
2319 else
2321 SwDelTxt aHint( nStartIdx, nCnt );
2322 SwModify::Modify( 0, &aHint );
2325 ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2327 // By deleting a character, the hidden flags
2328 // at the TxtNode can become invalid:
2329 SetCalcHiddenCharFlags();
2331 CHECK_SWPHINTS(this);
2334 /***********************************************************************
2335 #* Class : SwTxtNode
2336 #* Methode : GCAttr
2338 #* Beschreibung
2339 #* text.doc
2341 #* Datum : MS 28.11.90
2342 #* Update : VB 24.07.91
2343 #***********************************************************************/
2345 void SwTxtNode::GCAttr()
2347 if ( !HasHints() )
2348 return;
2350 bool bChanged = false;
2351 USHORT nMin = m_Text.Len(),
2352 nMax = 0;
2353 BOOL bAll = nMin != 0; // Bei leeren Absaetzen werden nur die
2354 // INet-Formate entfernt.
2356 for ( USHORT i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2358 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);
2360 // wenn Ende und Start gleich sind --> loeschen
2361 const xub_StrLen * const pEndIdx = pHt->GetEnd();
2362 if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
2363 && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
2365 bChanged = true;
2366 nMin = Min( nMin, *pHt->GetStart() );
2367 nMax = Max( nMax, *pHt->GetEnd() );
2368 DestroyAttr( m_pSwpHints->Cut(i) );
2369 --i;
2371 else
2373 pHt->SetDontExpand( false );
2376 TryDeleteSwpHints();
2378 if(bChanged)
2380 //TxtFrm's reagieren auf aHint, andere auf aNew
2381 SwUpdateAttr aHint( nMin, nMax, 0 );
2382 SwModify::Modify( 0, &aHint );
2383 SwFmtChg aNew( GetTxtColl() );
2384 SwModify::Modify( 0, &aNew );
2388 // #i23726#
2389 SwNumRule* SwTxtNode::_GetNumRule(BOOL bInParent) const
2391 SwNumRule* pRet = 0;
2393 const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
2394 bool bNoNumRule = false;
2395 if ( pItem )
2397 String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
2398 if (sNumRuleName.Len() > 0)
2400 pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
2402 else // numbering is turned off
2403 bNoNumRule = true;
2406 if ( !bNoNumRule )
2408 if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
2409 ( !HasSwAttrSet() ||
2410 SFX_ITEM_SET !=
2411 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE ) ) )
2413 SwTxtFmtColl* pColl = GetTxtColl();
2414 if ( pColl )
2416 const SwNumRuleItem& rDirectItem = pColl->GetNumRule( FALSE );
2417 if ( rDirectItem.GetValue().Len() == 0 )
2419 pRet = 0L;
2424 // --> OD 2006-11-20 #i71764#
2425 // Document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE has no influence
2426 // any more.
2427 // if ( !pRet &&
2428 // GetDoc()->get(IDocumentSettingAccess::OUTLINE_LEVEL_YIELDS_OUTLINE_RULE) &&
2429 // GetOutlineLevel() != NO_NUMBERING )
2430 // {
2431 // pRet = GetDoc()->GetOutlineNumRule();
2432 // }
2433 // <--
2435 // old code before tuning
2436 // // --> OD 2005-10-25 #126347#
2437 // // determine of numbering/bullet rule, which is set as a hard attribute
2438 // // at the text node
2439 // const SfxPoolItem* pItem( 0L );
2440 // if ( HasSwAttrSet() ) // does text node has hard attributes ?
2441 // {
2442 // if ( SFX_ITEM_SET !=
2443 // GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) )
2444 // {
2445 // pItem = 0L;
2446 // }
2447 // // else: <pItem> contains the numbering/bullet attribute, which is
2448 // // hard set at the paragraph.
2450 // }
2451 // // <--
2452 // bool bNoNumRule = false;
2453 // if (pItem)
2454 // {
2455 // String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
2456 // if (sNumRuleName.Len() > 0)
2457 // {
2458 // pRet = GetDoc()->FindNumRulePtr(sNumRuleName);
2459 // }
2460 // else // numbering is turned off by hard attribute
2461 // bNoNumRule = true;
2462 // }
2464 // if (! bNoNumRule)
2465 // {
2466 // if (! pRet && bInParent)
2467 // {
2468 // SwTxtFmtColl * pColl = GetTxtColl();
2470 // if (pColl)
2471 // {
2472 // const SwNumRuleItem & rItem = pColl->GetNumRule(TRUE);
2474 // pRet = const_cast<SwDoc *>(GetDoc())->
2475 // FindNumRulePtrWithPool(rItem.GetValue());
2476 // // --> OD 2005-10-13 #125993# - The outline numbering rule
2477 // // isn't allowed to be derived from a parent paragraph style
2478 // // to a derived one.
2479 // // Thus check, if the found outline numbering rule is directly
2480 // // set at the paragraph style <pColl>. If not, don't return
2481 // // the outline numbering rule.
2482 // if ( pRet && pRet == GetDoc()->GetOutlineNumRule() )
2483 // {
2484 // const SwNumRuleItem& rDirectItem = pColl->GetNumRule(FALSE);
2485 // SwNumRule* pNumRuleAtParaStyle = const_cast<SwDoc*>(GetDoc())->
2486 // FindNumRulePtrWithPool(rDirectItem.GetValue());
2487 // if ( !pNumRuleAtParaStyle )
2488 // {
2489 // pRet = 0L;
2490 // }
2491 // }
2492 // // <--
2493 // }
2494 // }
2496 // if (!pRet && GetDoc()->IsOutlineLevelYieldsOutlineRule() &&
2497 // GetOutlineLevel() != NO_NUMBERING)
2498 // pRet = GetDoc()->GetOutlineNumRule();
2499 // }
2500 // <--
2502 return pRet;
2505 SwNumRule* SwTxtNode::GetNumRule(BOOL bInParent) const
2507 SwNumRule * pRet = _GetNumRule(bInParent);
2509 return pRet;
2512 void SwTxtNode::NumRuleChgd()
2514 // --> OD 2008-04-04 #refactorlists#
2515 if ( IsInList() )
2517 SwNumRule* pNumRule = GetNumRule();
2518 if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
2520 mpNodeNum->ChangeNumRule( *pNumRule );
2523 // <--
2525 if( IsInCache() )
2527 SwFrm::GetCache().Delete( this );
2528 SetInCache( FALSE );
2530 SetInSwFntCache( FALSE );
2532 SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
2534 SwModify::Modify( &rLR, &rLR );
2537 // -> #i27615#
2538 BOOL SwTxtNode::IsNumbered() const
2540 BOOL bResult = FALSE;
2542 SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2543 if ( pRule && IsCountedInList() )
2544 bResult = TRUE;
2546 return bResult;
2549 // --> OD 2008-04-02 #refactorlists#
2550 bool SwTxtNode::HasMarkedLabel() const
2552 bool bResult = false;
2554 if ( IsInList() )
2556 bResult =
2557 GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
2560 return bResult;
2562 // <--
2563 // <- #i27615#
2565 SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, BOOL bNext,
2566 BOOL bChgFollow )
2568 /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
2569 SwAttrSet* pNewAttrSet = 0;
2570 // --> OD 2007-07-10 #i75353#
2571 bool bClearHardSetNumRuleWhenFmtCollChanges( false );
2572 // <--
2573 if( HasSwAttrSet() )
2575 pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
2576 const SfxItemSet* pTmpSet = GetpSwAttrSet();
2578 if( bNext ) // der naechste erbt keine Breaks!
2579 pTmpSet = pNewAttrSet;
2581 // PageBreaks/PageDesc/ColBreak rausschmeissen.
2582 BOOL bRemoveFromCache = FALSE;
2583 std::vector<USHORT> aClearWhichIds;
2584 if ( bNext )
2585 bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
2586 else
2587 aClearWhichIds.push_back( RES_PAGEDESC );
2589 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, FALSE ) )
2591 if ( bNext )
2592 pNewAttrSet->ClearItem( RES_BREAK );
2593 else
2594 aClearWhichIds.push_back( RES_BREAK );
2595 bRemoveFromCache = TRUE;
2597 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, FALSE ) )
2599 if ( bNext )
2600 pNewAttrSet->ClearItem( RES_KEEP );
2601 else
2602 aClearWhichIds.push_back( RES_KEEP );
2603 bRemoveFromCache = TRUE;
2605 if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, FALSE ) )
2607 if ( bNext )
2608 pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
2609 else
2610 aClearWhichIds.push_back( RES_PARATR_SPLIT );
2611 bRemoveFromCache = TRUE;
2613 if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, FALSE))
2615 SwNumRule * pRule = GetNumRule();
2617 if (pRule && IsOutline())
2619 if ( bNext )
2620 pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
2621 else
2623 // --> OD 2007-07-10 #i75353#
2624 // No clear of hard set numbering rule at an outline paragraph at this point.
2625 // Only if the paragraph style changes - see below.
2626 // aClearWhichIds.push_back( RES_PARATR_NUMRULE );
2627 bClearHardSetNumRuleWhenFmtCollChanges = true;
2628 // <--
2630 bRemoveFromCache = TRUE;
2634 if ( 0 != aClearWhichIds.size() )
2635 bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
2637 if( !bNext && bRemoveFromCache && IsInCache() )
2639 SwFrm::GetCache().Delete( this );
2640 SetInCache( FALSE );
2643 SwNodes& rNds = GetNodes();
2645 SwTxtFmtColl* pColl = GetTxtColl();
2647 SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );
2649 if( pNewAttrSet )
2650 delete pNewAttrSet;
2652 const SwNumRule* pRule = GetNumRule();
2653 if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
2655 // --> OD 2005-10-18 #i55459#
2656 // - correction: parameter <bNext> has to be checked, as it was in the
2657 // previous implementation.
2658 if ( !bNext && !IsCountedInList() )
2659 SetCountedInList(true);
2660 // <--
2663 // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
2664 // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
2665 // nochmal uebergeplaettet werden !!
2666 if( pColl != pNode->GetTxtColl() ||
2667 ( bChgFollow && pColl != GetTxtColl() ))
2668 return pNode; // mehr duerfte nicht gemacht werden oder ????
2670 pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
2671 if( bNext || !bChgFollow )
2672 return pNode;
2674 SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
2675 // --> OD 2009-08-12 #i101870#
2676 // perform action on different paragraph styles before applying the new paragraph style
2677 if (pNextColl != pColl)
2679 // --> OD 2007-07-10 #i75353#
2680 if ( bClearHardSetNumRuleWhenFmtCollChanges )
2682 std::vector<USHORT> aClearWhichIds;
2683 aClearWhichIds.push_back( RES_PARATR_NUMRULE );
2684 if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
2686 SwFrm::GetCache().Delete( this );
2687 SetInCache( FALSE );
2690 // <--
2692 // <--
2693 ChgFmtColl( pNextColl );
2695 return pNode;
2698 SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
2700 // Position hinter dem eingefuegt wird
2701 SwNodeIndex aIdx( rPos.nNode, 1 );
2702 SwTxtNode* pNew = _MakeNewTxtNode( aIdx, TRUE );
2704 // --> OD 2008-05-14 #refactorlists#
2705 // reset list attributes at appended text node
2706 pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
2707 pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
2708 pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
2709 if ( pNew->GetNumRule() == 0 )
2711 pNew->ResetAttr( RES_PARATR_LIST_ID );
2712 pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
2714 // <--
2715 // --> OD 2008-03-13 #refactorlists#
2716 // SyncNumberAndNumRule();
2717 if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
2719 AddToList();
2721 // <--
2723 if( GetDepends() )
2724 MakeFrms( *pNew );
2725 return pNew;
2728 /*************************************************************************
2729 * SwTxtNode::GetTxtAttr
2730 *************************************************************************/
2732 SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex,
2733 const RES_TXTATR nWhich ) const
2735 if ( HasHints() )
2737 for ( USHORT i = 0; i < m_pSwpHints->Count(); ++i )
2739 SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
2740 const xub_StrLen nStartPos = *pHint->GetStart();
2741 if ( nIndex < nStartPos )
2743 return 0;
2745 if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
2747 return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
2748 ? pHint : 0;
2752 return 0;
2755 // -> #i29560#
2756 BOOL SwTxtNode::HasNumber() const
2758 BOOL bResult = FALSE;
2760 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2761 if ( pRule )
2763 SwNumFmt aFmt(pRule->Get( static_cast<USHORT>(GetActualListLevel())));
2765 // #i40041#
2766 bResult = aFmt.IsEnumeration() &&
2767 SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
2770 return bResult;
2773 BOOL SwTxtNode::HasBullet() const
2775 BOOL bResult = FALSE;
2777 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2778 if ( pRule )
2780 SwNumFmt aFmt(pRule->Get( static_cast<USHORT>(GetActualListLevel())));
2782 bResult = aFmt.IsItemize();
2785 return bResult;
2787 // <- #i29560#
2789 // --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
2790 //i53420 added max outline parameter
2791 XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
2793 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2794 if ( pRule &&
2795 IsCountedInList() &&
2796 pRule->Get( static_cast<USHORT>(GetActualListLevel()) ).IsTxtFmt() )
2798 return pRule->MakeNumString( GetNum()->GetNumberVector(),
2799 _bInclPrefixAndSuffixStrings ? TRUE : FALSE,
2800 FALSE,
2801 _nRestrictToThisLevel );
2804 return aEmptyStr;
2807 long SwTxtNode::GetLeftMarginWithNum( BOOL bTxtLeft ) const
2809 long nRet = 0;
2810 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2811 if( pRule )
2813 const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
2814 // --> OD 2008-01-16 #newlistlevelattrs#
2815 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2817 nRet = rFmt.GetAbsLSpace();
2819 if( !bTxtLeft )
2821 if( 0 > rFmt.GetFirstLineOffset() &&
2822 nRet > -rFmt.GetFirstLineOffset() )
2823 nRet = nRet + rFmt.GetFirstLineOffset();
2824 else
2825 nRet = 0;
2828 if( pRule->IsAbsSpaces() )
2829 nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
2831 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2833 if ( AreListLevelIndentsApplicable() )
2835 nRet = rFmt.GetIndentAt();
2836 // --> OD 2008-06-06 #i90401#
2837 // Only negative first line indents have consider for the left margin
2838 if ( !bTxtLeft &&
2839 rFmt.GetFirstLineIndent() < 0 )
2841 nRet = nRet + rFmt.GetFirstLineIndent();
2843 // <--
2846 // <--
2849 return nRet;
2852 BOOL SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
2854 BOOL bRet( FALSE );
2856 // --> OD 2005-11-02 #i51089 - TUNING#
2857 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2858 if ( pRule )
2860 if ( IsCountedInList() )
2862 // --> OD 2008-01-16 #newlistlevelattrs#
2863 const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
2864 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2866 rFLOffset = pRule->Get( static_cast<USHORT>(GetActualListLevel() )).GetFirstLineOffset();
2868 if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2870 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2871 rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
2874 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2876 if ( AreListLevelIndentsApplicable() )
2878 rFLOffset = static_cast<USHORT>(rFmt.GetFirstLineIndent());
2880 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2882 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2883 rFLOffset = aItem.GetTxtFirstLineOfst();
2886 // <--
2888 else
2889 rFLOffset = 0;
2891 bRet = TRUE;
2893 else
2895 rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2898 return bRet;
2901 // --> OD 2008-12-02 #i96772#
2902 void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
2904 if ( AreListLevelIndentsApplicable() )
2906 const SwNumRule* pRule = GetNumRule();
2907 if ( pRule && GetActualListLevel() >= 0 )
2909 const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
2910 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2912 SvxLRSpaceItem aLR( RES_LR_SPACE );
2913 o_rLRSpaceItem = aLR;
2918 // <--
2920 // --> OD 2008-07-01 #i91133#
2921 long SwTxtNode::GetLeftMarginForTabCalculation() const
2923 long nLeftMarginForTabCalc = 0;
2925 bool bLeftMarginForTabCalcSetToListLevelIndent( false );
2926 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
2927 if( pRule )
2929 const SwNumFmt& rFmt = pRule->Get(static_cast<USHORT>(GetActualListLevel()));
2930 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2932 if ( AreListLevelIndentsApplicable() )
2934 nLeftMarginForTabCalc = rFmt.GetIndentAt();
2935 bLeftMarginForTabCalcSetToListLevelIndent = true;
2939 if ( !bLeftMarginForTabCalcSetToListLevelIndent )
2941 nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
2944 return nLeftMarginForTabCalc;
2946 // <--
2948 void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt,
2949 xub_StrLen nEndPos, BOOL bExpandFlds ) const
2951 if( GetpSwpHints() )
2953 sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
2954 for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter,
2955 cSrchChr = CH_TXTATR_INWORD )
2957 xub_StrLen nPos = rTxt.Search( cSrchChr );
2958 while( STRING_NOTFOUND != nPos && nPos < nEndPos )
2960 const SwTxtAttr* const pAttr =
2961 GetTxtAttrForCharAt( rTxtStt + nPos );
2962 if( pAttr )
2964 switch( pAttr->Which() )
2966 case RES_TXTATR_FIELD:
2967 rTxt.Erase( nPos, 1 );
2968 if( bExpandFlds )
2970 const XubString aExpand( ((SwTxtFld*)pAttr)->GetFld().
2971 GetFld()->Expand() );
2972 rTxt.Insert( aExpand, nPos );
2973 nPos = nPos + aExpand.Len();
2974 nEndPos = nEndPos + aExpand.Len();
2975 rTxtStt = rTxtStt - aExpand.Len();
2977 ++rTxtStt;
2978 break;
2979 case RES_TXTATR_FTN:
2980 rTxt.Erase( nPos, 1 );
2981 if( bExpandFlds )
2983 const SwFmtFtn& rFtn = pAttr->GetFtn();
2984 XubString sExpand;
2985 if( rFtn.GetNumStr().Len() )
2986 sExpand = rFtn.GetNumStr();
2987 else if( rFtn.IsEndNote() )
2988 sExpand = GetDoc()->GetEndNoteInfo().aFmt.
2989 GetNumStr( rFtn.GetNumber() );
2990 else
2991 sExpand = GetDoc()->GetFtnInfo().aFmt.
2992 GetNumStr( rFtn.GetNumber() );
2993 rTxt.Insert( sExpand, nPos );
2994 nPos = nPos + sExpand.Len();
2995 nEndPos = nEndPos + sExpand.Len();
2996 rTxtStt = rTxtStt - sExpand.Len();
2998 ++rTxtStt;
2999 break;
3000 default:
3001 rTxt.Erase( nPos, 1 );
3002 ++rTxtStt;
3005 else
3006 ++nPos, ++nEndPos;
3007 nPos = rTxt.Search( cSrchChr, nPos );
3013 /*************************************************************************
3014 * SwTxtNode::GetExpandTxt
3015 * Expand fields
3016 *************************************************************************/
3017 // --> OD 2007-11-15 #i83479# - handling of new parameters
3018 XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
3019 const xub_StrLen nLen,
3020 const bool bWithNum,
3021 const bool bAddSpaceAfterListLabelStr,
3022 const bool bWithSpacesForLevel ) const
3024 XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
3025 xub_StrLen nTxtStt = nIdx;
3026 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), TRUE );
3027 if( bWithNum )
3029 XubString aListLabelStr = GetNumString();
3030 if ( aListLabelStr.Len() > 0 )
3032 if ( bAddSpaceAfterListLabelStr )
3034 const sal_Unicode aSpace = ' ';
3035 aTxt.Insert( aSpace, 0 );
3037 aTxt.Insert( GetNumString(), 0 );
3041 if ( bWithSpacesForLevel && GetActualListLevel() > 0 )
3043 int nLevel( GetActualListLevel() );
3044 while ( nLevel > 0 )
3046 const sal_Unicode aSpace = ' ';
3047 aTxt.Insert( aSpace , 0 );
3048 aTxt.Insert( aSpace , 0 );
3049 --nLevel;
3053 return aTxt;
3055 // <--
3057 BOOL SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
3058 xub_StrLen nIdx, xub_StrLen nLen, BOOL bWithNum,
3059 BOOL bWithFtn, BOOL bReplaceTabsWithSpaces ) const
3061 if( &rDestNd == this )
3062 return FALSE;
3064 SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() );
3065 if( pDestIdx )
3066 aDestIdx = *pDestIdx;
3067 xub_StrLen nDestStt = aDestIdx.GetIndex();
3069 // Text einfuegen
3070 String sTmpText = GetTxt();
3071 if( bReplaceTabsWithSpaces )
3072 sTmpText.SearchAndReplaceAll('\t', ' ');
3074 // mask hidden characters
3075 const xub_Unicode cChar = CH_TXTATR_BREAKWORD;
3076 USHORT nHiddenChrs =
3077 SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar );
3079 sTmpText = sTmpText.Copy( nIdx, nLen );
3080 rDestNd.InsertText( sTmpText, aDestIdx );
3081 nLen = aDestIdx.GetIndex() - nDestStt;
3083 // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
3084 if ( HasHints() )
3086 xub_StrLen nInsPos = nDestStt - nIdx;
3087 for ( USHORT i = 0; i < m_pSwpHints->Count(); i++ )
3089 const SwTxtAttr* pHt = (*m_pSwpHints)[i];
3090 const xub_StrLen nAttrStartIdx = *pHt->GetStart();
3091 const USHORT nWhich = pHt->Which();
3092 if (nIdx + nLen <= nAttrStartIdx)
3093 break; // ueber das Textende
3095 const xub_StrLen *pEndIdx = pHt->GetEnd();
3096 if( pEndIdx && *pEndIdx > nIdx &&
3097 ( RES_CHRATR_FONT == nWhich ||
3098 RES_TXTATR_CHARFMT == nWhich ||
3099 RES_TXTATR_AUTOFMT == nWhich ))
3101 const SvxFontItem* const pFont =
3102 static_cast<const SvxFontItem*>(
3103 CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
3104 if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
3106 // attribute in area => copy
3107 rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
3108 nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
3111 else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
3113 aDestIdx = nInsPos + nAttrStartIdx;
3114 switch( nWhich )
3116 case RES_TXTATR_FIELD:
3118 const XubString aExpand( ((SwTxtFld*)pHt)->GetFld().GetFld()->Expand() );
3119 if( aExpand.Len() )
3121 aDestIdx++; // dahinter einfuegen;
3122 rDestNd.InsertText( aExpand, aDestIdx );
3123 aDestIdx = nInsPos + nAttrStartIdx;
3124 nInsPos = nInsPos + aExpand.Len();
3126 rDestNd.EraseText( aDestIdx, 1 );
3127 --nInsPos;
3129 break;
3131 case RES_TXTATR_FTN:
3133 if ( bWithFtn )
3135 const SwFmtFtn& rFtn = pHt->GetFtn();
3136 XubString sExpand;
3137 if( rFtn.GetNumStr().Len() )
3138 sExpand = rFtn.GetNumStr();
3139 else if( rFtn.IsEndNote() )
3140 sExpand = GetDoc()->GetEndNoteInfo().aFmt.
3141 GetNumStr( rFtn.GetNumber() );
3142 else
3143 sExpand = GetDoc()->GetFtnInfo().aFmt.
3144 GetNumStr( rFtn.GetNumber() );
3145 if( sExpand.Len() )
3147 aDestIdx++; // insert behind
3148 SvxEscapementItem aItem(
3149 SVX_ESCAPEMENT_SUPERSCRIPT );
3150 rDestNd.InsertItem(aItem,
3151 aDestIdx.GetIndex(),
3152 aDestIdx.GetIndex() );
3153 rDestNd.InsertText( sExpand, aDestIdx,
3154 IDocumentContentOperations::INS_EMPTYEXPAND);
3155 aDestIdx = nInsPos + nAttrStartIdx;
3156 nInsPos = nInsPos + sExpand.Len();
3159 rDestNd.EraseText( aDestIdx, 1 );
3160 --nInsPos;
3162 break;
3164 default:
3165 rDestNd.EraseText( aDestIdx, 1 );
3166 --nInsPos;
3172 if( bWithNum )
3174 aDestIdx = nDestStt;
3175 rDestNd.InsertText( GetNumString(), aDestIdx );
3178 if ( nHiddenChrs > 0 )
3180 aDestIdx = 0;
3181 while ( aDestIdx < rDestNd.GetTxt().Len() )
3183 if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) )
3185 xub_StrLen nIndex = aDestIdx.GetIndex();
3186 while ( nIndex < rDestNd.GetTxt().Len() &&
3187 cChar == rDestNd.GetTxt().GetChar( ++nIndex ) )
3189 rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() );
3191 else
3192 ++aDestIdx;
3196 return TRUE;
3199 const ModelToViewHelper::ConversionMap*
3200 SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const
3202 const rtl::OUString& rNodeText = GetTxt();
3203 rRetText = rNodeText;
3204 ModelToViewHelper::ConversionMap* pConversionMap = 0;
3206 const SwpHints* pSwpHints2 = GetpSwpHints();
3207 xub_StrLen nPos = 0;
3209 for ( USHORT i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
3211 const SwTxtAttr* pAttr = (*pSwpHints2)[i];
3212 if ( RES_TXTATR_FIELD == pAttr->Which() )
3214 const XubString aExpand( ((SwTxtFld*)pAttr)->GetFld().GetFld()->Expand() );
3215 if ( aExpand.Len() > 0 )
3217 const xub_StrLen nFieldPos = *pAttr->GetStart();
3218 rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
3219 if ( !pConversionMap )
3220 pConversionMap = new ModelToViewHelper::ConversionMap;
3221 pConversionMap->push_back(
3222 ModelToViewHelper::ConversionMapEntry(
3223 nFieldPos, nPos + nFieldPos ) );
3224 nPos += ( aExpand.Len() - 1 );
3229 if ( pConversionMap && pConversionMap->size() )
3230 pConversionMap->push_back(
3231 ModelToViewHelper::ConversionMapEntry(
3232 rNodeText.getLength()+1, rRetText.getLength()+1 ) );
3234 return pConversionMap;
3237 XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
3238 BOOL bExpandFlds, BOOL bWithNum ) const
3240 SvUShorts aRedlArr;
3241 const SwDoc* pDoc = GetDoc();
3242 USHORT nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
3243 if( USHRT_MAX != nRedlPos )
3245 // es existiert fuer den Node irgendein Redline-Delete-Object
3246 const ULONG nNdIdx = GetIndex();
3247 for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos )
3249 const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
3250 if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
3252 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
3253 if( pRStt->nNode < nNdIdx )
3255 if( pREnd->nNode > nNdIdx )
3256 // Absatz ist komplett geloescht
3257 return aEmptyStr;
3258 else if( pREnd->nNode == nNdIdx )
3260 // von 0 bis nContent ist alles geloescht
3261 aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() );
3262 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
3265 else if( pRStt->nNode == nNdIdx )
3267 aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
3268 if( pREnd->nNode == nNdIdx )
3269 aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
3270 else
3272 aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() );
3273 break; // mehr kann nicht kommen
3276 else
3277 break; // mehr kann nicht kommen
3282 XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
3284 xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
3285 for( USHORT n = 0; n < aRedlArr.Count(); n += 2 )
3287 xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
3288 if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
3289 ( nIdx <= nEnd && nEnd <= nIdxEnd ))
3291 if( nStt < nIdx ) nStt = nIdx;
3292 if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
3293 xub_StrLen nDelCnt = nEnd - nStt;
3294 aTxt.Erase( nStt - nTxtStt, nDelCnt );
3295 Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
3296 nTxtStt = nTxtStt + nDelCnt;
3298 else if( nStt >= nIdxEnd )
3299 break;
3301 Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );
3303 if( bWithNum )
3304 aTxt.Insert( GetNumString(), 0 );
3305 return aTxt;
3308 /*************************************************************************
3309 * SwTxtNode::ReplaceText
3310 *************************************************************************/
3312 void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
3313 const XubString& rText )
3315 ASSERT( rStart.GetIndex() < m_Text.Len() &&
3316 rStart.GetIndex() + nDelLen <= m_Text.Len(),
3317 "SwTxtNode::ReplaceText: index out of bounds" );
3318 const xub_StrLen nStartPos = rStart.GetIndex();
3319 xub_StrLen nEndPos = nStartPos + nDelLen;
3320 xub_StrLen nLen = nDelLen;
3321 for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
3323 if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) ||
3324 ( CH_TXTATR_INWORD == m_Text.GetChar( nPos ) ) )
3326 SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
3327 if (pHint)
3329 ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar()
3330 && (*pHint->GetStart() < nEndPos)
3331 && (*pHint->GetEnd() > nEndPos) ),
3332 "ReplaceText: ERROR: "
3333 "deleting left-overlapped attribute with CH_TXTATR");
3334 DeleteAttribute( pHint );
3335 --nEndPos;
3336 --nLen;
3341 BOOL bOldExpFlg = IsIgnoreDontExpand();
3342 SetIgnoreDontExpand( TRUE );
3344 if( nLen && rText.Len() )
3346 // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
3347 // Dadurch wird die Attributierung des 1. Zeichen expandiert!
3348 m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );
3350 ((SwIndex&)rStart)++;
3351 m_Text.Erase( rStart.GetIndex(), nLen - 1 );
3352 Update( rStart, nLen - 1, true );
3354 XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
3355 m_Text.Insert( aTmpTxt, rStart.GetIndex() );
3356 Update( rStart, aTmpTxt.Len(), false );
3358 else
3360 m_Text.Erase( nStartPos, nLen );
3361 Update( rStart, nLen, true );
3363 m_Text.Insert( rText, nStartPos );
3364 Update( rStart, rText.Len(), false );
3367 SetIgnoreDontExpand( bOldExpFlg );
3368 SwDelTxt aDelHint( nStartPos, nDelLen );
3369 SwModify::Modify( 0, &aDelHint );
3371 SwInsTxt aHint( nStartPos, rText.Len() );
3372 SwModify::Modify( 0, &aHint );
3375 // --> OD 2008-03-27 #refactorlists#
3376 namespace {
3377 // Helper method for special handling of modified attributes at text node.
3378 // The following is handled:
3379 // (1) on changing the paragraph style - RES_FMT_CHG:
3380 // Check, if list style of the text node is changed. If yes, add respectively
3381 // remove the text node to the corresponding list.
3382 // (2) on changing the attributes - RES_ATTRSET_CHG:
3383 // Same as (1).
3384 // (3) on changing the list style - RES_PARATR_NUMRULE:
3385 // Same as (1).
3386 void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
3387 const SfxPoolItem* pOldValue,
3388 const SfxPoolItem* pNewValue )
3390 const USHORT nWhich = pOldValue ? pOldValue->Which() :
3391 pNewValue ? pNewValue->Which() : 0 ;
3392 bool bNumRuleSet = false;
3393 bool bParagraphStyleChanged = false;
3394 String sNumRule;
3395 String sOldNumRule;
3396 switch ( nWhich )
3398 case RES_FMT_CHG:
3400 bParagraphStyleChanged = true;
3401 if( rTxtNode.GetNodes().IsDocNodes() )
3403 // --> OD 2008-12-17 #i70748#
3404 // The former list style set at the paragraph can not be
3405 // retrieved from the change set.
3406 // sOldNumRule =
3407 // dynamic_cast<const SwFmtChg*>(pOldValue)->pChangedFmt->GetNumRule().GetValue();
3408 const SwNumRule* pFormerNumRuleAtTxtNode =
3409 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3410 if ( pFormerNumRuleAtTxtNode )
3412 sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3414 // <--
3415 // --> OD 2008-11-19 #i70748#
3416 if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
3418 const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
3419 if ( rNumRuleItem.GetValue().Len() > 0 )
3421 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3424 // <--
3425 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3426 if ( pNumRuleAtTxtNode )
3428 bNumRuleSet = true;
3429 sNumRule = pNumRuleAtTxtNode->GetName();
3432 break;
3434 case RES_ATTRSET_CHG:
3436 const SfxPoolItem* pItem = 0;
3437 // --> OD 2008-12-19 #i70748#
3438 // The former list style set at the paragraph can not be
3439 // retrieved from the change set.
3440 // if ( dynamic_cast<const SwAttrSetChg*>(pOldValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) ==
3441 // SFX_ITEM_SET )
3442 // {
3443 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue();
3444 // }
3445 const SwNumRule* pFormerNumRuleAtTxtNode =
3446 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3447 if ( pFormerNumRuleAtTxtNode )
3449 sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3451 // <--
3452 if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) ==
3453 SFX_ITEM_SET )
3455 // --> OD 2008-11-19 #i70748#
3456 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3457 // <--
3458 bNumRuleSet = true;
3459 // The new list style set at the paragraph can not be
3460 // retrieved from the change set.
3461 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pItem)->GetValue();
3462 // <--
3464 // --> OD 2008-12-17 #i70748#
3465 // The new list style set at the paragraph.
3466 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3467 if ( pNumRuleAtTxtNode )
3469 sNumRule = pNumRuleAtTxtNode->GetName();
3471 // <--
3472 break;
3474 case RES_PARATR_NUMRULE:
3476 if ( rTxtNode.GetNodes().IsDocNodes() )
3478 // The former list style set at the paragraph can not be
3479 // retrieved from the change set.
3480 // if ( pOldValue )
3481 // {
3482 // sOldNumRule = dynamic_cast<const SwNumRuleItem*>(pOldValue)->GetValue();
3483 // }
3484 const SwNumRule* pFormerNumRuleAtTxtNode =
3485 rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3486 if ( pFormerNumRuleAtTxtNode )
3488 sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3490 // <--
3491 if ( pNewValue )
3493 // --> OD 2008-11-19 #i70748#
3494 rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3495 // <--
3496 bNumRuleSet = true;
3497 // --> OD 2008-12-17 #i70748#
3498 // The new list style set at the paragraph can not be
3499 // retrieved from the change set.
3500 // sNumRule = dynamic_cast<const SwNumRuleItem*>(pNewValue)->GetValue();
3501 // <--
3503 // --> OD 2008-12-17 #i70748#
3504 // The new list style set at the paragraph.
3505 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3506 if ( pNumRuleAtTxtNode )
3508 sNumRule = pNumRuleAtTxtNode->GetName();
3510 // <--
3512 break;
3515 if ( sNumRule != sOldNumRule )
3517 if ( bNumRuleSet )
3519 if ( sNumRule.Len() == 0 )
3521 rTxtNode.RemoveFromList();
3522 if ( bParagraphStyleChanged )
3524 SvUShortsSort aResetAttrsArray;
3525 aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
3526 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
3527 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
3528 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
3529 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
3530 SwPaM aPam( rTxtNode );
3531 // --> OD 2008-11-28 #i96644#
3532 // suppress side effect "send data changed events"
3533 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
3534 &aResetAttrsArray,
3535 false );
3536 // <--
3539 else
3541 rTxtNode.RemoveFromList();
3542 // If new list style is the outline style, apply outline
3543 // level as the list level.
3544 if ( sNumRule ==
3545 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) )
3547 // --> OD 2008-09-10 #i70748#
3548 ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
3549 "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
3550 int nNewListLevel =
3551 rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
3552 // <--
3553 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
3555 rTxtNode.SetAttrListLevel( nNewListLevel );
3558 rTxtNode.AddToList();
3561 else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
3563 rTxtNode.RemoveFromList();
3564 if ( bParagraphStyleChanged )
3566 SvUShortsSort aResetAttrsArray;
3567 aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
3568 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
3569 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
3570 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
3571 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
3572 SwPaM aPam( rTxtNode );
3573 // --> OD 2008-11-28 #i96644#
3574 // suppress side effect "send data changed events"
3575 rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
3576 &aResetAttrsArray,
3577 false );
3578 // <--
3579 // --> OD 2008-11-19 #i70748#
3580 if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, FALSE )).GetValue() > 0 )
3582 rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
3584 // <--
3588 else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
3590 rTxtNode.AddToList();
3592 // <--
3594 // End of method <HandleModifyAtTxtNode>
3596 // <--
3598 void SwTxtNode::Modify( SfxPoolItem* pOldValue, SfxPoolItem* pNewValue )
3600 bool bWasNotifiable = m_bNotifiable;
3601 m_bNotifiable = false;
3603 // Bug 24616/24617:
3604 // Modify ueberladen, damit beim Loeschen von Vorlagen diese
3605 // wieder richtig verwaltet werden (Outline-Numerierung!!)
3606 // Bug25481:
3607 // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
3608 if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
3609 pRegisteredIn == ((SwFmtChg*)pNewValue)->pChangedFmt &&
3610 GetNodes().IsDocNodes() )
3612 _ChgTxtCollUpdateNum(
3613 (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
3614 (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
3617 // --> OD 2008-03-27 #refactorlists#
3618 if ( !mbInSetOrResetAttr )
3620 HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
3622 // <--
3624 SwCntntNode::Modify( pOldValue, pNewValue );
3626 SwDoc * pDoc = GetDoc();
3627 // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array
3628 if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
3629 // <--
3631 pDoc->GetNodes().UpdateOutlineNode(*this);
3634 m_bNotifiable = bWasNotifiable;
3637 SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
3639 ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." );
3640 ASSERT( HAS_BASE( SwTxtFmtColl, pNewColl ),
3641 "ChgFmtColl: ist kein Text-Collectionpointer." );
3643 SwTxtFmtColl *pOldColl = GetTxtColl();
3644 if( pNewColl != pOldColl )
3646 SetCalcHiddenCharFlags();
3647 SwCntntNode::ChgFmtColl( pNewColl );
3648 // --> OD 2008-03-27 #refactorlists#
3649 // NumRuleChgd();
3650 #if OSL_DEBUG_LEVEL > 1
3651 ASSERT( !mbInSetOrResetAttr,
3652 "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" )
3653 #endif
3654 if ( !mbInSetOrResetAttr )
3656 SwFmtChg aTmp1( pOldColl );
3657 SwFmtChg aTmp2( pNewColl );
3658 HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 );
3660 // <--
3663 // nur wenn im normalen Nodes-Array
3664 if( GetNodes().IsDocNodes() )
3666 _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
3669 GetNodes().UpdateOutlineNode(*this);
3671 return pOldColl;
3674 SwNodeNum* SwTxtNode::CreateNum() const
3676 if ( !mpNodeNum )
3678 // --> OD 2008-02-19 #refactorlists#
3679 mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
3680 // <--
3682 return mpNodeNum;
3685 SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
3687 if ( GetNum() )
3689 return GetNum()->GetNumberVector();
3691 else
3693 SwNumberTree::tNumberVector aResult;
3694 return aResult;
3698 bool SwTxtNode::IsOutline() const
3700 bool bResult = false;
3702 //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei
3703 if ( GetAttrOutlineLevel() > 0 ) //<-end,zhaojianwei
3705 bResult = !IsInRedlines();
3707 else
3709 const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
3710 if ( pRule && pRule->IsOutlineRule() )
3712 bResult = !IsInRedlines();
3716 return bResult;
3719 bool SwTxtNode::IsOutlineStateChanged() const
3721 return IsOutline() != m_bLastOutlineState;
3724 void SwTxtNode::UpdateOutlineState()
3726 m_bLastOutlineState = IsOutline();
3729 //#outline level, zhaojianwei
3730 int SwTxtNode::GetAttrOutlineLevel() const
3732 return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
3734 void SwTxtNode::SetAttrOutlineLevel(int nLevel)
3736 ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei
3737 if ( 0 <= nLevel && nLevel <= MAXLEVEL )
3739 SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
3740 static_cast<UINT16>(nLevel) ) );
3743 //<-end
3745 // --> OD 2008-11-19 #i70748#
3746 bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
3748 return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
3751 void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
3753 if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3755 SetAttr( SwNumRuleItem() );
3756 mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
3760 void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
3762 if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3764 ResetAttr( RES_PARATR_NUMRULE );
3765 mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
3768 // <--
3771 // --> OD 2008-02-27 #refactorlists#
3772 void SwTxtNode::SetAttrListLevel( int nLevel )
3774 if ( nLevel < 0 || nLevel >= MAXLEVEL )
3776 ASSERT( false,
3777 "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" );
3778 return;
3781 SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
3782 static_cast<INT16>(nLevel) );
3783 SetAttr( aNewListLevelItem );
3785 // <--
3786 // --> OD 2008-02-27 #refactorlists#
3787 bool SwTxtNode::HasAttrListLevel() const
3789 return GetpSwAttrSet() &&
3790 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, FALSE ) == SFX_ITEM_SET;
3792 // <--
3793 // --> OD 2008-02-27 #refactorlists#
3794 int SwTxtNode::GetAttrListLevel() const
3796 int nAttrListLevel = 0;
3798 const SfxInt16Item& aListLevelItem =
3799 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
3800 nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
3802 return nAttrListLevel;
3804 // <--
3806 int SwTxtNode::GetActualListLevel() const
3808 return GetNum() ? GetNum()->GetLevelInListTree() : -1;
3811 // --> OD 2008-02-25 #refactorlists#
3812 void SwTxtNode::SetListRestart( bool bRestart )
3814 // CreateNum()->SetRestart(bRestart);
3815 if ( !bRestart )
3817 // attribute not contained in paragraph style's attribute set. Thus,
3818 // it can be reset to the attribute pool default by resetting the attribute.
3819 ResetAttr( RES_PARATR_LIST_ISRESTART );
3821 else
3823 SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
3824 TRUE );
3825 SetAttr( aNewIsRestartItem );
3829 // --> OD 2008-02-25 #refactorlists#
3830 bool SwTxtNode::IsListRestart() const
3832 // return GetNum() ? GetNum()->IsRestart() : false;
3833 const SfxBoolItem& aIsRestartItem =
3834 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));
3836 return aIsRestartItem.GetValue() ? true : false;
3838 // <--
3840 /** Returns if the paragraph has a visible numbering or bullet.
3841 This includes all kinds of numbering/bullet/outlines.
3842 OD 2008-02-28 #newlistlevelattrs#
3843 The concrete list label string has to be checked, too.
3845 bool SwTxtNode::HasVisibleNumberingOrBullet() const
3847 bool bRet = false;
3849 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
3850 if ( pRule && IsCountedInList())
3852 // --> OD 2008-03-19 #i87154#
3853 // Correction of #newlistlevelattrs#:
3854 // The numbering type has to be checked for bullet lists.
3855 const SwNumFmt& rFmt = pRule->Get( static_cast<USHORT>(GetActualListLevel() ));
3856 if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
3857 pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
3859 bRet = true;
3861 // <--
3864 return bRet;
3867 // --> OD 2008-02-25 #refactorlists#
3868 void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
3870 // CreateNum()->SetStart(nNumber);
3871 const bool bChanged( HasAttrListRestartValue()
3872 ? GetAttrListRestartValue() != nNumber
3873 : nNumber != USHRT_MAX );
3875 if ( bChanged || !HasAttrListRestartValue() )
3877 if ( nNumber == USHRT_MAX )
3879 ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
3881 else
3883 SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
3884 static_cast<INT16>(nNumber) );
3885 SetAttr( aNewListRestartValueItem );
3889 // <--
3891 // --> OD 2008-02-27 #refactorlists#
3892 bool SwTxtNode::HasAttrListRestartValue() const
3894 return GetpSwAttrSet() &&
3895 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, FALSE ) == SFX_ITEM_SET;
3897 // <--
3898 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
3900 ASSERT( HasAttrListRestartValue(),
3901 "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
3903 const SfxInt16Item& aListRestartValueItem =
3904 dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
3905 return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
3908 // --> OD 2008-02-25 #refactorlists#
3909 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
3911 // return GetNum() ? GetNum()->GetStart() : 1;
3912 SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
3914 if ( IsListRestart() && HasAttrListRestartValue() )
3916 nListRestartValue = GetAttrListRestartValue();
3918 else
3920 SwNumRule* pRule = GetNumRule();
3921 if ( pRule )
3923 const SwNumFmt* pFmt =
3924 pRule->GetNumFmt( static_cast<USHORT>(GetAttrListLevel()) );
3925 if ( pFmt )
3927 nListRestartValue = pFmt->GetStart();
3932 return nListRestartValue;
3934 // <--
3936 bool SwTxtNode::IsNotifiable() const
3938 return m_bNotifiable && IsNotificationEnabled();
3941 bool SwTxtNode::IsNotificationEnabled() const
3943 bool bResult = false;
3944 const SwDoc * pDoc = GetDoc();
3945 if( pDoc )
3947 bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
3949 return bResult;
3952 // --> OD 2008-02-27 #refactorlists#
3953 void SwTxtNode::SetCountedInList( bool bCounted )
3955 if ( bCounted )
3957 // attribute not contained in paragraph style's attribute set. Thus,
3958 // it can be reset to the attribute pool default by resetting the attribute.
3959 ResetAttr( RES_PARATR_LIST_ISCOUNTED );
3961 else
3963 SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, FALSE );
3964 SetAttr( aIsCountedInListItem );
3967 // <--
3969 bool SwTxtNode::IsCountedInList() const
3971 const SfxBoolItem& aIsCountedInListItem =
3972 dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));
3974 return aIsCountedInListItem.GetValue() ? true : false;
3977 // --> OD 2008-03-13 #refactorlists#
3978 void SwTxtNode::AddToList()
3980 if ( IsInList() )
3982 ASSERT( false,
3983 "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
3984 return;
3987 const String sListId = GetListId();
3988 if ( sListId.Len() > 0 )
3990 SwList* pList = GetDoc()->getListByName( sListId );
3991 if ( pList == 0 )
3993 // Create corresponding list.
3994 SwNumRule* pNumRule = GetNumRule();
3995 if ( pNumRule )
3997 pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
4000 ASSERT( pList != 0,
4001 "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
4002 if ( pList )
4004 pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
4005 mpList = pList;
4010 void SwTxtNode::RemoveFromList()
4012 if ( IsInList() )
4014 mpList->RemoveListItem( *mpNodeNum );
4015 mpList = 0;
4016 delete mpNodeNum;
4017 mpNodeNum = 0L;
4021 bool SwTxtNode::IsInList() const
4023 return GetNum() != 0 && GetNum()->GetParent() != 0;
4025 // <--
4027 bool SwTxtNode::IsFirstOfNumRule() const
4029 bool bResult = false;
4031 if ( GetNum() && GetNum()->GetNumRule())
4032 bResult = GetNum()->IsFirst();
4034 return bResult;
4037 // --> OD 2008-02-20 #refactorlists#
4038 void SwTxtNode::SetListId( const String sListId )
4040 const SfxStringItem& rListIdItem =
4041 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4042 if ( rListIdItem.GetValue() != sListId )
4044 if ( sListId.Len() == 0 )
4046 ResetAttr( RES_PARATR_LIST_ID );
4048 else
4050 SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
4051 SetAttr( aNewListIdItem );
4056 String SwTxtNode::GetListId() const
4058 String sListId;
4060 const SfxStringItem& rListIdItem =
4061 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4062 sListId = rListIdItem.GetValue();
4064 // As long as no explicit list id attribute is set, use the list id of
4065 // the list, which has been created for the applied list style.
4066 if ( sListId.Len() == 0 )
4068 SwNumRule* pRule = GetNumRule();
4069 if ( pRule )
4071 sListId = pRule->GetDefaultListId();
4072 //#if OSL_DEBUG_LEVEL > 1
4073 // ASSERT( false,
4074 // "DEBUG ASSERTION: default list id of list style is applied." );
4075 //#endif
4076 // // setting list id directly using <SwCntntNode::SetAttr(..)>,
4077 // // because no handling of this attribute set is needed and to avoid
4078 // // recursive calls of <SwTxtNode::SetAttr(..)>
4079 // SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
4080 // const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem );
4084 return sListId;
4086 // <--
4088 /** Determines, if the list level indent attributes can be applied to the
4089 paragraph.
4091 OD 2008-01-17 #newlistlevelattrs#
4092 The list level indents can be applied to the paragraph under the one
4093 of following conditions:
4094 - the list style is directly applied to the paragraph and the paragraph
4095 has no own indent attributes.
4096 - the list style is applied to the paragraph through one of its paragraph
4097 styles, the paragraph has no own indent attributes and on the paragraph
4098 style hierarchy from the paragraph to the paragraph style with the
4099 list style no indent attributes are found.
4101 @author OD
4103 @return boolean
4105 bool SwTxtNode::AreListLevelIndentsApplicable() const
4107 bool bAreListLevelIndentsApplicable( true );
4109 if ( !GetNum() || !GetNum()->GetNumRule() )
4111 // no list style applied to paragraph
4112 bAreListLevelIndentsApplicable = false;
4114 else if ( HasSwAttrSet() &&
4115 GetpSwAttrSet()->GetItemState( RES_LR_SPACE, FALSE ) == SFX_ITEM_SET )
4117 // paragraph has hard-set indent attributes
4118 bAreListLevelIndentsApplicable = false;
4120 else if ( HasSwAttrSet() &&
4121 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, FALSE ) == SFX_ITEM_SET )
4123 // list style is directly applied to paragraph and paragraph has no
4124 // hard-set indent attributes
4125 bAreListLevelIndentsApplicable = true;
4127 else
4129 // list style is applied through one of the paragraph styles and
4130 // paragraph has no hard-set indent attributes
4132 // check, paragraph's
4133 const SwTxtFmtColl* pColl = GetTxtColl();
4134 while ( pColl )
4136 if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, FALSE ) == SFX_ITEM_SET )
4138 // indent attributes found in the paragraph style hierarchy.
4139 bAreListLevelIndentsApplicable = false;
4140 break;
4143 if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, FALSE ) == SFX_ITEM_SET )
4145 // paragraph style with the list style found and until now no
4146 // indent attributes are found in the paragraph style hierarchy.
4147 bAreListLevelIndentsApplicable = true;
4148 break;
4151 pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
4152 ASSERT( pColl,
4153 "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
4157 return bAreListLevelIndentsApplicable;
4160 /** Retrieves the list tab stop position, if the paragraph's list level defines
4161 one and this list tab stop has to merged into the tap stops of the paragraph
4163 OD 2008-01-17 #newlistlevelattrs#
4165 @author OD
4167 @param nListTabStopPosition
4168 output parameter - containing the list tab stop position
4170 @return boolean - indicating, if a list tab stop position is provided
4172 bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
4174 bool bListTanStopPositionProvided( false );
4176 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4177 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4179 const SwNumFmt& rFmt = pNumRule->Get( static_cast<USHORT>(GetActualListLevel()) );
4180 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
4181 rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
4183 bListTanStopPositionProvided = true;
4184 nListTabStopPosition = rFmt.GetListtabPos();
4186 if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
4188 // tab stop position are treated to be relative to the "before text"
4189 // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
4190 if ( AreListLevelIndentsApplicable() )
4192 nListTabStopPosition -= rFmt.GetIndentAt();
4194 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
4196 SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
4197 nListTabStopPosition -= aItem.GetTxtLeft();
4203 return bListTanStopPositionProvided;
4206 /** Retrieves the character following the list label, if the paragraph's
4207 list level defines one.
4209 OD 2008-01-17 #newlistlevelattrs#
4211 @author OD
4213 @return XubString - the list tab stop position
4215 XubString SwTxtNode::GetLabelFollowedBy() const
4217 XubString aLabelFollowedBy;
4219 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4220 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4222 const SwNumFmt& rFmt = pNumRule->Get( static_cast<USHORT>(GetActualListLevel()) );
4223 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
4225 switch ( rFmt.GetLabelFollowedBy() )
4227 case SvxNumberFormat::LISTTAB:
4229 const sal_Unicode aTab = '\t';
4230 aLabelFollowedBy.Insert( aTab, 0 );
4232 break;
4233 case SvxNumberFormat::SPACE:
4235 const sal_Unicode aSpace = ' ';
4236 aLabelFollowedBy.Insert( aSpace, 0 );
4238 break;
4239 case SvxNumberFormat::NOTHING:
4241 // intentionally left blank.
4243 break;
4244 default:
4246 ASSERT( false,
4247 "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
4253 return aLabelFollowedBy;
4256 void SwTxtNode::CalcHiddenCharFlags() const
4258 xub_StrLen nStartPos;
4259 xub_StrLen nEndPos;
4260 // Update of the flags is done inside GetBoundsOfHiddenRange()
4261 SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
4264 // --> FME 2004-06-08 #i12836# enhanced pdf export
4265 bool SwTxtNode::IsHidden() const
4267 if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
4268 return true;
4270 const SwSectionNode* pSectNd = FindSectionNode();
4271 if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
4272 return true;
4274 return false;
4276 // <--
4278 // --> OD 2008-03-13 #refactorlists#
4279 namespace {
4280 // Helper class for special handling of setting attributes at text node:
4281 // In constructor an instance of the helper class recognize whose attributes
4282 // are set and perform corresponding actions before the intrinsic set of
4283 // attributes has been taken place.
4284 // In the destructor - after the attributes have been set at the text
4285 // node - corresponding actions are performed.
4286 // The following is handled:
4287 // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
4288 // (A) list style attribute is empty -> the text node is removed from
4289 // its list.
4290 // (B) list style attribute is not empty
4291 // (a) text node has no list style -> add text node to its list after
4292 // the attributes have been set.
4293 // (b) text node has list style -> change of list style is notified
4294 // after the attributes have been set.
4295 // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
4296 // the text node is removed from its current list before the attributes
4297 // are set and added to its new list after the attributes have been set.
4298 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
4299 // and changed after the attributes have been set
4300 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
4301 // and changed after the attributes have been set
4302 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
4303 // is set and changed after the attributes have been set
4304 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
4305 // and changed after the attributes have been set
4306 // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
4307 class HandleSetAttrAtTxtNode
4309 public:
4310 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4311 const SfxPoolItem& pItem );
4312 HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4313 const SfxItemSet& rItemSet );
4314 ~HandleSetAttrAtTxtNode();
4316 private:
4317 SwTxtNode& mrTxtNode;
4318 bool mbAddTxtNodeToList;
4319 bool mbUpdateListLevel;
4320 bool mbUpdateListRestart;
4321 bool mbUpdateListCount;
4322 // --> OD 2008-11-19 #i70748#
4323 bool mbOutlineLevelSet;
4324 // <--
4327 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4328 const SfxPoolItem& pItem )
4329 : mrTxtNode( rTxtNode ),
4330 mbAddTxtNodeToList( false ),
4331 mbUpdateListLevel( false ),
4332 mbUpdateListRestart( false ),
4333 mbUpdateListCount( false ),
4334 // --> OD 2008-11-19 #i70748#
4335 mbOutlineLevelSet( false )
4336 // <--
4338 switch ( pItem.Which() )
4340 // handle RES_PARATR_NUMRULE
4341 case RES_PARATR_NUMRULE:
4343 mrTxtNode.RemoveFromList();
4345 const SwNumRuleItem& pNumRuleItem =
4346 dynamic_cast<const SwNumRuleItem&>(pItem);
4347 if ( pNumRuleItem.GetValue().Len() > 0 )
4349 mbAddTxtNodeToList = true;
4352 break;
4354 // handle RES_PARATR_LIST_ID
4355 case RES_PARATR_LIST_ID:
4357 const SfxStringItem& pListIdItem =
4358 dynamic_cast<const SfxStringItem&>(pItem);
4359 ASSERT( pListIdItem.GetValue().Len() > 0,
4360 "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
4361 // const SfxStringItem& rListIdItemOfTxtNode =
4362 // dynamic_cast<const SfxStringItem&>(
4363 // rTxtNode.GetAttr( RES_PARATR_LIST_ID ));
4364 // if ( pListIdItem.GetValue() != rListIdItemOfTxtNode.GetValue() )
4365 const String sListIdOfTxtNode = rTxtNode.GetListId();
4366 if ( pListIdItem.GetValue() != sListIdOfTxtNode )
4368 mbAddTxtNodeToList = true;
4369 if ( mrTxtNode.IsInList() )
4371 mrTxtNode.RemoveFromList();
4375 break;
4377 // handle RES_PARATR_LIST_LEVEL
4378 case RES_PARATR_LIST_LEVEL:
4380 const SfxInt16Item& aListLevelItem =
4381 dynamic_cast<const SfxInt16Item&>(pItem);
4382 if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
4384 mbUpdateListLevel = true;
4387 break;
4389 // handle RES_PARATR_LIST_ISRESTART
4390 case RES_PARATR_LIST_ISRESTART:
4392 const SfxBoolItem& aListIsRestartItem =
4393 dynamic_cast<const SfxBoolItem&>(pItem);
4394 if ( aListIsRestartItem.GetValue() !=
4395 (mrTxtNode.IsListRestart() ? TRUE : FALSE) )
4397 mbUpdateListRestart = true;
4400 break;
4402 // handle RES_PARATR_LIST_RESTARTVALUE
4403 case RES_PARATR_LIST_RESTARTVALUE:
4405 const SfxInt16Item& aListRestartValueItem =
4406 dynamic_cast<const SfxInt16Item&>(pItem);
4407 if ( !mrTxtNode.HasAttrListRestartValue() ||
4408 aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
4410 mbUpdateListRestart = true;
4413 break;
4415 // handle RES_PARATR_LIST_ISCOUNTED
4416 case RES_PARATR_LIST_ISCOUNTED:
4418 const SfxBoolItem& aIsCountedInListItem =
4419 dynamic_cast<const SfxBoolItem&>(pItem);
4420 if ( aIsCountedInListItem.GetValue() !=
4421 (mrTxtNode.IsCountedInList() ? TRUE : FALSE) )
4423 mbUpdateListCount = true;
4426 break;
4428 // --> OD 2008-11-19 #i70748#
4429 // handle RES_PARATR_OUTLINELEVEL
4430 case RES_PARATR_OUTLINELEVEL:
4432 const SfxUInt16Item& aOutlineLevelItem =
4433 dynamic_cast<const SfxUInt16Item&>(pItem);
4434 if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4436 mbOutlineLevelSet = true;
4439 break;
4440 // <--
4445 HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4446 const SfxItemSet& rItemSet )
4447 : mrTxtNode( rTxtNode ),
4448 mbAddTxtNodeToList( false ),
4449 mbUpdateListLevel( false ),
4450 mbUpdateListRestart( false ),
4451 mbUpdateListCount( false ),
4452 // --> OD 2008-11-19 #i70748#
4453 mbOutlineLevelSet( false )
4454 // <--
4456 const SfxPoolItem* pItem = 0;
4457 // handle RES_PARATR_NUMRULE
4458 if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ) == SFX_ITEM_SET )
4460 mrTxtNode.RemoveFromList();
4462 const SwNumRuleItem* pNumRuleItem =
4463 dynamic_cast<const SwNumRuleItem*>(pItem);
4464 if ( pNumRuleItem->GetValue().Len() > 0 )
4466 mbAddTxtNodeToList = true;
4467 // --> OD 2008-11-19 #i70748#
4468 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4469 // <--
4473 // handle RES_PARATR_LIST_ID
4474 if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, FALSE, &pItem ) == SFX_ITEM_SET )
4476 const SfxStringItem* pListIdItem =
4477 dynamic_cast<const SfxStringItem*>(pItem);
4478 // const SfxStringItem& rListIdItemOfTxtNode =
4479 // dynamic_cast<const SfxStringItem&>(
4480 // mrTxtNode.GetAttr( RES_PARATR_LIST_ID ));
4481 // if ( pListIdItem &&
4482 // pListIdItem->GetValue() != rListIdItemOfTxtNode.GetValue() )
4483 const String sListIdOfTxtNode = mrTxtNode.GetListId();
4484 if ( pListIdItem &&
4485 pListIdItem->GetValue() != sListIdOfTxtNode )
4487 mbAddTxtNodeToList = true;
4488 if ( mrTxtNode.IsInList() )
4490 mrTxtNode.RemoveFromList();
4495 // handle RES_PARATR_LIST_LEVEL
4496 if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, FALSE, &pItem ) == SFX_ITEM_SET )
4498 const SfxInt16Item* pListLevelItem =
4499 dynamic_cast<const SfxInt16Item*>(pItem);
4500 if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
4502 mbUpdateListLevel = true;
4506 // handle RES_PARATR_LIST_ISRESTART
4507 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, FALSE, &pItem ) == SFX_ITEM_SET )
4509 const SfxBoolItem* pListIsRestartItem =
4510 dynamic_cast<const SfxBoolItem*>(pItem);
4511 if ( pListIsRestartItem->GetValue() !=
4512 (mrTxtNode.IsListRestart() ? TRUE : FALSE) )
4514 mbUpdateListRestart = true;
4518 // handle RES_PARATR_LIST_RESTARTVALUE
4519 if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, FALSE, &pItem ) == SFX_ITEM_SET )
4521 const SfxInt16Item* pListRestartValueItem =
4522 dynamic_cast<const SfxInt16Item*>(pItem);
4523 if ( !mrTxtNode.HasAttrListRestartValue() ||
4524 pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
4526 mbUpdateListRestart = true;
4530 // handle RES_PARATR_LIST_ISCOUNTED
4531 if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, FALSE, &pItem ) == SFX_ITEM_SET )
4533 const SfxBoolItem* pIsCountedInListItem =
4534 dynamic_cast<const SfxBoolItem*>(pItem);
4535 if ( pIsCountedInListItem->GetValue() !=
4536 (mrTxtNode.IsCountedInList() ? TRUE : FALSE) )
4538 mbUpdateListCount = true;
4542 // --> OD 2008-11-19 #i70748#
4543 // handle RES_PARATR_OUTLINELEVEL
4544 if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, FALSE, &pItem ) == SFX_ITEM_SET )
4546 const SfxUInt16Item* pOutlineLevelItem =
4547 dynamic_cast<const SfxUInt16Item*>(pItem);
4548 if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4550 mbOutlineLevelSet = true;
4553 // <--
4556 HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
4558 if ( mbAddTxtNodeToList )
4560 SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
4561 if ( pNumRuleAtTxtNode )
4563 mrTxtNode.AddToList();
4566 else
4568 if ( mbUpdateListLevel && mrTxtNode.IsInList() )
4570 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
4571 mrTxtNode.GetAttrListLevel() );
4574 if ( mbUpdateListRestart && mrTxtNode.IsInList() )
4576 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4577 pNodeNum->InvalidateMe();
4578 pNodeNum->NotifyInvalidSiblings();
4581 if ( mbUpdateListCount && mrTxtNode.IsInList() )
4583 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
4587 // --> OD 2008-11-19 #i70748#
4588 if ( mbOutlineLevelSet )
4590 if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
4592 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4594 else
4596 const SfxPoolItem* pItem = 0;
4597 if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
4598 TRUE, &pItem )
4599 != SFX_ITEM_SET )
4601 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4605 // <--
4607 // End of class <HandleSetAttrAtTxtNode>
4610 BOOL SwTxtNode::SetAttr( const SfxPoolItem& pItem )
4612 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4613 mbInSetOrResetAttr = true;
4615 HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );
4617 BOOL bRet = SwCntntNode::SetAttr( pItem );
4619 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4621 return bRet;
4624 BOOL SwTxtNode::SetAttr( const SfxItemSet& rSet )
4626 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4627 mbInSetOrResetAttr = true;
4629 HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );
4631 BOOL bRet = SwCntntNode::SetAttr( rSet );
4633 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4635 return bRet;
4638 namespace {
4639 // Helper class for special handling of resetting attributes at text node:
4640 // In constructor an instance of the helper class recognize whose attributes
4641 // are reset and perform corresponding actions before the intrinsic reset of
4642 // attributes has been taken place.
4643 // In the destructor - after the attributes have been reset at the text
4644 // node - corresponding actions are performed.
4645 // The following is handled:
4646 // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
4647 // the text is removed from its list before the attributes have been reset.
4648 // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
4649 // the text is removed from its list before the attributes have been reset.
4650 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
4651 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
4652 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
4653 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
4654 // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
4655 class HandleResetAttrAtTxtNode
4657 public:
4658 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4659 const USHORT nWhich1,
4660 const USHORT nWhich2 );
4661 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4662 const SvUShorts& rWhichArr );
4663 HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );
4665 ~HandleResetAttrAtTxtNode();
4667 private:
4668 SwTxtNode& mrTxtNode;
4669 bool mbListStyleOrIdReset;
4670 bool mbUpdateListLevel;
4671 bool mbUpdateListRestart;
4672 bool mbUpdateListCount;
4675 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4676 const USHORT nWhich1,
4677 const USHORT nWhich2 )
4678 : mrTxtNode( rTxtNode ),
4679 mbListStyleOrIdReset( false ),
4680 mbUpdateListLevel( false ),
4681 mbUpdateListRestart( false ),
4682 mbUpdateListCount( false )
4684 bool bRemoveFromList( false );
4685 if ( nWhich2 != 0 && nWhich2 > nWhich1 )
4687 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4688 if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
4690 bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4691 mbListStyleOrIdReset = true;
4693 else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
4695 bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4696 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET;
4697 // --> OD 2008-10-20 #i92898#
4698 mbListStyleOrIdReset = true;
4699 // <--
4702 if ( !bRemoveFromList )
4704 // RES_PARATR_LIST_LEVEL
4705 mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
4706 RES_PARATR_LIST_LEVEL <= nWhich2 &&
4707 mrTxtNode.HasAttrListLevel() );
4709 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4710 mbUpdateListRestart =
4711 ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
4712 mrTxtNode.IsListRestart() ) ||
4713 ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
4714 mrTxtNode.HasAttrListRestartValue() );
4716 // RES_PARATR_LIST_ISCOUNTED
4717 mbUpdateListCount =
4718 ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
4719 !mrTxtNode.IsCountedInList() );
4722 // --> OD 2008-11-19 #i70748#
4723 // RES_PARATR_OUTLINELEVEL
4724 if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
4726 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4728 // <--
4730 else
4732 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4733 if ( nWhich1 == RES_PARATR_NUMRULE )
4735 bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4736 mbListStyleOrIdReset = true;
4738 else if ( nWhich1 == RES_PARATR_LIST_ID )
4740 bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4741 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET;
4742 // --> OD 2008-10-20 #i92898#
4743 mbListStyleOrIdReset = true;
4744 // <--
4746 // --> OD 2008-11-19 #i70748#
4747 // RES_PARATR_OUTLINELEVEL
4748 else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
4750 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4752 // <--
4754 if ( !bRemoveFromList )
4756 // RES_PARATR_LIST_LEVEL
4757 mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
4758 mrTxtNode.HasAttrListLevel();
4760 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4761 mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
4762 mrTxtNode.IsListRestart() ) ||
4763 ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
4764 mrTxtNode.HasAttrListRestartValue() );
4766 // RES_PARATR_LIST_ISCOUNTED
4767 mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
4768 !mrTxtNode.IsCountedInList();
4772 if ( bRemoveFromList && mrTxtNode.IsInList() )
4774 mrTxtNode.RemoveFromList();
4778 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4779 const SvUShorts& rWhichArr )
4780 : mrTxtNode( rTxtNode ),
4781 mbListStyleOrIdReset( false ),
4782 mbUpdateListLevel( false ),
4783 mbUpdateListRestart( false ),
4784 mbUpdateListCount( false )
4786 bool bRemoveFromList( false );
4788 const USHORT nEnd = rWhichArr.Count();
4789 for ( USHORT n = 0; n < nEnd; ++n )
4791 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4792 if ( rWhichArr[ n ] == RES_PARATR_NUMRULE )
4794 bRemoveFromList = bRemoveFromList ||
4795 mrTxtNode.GetNumRule() != 0;
4796 mbListStyleOrIdReset = true;
4798 else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID )
4800 bRemoveFromList = bRemoveFromList ||
4801 ( mrTxtNode.GetpSwAttrSet() &&
4802 mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, FALSE ) == SFX_ITEM_SET );
4803 // --> OD 2008-10-20 #i92898#
4804 mbListStyleOrIdReset = true;
4805 // <--
4807 // --> OD 2008-11-19 #i70748#
4808 // RES_PARATR_OUTLINELEVEL
4809 else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL )
4811 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4813 // <--
4815 if ( !bRemoveFromList )
4817 // RES_PARATR_LIST_LEVEL
4818 mbUpdateListLevel = mbUpdateListLevel ||
4819 ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL &&
4820 mrTxtNode.HasAttrListLevel() );
4822 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4823 mbUpdateListRestart = mbUpdateListRestart ||
4824 ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART &&
4825 mrTxtNode.IsListRestart() ) ||
4826 ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE &&
4827 mrTxtNode.HasAttrListRestartValue() );
4829 // RES_PARATR_LIST_ISCOUNTED
4830 mbUpdateListCount = mbUpdateListCount ||
4831 ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED &&
4832 !mrTxtNode.IsCountedInList() );
4837 if ( bRemoveFromList && mrTxtNode.IsInList() )
4839 mrTxtNode.RemoveFromList();
4843 HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
4844 : mrTxtNode( rTxtNode ),
4845 mbListStyleOrIdReset( false ),
4846 mbUpdateListLevel( false ),
4847 mbUpdateListRestart( false ),
4848 mbUpdateListCount( false )
4850 mbListStyleOrIdReset = true;
4851 if ( rTxtNode.IsInList() )
4853 rTxtNode.RemoveFromList();
4855 // --> OD 2008-11-19 #i70748#
4856 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4857 // <--
4860 HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
4862 if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
4864 // check, if in spite of the reset of the list style or the list id
4865 // the paragraph still has to be added to a list.
4866 if ( mrTxtNode.GetNumRule() &&
4867 mrTxtNode.GetListId().Len() > 0 )
4869 // --> OD 2009-01-14 #i96062#
4870 // If paragraph has no list level attribute set and list style
4871 // is the outline style, apply outline level as the list level.
4872 if ( !mrTxtNode.HasAttrListLevel() &&
4873 mrTxtNode.GetNumRule()->GetName() ==
4874 String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) &&
4875 mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
4877 int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
4878 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
4880 mrTxtNode.SetAttrListLevel( nNewListLevel );
4883 // <--
4884 mrTxtNode.AddToList();
4886 // --> OD 2008-11-19 #i70748#
4887 else if ( dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, FALSE )).GetValue() > 0 )
4889 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4891 // <--
4894 if ( mrTxtNode.IsInList() )
4896 if ( mbUpdateListLevel )
4898 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4899 pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
4902 if ( mbUpdateListRestart )
4904 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4905 pNodeNum->InvalidateMe();
4906 pNodeNum->NotifyInvalidSiblings();
4909 if ( mbUpdateListCount )
4911 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4912 pNodeNum->InvalidateAndNotifyTree();
4916 // End of class <HandleResetAttrAtTxtNode>
4919 BOOL SwTxtNode::ResetAttr( USHORT nWhich1, USHORT nWhich2 )
4921 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4922 mbInSetOrResetAttr = true;
4924 HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );
4926 BOOL bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );
4928 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4930 return bRet;
4933 BOOL SwTxtNode::ResetAttr( const SvUShorts& rWhichArr )
4935 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4936 mbInSetOrResetAttr = true;
4938 HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );
4940 BOOL bRet = SwCntntNode::ResetAttr( rWhichArr );
4942 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4944 return bRet;
4947 USHORT SwTxtNode::ResetAllAttr()
4949 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4950 mbInSetOrResetAttr = true;
4952 HandleResetAttrAtTxtNode aHandleResetAttr( *this );
4954 USHORT nRet = SwCntntNode::ResetAllAttr();
4956 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4958 return nRet;
4960 // <--
4963 // sw::Metadatable
4964 ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
4966 return GetDoc()->GetXmlIdRegistry();
4969 bool SwTxtNode::IsInClipboard() const
4971 return GetDoc()->IsClipBoard();
4974 bool SwTxtNode::IsInUndo() const
4976 return &GetNodes() == GetDoc()->GetUndoNds();
4979 bool SwTxtNode::IsInContent() const
4981 return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
4984 #include <unoobj.hxx>
4986 ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable >
4987 SwTxtNode::MakeUnoObject()
4989 // re-use existing SwXParagraph
4990 SwClientIter iter( *this );
4991 SwClient * pClient( iter.First( TYPE( SwXParagraph ) ) );
4992 while (pClient) {
4993 SwXParagraph *pPara( dynamic_cast<SwXParagraph*>(pClient) );
4994 if (pPara && pPara->GetCoreObject() == this ) {
4995 return pPara;
4997 pClient = iter.Next();
5000 // create new SwXParagraph
5001 SwPosition Pos( *this );
5002 ::com::sun::star::uno::Reference< ::com::sun::star::text::XText > xParent(
5003 SwXTextRange::CreateParentXText( GetDoc(), Pos ) );
5004 SwXParagraph * pXPara( new SwXParagraph( xParent, this ) );
5005 return pXPara;