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