xref: /aoo42x/main/sw/source/core/txtnode/ndtxt.cxx (revision 69a74367)
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     SwIndexReg aTmpIdxReg;
1032     if ( !bNegative && !bDelete )
1033     {
1034         const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
1035         for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1036         {
1037             SwRedline *const pRedl = rTbl[ i ];
1038             if ( pRedl->HasMark() )
1039             {
1040                 SwPosition* const pEnd = pRedl->End();
1041                 if ( this == &pEnd->nNode.GetNode() &&
1042                      *pRedl->GetPoint() != *pRedl->GetMark() )
1043                 {
1044                     SwIndex & rIdx = pEnd->nContent;
1045                     if (nChangePos == rIdx.GetIndex())
1046                     {
1047                         rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1048                     }
1049                 }
1050             }
1051             else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
1052             {
1053                 SwIndex & rIdx = pRedl->GetPoint()->nContent;
1054                 if (nChangePos == rIdx.GetIndex())
1055                 {
1056                     rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1057                     // mst: FIXME: why does this adjust the unused position???
1058                     SwIndex * pIdx;
1059                     if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
1060                     {
1061                         pRedl->GetBound( false ) = pRedl->GetBound( true );
1062                         pIdx = &pRedl->GetBound( false ).nContent;
1063                     }
1064                     else
1065                     {
1066                         pRedl->GetBound( true ) = pRedl->GetBound( false );
1067                         pIdx = &pRedl->GetBound( true ).nContent;
1068                     }
1069                     pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
1070                 }
1071             }
1072         }
1073 
1074         const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
1075         for ( IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getMarksBegin();
1076               ppMark != pMarkAccess->getMarksEnd();
1077               ppMark++ )
1078         {
1079             // Bookmarks must never grow to either side, when
1080             // editing (directly) to the left or right (#i29942#)!
1081             // And a bookmark with same start and end must remain
1082             // to the left of the inserted text (used in XML import).
1083             const ::sw::mark::IMark* const pMark = ppMark->get();
1084             const SwPosition* pEnd = &pMark->GetMarkEnd();
1085             SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent);
1086             if( this == &pEnd->nNode.GetNode() &&
1087                 rPos.GetIndex() == rIdx.GetIndex() )
1088             {
1089                 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1090             }
1091         }
1092     }
1093 
1094     // base class
1095     SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );
1096 
1097     if ( pCollector.get() )
1098     {
1099         const sal_uInt16 nCount = pCollector->Count();
1100         for ( sal_uInt16 i = 0; i < nCount; ++i )
1101         {
1102             m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
1103         }
1104     }
1105 
1106     aTmpIdxReg.MoveTo( *this );
1107 }
1108 
1109 void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
1110 										const SwTxtFmtColl *pNewColl)
1111 {
1112 	SwDoc* pDoc = GetDoc();
1113 	ASSERT( pDoc, "Kein Doc?" );
1114 	// erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
1115 	// falls sich die Level geaendert haben !
1116 	//const sal_uInt8 nOldLevel = pOldColl ? pOldColl->GetOutlineLevel():NO_NUMBERING;//#outline level,removed by zhaojianwei
1117 	//const sal_uInt8 nNewLevel = pNewColl ? pNewColl->GetOutlineLevel():NO_NUMBERING;//<-end,zhaojianwei
1118 	const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
1119 	                 pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1120     const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
1121 					 pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1122 
1123 //	if ( NO_NUMBERING != nNewLevel )	//#outline level,zhaojianwei
1124 	if ( MAXLEVEL != nNewLevel )	//<-end,zhaojianwei
1125     {
1126         SetAttrListLevel(nNewLevel);
1127     }
1128 
1129 	{
1130         if (pDoc)
1131             pDoc->GetNodes().UpdateOutlineNode(*this);
1132     }
1133 
1134 
1135 	SwNodes& rNds = GetNodes();
1136 	// Update beim Level 0 noch die Fussnoten !!
1137 	if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() &&
1138 		FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
1139 		rNds.IsDocNodes() )
1140 	{
1141 		SwNodeIndex aTmpIndex( rNds, GetIndex());
1142 
1143 		pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
1144 	}
1145 
1146 //FEATURE::CONDCOLL
1147 	if( /*pOldColl != pNewColl && pNewColl && */
1148 		RES_CONDTXTFMTCOLL == pNewColl->Which() )
1149 	{
1150 		// Erfrage die akt. Condition des TextNodes:
1151 		ChkCondColl();
1152 	}
1153 //FEATURE::CONDCOLL
1154 }
1155 
1156 // Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
1157 // bekommt diese das DontExpand-Flag verpasst
1158 
1159 sal_Bool SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
1160 								sal_Bool bFmtToTxtAttributes )
1161 {
1162 	const xub_StrLen nIdx = rIdx.GetIndex();
1163     if ( bFmtToTxtAttributes && nIdx == m_Text.Len() )
1164     {
1165         FmtToTxtAttr( this );
1166     }
1167 
1168 	sal_Bool bRet = sal_False;
1169     if ( HasHints() )
1170     {
1171         const sal_uInt16 nEndCnt = m_pSwpHints->GetEndCount();
1172 		sal_uInt16 nPos = nEndCnt;
1173 		while( nPos )
1174         {
1175             SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
1176 			xub_StrLen *pEnd = pTmp->GetEnd();
1177 			if( !pEnd || *pEnd > nIdx )
1178 				continue;
1179 			if( nIdx != *pEnd )
1180 				nPos = 0;
1181 			else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
1182 					 && *pEnd > *pTmp->GetStart())
1183 			{
1184 				bRet = sal_True;
1185                 m_pSwpHints->NoteInHistory( pTmp );
1186 				pTmp->SetDontExpand( bFlag );
1187 			}
1188 		}
1189 	}
1190 	return bRet;
1191 }
1192 
1193 static bool lcl_GetTxtAttrDefault(xub_StrLen const nIndex,
1194     xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1195 {
1196     return ((nHintStart <= nIndex) && (nIndex <  nHintEnd));
1197 }
1198 static bool lcl_GetTxtAttrExpand(xub_StrLen const nIndex,
1199     xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1200 {
1201     return ((nHintStart <  nIndex) && (nIndex <= nHintEnd));
1202 }
1203 static bool lcl_GetTxtAttrParent(xub_StrLen const nIndex,
1204     xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1205 {
1206     return ((nHintStart <  nIndex) && (nIndex <  nHintEnd));
1207 }
1208 
1209 static void
1210 lcl_GetTxtAttrs(
1211     ::std::vector<SwTxtAttr *> *const pVector,
1212     SwTxtAttr **const ppTxtAttr,
1213     SwpHints *const pSwpHints,
1214     xub_StrLen const nIndex,
1215     RES_TXTATR const nWhich,
1216     enum SwTxtNode::GetTxtAttrMode const eMode)
1217 {
1218     sal_uInt16 const nSize = (pSwpHints) ? pSwpHints->Count() : 0;
1219     xub_StrLen nPreviousIndex(0); // index of last hint with nWhich
1220     bool (*pMatchFunc)(xub_StrLen const, xub_StrLen const, xub_StrLen const)=0;
1221     switch (eMode)
1222     {
1223         case SwTxtNode::DEFAULT:   pMatchFunc = &lcl_GetTxtAttrDefault; break;
1224         case SwTxtNode::EXPAND:    pMatchFunc = &lcl_GetTxtAttrExpand;  break;
1225         case SwTxtNode::PARENT:    pMatchFunc = &lcl_GetTxtAttrParent;  break;
1226         default: OSL_ASSERT(false);
1227     }
1228 
1229     for( sal_uInt16 i = 0; i < nSize; ++i )
1230     {
1231         SwTxtAttr *const pHint = pSwpHints->GetTextHint(i);
1232         xub_StrLen const nHintStart( *(pHint->GetStart()) );
1233         if (nIndex < nHintStart)
1234         {
1235             return; // hints are sorted by start, so we are done...
1236         }
1237 
1238         if (pHint->Which() != nWhich)
1239         {
1240             continue;
1241         }
1242 
1243         xub_StrLen const*const pEndIdx = pHint->GetEnd();
1244         ASSERT(pEndIdx || pHint->HasDummyChar(), "hint with no end and no dummy char?");
1245         // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
1246         // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
1247         bool const bContained( (pEndIdx)
1248             ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx)
1249             : (nHintStart == nIndex) );
1250         if (bContained)
1251         {
1252             if (pVector)
1253             {
1254                 if (nPreviousIndex < nHintStart)
1255                 {
1256                     pVector->clear(); // clear hints that are outside pHint
1257                     nPreviousIndex = nHintStart;
1258                 }
1259                 pVector->push_back(pHint);
1260             }
1261             else
1262             {
1263                 *ppTxtAttr = pHint; // and possibly overwrite outer hint
1264             }
1265             if (!pEndIdx)
1266             {
1267                 break;
1268             }
1269         }
1270     }
1271 }
1272 
1273 ::std::vector<SwTxtAttr *>
1274 SwTxtNode::GetTxtAttrsAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
1275                         enum GetTxtAttrMode const eMode) const
1276 {
1277     ::std::vector<SwTxtAttr *> ret;
1278     lcl_GetTxtAttrs(& ret, 0, m_pSwpHints, nIndex, nWhich, eMode);
1279     return ret;
1280 }
1281 
1282 SwTxtAttr *
1283 SwTxtNode::GetTxtAttrAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
1284                         enum GetTxtAttrMode const eMode) const
1285 {
1286     ASSERT(    (nWhich == RES_TXTATR_META)
1287             || (nWhich == RES_TXTATR_METAFIELD)
1288             || (nWhich == RES_TXTATR_AUTOFMT)
1289             || (nWhich == RES_TXTATR_INETFMT)
1290             || (nWhich == RES_TXTATR_CJK_RUBY)
1291             || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER)
1292             || (nWhich == RES_TXTATR_INPUTFIELD ),
1293         "GetTxtAttrAt() will give wrong result for this hint!");
1294 
1295     SwTxtAttr * pRet(0);
1296     lcl_GetTxtAttrs(0, & pRet, m_pSwpHints, nIndex, nWhich, eMode);
1297     return pRet;
1298 }
1299 
1300 const SwTxtInputFld* SwTxtNode::GetOverlappingInputFld( const SwTxtAttr& rTxtAttr ) const
1301 {
1302     const SwTxtInputFld* pTxtInputFld = NULL;
1303 
1304     pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtAttrAt( *(rTxtAttr.GetStart()), RES_TXTATR_INPUTFIELD, PARENT ));
1305 
1306     if ( pTxtInputFld == NULL && rTxtAttr.End() != NULL )
1307     {
1308         pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtAttrAt( *(rTxtAttr.End()), RES_TXTATR_INPUTFIELD, PARENT ));
1309     }
1310 
1311     return pTxtInputFld;
1312 }
1313 
1314 SwTxtFld* SwTxtNode::GetFldTxtAttrAt(
1315     const xub_StrLen nIndex,
1316     const bool bIncludeInputFldAtStart ) const
1317 {
1318     SwTxtFld* pTxtFld = NULL;
1319 
1320     pTxtFld = dynamic_cast<SwTxtFld*>(GetTxtAttrForCharAt( nIndex, RES_TXTATR_FIELD ));
1321     if ( pTxtFld == NULL )
1322     {
1323         pTxtFld =
1324             dynamic_cast<SwTxtFld*>( GetTxtAttrAt(
1325                 nIndex,
1326                 RES_TXTATR_INPUTFIELD,
1327                 bIncludeInputFldAtStart ? DEFAULT : PARENT ));
1328     }
1329 
1330     return pTxtFld;
1331 }
1332 
1333 
1334 /*************************************************************************
1335  *							CopyHint()
1336  *************************************************************************/
1337 
1338 SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
1339 {
1340 	if( rName.Len() )
1341 	{
1342 		SwCharFmt* pFmt;
1343 		sal_uInt16 nArrLen = pCharFmts->Count();
1344 		for( sal_uInt16 i = 1; i < nArrLen; i++ )
1345 		{
1346 			pFmt = (*pCharFmts)[ i ];
1347 			if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
1348 				return pFmt;
1349 		}
1350 	}
1351 	return NULL;
1352 }
1353 
1354 void lcl_CopyHint(
1355     const sal_uInt16 nWhich,
1356     const SwTxtAttr * const pHt,
1357     SwTxtAttr *const pNewHt,
1358     SwDoc *const pOtherDoc,
1359     SwTxtNode *const pDest )
1360 {
1361     ASSERT( nWhich == pHt->Which(), "Falsche Hint-Id" );
1362     switch( nWhich )
1363     {
1364     // copy nodesarray section with footnote content
1365     case RES_TXTATR_FTN :
1366             ASSERT(pDest, "lcl_CopyHint: no destination text node?");
1367             static_cast<const SwTxtFtn*>(pHt)->CopyFtn( *static_cast<SwTxtFtn*>(pNewHt), *pDest);
1368             break;
1369 
1370     // Beim Kopieren von Feldern in andere Dokumente
1371     // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.
1372 
1373     // TabellenFormel muessen relativ kopiert werden.
1374     case RES_TXTATR_FIELD :
1375     case RES_TXTATR_INPUTFIELD :
1376         {
1377             if( pOtherDoc )
1378             {
1379                 static_cast<const SwTxtFld*>(pHt)->CopyTxtFld( static_cast<SwTxtFld*>(pNewHt) );
1380             }
1381 
1382             // Tabellenformel ??
1383             const SwFmtFld& rFld = pHt->GetFmtFld();
1384             if( RES_TABLEFLD == rFld.GetField()->GetTyp()->Which()
1385                 && static_cast<const SwTblField*>(rFld.GetField())->IsIntrnlName())
1386             {
1387                 // wandel die interne in eine externe Formel um
1388                 const SwTableNode* const pDstTblNd =
1389                     static_cast<const SwTxtFld*>(pHt)->GetTxtNode().FindTableNode();
1390                 if( pDstTblNd )
1391                 {
1392                     SwTblField* const pTblFld = const_cast<SwTblField*>(
1393                         static_cast<const SwTblField*>(pNewHt->GetFmtFld().GetField()));
1394                     pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
1395                 }
1396             }
1397         }
1398         break;
1399 
1400     case RES_TXTATR_TOXMARK :
1401         if( pOtherDoc && pDest && pDest->GetpSwpHints()
1402             && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1403         {
1404             // Beim Kopieren von TOXMarks(Client) in andere Dokumente
1405             // muss der Verzeichnis (Modify) ausgetauscht werden
1406             static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
1407         }
1408         break;
1409 
1410     case RES_TXTATR_CHARFMT :
1411         // Wenn wir es mit einer Zeichenvorlage zu tun haben,
1412         // muessen wir natuerlich auch die Formate kopieren.
1413         if( pDest && pDest->GetpSwpHints()
1414             && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1415         {
1416             SwCharFmt* pFmt =
1417                 static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());
1418 
1419             if( pFmt && pOtherDoc )
1420             {
1421                 pFmt = pOtherDoc->CopyCharFmt( *pFmt );
1422             }
1423             const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
1424                 pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
1425         }
1426         break;
1427     case RES_TXTATR_INETFMT :
1428         {
1429             // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
1430             // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
1431             if( pOtherDoc && pDest && pDest->GetpSwpHints()
1432                 && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1433             {
1434                 const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
1435                     ->GetTxtNode().GetDoc();
1436                 if ( pDoc )
1437                 {
1438                     const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
1439                     const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
1440                     SwCharFmt* pFmt;
1441                     pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
1442                     if( pFmt )
1443                         pOtherDoc->CopyCharFmt( *pFmt );
1444                     pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
1445                     if( pFmt )
1446                         pOtherDoc->CopyCharFmt( *pFmt );
1447                 }
1448             }
1449             //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
1450             //				gesetzt sein, damit die Vorlagen erzeugt
1451             //				werden koenne
1452             SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
1453             if ( !pINetHt->GetpTxtNode() )
1454             {
1455                 pINetHt->ChgTxtNode( pDest );
1456             }
1457 
1458             //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
1459             pINetHt->GetCharFmt();
1460             break;
1461         }
1462     case RES_TXTATR_META:
1463     case RES_TXTATR_METAFIELD:
1464         OSL_ENSURE( pNewHt, "copying Meta should not fail!" );
1465         OSL_ENSURE( pDest
1466                     && (CH_TXTATR_INWORD == pDest->GetTxt().GetChar(*pNewHt->GetStart())),
1467             "missing CH_TXTATR?");
1468         break;
1469     }
1470 }
1471 
1472 /*************************************************************************
1473 |*	SwTxtNode::CopyAttr()
1474 |*	Beschreibung	kopiert Attribute an der Position nStart in pDest.
1475 |*	BP 7.6.93:		Es werden mit Absicht nur die Attribute _mit_ EndIdx
1476 |*					kopiert! CopyAttr wird vornehmlich dann gerufen,
1477 |*					wenn Attribute fuer einen Node mit leerem String
1478 |*					gesetzt werden sollen.
1479 *************************************************************************/
1480 
1481 void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
1482                           const xub_StrLen nOldPos )
1483 {
1484     if ( HasHints() )    // keine Attribute, keine Kekse
1485     {
1486         SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
1487                 pDest->GetDoc() : 0;
1488 
1489         for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
1490         {
1491             SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
1492             xub_StrLen const nAttrStartIdx = *pHt->GetStart();
1493             if ( nTxtStartIdx < nAttrStartIdx )
1494                 break; // ueber das Textende, da nLen == 0
1495 
1496             const xub_StrLen *const pEndIdx = pHt->GetEnd();
1497             if ( pEndIdx && !pHt->HasDummyChar() )
1498             {
1499                 if ( ( *pEndIdx > nTxtStartIdx
1500                        || ( *pEndIdx == nTxtStartIdx
1501                             && nAttrStartIdx == nTxtStartIdx ) ) )
1502                 {
1503                     sal_uInt16 const nWhich = pHt->Which();
1504                     if ( RES_TXTATR_REFMARK != nWhich )
1505                     {
1506                         // attribute in the area => copy
1507                         SwTxtAttr *const pNewHt =
1508                             pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, nsSetAttrMode::SETATTR_IS_COPY);
1509                         if ( pNewHt )
1510                         {
1511                             lcl_CopyHint( nWhich, pHt, pNewHt,
1512                                 pOtherDoc, pDest );
1513                         }
1514                     }
1515                     else if( !pOtherDoc
1516                              ? GetDoc()->IsCopyIsMove()
1517                              : 0 == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) )
1518                     {
1519                         pDest->InsertItem(
1520                             pHt->GetAttr(), nOldPos, nOldPos, nsSetAttrMode::SETATTR_IS_COPY);
1521                     }
1522                 }
1523             }
1524         }
1525     }
1526 
1527     if( this != pDest )
1528     {
1529         // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
1530         SwUpdateAttr aHint( nOldPos, nOldPos, 0 );
1531         pDest->ModifyNotification( 0, &aHint );
1532     }
1533 }
1534 
1535 /*************************************************************************
1536 |*	SwTxtNode::Copy()
1537 |*	Beschreibung		kopiert Zeichen und Attibute in pDest,
1538 |*						wird angehaengt
1539 *************************************************************************/
1540 
1541 // introduction of new optional parameter to control, if all attributes have to be copied.
1542 void SwTxtNode::CopyText( SwTxtNode *const pDest,
1543                       const SwIndex &rStart,
1544                       const xub_StrLen nLen,
1545                       const bool bForceCopyOfAllAttrs )
1546 {
1547     SwIndex aIdx( pDest, pDest->m_Text.Len() );
1548     CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
1549 }
1550 
1551 // introduction of new optional parameter to control, if all attributes have to be copied.
1552 void SwTxtNode::CopyText( SwTxtNode *const pDest,
1553                       const SwIndex &rDestStart,
1554                       const SwIndex &rStart,
1555                       xub_StrLen nLen,
1556                       const bool bForceCopyOfAllAttrs )
1557 {
1558     xub_StrLen nTxtStartIdx = rStart.GetIndex();
1559     xub_StrLen nDestStart = rDestStart.GetIndex();		// alte Pos merken
1560 
1561     if (pDest->GetDoc()->IsClipBoard() && this->GetNum())
1562     {
1563         // #i111677# cache expansion of source (for clipboard)
1564         pDest->m_pNumStringCache.reset(
1565             new ::rtl::OUString(this->GetNumString()));
1566     }
1567 
1568 	if( !nLen )
1569 	{
1570 		// wurde keine Laenge angegeben, dann Kopiere die Attribute
1571 		// an der Position rStart.
1572 		CopyAttr( pDest, nTxtStartIdx, nDestStart );
1573 
1574 		// harte Absatz umspannende Attribute kopieren
1575         if( HasSwAttrSet() )
1576 		{
1577 			// alle, oder nur die CharAttribute ?
1578             // --> OD 2008-11-18 #i96213#
1579             if ( !bForceCopyOfAllAttrs &&
1580                  ( nDestStart ||
1581                    pDest->HasSwAttrSet() ||
1582                    nLen != pDest->GetTxt().Len() ) )
1583             // <--
1584 			{
1585 				SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1586 									RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1587                                     RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1588                                     RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1589 									RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1590 									0 );
1591 				aCharSet.Put( *GetpSwAttrSet() );
1592 				if( aCharSet.Count() )
1593                 {
1594                     pDest->SetAttr( aCharSet, nDestStart, nDestStart );
1595                 }
1596 			}
1597 			else
1598             {
1599 				GetpSwAttrSet()->CopyToModify( *pDest );
1600             }
1601 		}
1602 		return;
1603 	}
1604 
1605 	// 1. Text kopieren
1606     const xub_StrLen oldLen = pDest->m_Text.Len();
1607 	//JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
1608 	//				ueber die InsertMethode den Text einfuegen und nicht
1609 	//				selbst direkt
1610     pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart,
1611                    IDocumentContentOperations::INS_EMPTYEXPAND );
1612 
1613     // um reale Groesse Updaten !
1614     nLen = pDest->m_Text.Len() - oldLen;
1615     if ( !nLen ) // string not longer?
1616         return;
1617 
1618     SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ? pDest->GetDoc() : 0;
1619 
1620     // harte Absatz umspannende Attribute kopieren
1621     if( HasSwAttrSet() )
1622     {
1623         // alle, oder nur die CharAttribute ?
1624         if ( !bForceCopyOfAllAttrs
1625              && ( nDestStart
1626                   || pDest->HasSwAttrSet()
1627                   || nLen != pDest->GetTxt().Len() ) )
1628         {
1629             SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1630                 RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1631                 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1632                 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1633                 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1634                 0 );
1635             aCharSet.Put( *GetpSwAttrSet() );
1636             if( aCharSet.Count() )
1637             {
1638                 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
1639             }
1640         }
1641         else
1642         {
1643             GetpSwAttrSet()->CopyToModify( *pDest );
1644         }
1645     }
1646 
1647     bool const bUndoNodes = !pOtherDoc
1648                             && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
1649 
1650     // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
1651     // Start-Index und alle Attribute vorher aktualisiert werden.
1652     nTxtStartIdx = rStart.GetIndex();
1653     const xub_StrLen nEnd = nTxtStartIdx + nLen;
1654 
1655     // 2. Attribute kopieren
1656     // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1657     // des Attributs hinter dem zu kopierenden Bereich liegt
1658     const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
1659 
1660     // wird in sich selbst kopiert, dann kann beim Einfuegen ein
1661     // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
1662     // dann erst ins eigene uebertragen.
1663     SwpHts aArr( 5 );
1664 
1665     // Del-Array fuer alle RefMarks ohne Ausdehnung
1666     SwpHts aRefMrkArr;
1667 
1668     sal_uInt16 nDeletedDummyChars(0);
1669     //Achtung: kann ungueltig sein!!
1670     for (sal_uInt16 n = 0; ( n < nSize ); ++n)
1671     {
1672         const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
1673         if ( !( nAttrStartIdx < nEnd) )
1674             break;
1675 
1676         SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
1677         const xub_StrLen * const pEndIdx = pHt->GetEnd();
1678         const sal_uInt16 nWhich = pHt->Which();
1679 
1680         // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
1681         //				keinen Bereich umspannt, so steht im Text ein 255
1682         //				dieses muss entfernt werden. Trick: erst kopieren,
1683         //				erkennen und sammeln, nach dem kopieren Loeschen.
1684         //				Nimmt sein Zeichen mit ins Grab !!
1685         // JP 14.08.95:	Duerfen RefMarks gemovt werden?
1686         const bool bCopyRefMark = RES_TXTATR_REFMARK == nWhich
1687                                   && ( bUndoNodes
1688                                        || ( !pOtherDoc
1689                                             ? GetDoc()->IsCopyIsMove()
1690                                             : 0 == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) ) );
1691 
1692         if ( pEndIdx
1693              && RES_TXTATR_REFMARK == nWhich
1694              && !bCopyRefMark )
1695         {
1696             continue;
1697         }
1698 
1699         // Input Fields are only copied, if completely covered by copied text
1700         if ( nWhich == RES_TXTATR_INPUTFIELD )
1701         {
1702             ASSERT( pEndIdx != NULL,
1703                     "<SwTxtNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" );
1704             if ( nAttrStartIdx < nTxtStartIdx
1705                  || ( pEndIdx != NULL
1706                       && *(pEndIdx) > nEnd ) )
1707             {
1708                 continue;
1709             }
1710         }
1711 
1712         xub_StrLen nAttrStt;
1713         xub_StrLen nAttrEnd;
1714 
1715         if( nAttrStartIdx < nTxtStartIdx )
1716         {
1717             // start is before selection
1718             // copy hints with end and CH_TXTATR only if dummy char is copied
1719             if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
1720             {
1721                 // attribute with extent and the end is in the selection
1722                 nAttrStt = nDestStart;
1723                 nAttrEnd = (*pEndIdx > nEnd)
1724                     ? rDestStart.GetIndex()
1725                     : nDestStart + (*pEndIdx) - nTxtStartIdx;
1726             }
1727             else
1728             {
1729                 continue;
1730             }
1731         }
1732         else
1733         {
1734             // start is in the selection
1735             nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
1736             if( pEndIdx )
1737             {
1738                 nAttrEnd = *pEndIdx > nEnd
1739                     ? rDestStart.GetIndex()
1740                     : nDestStart + ( *pEndIdx - nTxtStartIdx );
1741             }
1742             else
1743             {
1744                 nAttrEnd = nAttrStt;
1745             }
1746         }
1747 
1748         SwTxtAttr * pNewHt = 0;
1749 
1750         if( pDest == this )
1751         {
1752             // copy the hint here, but insert it later
1753             pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
1754                     nAttrStt, nAttrEnd, COPY, pDest );
1755 
1756             lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest);
1757             aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
1758         }
1759         else
1760         {
1761             pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt - nDeletedDummyChars,
1762                 nAttrEnd - nDeletedDummyChars,
1763                       nsSetAttrMode::SETATTR_NOTXTATRCHR
1764                     | nsSetAttrMode::SETATTR_IS_COPY);
1765             if (pNewHt)
1766             {
1767                 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
1768             }
1769             else if (pHt->HasDummyChar())
1770             {
1771                 // The attribute that has failed to be copied would insert
1772                 // dummy char, so positions of the following attributes have
1773                 // to be shifted by one to compensate for that missing char.
1774                 ++nDeletedDummyChars;
1775             }
1776         }
1777 
1778         if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
1779         {
1780             aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() );
1781         }
1782     }
1783 
1784     // nur falls im Array Attribute stehen (kann nur beim Kopieren
1785     // sich selbst passieren!!)
1786     for ( sal_uInt16 i = 0; i < aArr.Count(); ++i )
1787     {
1788         InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
1789     }
1790 
1791     if( pDest->GetpSwpHints() )
1792     {
1793         for ( sal_uInt16 i = 0; i < aRefMrkArr.Count(); ++i )
1794         {
1795             SwTxtAttr * const pNewHt = aRefMrkArr[i];
1796             if( pNewHt->GetEnd() )
1797             {
1798                 pDest->GetpSwpHints()->Delete( pNewHt );
1799                 pDest->DestroyAttr( pNewHt );
1800             }
1801             else
1802             {
1803                 const SwIndex aIdx( pDest, *pNewHt->GetStart() );
1804                 pDest->EraseText( aIdx, 1 );
1805             }
1806         }
1807     }
1808 
1809     CHECK_SWPHINTS(this);
1810 }
1811 
1812 
1813 void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
1814         const IDocumentContentOperations::InsertFlags nMode )
1815 {
1816     ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
1817     ASSERT( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN,
1818             "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );
1819 
1820 	xub_StrLen aPos = rIdx.GetIndex();
1821     xub_StrLen nLen = m_Text.Len() - aPos;
1822     m_Text.Insert( rStr, aPos );
1823     nLen = m_Text.Len() - aPos - nLen;
1824 
1825     if ( !nLen ) return;
1826 
1827     sal_Bool bOldExpFlg = IsIgnoreDontExpand();
1828     if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1829     {
1830         SetIgnoreDontExpand( sal_True );
1831     }
1832 
1833     Update( rIdx, nLen ); // text content changed!
1834 
1835     if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1836     {
1837         SetIgnoreDontExpand( bOldExpFlg );
1838     }
1839 
1840 	// analog zu Insert(char) in txtedt.cxx:
1841 	// 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
1842 	// 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen
1843 
1844     if ( HasHints() )
1845     {
1846         for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() &&
1847                 rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
1848         {
1849             SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
1850             xub_StrLen * const pEndIdx = pHt->GetEnd();
1851 			if( !pEndIdx )
1852 				continue;
1853 
1854 			if( rIdx == *pEndIdx )
1855 			{
1856                 if (  (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
1857                     (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1858                      && pHt->DontExpand()) )
1859 				{
1860 					// bei leeren Attributen auch Start veraendern
1861 					if( rIdx == *pHt->GetStart() )
1862 						*pHt->GetStart() = *pHt->GetStart() - nLen;
1863 					*pEndIdx = *pEndIdx - nLen;
1864                     m_pSwpHints->DeleteAtPos(i);
1865                     InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1866                 }
1867                 // empty hints at insert position?
1868                 else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
1869                         && (*pEndIdx == *pHt->GetStart()) )
1870 				{
1871 					*pHt->GetStart() = *pHt->GetStart() - nLen;
1872                     const sal_uInt16 nAktLen = m_pSwpHints->Count();
1873                     m_pSwpHints->DeleteAtPos(i);
1874                     InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
1875                     if ( nAktLen > m_pSwpHints->Count() && i )
1876                     {
1877 						--i;
1878                     }
1879 					continue;
1880 				}
1881 				else
1882                 {
1883 					continue;
1884                 }
1885 			}
1886             if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
1887 				 rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
1888 				 !pHt->IsDontExpandStartAttr() )
1889 			{
1890 				// Kein Feld, am Absatzanfang, HintExpand
1891                 m_pSwpHints->DeleteAtPos(i);
1892 				*pHt->GetStart() = *pHt->GetStart() - nLen;
1893                 InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1894             }
1895         }
1896         TryDeleteSwpHints();
1897     }
1898 
1899 	if ( GetDepends() )
1900 	{
1901 		SwInsTxt aHint( aPos, nLen );
1902 		NotifyClients( 0, &aHint );
1903 	}
1904 
1905     // By inserting a character, the hidden flags
1906     // at the TxtNode can become invalid:
1907     SetCalcHiddenCharFlags();
1908 
1909 	CHECK_SWPHINTS(this);
1910 }
1911 
1912 /*************************************************************************
1913 |*
1914 |*	SwTxtNode::Cut()
1915 |*
1916 |*	Beschreibung		text.doc
1917 |*	Ersterstellung		VB 20.03.91
1918 |*	Letzte Aenderung	JP 11.08.94
1919 |*
1920 *************************************************************************/
1921 
1922 void SwTxtNode::CutText( SwTxtNode * const pDest,
1923             const SwIndex & rStart, const xub_StrLen nLen )
1924 {
1925 	if(pDest)
1926 	{
1927 		SwIndex aDestStt( pDest, pDest->GetTxt().Len() );
1928         CutImpl( pDest, aDestStt, rStart, nLen, false );
1929     }
1930     else
1931     {
1932         ASSERT(false,
1933             "mst: entering dead and bitrotted code; fasten your seatbelts!");
1934         EraseText( rStart, nLen );
1935     }
1936 }
1937 
1938 
1939 void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
1940          const SwIndex & rStart, /*const*/ xub_StrLen nLen, const bool bUpdate )
1941 {
1942 	if(!pDest)
1943     {
1944         ASSERT(false,
1945             "mst: entering dead and bitrotted code; fasten your seatbelts!");
1946         EraseText( rStart, nLen );
1947 		return;
1948 	}
1949 
1950 	// nicht im Dokument verschieben ?
1951 	if( GetDoc() != pDest->GetDoc() )
1952 	{
1953         ASSERT(false,
1954             "mst: entering dead and bitrotted code; fasten your seatbelts!");
1955         CopyText( pDest, rDestStart, rStart, nLen);
1956         EraseText(rStart, nLen);
1957 		return;
1958 	}
1959 
1960 	if( !nLen )
1961 	{
1962 		// wurde keine Laenge angegeben, dann Kopiere die Attribute
1963 		// an der Position rStart.
1964 		CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
1965 		return;
1966 	}
1967 
1968 	xub_StrLen nTxtStartIdx = rStart.GetIndex();
1969 	xub_StrLen nDestStart = rDestStart.GetIndex();		// alte Pos merken
1970     const xub_StrLen nInitSize = pDest->m_Text.Len();
1971 
1972 	// wird in sich selbst verschoben, muss es gesondert behandelt werden !!
1973 	if( pDest == this )
1974 	{
1975         ASSERT(false,
1976             "mst: entering dead and bitrotted code; fasten your seatbelts!");
1977         m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
1978         m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen );
1979 
1980         const xub_StrLen nEnd = rStart.GetIndex() + nLen;
1981 
1982 		// dann suche mal alle Attribute zusammen, die im verschobenen
1983 		// Bereich liegen. Diese werden in das extra Array verschoben,
1984 		// damit sich die Indizies beim Updaten nicht veraendern !!!
1985 		SwpHts aArr( 5 );
1986 
1987 		// 2. Attribute verschieben
1988 		// durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1989 		// des Attributs hinter dem zu verschiebenden Bereich liegt
1990         sal_uInt16 nAttrCnt = 0;
1991         while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
1992         {
1993             SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
1994             const xub_StrLen nAttrStartIdx = *pHt->GetStart();
1995             if (!( nAttrStartIdx < nEnd ))
1996                 break;
1997             const xub_StrLen * const pEndIdx = pHt->GetEnd();
1998             const sal_uInt16 nWhich = pHt->Which();
1999             SwTxtAttr *pNewHt = 0;
2000 
2001 			if(nAttrStartIdx < nTxtStartIdx)
2002 			{
2003 				// Anfang liegt vor dem Bereich
2004                 if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
2005 					pEndIdx && *pEndIdx > nTxtStartIdx )
2006 				{
2007 					// Attribut mit einem Bereich
2008 					// und das Ende des Attribut liegt im Bereich
2009                     pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
2010 										*pEndIdx > nEnd
2011 											? nLen
2012 											: *pEndIdx - nTxtStartIdx );
2013 				}
2014 			}
2015 			else
2016 			{
2017 				// der Anfang liegt vollstaendig im Bereich
2018 				if( !pEndIdx || *pEndIdx < nEnd )
2019 				{
2020 					// Attribut verschieben
2021                     m_pSwpHints->Delete( pHt );
2022 					// die Start/End Indicies neu setzen
2023 					*pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
2024 					if( pEndIdx )
2025 						*pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
2026 					aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
2027 					continue;			// while-Schleife weiter, ohne ++ !
2028 				}
2029 					// das Ende liegt dahinter
2030                 else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
2031 				{
2032                     pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
2033 							nAttrStartIdx - nTxtStartIdx,
2034 							!pEndIdx ? 0
2035 									 : ( *pEndIdx > nEnd
2036 											? nLen
2037 											: *pEndIdx - nTxtStartIdx ));
2038 				}
2039 			}
2040 			if( pNewHt )
2041 			{
2042 				// die Daten kopieren
2043 				lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
2044 				aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
2045 			}
2046 			++nAttrCnt;
2047 		}
2048 
2049 		if( bUpdate )
2050         {
2051 			// Update aller Indizies
2052 			Update( rDestStart, nLen, sal_False, sal_True );
2053         }
2054 #ifdef CUTNOEXPAND
2055 		else
2056 			// wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
2057             if ( 0 < nLen && 0 < nInitSize && m_pSwpHints )
2058             {
2059                 // check if there was the end of an attribute at the insertion
2060                 // position: if it is not a field, it must be expanded
2061                 for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); n++ )
2062                 {
2063                     SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
2064                     const xub_StrLen * const pEndIdx = pHt->GetEnd();
2065                     if ( pEndIdx  && (*pEndIdx == nInitSize) )
2066                     {
2067                         *pEndIdx = *pEndIdx + nLen;
2068                     }
2069                 }
2070             }
2071 #endif
2072 		CHECK_SWPHINTS(this);
2073 
2074 		Update( rStart, nLen, sal_True, sal_True );
2075 
2076 		CHECK_SWPHINTS(this);
2077 
2078 		// dann setze die kopierten/geloeschten Attribute in den Node
2079 		if( nDestStart <= nTxtStartIdx )
2080         {
2081 			nTxtStartIdx = nTxtStartIdx + nLen;
2082         }
2083 		else
2084         {
2085 			nDestStart = nDestStart - nLen;
2086         }
2087 
2088         for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
2089         {
2090             SwTxtAttr *const pNewHt = aArr[n];
2091 			*pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
2092             xub_StrLen * const pEndIdx = pNewHt->GetEnd();
2093             if ( pEndIdx )
2094             {
2095                 *pEndIdx = nDestStart + *pEndIdx;
2096             }
2097             InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
2098         }
2099     }
2100     else
2101     {
2102         pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
2103         m_Text.Erase( nTxtStartIdx, nLen );
2104         nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size!
2105 		if( !nLen )					// String nicht gewachsen ??
2106 			return;
2107 
2108 		if( bUpdate )
2109         {
2110 			// Update aller Indizies
2111 			pDest->Update( rDestStart, nLen, sal_False, sal_True);
2112         }
2113 #ifdef CUTNOEXPAND
2114 		else
2115 			// wird am Ende eingefuegt, nur die Attribut-Indizies verschieben
2116             if ( 0 < nLen && 0 < nInitSize && pDest->m_pSwpHints )
2117             {
2118                 // check if there was the end of an attribute at the insertion
2119                 // position: if it is not a field, it must be expanded
2120                 for ( sal_uInt16 n = 0; n < pDest->m_pSwpHints->Count(); n++ )
2121                 {
2122                     SwTxtAttr * const pHt = pDest->m_pSwpHints->GetTextHint(n);
2123                     const xub_StrLen * const pEndIdx = pHt->GetEnd();
2124                     if ( pEndIdx  && (*pEndIdx == nInitSize) )
2125                     {
2126                         *pEndIdx = *pEndIdx + nLen;
2127                     }
2128                 }
2129             }
2130 #endif
2131 		CHECK_SWPHINTS(pDest);
2132 
2133         const xub_StrLen nEnd = rStart.GetIndex() + nLen;
2134         SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
2135             ? pDest->GetDoc() : 0;
2136         bool const bUndoNodes = !pOtherDoc
2137             && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
2138 
2139         ASSERT(!pOtherDoc,
2140             "mst: entering dead and bitrotted code; fasten your seatbelts!");
2141 
2142 		// harte Absatz umspannende Attribute kopieren
2143         if( HasSwAttrSet() )
2144 		{
2145 			// alle, oder nur die CharAttribute ?
2146             if( nInitSize || pDest->HasSwAttrSet() ||
2147 				nLen != pDest->GetTxt().Len() )
2148 			{
2149 				SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
2150 									RES_CHRATR_BEGIN, RES_CHRATR_END-1,
2151                                     RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
2152                                     RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
2153 									RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
2154 									0 );
2155 				aCharSet.Put( *GetpSwAttrSet() );
2156 				if( aCharSet.Count() )
2157                     pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
2158 			}
2159 			else
2160             {
2161 				GetpSwAttrSet()->CopyToModify( *pDest );
2162             }
2163 		}
2164 
2165 		// 2. Attribute verschieben
2166 		// durch das Attribute-Array, bis der Anfang des Geltungsbereiches
2167 		// des Attributs hinter dem zu verschiebenden Bereich liegt
2168         sal_uInt16 nAttrCnt = 0;
2169         while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
2170         {
2171             SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2172             const xub_StrLen nAttrStartIdx = *pHt->GetStart();
2173             if (!( nAttrStartIdx < nEnd ))
2174                 break;
2175             const xub_StrLen * const pEndIdx = pHt->GetEnd();
2176             const sal_uInt16 nWhich = pHt->Which();
2177             SwTxtAttr *pNewHt = 0;
2178 
2179             // if the hint has a dummy character, then it must not be split!
2180 			if(nAttrStartIdx < nTxtStartIdx)
2181 			{
2182 				// Anfang liegt vor dem Bereich
2183                 if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
2184 					|| bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
2185 				{
2186 					// Attribut mit einem Bereich
2187 					// und das Ende des Attribut liegt im Bereich
2188                     pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
2189                                     nDestStart,
2190                                     nDestStart + (
2191 										*pEndIdx > nEnd
2192 											? nLen
2193 											: *pEndIdx - nTxtStartIdx ) );
2194 				}
2195 			}
2196 			else
2197 			{
2198 				// der Anfang liegt vollstaendig im Bereich
2199 				if( !pEndIdx || *pEndIdx < nEnd ||
2200 					(!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
2201                     || pHt->HasDummyChar() )
2202 				{
2203 					// do not delete note and later add it -> sidebar flickering
2204 					if ( GetDoc()->GetDocShell() )
2205                     {
2206 						GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2207                     }
2208 					// Attribut verschieben
2209                     m_pSwpHints->Delete( pHt );
2210 					// die Start/End Indicies neu setzen
2211 					*pHt->GetStart() =
2212 							nDestStart + (nAttrStartIdx - nTxtStartIdx);
2213 					if( pEndIdx )
2214                     {
2215 						*pHt->GetEnd() = nDestStart + (
2216 										*pEndIdx > nEnd
2217 											? nLen
2218 											: *pEndIdx - nTxtStartIdx );
2219                     }
2220                     pDest->InsertHint( pHt,
2221                               nsSetAttrMode::SETATTR_NOTXTATRCHR
2222                             | nsSetAttrMode::SETATTR_DONTREPLACE );
2223 					if ( GetDoc()->GetDocShell() )
2224                     {
2225 						GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2226                     }
2227 					continue;			// while-Schleife weiter, ohne ++ !
2228 				}
2229 					// das Ende liegt dahinter
2230 				else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
2231 				{
2232                     pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
2233 							nDestStart + (nAttrStartIdx - nTxtStartIdx),
2234 							!pEndIdx ? 0
2235 									 : nDestStart + ( *pEndIdx > nEnd
2236 											? nLen
2237 											: *pEndIdx - nTxtStartIdx ));
2238 				}
2239 			}
2240 			if ( pNewHt )
2241             {
2242                 const bool bSuccess( pDest->InsertHint( pNewHt,
2243                               nsSetAttrMode::SETATTR_NOTXTATRCHR
2244                             | nsSetAttrMode::SETATTR_DONTREPLACE
2245                             | nsSetAttrMode::SETATTR_IS_COPY) );
2246                 if (bSuccess)
2247                 {
2248                     lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
2249                 }
2250             }
2251 			++nAttrCnt;
2252 		}
2253 		// sollten jetzt noch leere Attribute rumstehen, dann haben diese
2254 		// eine hoehere Praezedenz. Also herausholen und das Array updaten.
2255 		// Die dabei entstehenden leeren Hints werden von den gesicherten
2256 		// "uebergeplaettet".	(Bug: 6977)
2257         if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
2258         {
2259             SwpHts aArr( 5 );
2260             while ( nAttrCnt < m_pSwpHints->Count() )
2261             {
2262                 SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2263                 if ( nEnd != *pHt->GetStart() )
2264                     break;
2265                 const xub_StrLen * const pEndIdx = pHt->GetEnd();
2266                 if ( pEndIdx && *pEndIdx == nEnd )
2267                 {
2268 					aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
2269                     m_pSwpHints->Delete( pHt );
2270                 }
2271                 else
2272                 {
2273                     ++nAttrCnt;
2274                 }
2275 			}
2276 			Update( rStart, nLen, sal_True, sal_True );
2277 
2278             for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
2279 			{
2280                 SwTxtAttr * const pHt = aArr[ n ];
2281 				*pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
2282                 InsertHint( pHt );
2283             }
2284         }
2285 		else
2286         {
2287 			Update( rStart, nLen, sal_True, sal_True );
2288         }
2289 
2290 		CHECK_SWPHINTS(this);
2291 	}
2292 
2293     TryDeleteSwpHints();
2294 
2295 	// Frames benachrichtigen;
2296 	SwInsTxt aInsHint( nDestStart, nLen );
2297     pDest->ModifyNotification( 0, &aInsHint );
2298 	SwDelTxt aDelHint( nTxtStartIdx, nLen );
2299     ModifyNotification( 0, &aDelHint );
2300 }
2301 
2302 
2303 void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
2304         const IDocumentContentOperations::InsertFlags nMode )
2305 {
2306     ASSERT( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." );
2307 
2308     const xub_StrLen nStartIdx = rIdx.GetIndex();
2309     const xub_StrLen nCnt = (STRING_LEN == nCount)
2310                       ? m_Text.Len() - nStartIdx : nCount;
2311     const xub_StrLen nEndIdx = nStartIdx + nCnt;
2312     m_Text.Erase( nStartIdx, nCnt );
2313 
2314 	/* GCAttr(); alle leeren weggwerfen ist zu brutal.
2315 	 * Es duerfen nur die wegggeworfen werden,
2316 	 * die im Bereich liegen und nicht am Ende des Bereiches liegen
2317 	 */
2318 
2319     for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2320     {
2321         SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
2322 
2323         const xub_StrLen nHintStart = *pHt->GetStart();
2324 
2325         if ( nHintStart < nStartIdx )
2326             continue;
2327 
2328         if ( nHintStart > nEndIdx )
2329             break; // hints are sorted by end, so break here
2330 
2331         const xub_StrLen* pHtEndIdx = pHt->GetEnd();
2332         const sal_uInt16 nWhich = pHt->Which();
2333 
2334         if( !pHtEndIdx )
2335         {
2336             ASSERT(pHt->HasDummyChar(),
2337                     "attribute with neither end nor CH_TXTATR?");
2338             if (isTXTATR(nWhich) &&
2339                 (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
2340             {
2341                 m_pSwpHints->DeleteAtPos(i);
2342                 DestroyAttr( pHt );
2343                 --i;
2344             }
2345             continue;
2346         }
2347 
2348         ASSERT (!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
2349                     && pHt->HasDummyChar() )
2350                 // next line: deleting exactly dummy char: DeleteAttributes
2351                 || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)),
2352                 "ERROR: deleting left-overlapped attribute with CH_TXTATR");
2353 
2354         // Delete the hint if:
2355         // 1. The hint ends before the deletion end position or
2356         // 2. The hint ends at the deletion end position and
2357         //    we are not in empty expand mode and
2358         //    the hint is a [toxmark|refmark|ruby|inputfield] text attribute
2359         // 3. deleting exactly the dummy char of an hint with end and dummy
2360         //    char deletes the hint
2361         if (   (*pHtEndIdx < nEndIdx)
2362             || ( (*pHtEndIdx == nEndIdx)     &&
2363                  !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode)  &&
2364                  (  (RES_TXTATR_TOXMARK == nWhich)  ||
2365                     (RES_TXTATR_REFMARK == nWhich)  ||
2366                     (RES_TXTATR_CJK_RUBY == nWhich) ||
2367                     (RES_TXTATR_INPUTFIELD == nWhich) ) )
2368             || ( (nHintStart < nEndIdx)     &&
2369                  pHt->HasDummyChar()        )
2370            )
2371         {
2372             m_pSwpHints->DeleteAtPos(i);
2373             DestroyAttr( pHt );
2374             --i;
2375         }
2376     }
2377 
2378     ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2379 
2380     TryDeleteSwpHints();
2381 
2382     Update( rIdx, nCnt, sal_True );
2383 
2384     if( 1 == nCnt )
2385     {
2386         SwDelChr aHint( nStartIdx );
2387         NotifyClients( 0, &aHint );
2388     }
2389     else
2390     {
2391         SwDelTxt aHint( nStartIdx, nCnt );
2392         NotifyClients( 0, &aHint );
2393     }
2394 
2395     ASSERT(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2396 
2397     // By deleting a character, the hidden flags
2398     // at the TxtNode can become invalid:
2399     SetCalcHiddenCharFlags();
2400 
2401     CHECK_SWPHINTS(this);
2402 }
2403 
2404 /***********************************************************************
2405 #*	Class		:	SwTxtNode
2406 #*	Methode 	:	GCAttr
2407 #*
2408 #*	Beschreibung
2409 #*					text.doc
2410 #*
2411 #*	Datum		:	MS 28.11.90
2412 #*	Update		:	VB 24.07.91
2413 #***********************************************************************/
2414 
2415 void SwTxtNode::GCAttr()
2416 {
2417     if ( !HasHints() )
2418         return;
2419 
2420     bool   bChanged = false;
2421     sal_uInt16 nMin = m_Text.Len();
2422     sal_uInt16 nMax = 0;
2423     const bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die INet-Formate entfernt.
2424 
2425     for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2426     {
2427         SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);
2428 
2429         // wenn Ende und Start gleich sind --> loeschen
2430         const xub_StrLen * const pEndIdx = pHt->GetEnd();
2431         if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
2432             && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
2433         {
2434             bChanged = true;
2435             nMin = Min( nMin, *pHt->GetStart() );
2436             nMax = Max( nMax, *pHt->GetEnd() );
2437             DestroyAttr( m_pSwpHints->Cut(i) );
2438             --i;
2439         }
2440         else
2441         {
2442             pHt->SetDontExpand( false );
2443         }
2444     }
2445     TryDeleteSwpHints();
2446 
2447     if(bChanged)
2448     {
2449         //TxtFrm's reagieren auf aHint, andere auf aNew
2450         SwUpdateAttr aHint( nMin, nMax, 0 );
2451         NotifyClients( 0, &aHint );
2452         SwFmtChg aNew( GetTxtColl() );
2453         NotifyClients( 0, &aNew );
2454     }
2455 }
2456 
2457 // #i23726#
2458 SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const
2459 {
2460     SwNumRule* pRet = 0;
2461 
2462     const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
2463     bool bNoNumRule = false;
2464     if ( pItem )
2465     {
2466         String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
2467         if (sNumRuleName.Len() > 0)
2468         {
2469             pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
2470         }
2471         else // numbering is turned off
2472             bNoNumRule = true;
2473     }
2474 
2475     if ( !bNoNumRule )
2476     {
2477         if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
2478              ( !HasSwAttrSet() ||
2479                SFX_ITEM_SET !=
2480                 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
2481         {
2482             SwTxtFmtColl* pColl = GetTxtColl();
2483             if ( pColl )
2484             {
2485                 const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False );
2486                 if ( rDirectItem.GetValue().Len() == 0 )
2487                 {
2488                     pRet = 0L;
2489                 }
2490             }
2491         }
2492     }
2493 
2494     return pRet;
2495 }
2496 
2497 SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const
2498 {
2499     SwNumRule * pRet = _GetNumRule(bInParent);
2500 
2501     return pRet;
2502 }
2503 
2504 void SwTxtNode::NumRuleChgd()
2505 {
2506     // --> OD 2008-04-04 #refactorlists#
2507     if ( IsInList() )
2508     {
2509         SwNumRule* pNumRule = GetNumRule();
2510         if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
2511         {
2512             mpNodeNum->ChangeNumRule( *pNumRule );
2513         }
2514     }
2515     // <--
2516 
2517     if( IsInCache() )
2518 	{
2519 		SwFrm::GetCache().Delete( this );
2520 		SetInCache( sal_False );
2521 	}
2522 	SetInSwFntCache( sal_False );
2523 
2524     // Sending "noop" modify in order to cause invalidations of registered
2525     // <SwTxtFrm> instances to get the list style change respectively the change
2526     // in the list tree reflected in the layout.
2527     // Important note:
2528     {
2529         SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
2530         NotifyClients( &rLR, &rLR );
2531     }
2532 }
2533 
2534 // -> #i27615#
2535 sal_Bool SwTxtNode::IsNumbered() const
2536 {
2537     sal_Bool bResult = sal_False;
2538 
2539     SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2540     if ( pRule && IsCountedInList() )
2541         bResult = sal_True;
2542 
2543     return bResult;
2544 }
2545 
2546 // --> OD 2008-04-02 #refactorlists#
2547 bool SwTxtNode::HasMarkedLabel() const
2548 {
2549     bool bResult = false;
2550 
2551     if ( IsInList() )
2552     {
2553         bResult =
2554             GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
2555     }
2556 
2557     return bResult;
2558 }
2559 // <--
2560 // <- #i27615#
2561 
2562 SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext,
2563 										sal_Bool bChgFollow )
2564 {
2565 	/* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
2566 	SwAttrSet* pNewAttrSet = 0;
2567     // --> OD 2007-07-10 #i75353#
2568     bool bClearHardSetNumRuleWhenFmtCollChanges( false );
2569     // <--
2570     if( HasSwAttrSet() )
2571 	{
2572 		pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
2573         const SfxItemSet* pTmpSet = GetpSwAttrSet();
2574 
2575 		if( bNext )		// der naechste erbt keine Breaks!
2576 			pTmpSet = pNewAttrSet;
2577 
2578 		// PageBreaks/PageDesc/ColBreak rausschmeissen.
2579         sal_Bool bRemoveFromCache = sal_False;
2580         std::vector<sal_uInt16> aClearWhichIds;
2581         if ( bNext )
2582             bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
2583         else
2584             aClearWhichIds.push_back( RES_PAGEDESC );
2585 
2586 		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) )
2587 		{
2588             if ( bNext )
2589                 pNewAttrSet->ClearItem( RES_BREAK );
2590             else
2591                 aClearWhichIds.push_back( RES_BREAK );
2592             bRemoveFromCache = sal_True;
2593 		}
2594 		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) )
2595 		{
2596             if ( bNext )
2597                 pNewAttrSet->ClearItem( RES_KEEP );
2598             else
2599                 aClearWhichIds.push_back( RES_KEEP );
2600             bRemoveFromCache = sal_True;
2601 		}
2602 		if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) )
2603 		{
2604             if ( bNext )
2605                 pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
2606             else
2607                 aClearWhichIds.push_back( RES_PARATR_SPLIT );
2608             bRemoveFromCache = sal_True;
2609 		}
2610 		if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False))
2611         {
2612             SwNumRule * pRule = GetNumRule();
2613 
2614             if (pRule && IsOutline())
2615             {
2616                 if ( bNext )
2617                     pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
2618                 else
2619                 {
2620                     // --> OD 2007-07-10 #i75353#
2621                     // No clear of hard set numbering rule at an outline paragraph at this point.
2622                     // Only if the paragraph style changes - see below.
2623 //                    aClearWhichIds.push_back( RES_PARATR_NUMRULE );
2624                     bClearHardSetNumRuleWhenFmtCollChanges = true;
2625                     // <--
2626                 }
2627                 bRemoveFromCache = sal_True;
2628             }
2629         }
2630 
2631         if ( 0 != aClearWhichIds.size() )
2632             bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
2633 
2634 		if( !bNext && bRemoveFromCache && IsInCache() )
2635 		{
2636 			SwFrm::GetCache().Delete( this );
2637 			SetInCache( sal_False );
2638 		}
2639 	}
2640 	SwNodes& rNds = GetNodes();
2641 
2642 	SwTxtFmtColl* pColl = GetTxtColl();
2643 
2644 	SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );
2645 
2646 	if( pNewAttrSet )
2647 		delete pNewAttrSet;
2648 
2649 	const SwNumRule* pRule = GetNumRule();
2650 	if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
2651 	{
2652         // --> OD 2005-10-18 #i55459#
2653         // - correction: parameter <bNext> has to be checked, as it was in the
2654         //   previous implementation.
2655         if ( !bNext && !IsCountedInList() )
2656             SetCountedInList(true);
2657         // <--
2658 	}
2659 
2660 	// jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
2661 	// Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
2662 	// nochmal uebergeplaettet werden !!
2663 	if( pColl != pNode->GetTxtColl() ||
2664 		( bChgFollow && pColl != GetTxtColl() ))
2665 		return pNode;		// mehr duerfte nicht gemacht werden oder ????
2666 
2667 	pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
2668 	if( bNext || !bChgFollow )
2669 		return pNode;
2670 
2671 	SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
2672     // --> OD 2009-08-12 #i101870#
2673     // perform action on different paragraph styles before applying the new paragraph style
2674     if (pNextColl != pColl)
2675     {
2676         // --> OD 2007-07-10 #i75353#
2677         if ( bClearHardSetNumRuleWhenFmtCollChanges )
2678         {
2679             std::vector<sal_uInt16> aClearWhichIds;
2680             aClearWhichIds.push_back( RES_PARATR_NUMRULE );
2681             if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
2682             {
2683                 SwFrm::GetCache().Delete( this );
2684                 SetInCache( sal_False );
2685             }
2686         }
2687         // <--
2688     }
2689     // <--
2690 	ChgFmtColl( pNextColl );
2691 
2692 	return pNode;
2693 }
2694 
2695 SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
2696 {
2697     // Position hinter dem eingefuegt wird
2698     SwNodeIndex aIdx( rPos.nNode, 1 );
2699     SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True );
2700 
2701     // reset list attributes at appended text node
2702     pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
2703     pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
2704     pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
2705     if ( pNew->GetNumRule() == 0 )
2706     {
2707         pNew->ResetAttr( RES_PARATR_LIST_ID );
2708         pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
2709     }
2710 
2711     if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
2712     {
2713         AddToList();
2714     }
2715 
2716     if( GetDepends() )
2717         MakeFrms( *pNew );
2718     return pNew;
2719 }
2720 
2721 /*************************************************************************
2722  *						SwTxtNode::GetTxtAttr
2723  *************************************************************************/
2724 
2725 SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt(
2726     const xub_StrLen nIndex,
2727     const RES_TXTATR nWhich ) const
2728 {
2729     if ( HasHints() )
2730     {
2731         for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i )
2732         {
2733             SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
2734             const xub_StrLen nStartPos = *pHint->GetStart();
2735             if ( nIndex < nStartPos )
2736             {
2737                 return 0;
2738             }
2739             if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
2740             {
2741                 return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
2742                        ? pHint : 0;
2743             }
2744         }
2745     }
2746     return 0;
2747 }
2748 
2749 // -> #i29560#
2750 sal_Bool SwTxtNode::HasNumber() const
2751 {
2752     sal_Bool bResult = sal_False;
2753 
2754     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2755     if ( pRule )
2756     {
2757         SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
2758 
2759         // #i40041#
2760         bResult = aFmt.IsEnumeration() &&
2761             SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
2762     }
2763 
2764     return bResult;
2765 }
2766 
2767 sal_Bool SwTxtNode::HasBullet() const
2768 {
2769     sal_Bool bResult = sal_False;
2770 
2771     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2772     if ( pRule )
2773     {
2774         SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
2775 
2776         bResult = aFmt.IsItemize();
2777     }
2778 
2779     return bResult;
2780 }
2781 // <- #i29560#
2782 
2783 // --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
2784 //i53420 added max outline parameter
2785 XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
2786 {
2787     if (GetDoc()->IsClipBoard() && m_pNumStringCache.get())
2788     {
2789         // #i111677# do not expand number strings in clipboard documents
2790         return *m_pNumStringCache;
2791     }
2792     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2793     if ( pRule &&
2794          IsCountedInList() )
2795     {
2796         SvxNumberType const& rNumberType(
2797                 pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) );
2798         if (rNumberType.IsTxtFmt() ||
2799         // #b6432095#
2800             (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType()))
2801         {
2802             return pRule->MakeNumString( GetNum()->GetNumberVector(),
2803                                      _bInclPrefixAndSuffixStrings ? sal_True : sal_False,
2804                                      sal_False,
2805                                      _nRestrictToThisLevel );
2806         }
2807     }
2808 
2809     return aEmptyStr;
2810 }
2811 
2812 long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const
2813 {
2814     long nRet = 0;
2815     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2816 	if( pRule )
2817 	{
2818         const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2819         // --> OD 2008-01-16 #newlistlevelattrs#
2820         if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2821         {
2822             nRet = rFmt.GetAbsLSpace();
2823 
2824             if( !bTxtLeft )
2825             {
2826                 if( 0 > rFmt.GetFirstLineOffset() &&
2827                     nRet > -rFmt.GetFirstLineOffset() )
2828                     nRet = nRet + rFmt.GetFirstLineOffset();
2829                 else
2830                     nRet = 0;
2831             }
2832 
2833             if( pRule->IsAbsSpaces() )
2834                 nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
2835         }
2836         else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2837         {
2838             if ( AreListLevelIndentsApplicable() )
2839             {
2840                 nRet = rFmt.GetIndentAt();
2841                 // --> OD 2008-06-06 #i90401#
2842                 // Only negative first line indents have consider for the left margin
2843                 if ( !bTxtLeft &&
2844                      rFmt.GetFirstLineIndent() < 0 )
2845                 {
2846                     nRet = nRet + rFmt.GetFirstLineIndent();
2847                 }
2848                 // <--
2849             }
2850         }
2851         // <--
2852 	}
2853 
2854     return nRet;
2855 }
2856 
2857 sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
2858 {
2859     sal_Bool bRet( sal_False );
2860     // --> OD 2009-09-08 #i95907#, #b6879723#
2861     rFLOffset = 0;
2862     // <--
2863 
2864     // --> OD 2005-11-02 #i51089 - TUNING#
2865     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2866     if ( pRule )
2867 	{
2868         if ( IsCountedInList() )
2869         {
2870             // --> OD 2008-01-16 #newlistlevelattrs#
2871             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2872             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2873             {
2874                 rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset();
2875 
2876                 if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2877                 {
2878                     SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2879                     rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
2880                 }
2881             }
2882             else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2883             {
2884                 if ( AreListLevelIndentsApplicable() )
2885                 {
2886                     rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent());
2887                 }
2888                 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2889                 {
2890                     SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2891                     rFLOffset = aItem.GetTxtFirstLineOfst();
2892                 }
2893             }
2894             // <--
2895         }
2896 
2897         bRet = sal_True;
2898 	}
2899     else
2900     {
2901         rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2902     }
2903 
2904     return bRet;
2905 }
2906 
2907 // --> OD 2010-01-05 #b6884103#
2908 SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const
2909 {
2910     SwTwips nAdditionalIndent = 0;
2911 
2912     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2913     if ( pRule )
2914     {
2915         const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2916         if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2917         {
2918             nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2919 
2920             if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2921             {
2922                 nAdditionalIndent = nAdditionalIndent -
2923                                     GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2924             }
2925         }
2926         else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2927         {
2928             if ( AreListLevelIndentsApplicable() )
2929             {
2930                 nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent();
2931             }
2932             else
2933             {
2934                 nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2935                 if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2936                 {
2937                     nAdditionalIndent = nAdditionalIndent -
2938                                         GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2939                 }
2940             }
2941         }
2942     }
2943     else
2944     {
2945         nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2946     }
2947 
2948     return nAdditionalIndent;
2949 }
2950 // <--
2951 
2952 // --> OD 2008-12-02 #i96772#
2953 void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
2954 {
2955     if ( AreListLevelIndentsApplicable() )
2956     {
2957         const SwNumRule* pRule = GetNumRule();
2958         if ( pRule && GetActualListLevel() >= 0 )
2959         {
2960             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2961             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2962             {
2963                 SvxLRSpaceItem aLR( RES_LR_SPACE );
2964                 o_rLRSpaceItem = aLR;
2965             }
2966         }
2967     }
2968 }
2969 // <--
2970 
2971 // --> OD 2008-07-01 #i91133#
2972 long SwTxtNode::GetLeftMarginForTabCalculation() const
2973 {
2974     long nLeftMarginForTabCalc = 0;
2975 
2976     bool bLeftMarginForTabCalcSetToListLevelIndent( false );
2977     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
2978     if( pRule )
2979     {
2980         const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2981         if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2982         {
2983             if ( AreListLevelIndentsApplicable() )
2984             {
2985                 nLeftMarginForTabCalc = rFmt.GetIndentAt();
2986                 bLeftMarginForTabCalcSetToListLevelIndent = true;
2987             }
2988         }
2989     }
2990     if ( !bLeftMarginForTabCalcSetToListLevelIndent )
2991     {
2992         nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
2993     }
2994 
2995     return nLeftMarginForTabCalc;
2996 }
2997 // <--
2998 
2999 void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt,
3000 							xub_StrLen nEndPos, sal_Bool bExpandFlds ) const
3001 {
3002 	if( GetpSwpHints() )
3003 	{
3004 		sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
3005 		for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter,
3006 								cSrchChr = CH_TXTATR_INWORD )
3007 		{
3008 			xub_StrLen nPos = rTxt.Search( cSrchChr );
3009 			while( STRING_NOTFOUND != nPos && nPos < nEndPos )
3010             {
3011                 const SwTxtAttr* const pAttr =
3012                     GetTxtAttrForCharAt( rTxtStt + nPos );
3013 				if( pAttr )
3014 				{
3015 					switch( pAttr->Which() )
3016 					{
3017 					case RES_TXTATR_FIELD:
3018 						rTxt.Erase( nPos, 1 );
3019 						if( bExpandFlds )
3020 						{
3021                             const XubString aExpand(
3022                                 static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true));
3023 							rTxt.Insert( aExpand, nPos );
3024 							nPos = nPos + aExpand.Len();
3025 							nEndPos = nEndPos + aExpand.Len();
3026 							rTxtStt = rTxtStt - aExpand.Len();
3027 						}
3028 						++rTxtStt;
3029 						break;
3030 					case RES_TXTATR_FTN:
3031 						rTxt.Erase( nPos, 1 );
3032 						if( bExpandFlds )
3033 						{
3034 							const SwFmtFtn& rFtn = pAttr->GetFtn();
3035 							XubString sExpand;
3036 							if( rFtn.GetNumStr().Len() )
3037 								sExpand = rFtn.GetNumStr();
3038 							else if( rFtn.IsEndNote() )
3039 								sExpand = GetDoc()->GetEndNoteInfo().aFmt.
3040 												GetNumStr( rFtn.GetNumber() );
3041 							else
3042 								sExpand = GetDoc()->GetFtnInfo().aFmt.
3043 												GetNumStr( rFtn.GetNumber() );
3044 							rTxt.Insert( sExpand, nPos );
3045 							nPos = nPos + sExpand.Len();
3046 							nEndPos = nEndPos + sExpand.Len();
3047 							rTxtStt = rTxtStt - sExpand.Len();
3048 						}
3049 						++rTxtStt;
3050 						break;
3051 					default:
3052 						rTxt.Erase( nPos, 1 );
3053 						++rTxtStt;
3054 					}
3055 				}
3056 				else
3057 					++nPos, ++nEndPos;
3058 				nPos = rTxt.Search( cSrchChr, nPos );
3059 			}
3060 		}
3061 	}
3062 }
3063 
3064 /*************************************************************************
3065  *                      SwTxtNode::GetExpandTxt
3066  * Expand fields
3067  *************************************************************************/
3068 // --> OD 2007-11-15 #i83479# - handling of new parameters
3069 XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
3070                                    const xub_StrLen nLen,
3071                                    const bool bWithNum,
3072                                    const bool bAddSpaceAfterListLabelStr,
3073                                    const bool bWithSpacesForLevel ) const
3074 {
3075     XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
3076     xub_StrLen nTxtStt = nIdx;
3077     Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True );
3078 
3079     // remove dummy characters of Input Fields
3080     aTxt.EraseAllChars( CH_TXT_ATR_INPUTFIELDSTART );
3081     aTxt.EraseAllChars( CH_TXT_ATR_INPUTFIELDEND );
3082 
3083     if( bWithNum )
3084     {
3085         XubString aListLabelStr = GetNumString();
3086         if ( aListLabelStr.Len() > 0 )
3087         {
3088             if ( bAddSpaceAfterListLabelStr )
3089             {
3090                 const sal_Unicode aSpace = ' ';
3091                 aTxt.Insert( aSpace, 0 );
3092             }
3093             aTxt.Insert( GetNumString(), 0 );
3094         }
3095     }
3096 
3097     if ( bWithSpacesForLevel && GetActualListLevel() > 0 )
3098     {
3099         int nLevel( GetActualListLevel() );
3100         while ( nLevel > 0 )
3101         {
3102             const sal_Unicode aSpace = ' ';
3103             aTxt.Insert( aSpace , 0 );
3104             aTxt.Insert( aSpace , 0 );
3105             --nLevel;
3106         }
3107     }
3108 
3109 	return aTxt;
3110 }
3111 // <--
3112 
3113 sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
3114                         xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum,
3115                         sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const
3116 {
3117 	if( &rDestNd == this )
3118 		return sal_False;
3119 
3120 	SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() );
3121 	if( pDestIdx )
3122 		aDestIdx = *pDestIdx;
3123 	xub_StrLen nDestStt = aDestIdx.GetIndex();
3124 
3125 	// Text einfuegen
3126     String sTmpText = GetTxt();
3127     if( bReplaceTabsWithSpaces )
3128         sTmpText.SearchAndReplaceAll('\t', ' ');
3129 
3130     // mask hidden characters
3131     const xub_Unicode cChar = CH_TXTATR_BREAKWORD;
3132     sal_uInt16 nHiddenChrs =
3133         SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar );
3134 
3135     sTmpText = sTmpText.Copy( nIdx, nLen );
3136     // remove dummy characters of Input Fields
3137     {
3138         sTmpText.EraseAllChars( CH_TXT_ATR_INPUTFIELDSTART );
3139         sTmpText.EraseAllChars( CH_TXT_ATR_INPUTFIELDEND );
3140     }
3141     rDestNd.InsertText( sTmpText, aDestIdx );
3142     nLen = aDestIdx.GetIndex() - nDestStt;
3143 
3144 	// alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
3145     if ( HasHints() )
3146     {
3147 		xub_StrLen nInsPos = nDestStt - nIdx;
3148         for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
3149         {
3150             const SwTxtAttr* pHt = (*m_pSwpHints)[i];
3151             const xub_StrLen nAttrStartIdx = *pHt->GetStart();
3152             const sal_uInt16 nWhich = pHt->Which();
3153             if (nIdx + nLen <= nAttrStartIdx)
3154 				break;		// ueber das Textende
3155 
3156 			const xub_StrLen *pEndIdx = pHt->End();
3157 			if( pEndIdx && *pEndIdx > nIdx &&
3158 				( RES_CHRATR_FONT == nWhich ||
3159                   RES_TXTATR_CHARFMT == nWhich ||
3160                   RES_TXTATR_AUTOFMT == nWhich ))
3161             {
3162                 const SvxFontItem* const pFont =
3163                     static_cast<const SvxFontItem*>(
3164                         CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
3165                 if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
3166                 {
3167                     // attribute in area => copy
3168                     rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
3169                             nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
3170                 }
3171             }
3172             else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
3173 			{
3174 				aDestIdx = nInsPos + nAttrStartIdx;
3175 				switch( nWhich )
3176 				{
3177 				case RES_TXTATR_FIELD:
3178 					{
3179                         XubString const aExpand(
3180                             static_cast<SwTxtFld const*>(pHt)->GetFmtFld().GetField()->ExpandField(true) );
3181 						if( aExpand.Len() )
3182 						{
3183 							aDestIdx++;		// dahinter einfuegen;
3184                             rDestNd.InsertText( aExpand, aDestIdx );
3185 							aDestIdx = nInsPos + nAttrStartIdx;
3186 							nInsPos = nInsPos + aExpand.Len();
3187                         }
3188                         rDestNd.EraseText( aDestIdx, 1 );
3189 						--nInsPos;
3190 					}
3191 					break;
3192 
3193 				case RES_TXTATR_FTN:
3194 					{
3195                         if ( bWithFtn )
3196                         {
3197                             const SwFmtFtn& rFtn = pHt->GetFtn();
3198                             XubString sExpand;
3199                             if( rFtn.GetNumStr().Len() )
3200                                 sExpand = rFtn.GetNumStr();
3201                             else if( rFtn.IsEndNote() )
3202                                 sExpand = GetDoc()->GetEndNoteInfo().aFmt.
3203                                                 GetNumStr( rFtn.GetNumber() );
3204                             else
3205                                 sExpand = GetDoc()->GetFtnInfo().aFmt.
3206                                                 GetNumStr( rFtn.GetNumber() );
3207                             if( sExpand.Len() )
3208                             {
3209                                 aDestIdx++;     // insert behind
3210                                 SvxEscapementItem aItem(
3211                                         SVX_ESCAPEMENT_SUPERSCRIPT );
3212                                 rDestNd.InsertItem(aItem,
3213                                         aDestIdx.GetIndex(),
3214                                         aDestIdx.GetIndex() );
3215                                 rDestNd.InsertText( sExpand, aDestIdx,
3216                                   IDocumentContentOperations::INS_EMPTYEXPAND);
3217                                 aDestIdx = nInsPos + nAttrStartIdx;
3218                                 nInsPos = nInsPos + sExpand.Len();
3219                             }
3220                         }
3221                         rDestNd.EraseText( aDestIdx, 1 );
3222 						--nInsPos;
3223 					}
3224 					break;
3225 
3226 				default:
3227                     rDestNd.EraseText( aDestIdx, 1 );
3228 					--nInsPos;
3229 				}
3230 			}
3231 		}
3232 	}
3233 
3234 	if( bWithNum )
3235 	{
3236 		aDestIdx = nDestStt;
3237         rDestNd.InsertText( GetNumString(), aDestIdx );
3238 	}
3239 
3240     if ( nHiddenChrs > 0 )
3241     {
3242         aDestIdx = 0;
3243         while ( aDestIdx < rDestNd.GetTxt().Len() )
3244         {
3245             if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) )
3246             {
3247                 xub_StrLen nIndex = aDestIdx.GetIndex();
3248                 while ( nIndex < rDestNd.GetTxt().Len() &&
3249                         cChar == rDestNd.GetTxt().GetChar( ++nIndex ) )
3250                     ;
3251                 rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() );
3252             }
3253             else
3254                 ++aDestIdx;
3255         }
3256     }
3257 
3258 	return sal_True;
3259 }
3260 
3261 const ModelToViewHelper::ConversionMap*
3262         SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const
3263 {
3264     const rtl::OUString& rNodeText = GetTxt();
3265     rRetText = rNodeText;
3266     ModelToViewHelper::ConversionMap* pConversionMap = 0;
3267 
3268     const SwpHints* pSwpHints2 = GetpSwpHints();
3269     xub_StrLen nPos = 0;
3270 
3271     for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
3272     {
3273         const SwTxtAttr* pAttr = (*pSwpHints2)[i];
3274         if ( RES_TXTATR_FIELD == pAttr->Which() )
3275         {
3276             const XubString aExpand(
3277                 static_cast<SwTxtFld const*>(pAttr)->GetFmtFld().GetField()->ExpandField(true));
3278             if ( aExpand.Len() > 0 )
3279             {
3280                 const xub_StrLen nFieldPos = *pAttr->GetStart();
3281                 rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
3282                 if ( !pConversionMap )
3283                     pConversionMap = new ModelToViewHelper::ConversionMap;
3284                 pConversionMap->push_back(
3285                         ModelToViewHelper::ConversionMapEntry(
3286                             nFieldPos, nPos + nFieldPos ) );
3287                 nPos += ( aExpand.Len() - 1 );
3288             }
3289         }
3290     }
3291 
3292     if ( pConversionMap && pConversionMap->size() )
3293         pConversionMap->push_back(
3294             ModelToViewHelper::ConversionMapEntry(
3295                 rNodeText.getLength()+1, rRetText.getLength()+1 ) );
3296 
3297     return pConversionMap;
3298 }
3299 
3300 XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
3301 								sal_Bool bExpandFlds, sal_Bool bWithNum ) const
3302 {
3303 	SvUShorts aRedlArr;
3304 	const SwDoc* pDoc = GetDoc();
3305 	sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
3306 	if( USHRT_MAX != nRedlPos )
3307 	{
3308 		// es existiert fuer den Node irgendein Redline-Delete-Object
3309 		const sal_uLong nNdIdx = GetIndex();
3310 		for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos )
3311 		{
3312 			const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
3313 			if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
3314 			{
3315 				const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
3316 				if( pRStt->nNode < nNdIdx )
3317 				{
3318 					if( pREnd->nNode > nNdIdx )
3319 						// Absatz ist komplett geloescht
3320 						return aEmptyStr;
3321 					else if( pREnd->nNode == nNdIdx )
3322 					{
3323 						// von 0 bis nContent ist alles geloescht
3324 						aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() );
3325 						aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
3326 					}
3327 				}
3328 				else if( pRStt->nNode == nNdIdx )
3329 				{
3330 					aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
3331 					if( pREnd->nNode == nNdIdx )
3332 						aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
3333 					else
3334 					{
3335 						aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() );
3336 						break; 		// mehr kann nicht kommen
3337 					}
3338 				}
3339 				else
3340 					break; 		// mehr kann nicht kommen
3341 			}
3342 		}
3343 	}
3344 
3345 	XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
3346 
3347 	xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
3348 	for( sal_uInt16 n = 0; n < aRedlArr.Count(); n += 2 )
3349 	{
3350 		xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
3351 		if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
3352 			( nIdx <= nEnd && nEnd <= nIdxEnd ))
3353 		{
3354 			if( nStt < nIdx ) nStt = nIdx;
3355 			if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
3356 			xub_StrLen nDelCnt = nEnd - nStt;
3357 			aTxt.Erase( nStt - nTxtStt, nDelCnt );
3358 			Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
3359 			nTxtStt = nTxtStt + nDelCnt;
3360 		}
3361 		else if( nStt >= nIdxEnd )
3362 			break;
3363 	}
3364 	Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );
3365 
3366 	if( bWithNum )
3367 		aTxt.Insert( GetNumString(), 0 );
3368 	return aTxt;
3369 }
3370 
3371 /*************************************************************************
3372  *                        SwTxtNode::ReplaceText
3373  *************************************************************************/
3374 
3375 void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
3376                              const XubString& rText )
3377 {
3378     ASSERT( rStart.GetIndex() < m_Text.Len() &&
3379             rStart.GetIndex() + nDelLen <= m_Text.Len(),
3380             "SwTxtNode::ReplaceText: index out of bounds" );
3381     const xub_StrLen nStartPos = rStart.GetIndex();
3382     xub_StrLen nEndPos = nStartPos + nDelLen;
3383     xub_StrLen nLen = nDelLen;
3384     for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
3385     {
3386         if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) ||
3387              ( CH_TXTATR_INWORD    == m_Text.GetChar( nPos ) ) )
3388         {
3389             SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
3390             if (pHint)
3391             {
3392                 ASSERT (!( pHint->GetEnd() && pHint->HasDummyChar()
3393                             && (*pHint->GetStart() < nEndPos)
3394                             && (*pHint->GetEnd()   > nEndPos) ),
3395                     "ReplaceText: ERROR: "
3396                     "deleting left-overlapped attribute with CH_TXTATR");
3397                 DeleteAttribute( pHint );
3398                 --nEndPos;
3399                 --nLen;
3400             }
3401         }
3402     }
3403 
3404 	sal_Bool bOldExpFlg = IsIgnoreDontExpand();
3405 	SetIgnoreDontExpand( sal_True );
3406 
3407 	if( nLen && rText.Len() )
3408 	{
3409 		// dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
3410 		// Dadurch wird die Attributierung des 1. Zeichen expandiert!
3411         m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );
3412 
3413 		((SwIndex&)rStart)++;
3414         m_Text.Erase( rStart.GetIndex(), nLen - 1 );
3415         Update( rStart, nLen - 1, true );
3416 
3417 		XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
3418         m_Text.Insert( aTmpTxt, rStart.GetIndex() );
3419         Update( rStart, aTmpTxt.Len(), false );
3420     }
3421     else
3422     {
3423         m_Text.Erase( nStartPos, nLen );
3424         Update( rStart, nLen, true );
3425 
3426         m_Text.Insert( rText, nStartPos );
3427         Update( rStart, rText.Len(), false );
3428     }
3429 
3430 	SetIgnoreDontExpand( bOldExpFlg );
3431     SwDelTxt aDelHint( nStartPos, nDelLen );
3432 	NotifyClients( 0, &aDelHint );
3433 
3434     SwInsTxt aHint( nStartPos, rText.Len() );
3435 	NotifyClients( 0, &aHint );
3436 }
3437 
3438 // --> OD 2008-03-27 #refactorlists#
3439 namespace {
3440     // Helper method for special handling of modified attributes at text node.
3441     // The following is handled:
3442     // (1) on changing the paragraph style - RES_FMT_CHG:
3443     // Check, if list style of the text node is changed. If yes, add respectively
3444     // remove the text node to the corresponding list.
3445     // (2) on changing the attributes - RES_ATTRSET_CHG:
3446     // Same as (1).
3447     // (3) on changing the list style - RES_PARATR_NUMRULE:
3448     // Same as (1).
3449     void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
3450                                 const SfxPoolItem* pOldValue,
3451                                 const SfxPoolItem* pNewValue )
3452     {
3453         const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
3454                               pNewValue ? pNewValue->Which() : 0 ;
3455         bool bNumRuleSet = false;
3456         bool bParagraphStyleChanged = false;
3457         String sNumRule;
3458         String sOldNumRule;
3459         switch ( nWhich )
3460         {
3461             case RES_FMT_CHG:
3462             {
3463                 bParagraphStyleChanged = true;
3464                 if( rTxtNode.GetNodes().IsDocNodes() )
3465                 {
3466                     const SwNumRule* pFormerNumRuleAtTxtNode =
3467                         rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3468                     if ( pFormerNumRuleAtTxtNode )
3469                     {
3470                         sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3471                     }
3472                     if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
3473                     {
3474                         const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
3475                         if ( rNumRuleItem.GetValue().Len() > 0 )
3476                         {
3477                             rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3478                         }
3479                     }
3480                     const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3481                     if ( pNumRuleAtTxtNode )
3482                     {
3483                         bNumRuleSet = true;
3484                         sNumRule = pNumRuleAtTxtNode->GetName();
3485                     }
3486                 }
3487                 break;
3488             }
3489             case RES_ATTRSET_CHG:
3490             {
3491                 const SfxPoolItem* pItem = 0;
3492                 const SwNumRule* pFormerNumRuleAtTxtNode =
3493                     rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3494                 if ( pFormerNumRuleAtTxtNode )
3495                 {
3496                     sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3497                 }
3498                 if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ==
3499                         SFX_ITEM_SET )
3500                 {
3501                     rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3502                     bNumRuleSet = true;
3503                 }
3504                 const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3505                 if ( pNumRuleAtTxtNode )
3506                 {
3507                     sNumRule = pNumRuleAtTxtNode->GetName();
3508                 }
3509                 break;
3510             }
3511             case RES_PARATR_NUMRULE:
3512             {
3513                 if ( rTxtNode.GetNodes().IsDocNodes() )
3514                 {
3515                     const SwNumRule* pFormerNumRuleAtTxtNode =
3516                         rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3517                     if ( pFormerNumRuleAtTxtNode )
3518                     {
3519                         sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3520                     }
3521                     if ( pNewValue )
3522                     {
3523                         rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3524                         bNumRuleSet = true;
3525                     }
3526                     const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3527                     if ( pNumRuleAtTxtNode )
3528                     {
3529                         sNumRule = pNumRuleAtTxtNode->GetName();
3530                     }
3531                 }
3532                 break;
3533             }
3534         }
3535         if ( sNumRule != sOldNumRule )
3536         {
3537             if ( bNumRuleSet )
3538             {
3539                 if ( sNumRule.Len() == 0 )
3540                 {
3541                     rTxtNode.RemoveFromList();
3542                     if ( bParagraphStyleChanged )
3543                     {
3544                         SvUShortsSort aResetAttrsArray;
3545                         aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
3546                         aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
3547                         aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
3548                         aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
3549                         aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
3550                         SwPaM aPam( rTxtNode );
3551                         // suppress side effect "send data changed events"
3552                         rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
3553                                                        &aResetAttrsArray,
3554                                                        false );
3555                     }
3556                 }
3557                 else
3558                 {
3559                     rTxtNode.RemoveFromList();
3560                     // If new list style is the outline style, apply outline
3561                     // level as the list level.
3562                     if ( sNumRule ==
3563                             String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) )
3564                     {
3565                         ASSERT( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
3566                                 "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
3567                         const int nNewListLevel = rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
3568                         if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
3569                         {
3570                             rTxtNode.SetAttrListLevel( nNewListLevel );
3571                         }
3572                     }
3573                     rTxtNode.AddToList();
3574                 }
3575             }
3576             else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
3577             {
3578                 rTxtNode.RemoveFromList();
3579                 if ( bParagraphStyleChanged )
3580                 {
3581                     SvUShortsSort aResetAttrsArray;
3582                     aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
3583                     aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
3584                     aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
3585                     aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
3586                     aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
3587                     SwPaM aPam( rTxtNode );
3588                     rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
3589                                                    &aResetAttrsArray,
3590                                                    false );
3591                     if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
3592                     {
3593                         rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
3594                     }
3595                 }
3596             }
3597         }
3598         else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
3599         {
3600             rTxtNode.AddToList();
3601         }
3602     }
3603     // End of method <HandleModifyAtTxtNode>
3604 }
3605 // <--
3606 
3607 void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
3608 {
3609     bool bWasNotifiable = m_bNotifiable;
3610     m_bNotifiable = false;
3611 
3612 	// Bug 24616/24617:
3613 	// 		Modify ueberladen, damit beim Loeschen von Vorlagen diese
3614 	// 		wieder richtig verwaltet werden (Outline-Numerierung!!)
3615 	// 	Bug25481:
3616 	//		bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
3617 	if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
3618 		GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt &&
3619 		GetNodes().IsDocNodes() )
3620     {
3621 		_ChgTxtCollUpdateNum(
3622 						(SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
3623 						(SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
3624     }
3625 
3626     // --> OD 2008-03-27 #refactorlists#
3627     if ( !mbInSetOrResetAttr )
3628     {
3629         HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
3630     }
3631     // <--
3632 
3633 	SwCntntNode::Modify( pOldValue, pNewValue );
3634 
3635     SwDoc * pDoc = GetDoc();
3636     // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array
3637     if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
3638     // <--
3639     {
3640         pDoc->GetNodes().UpdateOutlineNode(*this);
3641     }
3642 
3643     m_bNotifiable = bWasNotifiable;
3644 
3645     if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
3646     {   // invalidate cached uno object
3647         SetXParagraph(::com::sun::star::uno::Reference<
3648                 ::com::sun::star::text::XTextContent>(0));
3649     }
3650 }
3651 
3652 SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
3653 {
3654     ASSERT( pNewColl,"ChgFmtColl: Collectionpointer ist 0." );
3655     ASSERT( HAS_BASE( SwTxtFmtColl, pNewColl ),
3656                 "ChgFmtColl: ist kein Text-Collectionpointer." );
3657 
3658     SwTxtFmtColl *pOldColl = GetTxtColl();
3659     if( pNewColl != pOldColl )
3660     {
3661         SetCalcHiddenCharFlags();
3662         SwCntntNode::ChgFmtColl( pNewColl );
3663         // --> OD 2008-03-27 #refactorlists#
3664 //        NumRuleChgd();
3665 #if OSL_DEBUG_LEVEL > 1
3666         ASSERT( !mbInSetOrResetAttr,
3667                 "DEBUG ASSERTION - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" )
3668 #endif
3669         if ( !mbInSetOrResetAttr )
3670         {
3671             SwFmtChg aTmp1( pOldColl );
3672             SwFmtChg aTmp2( pNewColl );
3673             HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2  );
3674         }
3675         // <--
3676     }
3677 
3678     // nur wenn im normalen Nodes-Array
3679     if( GetNodes().IsDocNodes() )
3680     {
3681         _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
3682     }
3683 
3684     GetNodes().UpdateOutlineNode(*this);
3685 
3686     return pOldColl;
3687 }
3688 
3689 SwNodeNum* SwTxtNode::CreateNum() const
3690 {
3691     if ( !mpNodeNum )
3692     {
3693         // --> OD 2008-02-19 #refactorlists#
3694         mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
3695         // <--
3696     }
3697     return mpNodeNum;
3698 }
3699 
3700 SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
3701 {
3702     if ( GetNum() )
3703     {
3704         return GetNum()->GetNumberVector();
3705     }
3706     else
3707     {
3708         SwNumberTree::tNumberVector aResult;
3709         return aResult;
3710     }
3711 }
3712 
3713 bool SwTxtNode::IsOutline() const
3714 {
3715     bool bResult = false;
3716 
3717     //if ( GetOutlineLevel() != NO_NUMBERING )//#outline level,removed by zhaojianwei
3718     if ( GetAttrOutlineLevel() > 0 )            //<-end,zhaojianwei
3719     {
3720         bResult = !IsInRedlines();
3721     }
3722     else
3723     {
3724         const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
3725         if ( pRule && pRule->IsOutlineRule() )
3726         {
3727             bResult = !IsInRedlines();
3728         }
3729     }
3730 
3731     return bResult;
3732 }
3733 
3734 bool SwTxtNode::IsOutlineStateChanged() const
3735 {
3736     return IsOutline() != m_bLastOutlineState;
3737 }
3738 
3739 void SwTxtNode::UpdateOutlineState()
3740 {
3741     m_bLastOutlineState = IsOutline();
3742 }
3743 
3744 //#outline level, zhaojianwei
3745 int SwTxtNode::GetAttrOutlineLevel() const
3746 {
3747 	return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
3748 }
3749 void SwTxtNode::SetAttrOutlineLevel(int nLevel)
3750 {
3751     ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei
3752     if ( 0 <= nLevel && nLevel <= MAXLEVEL )
3753     {
3754         SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
3755                                 static_cast<sal_uInt16>(nLevel) ) );
3756     }
3757 }
3758 //<-end
3759 
3760 // --> OD 2008-11-19 #i70748#
3761 bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
3762 {
3763     return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
3764 }
3765 
3766 void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
3767 {
3768     if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3769     {
3770         SetAttr( SwNumRuleItem() );
3771         mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
3772     }
3773 }
3774 
3775 void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
3776 {
3777     if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3778     {
3779         ResetAttr( RES_PARATR_NUMRULE );
3780         mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
3781     }
3782 }
3783 // <--
3784 
3785 
3786 // --> OD 2008-02-27 #refactorlists#
3787 void SwTxtNode::SetAttrListLevel( int nLevel )
3788 {
3789     if ( nLevel < 0 || nLevel >= MAXLEVEL )
3790     {
3791         ASSERT( false,
3792                 "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" );
3793         return;
3794     }
3795 
3796     SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
3797                                     static_cast<sal_Int16>(nLevel) );
3798     SetAttr( aNewListLevelItem );
3799 }
3800 // <--
3801 // --> OD 2008-02-27 #refactorlists#
3802 bool SwTxtNode::HasAttrListLevel() const
3803 {
3804     return GetpSwAttrSet() &&
3805            GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET;
3806 }
3807 // <--
3808 // --> OD 2008-02-27 #refactorlists#
3809 int SwTxtNode::GetAttrListLevel() const
3810 {
3811     int nAttrListLevel = 0;
3812 
3813     const SfxInt16Item& aListLevelItem =
3814         dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
3815     nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
3816 
3817     return nAttrListLevel;
3818 }
3819 // <--
3820 
3821 int SwTxtNode::GetActualListLevel() const
3822 {
3823     return GetNum() ? GetNum()->GetLevelInListTree() : -1;
3824 }
3825 
3826 // --> OD 2008-02-25 #refactorlists#
3827 void SwTxtNode::SetListRestart( bool bRestart )
3828 {
3829 //    CreateNum()->SetRestart(bRestart);
3830     if ( !bRestart )
3831     {
3832         // attribute not contained in paragraph style's attribute set. Thus,
3833         // it can be reset to the attribute pool default by resetting the attribute.
3834         ResetAttr( RES_PARATR_LIST_ISRESTART );
3835     }
3836     else
3837     {
3838         SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
3839                                        sal_True );
3840         SetAttr( aNewIsRestartItem );
3841     }
3842 }
3843 
3844 // --> OD 2008-02-25 #refactorlists#
3845 bool SwTxtNode::IsListRestart() const
3846 {
3847 //    return GetNum() ? GetNum()->IsRestart() : false;
3848     const SfxBoolItem& aIsRestartItem =
3849         dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));
3850 
3851     return aIsRestartItem.GetValue() ? true : false;
3852 }
3853 // <--
3854 
3855 /** Returns if the paragraph has a visible numbering or bullet.
3856     This includes all kinds of numbering/bullet/outlines.
3857     OD 2008-02-28 #newlistlevelattrs#
3858     The concrete list label string has to be checked, too.
3859  */
3860 bool SwTxtNode::HasVisibleNumberingOrBullet() const
3861 {
3862     bool bRet = false;
3863 
3864     const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
3865     if ( pRule && IsCountedInList())
3866     {
3867         // --> OD 2008-03-19 #i87154#
3868         // Correction of #newlistlevelattrs#:
3869         // The numbering type has to be checked for bullet lists.
3870         const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() ));
3871         if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
3872              pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
3873         {
3874             bRet = true;
3875         }
3876         // <--
3877     }
3878 
3879     return bRet;
3880 }
3881 
3882 // --> OD 2008-02-25 #refactorlists#
3883 void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
3884 {
3885 //    CreateNum()->SetStart(nNumber);
3886     const bool bChanged( HasAttrListRestartValue()
3887                          ? GetAttrListRestartValue() != nNumber
3888                          : nNumber != USHRT_MAX );
3889 
3890     if ( bChanged || !HasAttrListRestartValue() )
3891     {
3892         if ( nNumber == USHRT_MAX )
3893         {
3894             ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
3895         }
3896         else
3897         {
3898             SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
3899                                                    static_cast<sal_Int16>(nNumber) );
3900             SetAttr( aNewListRestartValueItem );
3901         }
3902     }
3903 }
3904 // <--
3905 
3906 // --> OD 2008-02-27 #refactorlists#
3907 bool SwTxtNode::HasAttrListRestartValue() const
3908 {
3909     return GetpSwAttrSet() &&
3910            GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET;
3911 }
3912 // <--
3913 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
3914 {
3915     ASSERT( HasAttrListRestartValue(),
3916             "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
3917 
3918     const SfxInt16Item& aListRestartValueItem =
3919         dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
3920     return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
3921 }
3922 
3923 // --> OD 2008-02-25 #refactorlists#
3924 SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
3925 {
3926 //    return GetNum() ? GetNum()->GetStart() : 1;
3927     SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
3928 
3929     if ( IsListRestart() && HasAttrListRestartValue() )
3930     {
3931         nListRestartValue = GetAttrListRestartValue();
3932     }
3933     else
3934     {
3935         SwNumRule* pRule = GetNumRule();
3936         if ( pRule )
3937         {
3938             const SwNumFmt* pFmt =
3939                     pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) );
3940             if ( pFmt )
3941             {
3942                 nListRestartValue = pFmt->GetStart();
3943             }
3944         }
3945     }
3946 
3947     return nListRestartValue;
3948 }
3949 // <--
3950 
3951 bool SwTxtNode::IsNotifiable() const
3952 {
3953     return m_bNotifiable && IsNotificationEnabled();
3954 }
3955 
3956 bool SwTxtNode::IsNotificationEnabled() const
3957 {
3958     bool bResult = false;
3959     const SwDoc * pDoc = GetDoc();
3960     if( pDoc )
3961     {
3962         bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
3963     }
3964     return bResult;
3965 }
3966 
3967 // --> OD 2008-02-27 #refactorlists#
3968 void SwTxtNode::SetCountedInList( bool bCounted )
3969 {
3970     if ( bCounted )
3971     {
3972         // attribute not contained in paragraph style's attribute set. Thus,
3973         // it can be reset to the attribute pool default by resetting the attribute.
3974         ResetAttr( RES_PARATR_LIST_ISCOUNTED );
3975     }
3976     else
3977     {
3978         SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False );
3979         SetAttr( aIsCountedInListItem );
3980     }
3981 }
3982 // <--
3983 
3984 bool SwTxtNode::IsCountedInList() const
3985 {
3986     const SfxBoolItem& aIsCountedInListItem =
3987         dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));
3988 
3989     return aIsCountedInListItem.GetValue() ? true : false;
3990 }
3991 
3992 // --> OD 2008-03-13 #refactorlists#
3993 void SwTxtNode::AddToList()
3994 {
3995     if ( IsInList() )
3996     {
3997         ASSERT( false,
3998                 "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
3999         return;
4000     }
4001 
4002     const String sListId = GetListId();
4003     if ( sListId.Len() > 0 )
4004     {
4005         SwList* pList = GetDoc()->getListByName( sListId );
4006         if ( pList == 0 )
4007         {
4008             // Create corresponding list.
4009             SwNumRule* pNumRule = GetNumRule();
4010             if ( pNumRule )
4011             {
4012                 pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
4013             }
4014         }
4015         ASSERT( pList != 0,
4016                 "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
4017         if ( pList )
4018         {
4019             pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
4020             mpList = pList;
4021         }
4022     }
4023 }
4024 
4025 void SwTxtNode::RemoveFromList()
4026 {
4027     if ( IsInList() )
4028     {
4029         mpList->RemoveListItem( *mpNodeNum );
4030         mpList = 0;
4031         delete mpNodeNum;
4032         mpNodeNum = 0L;
4033     }
4034 }
4035 
4036 bool SwTxtNode::IsInList() const
4037 {
4038     return GetNum() != 0 && GetNum()->GetParent() != 0;
4039 }
4040 // <--
4041 
4042 bool SwTxtNode::IsFirstOfNumRule() const
4043 {
4044     bool bResult = false;
4045 
4046     if ( GetNum() && GetNum()->GetNumRule())
4047         bResult = GetNum()->IsFirst();
4048 
4049     return bResult;
4050 }
4051 
4052 // --> OD 2008-02-20 #refactorlists#
4053 void SwTxtNode::SetListId( const String sListId )
4054 {
4055     const SfxStringItem& rListIdItem =
4056             dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4057     if ( rListIdItem.GetValue() != sListId )
4058     {
4059         if ( sListId.Len() == 0 )
4060         {
4061             ResetAttr( RES_PARATR_LIST_ID );
4062         }
4063         else
4064         {
4065             SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
4066             SetAttr( aNewListIdItem );
4067         }
4068     }
4069 }
4070 
4071 String SwTxtNode::GetListId() const
4072 {
4073     String sListId;
4074 
4075     const SfxStringItem& rListIdItem =
4076                 dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4077     sListId = rListIdItem.GetValue();
4078 
4079     // As long as no explicit list id attribute is set, use the list id of
4080     // the list, which has been created for the applied list style.
4081     if ( sListId.Len() == 0 )
4082     {
4083         SwNumRule* pRule = GetNumRule();
4084         if ( pRule )
4085         {
4086             sListId = pRule->GetDefaultListId();
4087 //#if OSL_DEBUG_LEVEL > 1
4088 //            ASSERT( false,
4089 //                    "DEBUG ASSERTION: default list id of list style is applied." );
4090 //#endif
4091 //            // setting list id directly using <SwCntntNode::SetAttr(..)>,
4092 //            // because no handling of this attribute set is needed and to avoid
4093 //            // recursive calls of <SwTxtNode::SetAttr(..)>
4094 //            SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
4095 //            const_cast<SwTxtNode*>(this)->SwCntntNode::SetAttr( aNewListIdItem );
4096         }
4097     }
4098 
4099     return sListId;
4100 }
4101 // <--
4102 
4103 /** Determines, if the list level indent attributes can be applied to the
4104     paragraph.
4105 
4106     OD 2008-01-17 #newlistlevelattrs#
4107     The list level indents can be applied to the paragraph under the one
4108     of following conditions:
4109     - the list style is directly applied to the paragraph and the paragraph
4110       has no own indent attributes.
4111     - the list style is applied to the paragraph through one of its paragraph
4112       styles, the paragraph has no own indent attributes and on the paragraph
4113       style hierarchy from the paragraph to the paragraph style with the
4114       list style no indent attributes are found.
4115 
4116     @author OD
4117 
4118     @return boolean
4119 */
4120 bool SwTxtNode::AreListLevelIndentsApplicable() const
4121 {
4122     bool bAreListLevelIndentsApplicable( true );
4123 
4124     if ( !GetNum() || !GetNum()->GetNumRule() )
4125     {
4126         // no list style applied to paragraph
4127         bAreListLevelIndentsApplicable = false;
4128     }
4129     else if ( HasSwAttrSet() &&
4130               GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
4131     {
4132         // paragraph has hard-set indent attributes
4133         bAreListLevelIndentsApplicable = false;
4134     }
4135     else if ( HasSwAttrSet() &&
4136               GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
4137     {
4138         // list style is directly applied to paragraph and paragraph has no
4139         // hard-set indent attributes
4140         bAreListLevelIndentsApplicable = true;
4141     }
4142     else
4143     {
4144         // list style is applied through one of the paragraph styles and
4145         // paragraph has no hard-set indent attributes
4146 
4147         // check, paragraph's
4148         const SwTxtFmtColl* pColl = GetTxtColl();
4149         while ( pColl )
4150         {
4151             if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
4152             {
4153                 // indent attributes found in the paragraph style hierarchy.
4154                 bAreListLevelIndentsApplicable = false;
4155                 break;
4156             }
4157 
4158             if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
4159             {
4160                 // paragraph style with the list style found and until now no
4161                 // indent attributes are found in the paragraph style hierarchy.
4162                 bAreListLevelIndentsApplicable = true;
4163                 break;
4164             }
4165 
4166             pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
4167             ASSERT( pColl,
4168                     "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
4169         }
4170     }
4171 
4172     return bAreListLevelIndentsApplicable;
4173 }
4174 
4175 /** Retrieves the list tab stop position, if the paragraph's list level defines
4176     one and this list tab stop has to merged into the tap stops of the paragraph
4177 
4178     OD 2008-01-17 #newlistlevelattrs#
4179 
4180     @author OD
4181 
4182     @param nListTabStopPosition
4183     output parameter - containing the list tab stop position
4184 
4185     @return boolean - indicating, if a list tab stop position is provided
4186 */
4187 bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
4188 {
4189     bool bListTanStopPositionProvided( false );
4190 
4191     const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4192     if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4193     {
4194         const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
4195         if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
4196              rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
4197         {
4198             bListTanStopPositionProvided = true;
4199             nListTabStopPosition = rFmt.GetListtabPos();
4200 
4201             if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
4202             {
4203                 // tab stop position are treated to be relative to the "before text"
4204                 // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
4205                 if ( AreListLevelIndentsApplicable() )
4206                 {
4207                     nListTabStopPosition -= rFmt.GetIndentAt();
4208                 }
4209                 else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
4210                 {
4211                     SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
4212                     nListTabStopPosition -= aItem.GetTxtLeft();
4213                 }
4214             }
4215         }
4216     }
4217 
4218     return bListTanStopPositionProvided;
4219 }
4220 
4221 /** Retrieves the character following the list label, if the paragraph's
4222     list level defines one.
4223 
4224     OD 2008-01-17 #newlistlevelattrs#
4225 
4226     @author OD
4227 
4228     @return XubString - the list tab stop position
4229 */
4230 XubString SwTxtNode::GetLabelFollowedBy() const
4231 {
4232     XubString aLabelFollowedBy;
4233 
4234     const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4235     if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4236     {
4237         const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
4238         if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
4239         {
4240             switch ( rFmt.GetLabelFollowedBy() )
4241             {
4242                 case SvxNumberFormat::LISTTAB:
4243                 {
4244                     const sal_Unicode aTab = '\t';
4245                     aLabelFollowedBy.Insert( aTab, 0 );
4246                 }
4247                 break;
4248                 case SvxNumberFormat::SPACE:
4249                 {
4250                     const sal_Unicode aSpace = ' ';
4251                     aLabelFollowedBy.Insert( aSpace, 0 );
4252                 }
4253                 break;
4254                 case SvxNumberFormat::NOTHING:
4255                 {
4256                     // intentionally left blank.
4257                 }
4258                 break;
4259                 default:
4260                 {
4261                     ASSERT( false,
4262                             "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
4263                 }
4264             }
4265         }
4266     }
4267 
4268     return aLabelFollowedBy;
4269 }
4270 
4271 void SwTxtNode::CalcHiddenCharFlags() const
4272 {
4273     xub_StrLen nStartPos;
4274     xub_StrLen nEndPos;
4275     // Update of the flags is done inside GetBoundsOfHiddenRange()
4276     SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
4277 }
4278 
4279 // --> FME 2004-06-08 #i12836# enhanced pdf export
4280 bool SwTxtNode::IsHidden() const
4281 {
4282     if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
4283         return true;
4284 
4285     const SwSectionNode* pSectNd = FindSectionNode();
4286     if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
4287         return true;
4288 
4289     return false;
4290 }
4291 // <--
4292 
4293 // --> OD 2008-03-13 #refactorlists#
4294 namespace {
4295     // Helper class for special handling of setting attributes at text node:
4296     // In constructor an instance of the helper class recognize whose attributes
4297     // are set and perform corresponding actions before the intrinsic set of
4298     // attributes has been taken place.
4299     // In the destructor - after the attributes have been set at the text
4300     // node - corresponding actions are performed.
4301     // The following is handled:
4302     // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
4303     //     (A) list style attribute is empty -> the text node is removed from
4304     //         its list.
4305     //     (B) list style attribute is not empty
4306     //         (a) text node has no list style -> add text node to its list after
4307     //             the attributes have been set.
4308     //         (b) text node has list style -> change of list style is notified
4309     //             after the attributes have been set.
4310     // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
4311     //     the text node is removed from its current list before the attributes
4312     //     are set and added to its new list after the attributes have been set.
4313     // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
4314     //     and changed after the attributes have been set
4315     // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
4316     //     and changed after the attributes have been set
4317     // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
4318     //     is set and changed after the attributes have been set
4319     // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
4320     //     and changed after the attributes have been set
4321     // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
4322     class HandleSetAttrAtTxtNode
4323     {
4324         public:
4325             HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4326                                     const SfxPoolItem& pItem );
4327             HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4328                                     const SfxItemSet& rItemSet );
4329             ~HandleSetAttrAtTxtNode();
4330 
4331         private:
4332             SwTxtNode& mrTxtNode;
4333             bool mbAddTxtNodeToList;
4334             bool mbUpdateListLevel;
4335             bool mbUpdateListRestart;
4336             bool mbUpdateListCount;
4337             // --> OD 2008-11-19 #i70748#
4338             bool mbOutlineLevelSet;
4339             // <--
4340     };
4341 
4342     HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4343                                                     const SfxPoolItem& pItem )
4344         : mrTxtNode( rTxtNode ),
4345           mbAddTxtNodeToList( false ),
4346           mbUpdateListLevel( false ),
4347           mbUpdateListRestart( false ),
4348           mbUpdateListCount( false ),
4349           // --> OD 2008-11-19 #i70748#
4350           mbOutlineLevelSet( false )
4351           // <--
4352     {
4353         switch ( pItem.Which() )
4354         {
4355             // handle RES_PARATR_NUMRULE
4356             case RES_PARATR_NUMRULE:
4357             {
4358                 mrTxtNode.RemoveFromList();
4359 
4360                 const SwNumRuleItem& pNumRuleItem =
4361                                 dynamic_cast<const SwNumRuleItem&>(pItem);
4362                 if ( pNumRuleItem.GetValue().Len() > 0 )
4363                 {
4364                     mbAddTxtNodeToList = true;
4365                     // --> OD 2010-05-12 #i105562#
4366                     //
4367                     mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4368                     // <--
4369                 }
4370             }
4371             break;
4372 
4373             // handle RES_PARATR_LIST_ID
4374             case RES_PARATR_LIST_ID:
4375             {
4376                 const SfxStringItem& pListIdItem =
4377                                         dynamic_cast<const SfxStringItem&>(pItem);
4378                 ASSERT( pListIdItem.GetValue().Len() > 0,
4379                         "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
4380                 const String sListIdOfTxtNode = rTxtNode.GetListId();
4381                 if ( pListIdItem.GetValue() != sListIdOfTxtNode )
4382                 {
4383                     mbAddTxtNodeToList = true;
4384                     if ( mrTxtNode.IsInList() )
4385                     {
4386                         mrTxtNode.RemoveFromList();
4387                     }
4388                 }
4389             }
4390             break;
4391 
4392             // handle RES_PARATR_LIST_LEVEL
4393             case RES_PARATR_LIST_LEVEL:
4394             {
4395                 const SfxInt16Item& aListLevelItem =
4396                                     dynamic_cast<const SfxInt16Item&>(pItem);
4397                 if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
4398                 {
4399                     mbUpdateListLevel = true;
4400                 }
4401             }
4402             break;
4403 
4404             // handle RES_PARATR_LIST_ISRESTART
4405             case RES_PARATR_LIST_ISRESTART:
4406             {
4407                 const SfxBoolItem& aListIsRestartItem =
4408                                     dynamic_cast<const SfxBoolItem&>(pItem);
4409                 if ( aListIsRestartItem.GetValue() !=
4410                                     (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
4411                 {
4412                     mbUpdateListRestart = true;
4413                 }
4414             }
4415             break;
4416 
4417             // handle RES_PARATR_LIST_RESTARTVALUE
4418             case RES_PARATR_LIST_RESTARTVALUE:
4419             {
4420                 const SfxInt16Item& aListRestartValueItem =
4421                                     dynamic_cast<const SfxInt16Item&>(pItem);
4422                 if ( !mrTxtNode.HasAttrListRestartValue() ||
4423                      aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
4424                 {
4425                     mbUpdateListRestart = true;
4426                 }
4427             }
4428             break;
4429 
4430             // handle RES_PARATR_LIST_ISCOUNTED
4431             case RES_PARATR_LIST_ISCOUNTED:
4432             {
4433                 const SfxBoolItem& aIsCountedInListItem =
4434                                     dynamic_cast<const SfxBoolItem&>(pItem);
4435                 if ( aIsCountedInListItem.GetValue() !=
4436                                     (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
4437                 {
4438                     mbUpdateListCount = true;
4439                 }
4440             }
4441             break;
4442 
4443             // --> OD 2008-11-19 #i70748#
4444             // handle RES_PARATR_OUTLINELEVEL
4445             case RES_PARATR_OUTLINELEVEL:
4446             {
4447                 const SfxUInt16Item& aOutlineLevelItem =
4448                                     dynamic_cast<const SfxUInt16Item&>(pItem);
4449                 if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4450                 {
4451                     mbOutlineLevelSet = true;
4452                 }
4453             }
4454             break;
4455             // <--
4456         }
4457 
4458     }
4459 
4460     HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4461                                                     const SfxItemSet& rItemSet )
4462         : mrTxtNode( rTxtNode ),
4463           mbAddTxtNodeToList( false ),
4464           mbUpdateListLevel( false ),
4465           mbUpdateListRestart( false ),
4466           mbUpdateListCount( false ),
4467           // --> OD 2008-11-19 #i70748#
4468           mbOutlineLevelSet( false )
4469           // <--
4470     {
4471         const SfxPoolItem* pItem = 0;
4472         // handle RES_PARATR_NUMRULE
4473         if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET )
4474         {
4475             mrTxtNode.RemoveFromList();
4476 
4477             const SwNumRuleItem* pNumRuleItem =
4478                             dynamic_cast<const SwNumRuleItem*>(pItem);
4479             if ( pNumRuleItem->GetValue().Len() > 0 )
4480             {
4481                 mbAddTxtNodeToList = true;
4482                 // --> OD 2008-11-19 #i70748#
4483                 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4484                 // <--
4485             }
4486         }
4487 
4488         // handle RES_PARATR_LIST_ID
4489         if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
4490         {
4491             const SfxStringItem* pListIdItem =
4492                                     dynamic_cast<const SfxStringItem*>(pItem);
4493             const String sListIdOfTxtNode = mrTxtNode.GetListId();
4494             if ( pListIdItem &&
4495                  pListIdItem->GetValue() != sListIdOfTxtNode )
4496             {
4497                 mbAddTxtNodeToList = true;
4498                 if ( mrTxtNode.IsInList() )
4499                 {
4500                     mrTxtNode.RemoveFromList();
4501                 }
4502             }
4503         }
4504 
4505         // handle RES_PARATR_LIST_LEVEL
4506         if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
4507         {
4508             const SfxInt16Item* pListLevelItem =
4509                                 dynamic_cast<const SfxInt16Item*>(pItem);
4510             if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
4511             {
4512                 mbUpdateListLevel = true;
4513             }
4514         }
4515 
4516         // handle RES_PARATR_LIST_ISRESTART
4517         if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET )
4518         {
4519             const SfxBoolItem* pListIsRestartItem =
4520                                 dynamic_cast<const SfxBoolItem*>(pItem);
4521             if ( pListIsRestartItem->GetValue() !=
4522                                     (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
4523             {
4524                 mbUpdateListRestart = true;
4525             }
4526         }
4527 
4528         // handle RES_PARATR_LIST_RESTARTVALUE
4529         if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET )
4530         {
4531             const SfxInt16Item* pListRestartValueItem =
4532                                 dynamic_cast<const SfxInt16Item*>(pItem);
4533             if ( !mrTxtNode.HasAttrListRestartValue() ||
4534                  pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
4535             {
4536                 mbUpdateListRestart = true;
4537             }
4538         }
4539 
4540         // handle RES_PARATR_LIST_ISCOUNTED
4541         if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET )
4542         {
4543             const SfxBoolItem* pIsCountedInListItem =
4544                                 dynamic_cast<const SfxBoolItem*>(pItem);
4545             if ( pIsCountedInListItem->GetValue() !=
4546                                 (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
4547             {
4548                 mbUpdateListCount = true;
4549             }
4550         }
4551 
4552         // --> OD 2008-11-19 #i70748#
4553         // handle RES_PARATR_OUTLINELEVEL
4554         if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
4555         {
4556             const SfxUInt16Item* pOutlineLevelItem =
4557                                 dynamic_cast<const SfxUInt16Item*>(pItem);
4558             if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4559             {
4560                 mbOutlineLevelSet = true;
4561             }
4562         }
4563         // <--
4564     }
4565 
4566     HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
4567     {
4568         if ( mbAddTxtNodeToList )
4569         {
4570             SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
4571             if ( pNumRuleAtTxtNode )
4572             {
4573                 mrTxtNode.AddToList();
4574             }
4575         }
4576         else
4577         {
4578             if ( mbUpdateListLevel && mrTxtNode.IsInList() )
4579             {
4580                 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
4581                                                     mrTxtNode.GetAttrListLevel() );
4582             }
4583 
4584             if ( mbUpdateListRestart && mrTxtNode.IsInList() )
4585             {
4586                 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4587                 pNodeNum->InvalidateMe();
4588                 pNodeNum->NotifyInvalidSiblings();
4589             }
4590 
4591             if ( mbUpdateListCount && mrTxtNode.IsInList() )
4592             {
4593                 const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
4594             }
4595         }
4596 
4597         // --> OD 2008-11-19 #i70748#
4598         if ( mbOutlineLevelSet )
4599         {
4600             if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
4601             {
4602                 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4603             }
4604             else
4605             {
4606                 const SfxPoolItem* pItem = 0;
4607                 if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
4608                                                             sal_True, &pItem )
4609                                                                 != SFX_ITEM_SET )
4610                 {
4611                     mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4612                 }
4613             }
4614         }
4615         // <--
4616     }
4617     // End of class <HandleSetAttrAtTxtNode>
4618 }
4619 
4620 sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem )
4621 {
4622     const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4623     mbInSetOrResetAttr = true;
4624 
4625     HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );
4626 
4627     sal_Bool bRet = SwCntntNode::SetAttr( pItem );
4628 
4629     mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4630 
4631     return bRet;
4632 }
4633 
4634 sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet )
4635 {
4636     const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4637     mbInSetOrResetAttr = true;
4638 
4639     HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );
4640 
4641     sal_Bool bRet = SwCntntNode::SetAttr( rSet );
4642 
4643     mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4644 
4645     return bRet;
4646 }
4647 
4648 namespace {
4649     // Helper class for special handling of resetting attributes at text node:
4650     // In constructor an instance of the helper class recognize whose attributes
4651     // are reset and perform corresponding actions before the intrinsic reset of
4652     // attributes has been taken place.
4653     // In the destructor - after the attributes have been reset at the text
4654     // node - corresponding actions are performed.
4655     // The following is handled:
4656     // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
4657     //     the text is removed from its list before the attributes have been reset.
4658     // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
4659     //     the text is removed from its list before the attributes have been reset.
4660     // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
4661     // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
4662     // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
4663     // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
4664     // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
4665     class HandleResetAttrAtTxtNode
4666     {
4667         public:
4668             HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4669                                       const sal_uInt16 nWhich1,
4670                                       const sal_uInt16 nWhich2 );
4671             HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4672                                       const SvUShorts& rWhichArr );
4673             HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );
4674 
4675             ~HandleResetAttrAtTxtNode();
4676 
4677         private:
4678             SwTxtNode& mrTxtNode;
4679             bool mbListStyleOrIdReset;
4680             bool mbUpdateListLevel;
4681             bool mbUpdateListRestart;
4682             bool mbUpdateListCount;
4683     };
4684 
4685     HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4686                                                         const sal_uInt16 nWhich1,
4687                                                         const sal_uInt16 nWhich2 )
4688         : mrTxtNode( rTxtNode ),
4689           mbListStyleOrIdReset( false ),
4690           mbUpdateListLevel( false ),
4691           mbUpdateListRestart( false ),
4692           mbUpdateListCount( false )
4693     {
4694         bool bRemoveFromList( false );
4695         if ( nWhich2 != 0 && nWhich2 > nWhich1 )
4696         {
4697             // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4698             if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
4699             {
4700                 bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4701                 mbListStyleOrIdReset = true;
4702             }
4703             else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
4704             {
4705                 bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4706                     mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
4707                 // --> OD 2008-10-20 #i92898#
4708                 mbListStyleOrIdReset = true;
4709                 // <--
4710             }
4711 
4712             if ( !bRemoveFromList )
4713             {
4714                 // RES_PARATR_LIST_LEVEL
4715                 mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
4716                                       RES_PARATR_LIST_LEVEL <= nWhich2 &&
4717                                       mrTxtNode.HasAttrListLevel() );
4718 
4719                 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4720                 mbUpdateListRestart =
4721                     ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
4722                       mrTxtNode.IsListRestart() ) ||
4723                     ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
4724                       mrTxtNode.HasAttrListRestartValue() );
4725 
4726                 // RES_PARATR_LIST_ISCOUNTED
4727                 mbUpdateListCount =
4728                     ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
4729                       !mrTxtNode.IsCountedInList() );
4730             }
4731 
4732             // --> OD 2008-11-19 #i70748#
4733             // RES_PARATR_OUTLINELEVEL
4734             if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
4735             {
4736                 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4737             }
4738             // <--
4739         }
4740         else
4741         {
4742             // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4743             if ( nWhich1 == RES_PARATR_NUMRULE )
4744             {
4745                 bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4746                 mbListStyleOrIdReset = true;
4747             }
4748             else if ( nWhich1 == RES_PARATR_LIST_ID )
4749             {
4750                 bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4751                     mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
4752                 // --> OD 2008-10-20 #i92898#
4753                 mbListStyleOrIdReset = true;
4754                 // <--
4755             }
4756             // --> OD 2008-11-19 #i70748#
4757             // RES_PARATR_OUTLINELEVEL
4758             else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
4759             {
4760                 mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4761             }
4762             // <--
4763 
4764             if ( !bRemoveFromList )
4765             {
4766                 // RES_PARATR_LIST_LEVEL
4767                 mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
4768                                     mrTxtNode.HasAttrListLevel();
4769 
4770                 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4771                 mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
4772                                         mrTxtNode.IsListRestart() ) ||
4773                                       ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
4774                                         mrTxtNode.HasAttrListRestartValue() );
4775 
4776                 // RES_PARATR_LIST_ISCOUNTED
4777                 mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
4778                                     !mrTxtNode.IsCountedInList();
4779             }
4780         }
4781 
4782         if ( bRemoveFromList && mrTxtNode.IsInList() )
4783         {
4784             mrTxtNode.RemoveFromList();
4785         }
4786     }
4787 
4788     HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4789                                                         const SvUShorts& rWhichArr )
4790         : mrTxtNode( rTxtNode ),
4791           mbListStyleOrIdReset( false ),
4792           mbUpdateListLevel( false ),
4793           mbUpdateListRestart( false ),
4794           mbUpdateListCount( false )
4795     {
4796         bool bRemoveFromList( false );
4797         {
4798             const sal_uInt16 nEnd = rWhichArr.Count();
4799             for ( sal_uInt16 n = 0; n < nEnd; ++n )
4800             {
4801                 // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4802                 if ( rWhichArr[ n ] == RES_PARATR_NUMRULE )
4803                 {
4804                     bRemoveFromList = bRemoveFromList ||
4805                                       mrTxtNode.GetNumRule() != 0;
4806                     mbListStyleOrIdReset = true;
4807                 }
4808                 else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID )
4809                 {
4810                     bRemoveFromList = bRemoveFromList ||
4811                         ( mrTxtNode.GetpSwAttrSet() &&
4812                           mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET );
4813                     // --> OD 2008-10-20 #i92898#
4814                     mbListStyleOrIdReset = true;
4815                     // <--
4816                 }
4817                 // --> OD 2008-11-19 #i70748#
4818                 // RES_PARATR_OUTLINELEVEL
4819                 else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL )
4820                 {
4821                     mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4822                 }
4823                 // <--
4824 
4825                 if ( !bRemoveFromList )
4826                 {
4827                     // RES_PARATR_LIST_LEVEL
4828                     mbUpdateListLevel = mbUpdateListLevel ||
4829                                         ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL &&
4830                                           mrTxtNode.HasAttrListLevel() );
4831 
4832                     // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4833                     mbUpdateListRestart = mbUpdateListRestart ||
4834                                           ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART &&
4835                                             mrTxtNode.IsListRestart() ) ||
4836                                           ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE &&
4837                                             mrTxtNode.HasAttrListRestartValue() );
4838 
4839                     // RES_PARATR_LIST_ISCOUNTED
4840                     mbUpdateListCount = mbUpdateListCount ||
4841                                         ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED &&
4842                                           !mrTxtNode.IsCountedInList() );
4843                 }
4844             }
4845         }
4846 
4847         if ( bRemoveFromList && mrTxtNode.IsInList() )
4848         {
4849             mrTxtNode.RemoveFromList();
4850         }
4851     }
4852 
4853     HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
4854         : mrTxtNode( rTxtNode ),
4855           mbListStyleOrIdReset( false ),
4856           mbUpdateListLevel( false ),
4857           mbUpdateListRestart( false ),
4858           mbUpdateListCount( false )
4859     {
4860         mbListStyleOrIdReset = true;
4861         if ( rTxtNode.IsInList() )
4862         {
4863             rTxtNode.RemoveFromList();
4864         }
4865         // --> OD 2008-11-19 #i70748#
4866         mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4867         // <--
4868     }
4869 
4870     HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
4871     {
4872         if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
4873         {
4874             // check, if in spite of the reset of the list style or the list id
4875             // the paragraph still has to be added to a list.
4876             if ( mrTxtNode.GetNumRule() &&
4877                  mrTxtNode.GetListId().Len() > 0 )
4878             {
4879                 // --> OD 2009-01-14 #i96062#
4880                 // If paragraph has no list level attribute set and list style
4881                 // is the outline style, apply outline level as the list level.
4882                 if ( !mrTxtNode.HasAttrListLevel() &&
4883                      mrTxtNode.GetNumRule()->GetName() ==
4884                         String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) &&
4885                      mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
4886                 {
4887                     int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
4888                     if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
4889                     {
4890                         mrTxtNode.SetAttrListLevel( nNewListLevel );
4891                     }
4892                 }
4893                 // <--
4894                 mrTxtNode.AddToList();
4895             }
4896             // --> OD 2008-11-19 #i70748#
4897             // --> OD 2010-05-12 #i105562#
4898             else if ( mrTxtNode.GetpSwAttrSet() &&
4899                       dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
4900             {
4901                 mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4902             }
4903             // <--
4904         }
4905 
4906         if ( mrTxtNode.IsInList() )
4907         {
4908             if ( mbUpdateListLevel )
4909             {
4910                 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4911                 pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
4912             }
4913 
4914             if ( mbUpdateListRestart )
4915             {
4916                 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4917                 pNodeNum->InvalidateMe();
4918                 pNodeNum->NotifyInvalidSiblings();
4919             }
4920 
4921             if ( mbUpdateListCount )
4922             {
4923                 SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4924                 pNodeNum->InvalidateAndNotifyTree();
4925             }
4926         }
4927     }
4928     // End of class <HandleResetAttrAtTxtNode>
4929 }
4930 
4931 sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
4932 {
4933     const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4934     mbInSetOrResetAttr = true;
4935 
4936     HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );
4937 
4938     sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );
4939 
4940     mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4941 
4942     return bRet;
4943 }
4944 
4945 sal_Bool SwTxtNode::ResetAttr( const SvUShorts& rWhichArr )
4946 {
4947     const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4948     mbInSetOrResetAttr = true;
4949 
4950     HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );
4951 
4952     sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr );
4953 
4954     mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4955 
4956     return bRet;
4957 }
4958 
4959 sal_uInt16 SwTxtNode::ResetAllAttr()
4960 {
4961     const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4962     mbInSetOrResetAttr = true;
4963 
4964     HandleResetAttrAtTxtNode aHandleResetAttr( *this );
4965 
4966     sal_uInt16 nRet = SwCntntNode::ResetAllAttr();
4967 
4968     mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4969 
4970     return nRet;
4971 }
4972 // <--
4973 
4974 // sw::Metadatable
4975 ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
4976 {
4977     return GetDoc()->GetXmlIdRegistry();
4978 }
4979 
4980 bool SwTxtNode::IsInClipboard() const
4981 {
4982     return GetDoc()->IsClipBoard();
4983 }
4984 
4985 bool SwTxtNode::IsInUndo() const
4986 {
4987     return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
4988 }
4989 
4990 bool SwTxtNode::IsInContent() const
4991 {
4992     return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
4993 }
4994 
4995 void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint )
4996 {
4997     const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint);
4998     if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() )
4999         ChkCondColl();
5000 }
5001 
5002 #include <unoparagraph.hxx>
5003 
5004 uno::Reference< rdf::XMetadatable >
5005 SwTxtNode::MakeUnoObject()
5006 {
5007     const uno::Reference<rdf::XMetadatable> xMeta(
5008             SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY);
5009     return xMeta;
5010 }
5011 
5012 //Bug 120881:Modify here for Directly Page Numbering
5013 bool SwTxtNode::HasPageNumberField()
5014 {
5015     const xub_StrLen nEnd = Len();
5016     for( xub_StrLen nStart = 0; nStart < nEnd; ++nStart )
5017     {
5018         const SwTxtAttr* pTxtAttr = GetTxtAttrAt( nStart, RES_TXTATR_FIELD );
5019         if ( pTxtAttr == NULL )
5020         {
5021             continue;
5022         }
5023         const SwField* pSwField = pTxtAttr->GetFmtFld().GetField();
5024         const SwFieldType* pType = pSwField
5025             ? pSwField->GetTyp()
5026             : NULL;
5027         if ( pType && pType->Which() == RES_PAGENUMBERFLD )
5028         {
5029             return true;
5030         }
5031     }
5032     return false;
5033 
5034 }
5035 //Bug 120881(End)
5036 
5037