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