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