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