xref: /AOO41X/main/sw/source/core/docnode/node.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <hintids.hxx>
32 #include <editeng/frmdiritem.hxx>
33 #include <editeng/protitem.hxx>
34 #include <com/sun/star/i18n/CharacterIteratorMode.hdl>
35 #include <fmtcntnt.hxx>
36 #include <fmtanchr.hxx>
37 #include <frmfmt.hxx>
38 #include <txtftn.hxx>
39 #include <ftnfrm.hxx>
40 #include <doc.hxx>
41 #include <docary.hxx>
42 #include <node.hxx>
43 #include <ndindex.hxx>
44 #include <numrule.hxx>
45 #include <swtable.hxx>
46 #include <ndtxt.hxx>
47 #include <pam.hxx>
48 #include <swcache.hxx>
49 #include <section.hxx>
50 #include <cntfrm.hxx>
51 #include <flyfrm.hxx>
52 #include <txtfrm.hxx>
53 #include <tabfrm.hxx>  // SwTabFrm
54 #include <viewsh.hxx>
55 #include <paratr.hxx>
56 #include <ftnidx.hxx>
57 #include <fmtftn.hxx>
58 #include <fmthdft.hxx>
59 #include <frmatr.hxx>
60 #include <fmtautofmt.hxx>
61 #include <frmtool.hxx>
62 #include <pagefrm.hxx>
63 #include <node2lay.hxx>
64 #include <pagedesc.hxx>
65 #include <fmtpdsc.hxx>
66 #include <breakit.hxx>
67 #include <crsskip.hxx>
68 #include <SwStyleNameMapper.hxx>
69 #include <scriptinfo.hxx>
70 #include <rootfrm.hxx>
71 #include <istyleaccess.hxx>
72 #include <IDocumentListItems.hxx>
73 #include <switerator.hxx>
74 #include "ndole.hxx"
75 
76 using namespace ::com::sun::star::i18n;
77 
78 TYPEINIT2( SwCntntNode, SwModify, SwIndexReg )
79 
80 /*
81  * Some local helper functions for the attribute set handle of a content node.
82  * Since the attribute set of a content node may not be modified directly,
83  * we always have to create a new SwAttrSet, do the modifications, and get
84  * a new handle from the style access
85  */
86 
87 namespace AttrSetHandleHelper
88 {
89 
90 void GetNewAutoStyle( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
91                       const SwCntntNode& rNode,
92                       SwAttrSet& rNewAttrSet )
93 {
94     const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
95 	if( rNode.GetModifyAtAttr() )
96         const_cast<SwAttrSet*>(pAttrSet)->SetModifyAtAttr( 0 );
97     IStyleAccess& rSA = pAttrSet->GetPool()->GetDoc()->GetIStyleAccess();
98     mrpAttrSet = rSA.getAutomaticStyle( rNewAttrSet, rNode.IsTxtNode() ?
99                                                      IStyleAccess::AUTO_STYLE_PARA :
100                                                      IStyleAccess::AUTO_STYLE_NOTXT );
101     const bool bSetModifyAtAttr = ((SwAttrSet*)mrpAttrSet.get())->SetModifyAtAttr( &rNode );
102     rNode.SetModifyAtAttr( bSetModifyAtAttr );
103 }
104 
105 
106 void SetParent( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
107                 const SwCntntNode& rNode,
108                 const SwFmt* pParentFmt,
109                 const SwFmt* pConditionalFmt )
110 {
111     const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
112     ASSERT( pAttrSet, "no SwAttrSet" )
113     ASSERT( pParentFmt || !pConditionalFmt, "ConditionalFmt without ParentFmt?" )
114 
115     const SwAttrSet* pParentSet = pParentFmt ? &pParentFmt->GetAttrSet() : 0;
116 
117     if ( pParentSet != pAttrSet->GetParent() )
118     {
119         SwAttrSet aNewSet( *pAttrSet );
120         aNewSet.SetParent( pParentSet );
121         aNewSet.ClearItem( RES_FRMATR_STYLE_NAME );
122         aNewSet.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME );
123         String sVal;
124 
125         if ( pParentFmt )
126         {
127             SwStyleNameMapper::FillProgName( pParentFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
128             const SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
129             aNewSet.Put( aAnyFmtColl );
130 
131             if ( pConditionalFmt != pParentFmt )
132                 SwStyleNameMapper::FillProgName( pConditionalFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
133 
134             const SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
135             aNewSet.Put( aFmtColl );
136         }
137 
138         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
139     }
140 }
141 
142 const SfxPoolItem* Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
143                         const SwCntntNode& rNode,
144                         const SfxPoolItem& rAttr )
145 {
146     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
147     const SfxPoolItem* pRet = aNewSet.Put( rAttr );
148     if ( pRet )
149         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
150     return pRet;
151 }
152 
153 int Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, const SwCntntNode& rNode,
154          const SfxItemSet& rSet )
155 {
156     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
157 
158     // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
159     SfxItemSet* pStyleNames = 0;
160     if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
161     {
162         pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
163         pStyleNames->Put( aNewSet );
164     }
165     // <--
166 
167     const int nRet = aNewSet.Put( rSet );
168 
169     // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
170     if ( pStyleNames )
171     {
172         aNewSet.Put( *pStyleNames );
173         delete pStyleNames;
174     }
175     // <--
176 
177     if ( nRet )
178         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
179 
180     return nRet;
181 }
182 
183 int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
184             const SwCntntNode& rNode, const SfxPoolItem& rAttr,
185             SwAttrSet* pOld, SwAttrSet* pNew )
186 {
187     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
188 
189     // for a correct broadcast, we need to do a SetModifyAtAttr with the items
190     // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
191     if( rNode.GetModifyAtAttr() )
192         aNewSet.SetModifyAtAttr( &rNode );
193 
194     const int nRet = aNewSet.Put_BC( rAttr, pOld, pNew );
195 
196     if ( nRet )
197         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
198 
199     return nRet;
200 }
201 
202 int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
203             const SwCntntNode& rNode, const SfxItemSet& rSet,
204             SwAttrSet* pOld, SwAttrSet* pNew )
205 {
206     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
207 
208     // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
209     SfxItemSet* pStyleNames = 0;
210     if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
211     {
212         pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
213         pStyleNames->Put( aNewSet );
214     }
215     // <--
216 
217     // for a correct broadcast, we need to do a SetModifyAtAttr with the items
218     // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
219 	if( rNode.GetModifyAtAttr() )
220         aNewSet.SetModifyAtAttr( &rNode );
221 
222     const int nRet = aNewSet.Put_BC( rSet, pOld, pNew );
223 
224     // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
225     if ( pStyleNames )
226     {
227         aNewSet.Put( *pStyleNames );
228         delete pStyleNames;
229     }
230     // <--
231 
232     if ( nRet )
233         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
234 
235     return nRet;
236 }
237 
238 sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
239                      const SwCntntNode& rNode, sal_uInt16 nWhich,
240                      SwAttrSet* pOld, SwAttrSet* pNew )
241 {
242     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
243 	if( rNode.GetModifyAtAttr() )
244         aNewSet.SetModifyAtAttr( &rNode );
245     const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich, pOld, pNew );
246     if ( nRet )
247         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
248     return nRet;
249 }
250 
251 sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
252                      const SwCntntNode& rNode,
253                      sal_uInt16 nWhich1, sal_uInt16 nWhich2,
254                      SwAttrSet* pOld, SwAttrSet* pNew )
255 {
256     SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
257 	if( rNode.GetModifyAtAttr() )
258         aNewSet.SetModifyAtAttr( &rNode );
259     const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich1, nWhich2, pOld, pNew );
260     if ( nRet )
261         GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
262     return nRet;
263 }
264 
265 }
266 
267 /*******************************************************************
268 |*
269 |*	SwNode::GetSectionLevel
270 |*
271 |*	Beschreibung
272 |*		Die Funktion liefert den Sectionlevel an der durch
273 |*		aIndex bezeichneten Position.
274 |*
275 |*		Die Logik ist wie folgt:   ( S -> Start, E -> End, C -> CntntNode)
276 |*			Level 	0		E
277 |*					1 	S  E
278 |*					2  	 SC
279 |*
280 |*		alle EndNodes der GrundSection haben den Level 0
281 |*		alle StartNodes der GrundSection haben den Level 1
282 |*
283 |*	Ersterstellung
284 |*		VER0100 vb 901214
285 |*
286 |*	Aenderung:	JP	11.08.93
287 |*		keine Rekursion mehr !!
288 |*
289 *******************************************************************/
290 
291 
292 sal_uInt16 SwNode::GetSectionLevel() const
293 {
294 	// EndNode einer Grund-Section ?? diese sind immer 0 !!
295 	if( IsEndNode() && 0 == pStartOfSection->StartOfSectionIndex() )
296 		return 0;
297 
298 	sal_uInt16 nLevel;
299 	const SwNode* pNode = IsStartNode() ? this : pStartOfSection;
300 	for( nLevel = 1; 0 != pNode->StartOfSectionIndex(); ++nLevel )
301 		pNode = pNode->pStartOfSection;
302 	return IsEndNode() ? nLevel-1 : nLevel;
303 }
304 
305 /*******************************************************************
306 |*
307 |*	SwNode::SwNode
308 |*
309 |*	Beschreibung
310 |*		Konstruktor; dieser fuegt einen Node in das Array rNodes
311 |*		an der Position rWhere ein. Dieser bekommt als
312 |*		theEndOfSection den EndOfSection-Index des Nodes
313 |*		unmittelbar vor ihm. Falls er sich an der Position 0
314 |*		innerhalb des variablen Arrays befindet, wird
315 |*		theEndOfSection 0 (der neue selbst).
316 |*
317 |*	Parameter
318 |*		IN
319 |*		rNodes bezeichnet das variable Array, in das der Node
320 |*		eingefuegt werden soll
321 |*		IN
322 |*		rWhere bezeichnet die Position innerhalb dieses Arrays,
323 |*		an der der Node eingefuegt werden soll
324 |*
325 |*	Ersterstellung
326 |*		VER0100 vb 901214
327 |*
328 |*	Stand
329 |*		VER0100 vb 901214
330 |*
331 *******************************************************************/
332 
333 #ifdef DBG_UTIL
334 long SwNode::nSerial = 0;
335 #endif
336 
337 SwNode::SwNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType )
338 	: nNodeType( nNdType ), pStartOfSection( 0 )
339 {
340     bSetNumLSpace = bIgnoreDontExpand = sal_False;
341 	nAFmtNumLvl = 0;
342 
343 	SwNodes& rNodes = (SwNodes&)rWhere.GetNodes();
344 	SwNode* pInsNd = this; 		// der MAC kann this nicht einfuegen !!
345 	if( rWhere.GetIndex() )
346 	{
347 		SwNode* pNd = rNodes[ rWhere.GetIndex() -1 ];
348         rNodes.InsertNode( pInsNd, rWhere );
349 		if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
350 		{
351 			pStartOfSection = pNd->pStartOfSection;
352 			if( pNd->GetEndNode() )		// EndNode ? Section ueberspringen!
353 			{
354 				pNd = pStartOfSection;
355 				pStartOfSection = pNd->pStartOfSection;
356 			}
357 		}
358 	}
359 	else
360 	{
361         rNodes.InsertNode( pInsNd, rWhere );
362 		pStartOfSection = (SwStartNode*)this;
363 	}
364 
365 #ifdef DBG_UTIL
366     nMySerial = nSerial;
367     nSerial++;
368 #endif
369 }
370 
371 SwNode::SwNode( SwNodes& rNodes, sal_uLong nPos, const sal_uInt8 nNdType )
372 	: nNodeType( nNdType ), pStartOfSection( 0 )
373 {
374     bSetNumLSpace = bIgnoreDontExpand = sal_False;
375 	nAFmtNumLvl = 0;
376 
377 	SwNode* pInsNd = this; 		// der MAC kann this nicht einfuegen !!
378 	if( nPos )
379 	{
380 		SwNode* pNd = rNodes[ nPos - 1 ];
381         rNodes.InsertNode( pInsNd, nPos );
382 		if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
383 		{
384 			pStartOfSection = pNd->pStartOfSection;
385 			if( pNd->GetEndNode() )		// EndNode ? Section ueberspringen!
386 			{
387 				pNd = pStartOfSection;
388 				pStartOfSection = pNd->pStartOfSection;
389 			}
390 		}
391 	}
392 	else
393 	{
394         rNodes.InsertNode( pInsNd, nPos );
395 		pStartOfSection = (SwStartNode*)this;
396 	}
397 
398 #ifdef DBG_UTIL
399     nMySerial = nSerial;
400     nSerial++;
401 #endif
402 }
403 
404 SwNode::~SwNode()
405 {
406 }
407 
408 // suche den TabellenNode, in dem dieser steht. Wenn in keiner
409 // Tabelle wird 0 returnt.
410 
411 
412 SwTableNode* SwNode::FindTableNode()
413 {
414 	if( IsTableNode() )
415 		return GetTableNode();
416 	SwStartNode* pTmp = pStartOfSection;
417 	while( !pTmp->IsTableNode() && pTmp->GetIndex() )
418 #if defined( ALPHA ) && defined( UNX )
419 		pTmp = ((SwNode*)pTmp)->pStartOfSection;
420 #else
421 		pTmp = pTmp->pStartOfSection;
422 #endif
423 	return pTmp->GetTableNode();
424 }
425 
426 
427 // liegt der Node im Sichtbarenbereich der Shell ?
428 sal_Bool SwNode::IsInVisibleArea( ViewShell* pSh ) const
429 {
430 	sal_Bool bRet = sal_False;
431 	const SwCntntNode* pNd;
432 
433 	if( ND_STARTNODE & nNodeType )
434 	{
435 		SwNodeIndex aIdx( *this );
436 		pNd = GetNodes().GoNext( &aIdx );
437 	}
438 	else if( ND_ENDNODE & nNodeType )
439 	{
440 		SwNodeIndex aIdx( *EndOfSectionNode() );
441 		pNd = GetNodes().GoPrevious( &aIdx );
442 	}
443 	else
444 		pNd = GetCntntNode();
445 
446 	if( !pSh )
447 		// dann die Shell vom Doc besorgen:
448 		GetDoc()->GetEditShell( &pSh );
449 
450     if( pSh )
451     {
452 	    const SwFrm* pFrm;
453 	    if( pNd && 0 != ( pFrm = pNd->getLayoutFrm( pSh->GetLayout(), 0, 0, sal_False ) ) )
454 	    {
455 
456 			if ( pFrm->IsInTab() )
457 				pFrm = pFrm->FindTabFrm();
458 
459 			if( !pFrm->IsValid() )
460 				do
461 				{	pFrm = pFrm->FindPrev();
462 				} while ( pFrm && !pFrm->IsValid() );
463 
464 			if( !pFrm || pSh->VisArea().IsOver( pFrm->Frm() ) )
465 				bRet = sal_True;
466 		}
467 	}
468 
469 	return bRet;
470 }
471 
472 sal_Bool SwNode::IsInProtectSect() const
473 {
474 	const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
475 	const SwSectionNode* pSectNd = pNd->FindSectionNode();
476 	return pSectNd && pSectNd->GetSection().IsProtectFlag();
477 }
478 
479 	// befindet sich der Node in irgendetwas geschuetzten ?
480 	// (Bereich/Rahmen/Tabellenzellen/... incl. des Ankers bei
481 	//	Rahmen/Fussnoten/..)
482 sal_Bool SwNode::IsProtect() const
483 {
484 	const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
485 	const SwStartNode* pSttNd = pNd->FindSectionNode();
486 	if( pSttNd && ((SwSectionNode*)pSttNd)->GetSection().IsProtectFlag() )
487 		return sal_True;
488 
489 	if( 0 != ( pSttNd = FindTableBoxStartNode() ) )
490 	{
491 		SwCntntFrm* pCFrm;
492 		if( IsCntntNode() && 0 != (pCFrm = ((SwCntntNode*)this)->getLayoutFrm( GetDoc()->GetCurrentLayout() ) ))
493 			return pCFrm->IsProtected();
494 
495 		const SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
496 										GetTblBox( pSttNd->GetIndex() );
497         //Robust #149568
498 		if( pBox && pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
499 			return sal_True;
500 	}
501 
502 	SwFrmFmt* pFlyFmt = GetFlyFmt();
503 	if( pFlyFmt )
504 	{
505 		if( pFlyFmt->GetProtect().IsCntntProtected() )
506 			return sal_True;
507 		const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
508 		return rAnchor.GetCntntAnchor()
509 				? rAnchor.GetCntntAnchor()->nNode.GetNode().IsProtect()
510 				: sal_False;
511 	}
512 
513 	if( 0 != ( pSttNd = FindFootnoteStartNode() ) )
514 	{
515 		const SwTxtFtn* pTFtn = GetDoc()->GetFtnIdxs().SeekEntry(
516 								SwNodeIndex( *pSttNd ) );
517 		if( pTFtn )
518 			return pTFtn->GetTxtNode().IsProtect();
519 	}
520 
521 	return sal_False;
522 }
523 
524 	// suche den PageDesc, mit dem dieser Node formatiert ist. Wenn das
525 	// Layout vorhanden ist wird ueber das gesucht, ansonsten gibt es nur
526 	// die harte Tour ueber die Nodes nach vorne suchen!!
527 const SwPageDesc* SwNode::FindPageDesc( sal_Bool bCalcLay,
528                                         sal_uInt32* pPgDescNdIdx ) const
529 {
530     // OD 18.03.2003 #106329#
531     if ( !GetNodes().IsDocNodes() )
532     {
533         return 0;
534     }
535 
536     const SwPageDesc* pPgDesc = 0;
537 
538     const SwCntntNode* pNode;
539     if( ND_STARTNODE & nNodeType )
540     {
541         SwNodeIndex aIdx( *this );
542         pNode = GetNodes().GoNext( &aIdx );
543     }
544     else if( ND_ENDNODE & nNodeType )
545     {
546         SwNodeIndex aIdx( *EndOfSectionNode() );
547         pNode = GetNodes().GoPrevious( &aIdx );
548     }
549     else
550     {
551         pNode = GetCntntNode();
552         if( pNode )
553             pPgDesc = ((SwFmtPageDesc&)pNode->GetAttr( RES_PAGEDESC )).GetPageDesc();
554     }
555 
556     // geht es uebers Layout?
557     if( !pPgDesc )
558     {
559         const SwFrm* pFrm;
560         const SwPageFrm* pPage;
561         if( pNode && 0 != ( pFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout(), 0, 0, bCalcLay ) ) &&
562             0 != ( pPage = pFrm->FindPageFrm() ) )
563         {
564             pPgDesc = pPage->GetPageDesc();
565             // OD 18.03.2003 #106329#
566             if ( pPgDescNdIdx )
567             {
568                 *pPgDescNdIdx = pNode->GetIndex();
569             }
570         }
571     }
572 
573     if( !pPgDesc )
574     {
575         // dann also uebers Nodes-Array
576         const SwDoc* pDoc = GetDoc();
577         const SwNode* pNd = this;
578         const SwStartNode* pSttNd;
579         if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() &&
580             0 != ( pSttNd = pNd->FindFlyStartNode() ) )
581         {
582             // dann erstmal den richtigen Anker finden
583             const SwFrmFmt* pFmt = 0;
584             const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
585             sal_uInt16 n;
586 
587             for( n = 0; n < rFmts.Count(); ++n )
588             {
589                 SwFrmFmt* pFrmFmt = rFmts[ n ];
590                 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
591                 if( rCntnt.GetCntntIdx() &&
592                     &rCntnt.GetCntntIdx()->GetNode() == (SwNode*)pSttNd )
593                 {
594                     pFmt = pFrmFmt;
595                     break;
596                 }
597             }
598 
599             if( pFmt )
600             {
601                 const SwFmtAnchor* pAnchor = &pFmt->GetAnchor();
602                 if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
603                     pAnchor->GetCntntAnchor() )
604                 {
605                     pNd = &pAnchor->GetCntntAnchor()->nNode.GetNode();
606                     const SwNode* pFlyNd = pNd->FindFlyStartNode();
607                     while( pFlyNd )
608                     {
609                         // dann ueber den Anker nach oben "hangeln"
610                         for( n = 0; n < rFmts.Count(); ++n )
611                         {
612                             const SwFrmFmt* pFrmFmt = rFmts[ n ];
613                             const SwNodeIndex* pIdx = pFrmFmt->GetCntnt().
614                                                         GetCntntIdx();
615                             if( pIdx && pFlyNd == &pIdx->GetNode() )
616                             {
617                                 if( pFmt == pFrmFmt )
618                                 {
619                                     pNd = pFlyNd;
620                                     pFlyNd = 0;
621                                     break;
622                                 }
623                                 pAnchor = &pFrmFmt->GetAnchor();
624                                 if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
625                                     !pAnchor->GetCntntAnchor() )
626                                 {
627                                     pFlyNd = 0;
628                                     break;
629                                 }
630 
631                                 pFlyNd = pAnchor->GetCntntAnchor()->nNode.
632                                         GetNode().FindFlyStartNode();
633                                 break;
634                             }
635                         }
636                         if( n >= rFmts.Count() )
637                         {
638                             ASSERT( !this, "Fly-Section aber kein Format gefunden" );
639                             return sal_False;
640                         }
641                     }
642                 }
643             }
644             // in pNd sollte jetzt der richtige Anker Node stehen oder
645             // immer noch der this
646         }
647 
648         if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
649         {
650             if( pNd->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() )
651             {
652                 pPgDesc = &pDoc->GetPageDesc( 0 );
653                 pNd = 0;
654             }
655             else
656             {
657                 // suche den Body Textnode
658                 if( 0 != ( pSttNd = pNd->FindHeaderStartNode() ) ||
659                     0 != ( pSttNd = pNd->FindFooterStartNode() ))
660                 {
661                     // dann in den PageDescs diesen StartNode suchen
662                     sal_uInt16 nId;
663                     UseOnPage eAskUse;
664                     if( SwHeaderStartNode == pSttNd->GetStartNodeType())
665                     {
666                         nId = RES_HEADER;
667                         eAskUse = nsUseOnPage::PD_HEADERSHARE;
668                     }
669                     else
670                     {
671                         nId = RES_FOOTER;
672                         eAskUse = nsUseOnPage::PD_FOOTERSHARE;
673                     }
674 
675                     for( sal_uInt16 n = pDoc->GetPageDescCnt(); n && !pPgDesc; )
676                     {
677                         const SwPageDesc& rPgDsc = pDoc->GetPageDesc( --n );
678                         const SwFrmFmt* pFmt = &rPgDsc.GetMaster();
679                         int nStt = 0, nLast = 1;
680                         if( !( eAskUse & rPgDsc.ReadUseOn() )) ++nLast;
681 
682                         for( ; nStt < nLast; ++nStt, pFmt = &rPgDsc.GetLeft() )
683                         {
684                             const SwFmtHeader& rHdFt = (SwFmtHeader&)
685                                                     pFmt->GetFmtAttr( nId );
686                             if( rHdFt.GetHeaderFmt() )
687                             {
688                                 const SwFmtCntnt& rCntnt =
689                                     rHdFt.GetHeaderFmt()->GetCntnt();
690                                 if( rCntnt.GetCntntIdx() &&
691                                     &rCntnt.GetCntntIdx()->GetNode() ==
692                                     (SwNode*)pSttNd )
693                                 {
694                                     pPgDesc = &rPgDsc;
695                                     break;
696                                 }
697                             }
698                         }
699                     }
700 
701                     if( !pPgDesc )
702                         pPgDesc = &pDoc->GetPageDesc( 0 );
703                     pNd = 0;
704                 }
705                 else if( 0 != ( pSttNd = pNd->FindFootnoteStartNode() ))
706                 {
707                     // der Anker kann nur im Bodytext sein
708                     const SwTxtFtn* pTxtFtn;
709                     const SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs();
710                     for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
711                         if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
712                             (SwNode*)pSttNd ==
713                             &pTxtFtn->GetStartNode()->GetNode() )
714                         {
715                             pNd = &pTxtFtn->GetTxtNode();
716                             break;
717                         }
718                 }
719                 else
720                 {
721                     // kann jetzt nur noch ein Seitengebundener Fly sein
722                     // oder irgendetwas neueres.
723                     // Hier koennen wir nur noch den Standard returnen
724                     ASSERT( pNd->FindFlyStartNode(),
725                             "wo befindet sich dieser Node?" );
726 
727                     pPgDesc = &pDoc->GetPageDesc( 0 );
728                     pNd = 0;
729                 }
730             }
731         }
732 
733         if( pNd )
734         {
735             SwFindNearestNode aInfo( *pNd );
736             // dann ueber alle Nodes aller PageDesc
737             const SfxPoolItem* pItem;
738             sal_uInt32 i, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_PAGEDESC );
739             for( i = 0; i < nMaxItems; ++i )
740                 if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_PAGEDESC, i ) ) &&
741                     ((SwFmtPageDesc*)pItem)->GetDefinedIn() )
742                 {
743                     const SwModify* pMod = ((SwFmtPageDesc*)pItem)->GetDefinedIn();
744                     if( pMod->ISA( SwCntntNode ) )
745                         aInfo.CheckNode( *(SwCntntNode*)pMod );
746                     else if( pMod->ISA( SwFmt ))
747                         ((SwFmt*)pMod)->GetInfo( aInfo );
748                 }
749 
750             if( 0 != ( pNd = aInfo.GetFoundNode() ))
751             {
752                 if( pNd->IsCntntNode() )
753                     pPgDesc = ((SwFmtPageDesc&)pNd->GetCntntNode()->
754                                 GetAttr( RES_PAGEDESC )).GetPageDesc();
755                 else if( pNd->IsTableNode() )
756                     pPgDesc = pNd->GetTableNode()->GetTable().
757                             GetFrmFmt()->GetPageDesc().GetPageDesc();
758                 else if( pNd->IsSectionNode() )
759                     pPgDesc = pNd->GetSectionNode()->GetSection().
760                             GetFmt()->GetPageDesc().GetPageDesc();
761                 // OD 18.03.2003 #106329#
762                 if ( pPgDescNdIdx )
763                 {
764                     *pPgDescNdIdx = pNd->GetIndex();
765                 }
766             }
767             if( !pPgDesc )
768                 pPgDesc = &pDoc->GetPageDesc( 0 );
769         }
770     }
771 	return pPgDesc;
772 }
773 
774 
775 	// falls der Node in einem Fly steht, dann wird das entsprechende Format
776 	// returnt
777 SwFrmFmt* SwNode::GetFlyFmt() const
778 {
779 	SwFrmFmt* pRet = 0;
780 	const SwNode* pSttNd = FindFlyStartNode();
781 	if( pSttNd )
782 	{
783 		if( IsCntntNode() )
784 		{
785 			SwCntntFrm* pFrm = SwIterator<SwCntntFrm,SwCntntNode>::FirstElement( *(SwCntntNode*)this );
786 			if( pFrm )
787 				pRet = pFrm->FindFlyFrm()->GetFmt();
788 		}
789 		if( !pRet )
790 		{
791 			// dann gibts noch harten steinigen Weg uebers Dokument:
792 			const SwSpzFrmFmts& rFrmFmtTbl = *GetDoc()->GetSpzFrmFmts();
793 			for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
794 			{
795 				SwFrmFmt* pFmt = rFrmFmtTbl[n];
796 				const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
797 				if( rCntnt.GetCntntIdx() &&
798 					&rCntnt.GetCntntIdx()->GetNode() == pSttNd )
799 				{
800 					pRet = pFmt;
801 					break;
802 				}
803 			}
804 		}
805 	}
806 	return pRet;
807 }
808 
809 SwTableBox* SwNode::GetTblBox() const
810 {
811 	SwTableBox* pBox = 0;
812 	const SwNode* pSttNd = FindTableBoxStartNode();
813 	if( pSttNd )
814 		pBox = (SwTableBox*)pSttNd->FindTableNode()->GetTable().GetTblBox(
815 													pSttNd->GetIndex() );
816 	return pBox;
817 }
818 
819 SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp )
820 {
821 	SwStartNode* pTmp = IsStartNode() ? (SwStartNode*)this : pStartOfSection;
822 
823 	while( eTyp != pTmp->GetStartNodeType() && pTmp->GetIndex() )
824 #if defined( ALPHA ) && defined( UNX )
825 		pTmp = ((SwNode*)pTmp)->pStartOfSection;
826 #else
827 		pTmp = pTmp->pStartOfSection;
828 #endif
829 	return eTyp == pTmp->GetStartNodeType() ? pTmp : 0;
830 }
831 
832 const SwTxtNode* SwNode::FindOutlineNodeOfLevel( sal_uInt8 nLvl ) const
833 {
834 	const SwTxtNode* pRet = 0;
835 	const SwOutlineNodes& rONds = GetNodes().GetOutLineNds();
836 	if( MAXLEVEL > nLvl && rONds.Count() )
837 	{
838 		sal_uInt16 nPos;
839 		SwNode* pNd = (SwNode*)this;
840 		sal_Bool bCheckFirst = sal_False;
841 		if( !rONds.Seek_Entry( pNd, &nPos ))
842 		{
843 			if( nPos )
844 				nPos = nPos-1;
845 			else
846 				bCheckFirst = sal_True;
847 		}
848 
849 		if( bCheckFirst )
850 		{
851 			// der 1.GliederungsNode liegt hinter dem Fragenden. Dann
852 			// teste mal, ob dieser auf der gleichen Seite steht. Wenn
853 			// nicht, ist das ein ungueltiger. Bug 61865
854 			pRet = rONds[0]->GetTxtNode();
855 
856 			const SwCntntNode* pCNd = GetCntntNode();
857 
858 			Point aPt( 0, 0 );
859 			const SwFrm* pFrm = pRet->getLayoutFrm( pRet->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ),
860 					   * pMyFrm = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ) : 0;
861 			const SwPageFrm* pPgFrm = pFrm ? pFrm->FindPageFrm() : 0;
862 			if( pPgFrm && pMyFrm &&
863 				pPgFrm->Frm().Top() > pMyFrm->Frm().Top() )
864 			{
865 				// der Fragende liegt vor der Seite, also ist er ungueltig
866 				pRet = 0;
867 			}
868 		}
869 		else
870 		{
871 			// oder ans Feld und von dort holen !!
872             while( nPos &&
873                    nLvl < ( pRet = rONds[nPos]->GetTxtNode() )
874 					//->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
875                     ->GetAttrOutlineLevel() - 1 )  //<-end,zhaojianwei
876 				--nPos;
877 
878 			if( !nPos )		// bei 0 gesondert holen !!
879 				pRet = rONds[0]->GetTxtNode();
880 		}
881 	}
882 	return pRet;
883 }
884 
885 inline sal_Bool IsValidNextPrevNd( const SwNode& rNd )
886 {
887 	return ND_TABLENODE == rNd.GetNodeType() ||
888            ( ND_CONTENTNODE & rNd.GetNodeType() ) ||
889 			( ND_ENDNODE == rNd.GetNodeType() && rNd.StartOfSectionNode() &&
890             ND_TABLENODE == rNd.StartOfSectionNode()->GetNodeType() );
891 }
892 
893 sal_uInt8 SwNode::HasPrevNextLayNode() const
894 {
895     // assumption: <this> node is a node inside the document nodes array section.
896 
897 	sal_uInt8 nRet = 0;
898 	if( IsValidNextPrevNd( *this ))
899 	{
900 		SwNodeIndex aIdx( *this, -1 );
901         // --> OD 2007-06-04 #i77805#
902         // skip section start and end nodes
903         while ( aIdx.GetNode().IsSectionNode() ||
904                 ( aIdx.GetNode().IsEndNode() &&
905                   aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
906         {
907             --aIdx;
908         }
909         // <--
910 		if( IsValidNextPrevNd( aIdx.GetNode() ))
911 			nRet |= ND_HAS_PREV_LAYNODE;
912         // --> OD 2007-06-04 #i77805#
913         // skip section start and end nodes
914 //        aIdx += 2;
915         aIdx = SwNodeIndex( *this, +1 );
916         while ( aIdx.GetNode().IsSectionNode() ||
917                 ( aIdx.GetNode().IsEndNode() &&
918                   aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
919         {
920             ++aIdx;
921         }
922         // <--
923         if( IsValidNextPrevNd( aIdx.GetNode() ))
924 			nRet |= ND_HAS_NEXT_LAYNODE;
925 	}
926 	return nRet;
927 }
928 
929 /*******************************************************************
930 |*
931 |*	SwNode::StartOfSection
932 |*
933 |*	Beschreibung
934 |*		Die Funktion liefert die StartOfSection des Nodes.
935 |*
936 |*	Parameter
937 |*		IN
938 |*		rNodes bezeichnet das variable Array, in dem sich der Node
939 |*		befindet
940 |*	Ersterstellung
941 |*		VER0100 vb 901214
942 |*
943 |*	Stand
944 |*		VER0100 vb 901214
945 |*
946 *******************************************************************/
947 
948 
949 SwStartNode::SwStartNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
950 							SwStartNodeType eSttNd )
951 	: SwNode( rWhere, nNdType ), eSttNdTyp( eSttNd )
952 {
953 	// erstmal temporaer, bis der EndNode eingefuegt wird.
954 	pEndOfSection = (SwEndNode*)this;
955 }
956 
957 SwStartNode::SwStartNode( SwNodes& rNodes, sal_uLong nPos )
958 	: SwNode( rNodes, nPos, ND_STARTNODE ), eSttNdTyp( SwNormalStartNode )
959 {
960 	// erstmal temporaer, bis der EndNode eingefuegt wird.
961 	pEndOfSection = (SwEndNode*)this;
962 }
963 
964 
965 void SwStartNode::CheckSectionCondColl() const
966 {
967 //FEATURE::CONDCOLL
968 	SwNodeIndex aIdx( *this );
969 	sal_uLong nEndIdx = EndOfSectionIndex();
970 	const SwNodes& rNds = GetNodes();
971 	SwCntntNode* pCNd;
972 	while( 0 != ( pCNd = rNds.GoNext( &aIdx )) && pCNd->GetIndex() < nEndIdx )
973 		pCNd->ChkCondColl();
974 //FEATURE::CONDCOLL
975 }
976 
977 /*******************************************************************
978 |*
979 |*	SwEndNode::SwEndNode
980 |*
981 |*	Beschreibung
982 |*		Konstruktor; dieser fuegt einen Node in das Array rNodes
983 |*		an der Position aWhere ein. Der
984 |*		theStartOfSection-Pointer wird entsprechend gesetzt,
985 |*		und der EndOfSection-Pointer des zugehoerigen
986 |*		Startnodes -- durch rStartOfSection bezeichnet --
987 |*		wird auf diesen Node gesetzt.
988 |*
989 |*	Parameter
990 |*		IN
991 |*		rNodes bezeichnet das variable Array, in das der Node
992 |*		eingefuegt werden soll
993 |*		IN
994 |*		aWhere bezeichnet die Position innerhalb dieses Arrays,
995 |*		an der der Node eingefuegt werden soll
996 |*		!!!!!!!!!!!!
997 |*		Es wird eine Kopie uebergeben!
998 |*
999 |*	Ersterstellung
1000 |*		VER0100 vb 901214
1001 |*
1002 |*	Stand
1003 |*		VER0100 vb 901214
1004 |*
1005 *******************************************************************/
1006 
1007 
1008 SwEndNode::SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd )
1009 	: SwNode( rWhere, ND_ENDNODE )
1010 {
1011 	pStartOfSection = &rSttNd;
1012 	pStartOfSection->pEndOfSection = this;
1013 }
1014 
1015 SwEndNode::SwEndNode( SwNodes& rNds, sal_uLong nPos, SwStartNode& rSttNd )
1016 	: SwNode( rNds, nPos, ND_ENDNODE )
1017 {
1018 	pStartOfSection = &rSttNd;
1019 	pStartOfSection->pEndOfSection = this;
1020 }
1021 
1022 
1023 
1024 // --------------------
1025 // SwCntntNode
1026 // --------------------
1027 
1028 
1029 SwCntntNode::SwCntntNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
1030 							SwFmtColl *pColl )
1031 	: SwModify( pColl ),	 // CrsrsShell, FrameFmt,
1032     SwNode( rWhere, nNdType ),
1033     pCondColl( 0 ),
1034     mbSetModifyAtAttr( false )
1035 #ifdef OLD_INDEX
1036 	,SwIndexReg(2)
1037 #endif
1038 {
1039 }
1040 
1041 
1042 SwCntntNode::~SwCntntNode()
1043 {
1044 	// Die Basisklasse SwClient vom SwFrm nimmt sich aus
1045 	// der Abhaengikeitsliste raus!
1046 	// Daher muessen alle Frames in der Abhaengigkeitsliste geloescht werden.
1047 	if( GetDepends() )
1048 		DelFrms();
1049 
1050     if( pCondColl )
1051 		delete pCondColl;
1052 
1053     if ( mpAttrSet.get() && mbSetModifyAtAttr )
1054         ((SwAttrSet*)mpAttrSet.get())->SetModifyAtAttr( 0 );
1055 }
1056 
1057 void SwCntntNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
1058 {
1059 	sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
1060 					pNewValue ? pNewValue->Which() : 0 ;
1061 
1062 	switch( nWhich )
1063 	{
1064 	case RES_OBJECTDYING :
1065 		{
1066 			SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject;
1067 
1068 			// nicht umhaengen wenn dieses das oberste Format ist !!
1069 			if( GetRegisteredIn() == pFmt )
1070 			{
1071 				if( pFmt->GetRegisteredIn() )
1072 				{
1073 					// wenn Parent, dann im neuen Parent wieder anmelden
1074 					((SwModify*)pFmt->GetRegisteredIn())->Add( this );
1075                     if ( GetpSwAttrSet() )
1076                         AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
1077 				}
1078 				else
1079 				{
1080 					// sonst auf jeden Fall beim sterbenden abmelden
1081 					((SwModify*)GetRegisteredIn())->Remove( this );
1082                     if ( GetpSwAttrSet() )
1083                         AttrSetHandleHelper::SetParent( mpAttrSet, *this, 0, 0 );
1084 				}
1085 			}
1086 		}
1087 		break;
1088 
1089 
1090 	case RES_FMT_CHG:
1091 		// falls mein Format Parent umgesetzt wird, dann melde ich
1092 		// meinen Attrset beim Neuen an.
1093 
1094 		// sein eigenes Modify ueberspringen !!
1095         if( GetpSwAttrSet() &&
1096 			((SwFmtChg*)pNewValue)->pChangedFmt == GetRegisteredIn() )
1097 		{
1098 			// den Set an den neuen Parent haengen
1099             AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
1100 		}
1101 		break;
1102 //FEATURE::CONDCOLL
1103 	case RES_CONDCOLL_CONDCHG:
1104 		if( ((SwCondCollCondChg*)pNewValue)->pChangedFmt == GetRegisteredIn() &&
1105 			&GetNodes() == &GetDoc()->GetNodes() )
1106 		{
1107 			ChkCondColl();
1108 		}
1109 		return ;	// nicht an die Basisklasse / Frames weitergeben
1110 //FEATURE::CONDCOLL
1111 
1112 	case RES_ATTRSET_CHG:
1113 		if( GetNodes().IsDocNodes() && IsTxtNode() )
1114 		{
1115             if( SFX_ITEM_SET == ((SwAttrSetChg*)pOldValue)->GetChgSet()->GetItemState(
1116                 RES_CHRATR_HIDDEN, sal_False ) )
1117             {
1118                 ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
1119             }
1120 		}
1121 		break;
1122 
1123     case RES_UPDATE_ATTR:
1124 		if( GetNodes().IsDocNodes() && IsTxtNode() )
1125         {
1126             const sal_uInt16 nTmp = ((SwUpdateAttr*)pNewValue)->nWhichAttr;
1127             if ( RES_ATTRSET_CHG == nTmp )
1128             {
1129                 // anybody wants to do some optimization here?
1130                 ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
1131             }
1132         }
1133         break;
1134 	}
1135 
1136 	NotifyClients( pOldValue, pNewValue );
1137 }
1138 
1139 sal_Bool SwCntntNode::InvalidateNumRule()
1140 {
1141 	SwNumRule* pRule = 0;
1142 	const SfxPoolItem* pItem;
1143 	if( GetNodes().IsDocNodes() &&
1144 		0 != ( pItem = GetNoCondAttr( RES_PARATR_NUMRULE, sal_True )) &&
1145 		((SwNumRuleItem*)pItem)->GetValue().Len() &&
1146 		0 != (pRule = GetDoc()->FindNumRulePtr(
1147 								((SwNumRuleItem*)pItem)->GetValue() ) ) )
1148 	{
1149 		pRule->SetInvalidRule( sal_True );
1150 	}
1151 	return 0 != pRule;
1152 }
1153 
1154 SwCntntFrm *SwCntntNode::getLayoutFrm( const SwRootFrm* _pRoot,
1155     const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm ) const
1156 {
1157 	return (SwCntntFrm*) ::GetFrmOfModify( _pRoot, *(SwModify*)this, FRM_CNTNT,
1158 											pPoint, pPos, bCalcFrm );
1159 }
1160 
1161 SwRect SwCntntNode::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint,
1162 									const sal_Bool bCalcFrm ) const
1163 {
1164 	SwRect aRet;
1165 	SwCntntFrm* pFrm = (SwCntntFrm*)::GetFrmOfModify( 0, *(SwModify*)this,
1166 											FRM_CNTNT, pPoint, 0, bCalcFrm );
1167 	if( pFrm )
1168 		aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
1169 	return aRet;
1170 }
1171 
1172 SwRect SwCntntNode::FindPageFrmRect( const sal_Bool bPrtArea, const Point* pPoint,
1173 									const sal_Bool bCalcFrm ) const
1174 {
1175 	SwRect aRet;
1176 	SwFrm* pFrm = ::GetFrmOfModify( 0, *(SwModify*)this,
1177 											FRM_CNTNT, pPoint, 0, bCalcFrm );
1178 	if( pFrm && 0 != ( pFrm = pFrm->FindPageFrm() ))
1179 		aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
1180 	return aRet;
1181 }
1182 
1183 xub_StrLen SwCntntNode::Len() const { return 0; }
1184 
1185 
1186 
1187 SwFmtColl *SwCntntNode::ChgFmtColl( SwFmtColl *pNewColl )
1188 {
1189 	ASSERT( pNewColl, "Collectionpointer ist 0." );
1190 	SwFmtColl *pOldColl = GetFmtColl();
1191 
1192 	if( pNewColl != pOldColl )
1193 	{
1194 		pNewColl->Add( this );
1195 
1196 		// setze den Parent von unseren Auto-Attributen auf die neue
1197 		// Collection:
1198         if( GetpSwAttrSet() )
1199             AttrSetHandleHelper::SetParent( mpAttrSet, *this, pNewColl, pNewColl );
1200 
1201 //FEATURE::CONDCOLL
1202 		// HACK: hier muss die entsprechend der neuen Vorlage die Bedingungen
1203 		//		neu ueberprueft werden!
1204 		if( sal_True /*pNewColl */ )
1205 		{
1206 			SetCondFmtColl( 0 );
1207 		}
1208 //FEATURE::CONDCOLL
1209 
1210 		if( !IsModifyLocked() )
1211 		{
1212 			SwFmtChg aTmp1( pOldColl );
1213 			SwFmtChg aTmp2( pNewColl );
1214             SwCntntNode::Modify( &aTmp1, &aTmp2 );
1215 		}
1216 	}
1217 	if ( IsInCache() )
1218 	{
1219 		SwFrm::GetCache().Delete( this );
1220 		SetInCache( sal_False );
1221 	}
1222 	return pOldColl;
1223 }
1224 
1225 
1226 sal_Bool SwCntntNode::GoNext(SwIndex * pIdx, sal_uInt16 nMode ) const
1227 {
1228 	sal_Bool bRet = sal_True;
1229 	if( pIdx->GetIndex() < Len() )
1230 	{
1231 		if( !IsTxtNode() )
1232 			(*pIdx)++;
1233 		else
1234 		{
1235 			const SwTxtNode& rTNd = *GetTxtNode();
1236 			xub_StrLen nPos = pIdx->GetIndex();
1237 			if( pBreakIt->GetBreakIter().is() )
1238 			{
1239 				sal_Int32 nDone = 0;
1240 				sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
1241                                         CharacterIteratorMode::SKIPCELL :
1242                                         CharacterIteratorMode::SKIPCONTROLCHARACTER;
1243                 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rTNd.GetTxt(), nPos,
1244                                    pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
1245                                    nItrMode, 1, nDone );
1246 
1247                 // Check if nPos is inside hidden text range:
1248                 if ( CRSR_SKIP_HIDDEN & nMode )
1249                 {
1250                     xub_StrLen nHiddenStart;
1251                     xub_StrLen nHiddenEnd;
1252                     SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
1253                     if ( nHiddenStart != STRING_LEN && nHiddenStart != nPos )
1254                          nPos = nHiddenEnd;
1255                 }
1256 
1257 				if( 1 == nDone )
1258 					*pIdx = nPos;
1259 				else
1260 					bRet = sal_False;
1261 			}
1262 			else if( nPos < rTNd.GetTxt().Len() )
1263 				(*pIdx)++;
1264 			else
1265 				bRet = sal_False;
1266 		}
1267 	}
1268 	else
1269 		bRet = sal_False;
1270 	return bRet;
1271 }
1272 
1273 
1274 sal_Bool SwCntntNode::GoPrevious(SwIndex * pIdx, sal_uInt16 nMode ) const
1275 {
1276 	sal_Bool bRet = sal_True;
1277 	if( pIdx->GetIndex() > 0 )
1278 	{
1279 		if( !IsTxtNode() )
1280 			(*pIdx)--;
1281 		else
1282 		{
1283 			const SwTxtNode& rTNd = *GetTxtNode();
1284 			xub_StrLen nPos = pIdx->GetIndex();
1285 			if( pBreakIt->GetBreakIter().is() )
1286 			{
1287 				sal_Int32 nDone = 0;
1288 				sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
1289                                         CharacterIteratorMode::SKIPCELL :
1290                                         CharacterIteratorMode::SKIPCONTROLCHARACTER;
1291                 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousCharacters( rTNd.GetTxt(), nPos,
1292                                    pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
1293                                    nItrMode, 1, nDone );
1294 
1295                 // Check if nPos is inside hidden text range:
1296                 if ( CRSR_SKIP_HIDDEN & nMode )
1297                 {
1298                     xub_StrLen nHiddenStart;
1299                     xub_StrLen nHiddenEnd;
1300                     SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
1301                     if ( nHiddenStart != STRING_LEN  )
1302                          nPos = nHiddenStart;
1303                 }
1304 
1305 				if( 1 == nDone )
1306 					*pIdx = nPos;
1307 				else
1308 					bRet = sal_False;
1309 			}
1310 			else if( nPos )
1311 				(*pIdx)--;
1312 			else
1313 				bRet = sal_False;
1314 		}
1315 	}
1316 	else
1317 		bRet = sal_False;
1318 	return bRet;
1319 }
1320 
1321 
1322 /*
1323  * Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
1324  * Dokument. Die erzeugten Contentframes werden in das entsprechende
1325  * Layout gehaengt.
1326  */
1327 
1328 
1329 void SwCntntNode::MakeFrms( SwCntntNode& rNode )
1330 {
1331 	ASSERT( &rNode != this,
1332 			"Kein Contentnode oder Copy-Node und neuer Node identisch." );
1333 
1334 	if( !GetDepends() || &rNode == this )	// gibt es ueberhaupt Frames ??
1335 		return;
1336 
1337 	SwFrm *pFrm, *pNew;
1338 	SwLayoutFrm *pUpper;
1339 	// Frames anlegen fuer Nodes, die vor oder hinter der Tabelle stehen ??
1340 	ASSERT( FindTableNode() == rNode.FindTableNode(), "Table confusion" )
1341 
1342 	SwNode2Layout aNode2Layout( *this, rNode.GetIndex() );
1343 
1344 	while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, rNode )) )
1345 	{
1346 		pNew = rNode.MakeFrm( pUpper );
1347 		pNew->Paste( pUpper, pFrm );
1348         // --> OD 2005-12-01 #i27138#
1349         // notify accessibility paragraphs objects about changed
1350         // CONTENT_FLOWS_FROM/_TO relation.
1351         // Relation CONTENT_FLOWS_FROM for next paragraph will change
1352         // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1353         if ( pNew->IsTxtFrm() )
1354         {
1355             ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
1356             if ( pViewShell && pViewShell->GetLayout() &&
1357                  pViewShell->GetLayout()->IsAnyShellAccessible() )
1358             {
1359                 pViewShell->InvalidateAccessibleParaFlowRelation(
1360                             dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
1361                             dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
1362             }
1363         }
1364         // <--
1365     }
1366 }
1367 
1368 /*
1369  * Methode loescht fuer den Node alle Ansichten vom
1370  * Dokument. Die Contentframes werden aus dem entsprechenden
1371  * Layout ausgehaengt.
1372  */
1373 
1374 
1375 void SwCntntNode::DelFrms()
1376 {
1377 	if( !GetDepends() )
1378 		return;
1379 
1380     SwCntntFrm::DelFrms(*this);
1381 	if( IsTxtNode() )
1382 	{
1383         ((SwTxtNode*)this)->SetWrong( NULL );
1384         ((SwTxtNode*)this)->SetWrongDirty( true );
1385 
1386         ((SwTxtNode*)this)->SetGrammarCheck( NULL );
1387         ((SwTxtNode*)this)->SetGrammarCheckDirty( true );
1388         // SMARTTAGS
1389         ((SwTxtNode*)this)->SetSmartTags( NULL );
1390         ((SwTxtNode*)this)->SetSmartTagDirty( true );
1391 
1392         ((SwTxtNode*)this)->SetWordCountDirty( true );
1393         ((SwTxtNode*)this)->SetAutoCompleteWordDirty( true );
1394 	}
1395 }
1396 
1397 
1398 SwCntntNode *SwCntntNode::JoinNext()
1399 {
1400 	return this;
1401 }
1402 
1403 
1404 SwCntntNode *SwCntntNode::JoinPrev()
1405 {
1406 	return this;
1407 }
1408 
1409 
1410 
1411 	// erfrage vom Modify Informationen
1412 sal_Bool SwCntntNode::GetInfo( SfxPoolItem& rInfo ) const
1413 {
1414 	switch( rInfo.Which() )
1415 	{
1416 	case RES_AUTOFMT_DOCNODE:
1417 		if( &GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
1418 		{
1419 			((SwAutoFmtGetDocNode&)rInfo).pCntntNode = this;
1420 			return sal_False;
1421 		}
1422 		break;
1423     // --> OD 2008-02-19 #refactorlists#
1424 //    case RES_GETNUMNODES:
1425 //        // #111955# only numbered nodes in rInfo
1426 //        if( IsTxtNode())
1427 //        {
1428 //            SwTxtNode * pTxtNode = (SwTxtNode*)this;
1429 //            pItem = (SwNumRuleItem*)GetNoCondAttr(RES_PARATR_NUMRULE, sal_True );
1430 
1431 //            if (0 != pItem  &&
1432 //                pItem->GetValue().Len() &&
1433 //                pItem->GetValue() == ((SwNumRuleInfo&)rInfo).GetName() &&
1434 //                GetNodes().IsDocNodes())
1435 //            {
1436 //                ((SwNumRuleInfo&)rInfo).AddNode( *pTxtNode );
1437 //            }
1438 //        }
1439 
1440 //        return sal_True;
1441     // <--
1442 
1443 	case RES_FINDNEARESTNODE:
1444         if( ((SwFmtPageDesc&)GetAttr( RES_PAGEDESC )).GetPageDesc() )
1445 			((SwFindNearestNode&)rInfo).CheckNode( *this );
1446 		return sal_True;
1447 
1448 	case RES_CONTENT_VISIBLE:
1449 		{
1450 			((SwPtrMsgPoolItem&)rInfo).pObject =
1451 				SwIterator<SwFrm,SwCntntNode>::FirstElement(*this);
1452 		}
1453 		return sal_False;
1454 	}
1455 
1456 	return SwModify::GetInfo( rInfo );
1457 }
1458 
1459 
1460 	// setze ein Attribut
1461 sal_Bool SwCntntNode::SetAttr(const SfxPoolItem& rAttr )
1462 {
1463     if( !GetpSwAttrSet() )            // lasse von den entsprechenden Nodes die
1464 		NewAttrSet( GetDoc()->GetAttrPool() );		// AttrSets anlegen
1465 
1466     ASSERT( GetpSwAttrSet(), "warum wurde kein AttrSet angelegt?" );
1467 
1468     if ( IsInCache() )
1469 	{
1470 		SwFrm::GetCache().Delete( this );
1471 		SetInCache( sal_False );
1472 	}
1473 
1474 	sal_Bool bRet = sal_False;
1475 	// wenn Modify gelockt ist, werden keine Modifies verschickt
1476 	if( IsModifyLocked() ||
1477 		( !GetDepends() &&  RES_PARATR_NUMRULE != rAttr.Which() ))
1478 	{
1479         bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rAttr );
1480 	}
1481 	else
1482 	{
1483         SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1484                   aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1485         if( 0 != ( bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rAttr, &aOld, &aNew ) ))
1486 		{
1487             SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1488             SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1489 			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
1490 		}
1491 	}
1492 	return bRet;
1493 }
1494 #include <svl/itemiter.hxx>
1495 
1496 sal_Bool SwCntntNode::SetAttr( const SfxItemSet& rSet )
1497 {
1498     if ( IsInCache() )
1499 	{
1500 		SwFrm::GetCache().Delete( this );
1501 		SetInCache( sal_False );
1502 	}
1503 
1504     const SfxPoolItem* pFnd = 0;
1505     if( SFX_ITEM_SET == rSet.GetItemState( RES_AUTO_STYLE, sal_False, &pFnd ) )
1506     {
1507         ASSERT( rSet.Count() == 1, "SetAutoStyle mixed with other attributes?!" );
1508         const SwFmtAutoFmt* pTmp = static_cast<const SwFmtAutoFmt*>(pFnd);
1509 
1510         // If there already is an attribute set (usually containing a numbering
1511         // item), we have to merge the attribute of the new set into the old set:
1512         bool bSetParent = true;
1513         if ( GetpSwAttrSet() )
1514         {
1515             bSetParent = false;
1516             AttrSetHandleHelper::Put( mpAttrSet, *this, *pTmp->GetStyleHandle() );
1517         }
1518         else
1519         {
1520             mpAttrSet = pTmp->GetStyleHandle();
1521         }
1522 
1523         if ( bSetParent )
1524         {
1525             // If the content node has a conditional style, we have to set the
1526             // string item containing the correct conditional style name (the
1527             // style name property has already been set during the import!)
1528             // In case we do not have a conditional style, we make use of the
1529             // fact that nobody else uses the attribute set behind the handle.
1530             // FME 2007-07-10 #i78124# If autostyle does not have a parent,
1531             // the string is empty.
1532             const SfxPoolItem* pNameItem = 0;
1533             if ( 0 != GetCondFmtColl() ||
1534                  SFX_ITEM_SET != mpAttrSet->GetItemState( RES_FRMATR_STYLE_NAME, sal_False, &pNameItem ) ||
1535                  0 == static_cast<const SfxStringItem*>(pNameItem)->GetValue().Len() )
1536                 AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
1537             else
1538                 const_cast<SfxItemSet*>(mpAttrSet.get())->SetParent( &GetFmtColl()->GetAttrSet() );
1539         }
1540 
1541         return sal_True;
1542     }
1543 
1544     if( !GetpSwAttrSet() )            // lasse von den entsprechenden Nodes die
1545 		NewAttrSet( GetDoc()->GetAttrPool() );		// AttrSets anlegen
1546 
1547     sal_Bool bRet = sal_False;
1548 	// wenn Modify gelockt ist, werden keine Modifies verschickt
1549     if ( IsModifyLocked() ||
1550          ( !GetDepends() &&
1551            SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
1552 	{
1553 		// einige Sonderbehandlungen fuer Attribute
1554         bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rSet );
1555 	}
1556 	else
1557 	{
1558         SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1559                   aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1560         if( 0 != (bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rSet, &aOld, &aNew )) )
1561 		{
1562 			// einige Sonderbehandlungen fuer Attribute
1563             SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1564             SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1565 			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
1566 		}
1567 	}
1568 	return bRet;
1569 }
1570 
1571 // Nimmt den Hint mit nWhich aus dem Delta-Array
1572 
1573 
1574 sal_Bool SwCntntNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
1575 {
1576     if( !GetpSwAttrSet() )
1577 		return sal_False;
1578 
1579     if ( IsInCache() )
1580 	{
1581 		SwFrm::GetCache().Delete( this );
1582 		SetInCache( sal_False );
1583 	}
1584 
1585 	// wenn Modify gelockt ist, werden keine Modifies verschickt
1586 	if( IsModifyLocked() )
1587 	{
1588         sal_uInt16 nDel = 0;
1589         if ( !nWhich2 || nWhich2 < nWhich1 )
1590         {
1591             std::vector<sal_uInt16> aClearWhichIds;
1592             aClearWhichIds.push_back( nWhich1 );
1593             nDel = ClearItemsFromAttrSet( aClearWhichIds );
1594         }
1595         else
1596             nDel = AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, 0, 0 );
1597 
1598         if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
1599             mpAttrSet.reset();//DELETEZ( mpAttrSet );
1600 		return 0 != nDel;
1601 	}
1602 
1603 	// sollte kein gueltiger Bereich definiert sein ?
1604 	if( !nWhich2 || nWhich2 < nWhich1 )
1605 		nWhich2 = nWhich1;		// dann setze auf 1. Id, nur dieses Item
1606 
1607     SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1608               aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1609     sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, &aOld, &aNew );
1610 
1611 	if( bRet )
1612 	{
1613         SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1614         SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1615 		ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
1616 
1617         if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
1618             mpAttrSet.reset();//DELETEZ( mpAttrSet );
1619 	}
1620 	return bRet;
1621 }
1622 sal_Bool SwCntntNode::ResetAttr( const SvUShorts& rWhichArr )
1623 {
1624     if( !GetpSwAttrSet() )
1625 		return sal_False;
1626 
1627     if ( IsInCache() )
1628 	{
1629 		SwFrm::GetCache().Delete( this );
1630 		SetInCache( sal_False );
1631 	}
1632 
1633 	// wenn Modify gelockt ist, werden keine Modifies verschickt
1634 	sal_uInt16 nDel = 0;
1635 	if( IsModifyLocked() )
1636 	{
1637         std::vector<sal_uInt16> aClearWhichIds;
1638 		for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
1639             aClearWhichIds.push_back( rWhichArr[ n ] );
1640 
1641         nDel = ClearItemsFromAttrSet( aClearWhichIds );
1642     }
1643 	else
1644 	{
1645         SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1646                   aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1647 
1648 		for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
1649             if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, rWhichArr[ n ], &aOld, &aNew ))
1650 				++nDel;
1651 
1652 		if( nDel )
1653 		{
1654             SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1655             SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1656 			ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
1657 		}
1658 	}
1659     if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
1660         mpAttrSet.reset();//DELETEZ( mpAttrSet );
1661 	return 0 != nDel ;
1662 }
1663 
1664 
1665 sal_uInt16 SwCntntNode::ResetAllAttr()
1666 {
1667     if( !GetpSwAttrSet() )
1668 		return 0;
1669 
1670     if ( IsInCache() )
1671 	{
1672 		SwFrm::GetCache().Delete( this );
1673 		SetInCache( sal_False );
1674 	}
1675 
1676 	// wenn Modify gelockt ist, werden keine Modifies verschickt
1677 	if( IsModifyLocked() )
1678 	{
1679         std::vector<sal_uInt16> aClearWhichIds;
1680         aClearWhichIds.push_back(0);
1681         sal_uInt16 nDel = ClearItemsFromAttrSet( aClearWhichIds );
1682         if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
1683             mpAttrSet.reset();            // DELETEZ( mpAttrSet );
1684 		return nDel;
1685 	}
1686 
1687     SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1688               aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1689     sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, 0, &aOld, &aNew );
1690 
1691 	if( bRet )
1692 	{
1693         SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1694         SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1695 		ModifyNotification( &aChgOld, &aChgNew );		// alle veraenderten werden verschickt
1696 
1697         if( !GetpSwAttrSet()->Count() )   // leer, dann loeschen
1698             mpAttrSet.reset();//DELETEZ( mpAttrSet );
1699 	}
1700 	return aNew.Count();
1701 }
1702 
1703 
1704 sal_Bool SwCntntNode::GetAttr( SfxItemSet& rSet, sal_Bool bInParent ) const
1705 {
1706 	if( rSet.Count() )
1707 		rSet.ClearItem();
1708 
1709 	const SwAttrSet& rAttrSet = GetSwAttrSet();
1710 	if( bInParent )
1711 		return rSet.Set( rAttrSet, sal_True ) ? sal_True : sal_False;
1712 
1713 	rSet.Put( rAttrSet );
1714 	return rSet.Count() ? sal_True : sal_False;
1715 }
1716 
1717 sal_uInt16 SwCntntNode::ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds )
1718 {
1719     sal_uInt16 nRet = 0;
1720     if ( 0 == rWhichIds.size() )
1721         return nRet;
1722 
1723     ASSERT( GetpSwAttrSet(), "no item set" )
1724     SwAttrSet aNewAttrSet( *GetpSwAttrSet() );
1725     for ( std::vector<sal_uInt16>::const_iterator aIter = rWhichIds.begin();
1726           aIter != rWhichIds.end();
1727           ++aIter )
1728     {
1729         nRet = nRet + aNewAttrSet.ClearItem( *aIter );
1730     }
1731     if ( nRet )
1732         AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet, *this, aNewAttrSet );
1733 
1734     return nRet;
1735 }
1736 
1737 const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich,
1738 												sal_Bool bInParents ) const
1739 {
1740 	const SfxPoolItem* pFnd = 0;
1741 	if( pCondColl && pCondColl->GetRegisteredIn() )
1742 	{
1743         if( !GetpSwAttrSet() || ( SFX_ITEM_SET != GetpSwAttrSet()->GetItemState(
1744 					nWhich, sal_False, &pFnd ) && bInParents ))
1745 			((SwFmt*)GetRegisteredIn())->GetItemState( nWhich, bInParents, &pFnd );
1746 	}
1747     // --> OD 2005-10-25 #126347# - undo change of issue #i51029#
1748     // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns
1749     //       the attribute set of the paragraph style, which is valid for the
1750     //       content node - see file <node.hxx>
1751     else
1752     // <--
1753     {
1754 		GetSwAttrSet().GetItemState( nWhich, bInParents, &pFnd );
1755     }
1756 	return pFnd;
1757 }
1758 
1759 	// koennen 2 Nodes zusammengefasst werden ?
1760 	// in pIdx kann die 2. Position returnt werden.
1761 int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
1762 {
1763 	const SwNodes& rNds = GetNodes();
1764 	sal_uInt8 nNdType = GetNodeType();
1765 	SwNodeIndex aIdx( *this, 1 );
1766 
1767 	const SwNode* pNd = this;
1768 	while( aIdx < rNds.Count()-1 &&
1769 		(( pNd = &aIdx.GetNode())->IsSectionNode() ||
1770             ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
1771 		aIdx++;
1772 
1773 	if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() )
1774 		return sal_False;
1775     if( IsTxtNode() )
1776     {   // Do not merge strings if the result exceeds the allowed string length
1777         const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this);
1778         sal_uInt64 nSum = pTxtNd->GetTxt().Len();
1779         pTxtNd = static_cast<const SwTxtNode*>(pNd);
1780         nSum += pTxtNd->GetTxt().Len();
1781         if( nSum > STRING_LEN )
1782             return sal_False;
1783     }
1784 	if( pIdx )
1785 		*pIdx = aIdx;
1786 	return sal_True;
1787 }
1788 
1789 
1790 	// koennen 2 Nodes zusammengefasst werden ?
1791 	// in pIdx kann die 2. Position returnt werden.
1792 int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
1793 {
1794     sal_uInt8 nNdType = GetNodeType();
1795 	SwNodeIndex aIdx( *this, -1 );
1796 
1797 	const SwNode* pNd = this;
1798 	while( aIdx.GetIndex() &&
1799 		(( pNd = &aIdx.GetNode())->IsSectionNode() ||
1800             ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
1801 		aIdx--;
1802 
1803 	if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() )
1804 		return sal_False;
1805 	if( pIdx )
1806 		*pIdx = aIdx;
1807 	return sal_True;
1808 }
1809 
1810 
1811 //FEATURE::CONDCOLL
1812 
1813 
1814 void SwCntntNode::SetCondFmtColl( SwFmtColl* pColl )
1815 {
1816 	if( (!pColl && pCondColl) || ( pColl && !pCondColl ) ||
1817 		( pColl && pColl != pCondColl->GetRegisteredIn() ) )
1818 	{
1819 		SwFmtColl* pOldColl = GetCondFmtColl();
1820 		delete pCondColl;
1821 		if( pColl )
1822 			pCondColl = new SwDepend( this, pColl );
1823 		else
1824 			pCondColl = 0;
1825 
1826         if( GetpSwAttrSet() )
1827 		{
1828             AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
1829 		}
1830 
1831 		if( !IsModifyLocked() )
1832 		{
1833 			SwFmtChg aTmp1( pOldColl ? pOldColl : GetFmtColl() );
1834 			SwFmtChg aTmp2( pColl ? pColl : GetFmtColl() );
1835 			NotifyClients( &aTmp1, &aTmp2 );
1836 		}
1837 		if( IsInCache() )
1838 		{
1839 			SwFrm::GetCache().Delete( this );
1840 			SetInCache( sal_False );
1841 		}
1842 	}
1843 }
1844 
1845 
1846 sal_Bool SwCntntNode::IsAnyCondition( SwCollCondition& rTmp ) const
1847 {
1848 	const SwNodes& rNds = GetNodes();
1849 	{
1850 		int nCond = 0;
1851         const SwStartNode* pSttNd = StartOfSectionNode();
1852 		while( pSttNd )
1853 		{
1854 			switch( pSttNd->GetNodeType() )
1855 			{
1856 			case ND_TABLENODE:		nCond = PARA_IN_TABLEBODY; break;
1857 			case ND_SECTIONNODE: 	nCond = PARA_IN_SECTION; break;
1858 
1859 			default:
1860 				switch( pSttNd->GetStartNodeType() )
1861 				{
1862 				case SwTableBoxStartNode:
1863 					{
1864 						nCond = PARA_IN_TABLEBODY;
1865 						const SwTableNode* pTblNd = pSttNd->FindTableNode();
1866 						const SwTableBox* pBox;
1867 						if( pTblNd && 0 != ( pBox = pTblNd->GetTable().
1868 							GetTblBox( pSttNd->GetIndex() ) ) && pBox &&
1869 							pBox->IsInHeadline( &pTblNd->GetTable() ) )
1870 							nCond = PARA_IN_TABLEHEAD;
1871 					}
1872 					break;
1873 				case SwFlyStartNode:		nCond = PARA_IN_FRAME; break;
1874 				case SwFootnoteStartNode:
1875 					{
1876 						nCond = PARA_IN_FOOTENOTE;
1877 						const SwFtnIdxs& rFtnArr = rNds.GetDoc()->GetFtnIdxs();
1878 						const SwTxtFtn* pTxtFtn;
1879 						const SwNode* pSrchNd = pSttNd;
1880 
1881 						for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
1882 							if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
1883 								pSrchNd == &pTxtFtn->GetStartNode()->GetNode() )
1884 							{
1885 								if( pTxtFtn->GetFtn().IsEndNote() )
1886 									nCond = PARA_IN_ENDNOTE;
1887 								break;
1888 							}
1889 					}
1890 					break;
1891 				case SwHeaderStartNode:     nCond = PARA_IN_HEADER; break;
1892 				case SwFooterStartNode:     nCond = PARA_IN_FOOTER; break;
1893 				case SwNormalStartNode:     break;
1894 				}
1895 			}
1896 
1897 			if( nCond )
1898 			{
1899 				rTmp.SetCondition( (Master_CollConditions)nCond, 0 );
1900 				return sal_True;
1901 			}
1902 			pSttNd = pSttNd->GetIndex()
1903                         ? pSttNd->StartOfSectionNode()
1904 						: 0;
1905 		}
1906 	}
1907 
1908 	{
1909 		sal_uInt16 nPos;
1910 		const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1911 		if( rOutlNds.Count() )
1912 		{
1913 			if( !rOutlNds.Seek_Entry( (SwCntntNode*)this, &nPos ) && nPos )
1914 				--nPos;
1915 			if( nPos < rOutlNds.Count() &&
1916 				rOutlNds[ nPos ]->GetIndex() < GetIndex() )
1917 			{
1918 				SwTxtNode* pOutlNd = rOutlNds[ nPos ]->GetTxtNode();
1919 
1920 				if( pOutlNd->IsOutline())
1921 				{
1922                     rTmp.SetCondition( PARA_IN_OUTLINE, pOutlNd->GetAttrOutlineLevel() - 1 );
1923 					return sal_True;
1924 				}
1925 			}
1926 		}
1927 	}
1928 
1929 	return sal_False;
1930 }
1931 
1932 
1933 void SwCntntNode::ChkCondColl()
1934 {
1935 	// zur Sicherheit abfragen
1936 	if( RES_CONDTXTFMTCOLL == GetFmtColl()->Which() )
1937 	{
1938 		SwCollCondition aTmp( 0, 0, 0 );
1939 		const SwCollCondition* pCColl;
1940 
1941         bool bDone = false;
1942 
1943 		if( IsAnyCondition( aTmp ))
1944         {
1945             pCColl = static_cast<SwConditionTxtFmtColl*>(GetFmtColl())
1946                 ->HasCondition( aTmp );
1947 
1948             if (pCColl)
1949             {
1950                 SetCondFmtColl( pCColl->GetTxtFmtColl() );
1951                 bDone = true;
1952             }
1953         }
1954 
1955 		if (!bDone)
1956 		{
1957             if( IsTxtNode() && ((SwTxtNode*)this)->GetNumRule())
1958 			{
1959 				// steht in einer Numerierung
1960 				// welcher Level?
1961 				aTmp.SetCondition( PARA_IN_LIST,
1962                                 ((SwTxtNode*)this)->GetActualListLevel() );
1963 				pCColl = ((SwConditionTxtFmtColl*)GetFmtColl())->
1964 								HasCondition( aTmp );
1965 			}
1966 			else
1967 				pCColl = 0;
1968 
1969 			if( pCColl )
1970 				SetCondFmtColl( pCColl->GetTxtFmtColl() );
1971 			else if( pCondColl )
1972 				SetCondFmtColl( 0 );
1973 		}
1974 	}
1975 }
1976 
1977 // --> OD 2005-02-21 #i42921#
1978 short SwCntntNode::GetTextDirection( const SwPosition& rPos,
1979                                      const Point* pPt ) const
1980 {
1981     short nRet = -1;
1982 
1983     Point aPt;
1984     if( pPt )
1985         aPt = *pPt;
1986 
1987     // --> OD 2007-01-10 #i72024#
1988     // No format of the frame, because this can cause recursive layout actions
1989     SwFrm* pFrm = getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, &rPos, sal_False );
1990     // <--
1991 
1992     if ( pFrm )
1993     {
1994         if ( pFrm->IsVertical() )
1995         {
1996             if ( pFrm->IsRightToLeft() )
1997                 nRet = FRMDIR_VERT_TOP_LEFT;
1998             else
1999                 nRet = FRMDIR_VERT_TOP_RIGHT;
2000         }
2001         else
2002         {
2003             if ( pFrm->IsRightToLeft() )
2004                 nRet = FRMDIR_HORI_RIGHT_TOP;
2005             else
2006                 nRet = FRMDIR_HORI_LEFT_TOP;
2007         }
2008     }
2009 
2010 
2011     return nRet;
2012 }
2013 // <--
2014 
2015 SwOLENodes* SwCntntNode::CreateOLENodesArray( const SwFmtColl& rColl, bool bOnlyWithInvalidSize )
2016 {
2017     SwOLENodes *pNodes = 0;
2018     SwIterator<SwCntntNode,SwFmtColl> aIter( rColl );
2019     for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
2020     {
2021         SwOLENode *pONd = pNd->GetOLENode();
2022         if ( pONd && (!bOnlyWithInvalidSize || pONd->IsOLESizeInvalid()) )
2023         {
2024             if ( !pNodes  )
2025                 pNodes = new SwOLENodes;
2026             pNodes->Insert( pONd, pNodes->Count() );
2027         }
2028     }
2029 
2030     return pNodes;
2031 }
2032 
2033 //FEATURE::CONDCOLL
2034 // Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
2035 // os: nur fuer ICC, da der zum optimieren zu dumm ist
2036 #ifdef ICC
2037 SwTxtNode   *SwNode::GetTxtNode()
2038 {
2039 	 return ND_TEXTNODE == nNodeType ? (SwTxtNode*)this : 0;
2040 }
2041 const SwTxtNode   *SwNode::GetTxtNode() const
2042 {
2043 	 return ND_TEXTNODE == nNodeType ? (const SwTxtNode*)this : 0;
2044 }
2045 #endif
2046 
2047 /*
2048  * Document Interface Access
2049  */
2050 const IDocumentSettingAccess* SwNode::getIDocumentSettingAccess() const { return GetDoc(); }
2051 const IDocumentDeviceAccess* SwNode::getIDocumentDeviceAccess() const { return GetDoc(); }
2052 const IDocumentMarkAccess* SwNode::getIDocumentMarkAccess() const { return GetDoc()->getIDocumentMarkAccess(); }
2053 const IDocumentRedlineAccess* SwNode::getIDocumentRedlineAccess() const { return GetDoc(); }
2054 const IDocumentStylePoolAccess* SwNode::getIDocumentStylePoolAccess() const { return GetDoc(); }
2055 const IDocumentLineNumberAccess* SwNode::getIDocumentLineNumberAccess() const { return GetDoc(); }
2056 const IDocumentDrawModelAccess* SwNode::getIDocumentDrawModelAccess() const { return GetDoc(); }
2057 const IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() const { return GetDoc(); }
2058 IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() { return GetDoc(); }
2059 const IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() const { return GetDoc(); }
2060 IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() { return GetDoc(); }
2061 const IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() const { return GetDoc(); }
2062 IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() { return GetDoc(); }
2063 IDocumentContentOperations* SwNode::getIDocumentContentOperations() { return GetDoc(); }
2064 IStyleAccess& SwNode::getIDocumentStyleAccess() { return GetDoc()->GetIStyleAccess(); }
2065 // --> OD 2007-10-31 #i83479#
2066 IDocumentListItems& SwNode::getIDocumentListItems()
2067 {
2068     return *GetDoc();
2069 }
2070 // <--
2071 
2072 sal_Bool SwNode::IsInRedlines() const
2073 {
2074     const SwDoc * pDoc = GetDoc();
2075     sal_Bool bResult = sal_False;
2076 
2077     if (pDoc != NULL)
2078         bResult = pDoc->IsInRedlines(*this);
2079 
2080     return bResult;
2081 }
2082