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