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