xref: /aoo42x/main/sw/source/core/doc/doctxm.cxx (revision efeef26f)
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 
27 
28 #include <limits.h>
29 #include <hintids.hxx>
30 
31 #define _SVSTDARR_STRINGSSORT
32 #include <svl/svstdarr.hxx>
33 #include <editeng/langitem.hxx>
34 #include <editeng/brkitem.hxx>
35 #include <editeng/tstpitem.hxx>
36 #include <editeng/lrspitem.hxx>
37 #include <sot/clsids.hxx>
38 #include <docsh.hxx>
39 #include <ndole.hxx>
40 #include <txttxmrk.hxx>
41 #include <fmtinfmt.hxx>
42 #include <fmtpdsc.hxx>
43 #include <frmfmt.hxx>
44 #include <fmtfsize.hxx>
45 #include <frmatr.hxx>
46 #include <pagedesc.hxx>
47 #include <doc.hxx>
48 #include <IDocumentUndoRedo.hxx>
49 #include <pagefrm.hxx>
50 #include <ndtxt.hxx>
51 #include <swtable.hxx>
52 #include <doctxm.hxx>
53 #include <txmsrt.hxx>
54 #include <rolbck.hxx>
55 #include <poolfmt.hxx>
56 #include <txtfrm.hxx>
57 #include <rootfrm.hxx>
58 #include <UndoAttribute.hxx>
59 #include <swundo.hxx>
60 #include <mdiexp.hxx>
61 #include <docary.hxx>
62 #include <charfmt.hxx>
63 #include <fchrfmt.hxx>
64 #include <fldbas.hxx>
65 #include <fmtfld.hxx>
66 #include <txtfld.hxx>
67 #include <expfld.hxx>
68 #include <chpfld.hxx>
69 #include <mvsave.hxx>
70 #include <node2lay.hxx>
71 #include <SwStyleNameMapper.hxx>
72 #include <breakit.hxx>
73 #include <editsh.hxx>
74 #include <scriptinfo.hxx>
75 #include <switerator.hxx>
76 
77 using namespace ::com::sun::star;
78 
79 const sal_Unicode cNumRepl		= '@';
80 const sal_Unicode cEndPageNum 	= '~';
81 const sal_Char __FAR_DATA sPageDeli[] = ", ";
82 
83 SV_IMPL_PTRARR(SwTOXSortTabBases, SwTOXSortTabBasePtr)
84 
85 TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection );	// fuers RTTI
86 
87 struct LinkStruct
88 {
89 	SwFmtINetFmt	aINetFmt;
90 	xub_StrLen nStartTextPos, nEndTextPos;
91 
92 	LinkStruct( const String& rURL, xub_StrLen nStart, xub_StrLen nEnd )
93 		: aINetFmt( rURL, aEmptyStr),
94 		nStartTextPos( nStart),
95 		nEndTextPos(nEnd) {}
96 };
97 
98 typedef LinkStruct* LinkStructPtr;
99 SV_DECL_PTRARR(LinkStructArr, LinkStructPtr, 0, 5 )
100 SV_IMPL_PTRARR(LinkStructArr, LinkStructPtr)
101 
102 sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, SvStringsSort& rArr ) const
103 {
104 	if( rArr.Count() )
105 		rArr.Remove( sal_uInt16(0), rArr.Count() );
106 
107 	// dann mal ueber den Pool und alle Primary oder Secondary heraussuchen
108 	const SwTxtTOXMark* pMark;
109 	const SfxPoolItem* pItem;
110     const SwTOXType* pTOXType;
111 	sal_uInt32 i, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
112 	for( i = 0; i < nMaxItems; ++i )
113 		if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ) ) &&
114 			0!= ( pTOXType = ((SwTOXMark*)pItem)->GetTOXType()) &&
115             TOX_INDEX == pTOXType->GetType() &&
116 			0 != ( pMark = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
117 			pMark->GetpTxtNd() &&
118 			pMark->GetpTxtNd()->GetNodes().IsDocNodes() )
119 		{
120 			const String* pStr;
121 			if( TOI_PRIMARY == eTyp )
122 				pStr = &((SwTOXMark*)pItem)->GetPrimaryKey();
123 			else
124 				pStr = &((SwTOXMark*)pItem)->GetSecondaryKey();
125 
126 			if( pStr->Len() )
127 				rArr.Insert( (StringPtr)pStr );
128 		}
129 
130 	return rArr.Count();
131 }
132 
133 /*--------------------------------------------------------------------
134 	 Beschreibung: aktuelle Verzeichnismarkierungen ermitteln
135  --------------------------------------------------------------------*/
136 
137 
138 sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
139 								SwTOXMarks& rArr ) const
140 {
141     // search on Position rPos for all SwTOXMarks
142     SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
143 	if( !pTxtNd || !pTxtNd->GetpSwpHints() )
144 		return 0;
145 
146 	const SwpHints & rHts = *pTxtNd->GetpSwpHints();
147 	const SwTxtAttr* pHt;
148 	xub_StrLen nSttIdx;
149 	const xub_StrLen *pEndIdx;
150 
151 	xub_StrLen nAktPos = rPos.nContent.GetIndex();
152 
153 	for( sal_uInt16 n = 0; n < rHts.Count(); ++n )
154 	{
155 		if( RES_TXTATR_TOXMARK != (pHt = rHts[n])->Which() )
156 			continue;
157 		if( ( nSttIdx = *pHt->GetStart() ) < nAktPos )
158 		{
159 			// pruefe Ende mit ab
160 			if( 0 == ( pEndIdx = pHt->GetEnd() ) ||
161 				*pEndIdx <= nAktPos )
162 				continue;		// weiter suchen
163 		}
164 		else if( nSttIdx > nAktPos )
165 			// ist Start vom Hint groesser als rPos, dann abbrechen. Denn
166 			// die Attribute sind nach Start sortiert !
167 			break;
168 
169 		const SwTOXMark* pTMark = &pHt->GetTOXMark();
170 		rArr.Insert( pTMark, rArr.Count() );
171 	}
172 	return rArr.Count();
173 }
174 
175 /*--------------------------------------------------------------------
176 	 Beschreibung: Marke loeschen
177  --------------------------------------------------------------------*/
178 
179 void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
180 {
181 	// hole den TextNode und
182     const SwTxtTOXMark* pTxtTOXMark = pTOXMark->GetTxtTOXMark();
183 	ASSERT( pTxtTOXMark, "Kein TxtTOXMark, kann nicht geloescht werden" );
184 
185     SwTxtNode& rTxtNd = const_cast<SwTxtNode&>(pTxtTOXMark->GetTxtNode());
186 	ASSERT( rTxtNd.GetpSwpHints(), "kann nicht geloescht werden" );
187 
188     if (GetIDocumentUndoRedo().DoesUndo())
189     {
190         // save attributes for Undo
191         SwUndoResetAttr* pUndo = new SwUndoResetAttr(
192             SwPosition( rTxtNd, SwIndex( &rTxtNd, *pTxtTOXMark->GetStart() ) ),
193             RES_TXTATR_TOXMARK );
194         GetIDocumentUndoRedo().AppendUndo( pUndo );
195 
196         SwRegHistory aRHst( rTxtNd, &pUndo->GetHistory() );
197 		rTxtNd.GetpSwpHints()->Register( &aRHst );
198     }
199 
200     rTxtNd.DeleteAttribute( const_cast<SwTxtTOXMark*>(pTxtTOXMark) );
201 
202     if (GetIDocumentUndoRedo().DoesUndo())
203     {
204         if( rTxtNd.GetpSwpHints() )
205 			rTxtNd.GetpSwpHints()->DeRegister();
206 	}
207 	SetModified();
208 }
209 
210 /*--------------------------------------------------------------------
211 	 Beschreibung: Traveln zwischen TOXMarks
212  --------------------------------------------------------------------*/
213 
214 class CompareNodeCntnt
215 {
216 	sal_uLong nNode;
217 	xub_StrLen nCntnt;
218 public:
219 	CompareNodeCntnt( sal_uLong nNd, xub_StrLen nCnt )
220 		: nNode( nNd ), nCntnt( nCnt ) {}
221 
222 	int operator==( const CompareNodeCntnt& rCmp )
223 		{ return nNode == rCmp.nNode && nCntnt == rCmp.nCntnt; }
224 	int operator!=( const CompareNodeCntnt& rCmp )
225 		{ return nNode != rCmp.nNode || nCntnt != rCmp.nCntnt; }
226 	int operator< ( const CompareNodeCntnt& rCmp )
227 		{ return nNode < rCmp.nNode ||
228 			( nNode == rCmp.nNode && nCntnt < rCmp.nCntnt); }
229 	int operator<=( const CompareNodeCntnt& rCmp )
230 		{ return nNode < rCmp.nNode ||
231 			( nNode == rCmp.nNode && nCntnt <= rCmp.nCntnt); }
232 	int operator> ( const CompareNodeCntnt& rCmp )
233 		{ return nNode > rCmp.nNode ||
234 			( nNode == rCmp.nNode && nCntnt > rCmp.nCntnt); }
235 	int operator>=( const CompareNodeCntnt& rCmp )
236 		{ return nNode > rCmp.nNode ||
237 			( nNode == rCmp.nNode && nCntnt >= rCmp.nCntnt); }
238 };
239 
240 const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
241 									SwTOXSearch eDir, sal_Bool bInReadOnly )
242 {
243 	const SwTxtTOXMark* pMark = rCurTOXMark.GetTxtTOXMark();
244 	ASSERT(pMark, "pMark==0 Ungueltige TxtTOXMark");
245 
246 	const SwTxtNode *pTOXSrc = pMark->GetpTxtNd();
247 
248 	CompareNodeCntnt aAbsIdx( pTOXSrc->GetIndex(), *pMark->GetStart() );
249 	CompareNodeCntnt aPrevPos( 0, 0 );
250 	CompareNodeCntnt aNextPos( ULONG_MAX, STRING_NOTFOUND );
251 	CompareNodeCntnt aMax( 0, 0 );
252 	CompareNodeCntnt aMin( ULONG_MAX, STRING_NOTFOUND );
253 
254 	const SwTOXMark*	pNew	= 0;
255 	const SwTOXMark*	pMax	= &rCurTOXMark;
256 	const SwTOXMark*	pMin	= &rCurTOXMark;
257 
258 	const SwTOXType* pType = rCurTOXMark.GetTOXType();
259     SwTOXMarks aMarks;
260     SwTOXMark::InsertTOXMarks( aMarks, *pType );
261 
262 	const SwTOXMark* pTOXMark;
263 	const SwCntntFrm* pCFrm;
264 	Point aPt;
265 	for( sal_Int32 nMark=0; nMark<aMarks.Count(); nMark++ )
266 	{
267         pTOXMark = aMarks[nMark];
268 		if( pTOXMark != &rCurTOXMark &&
269 			0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
270 			0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
271 			0 != ( pCFrm = pTOXSrc->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False )) &&
272 			( bInReadOnly || !pCFrm->IsProtected() ))
273 		{
274 			CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
275 			switch( eDir )
276 			{
277 				//Die untenstehenden etwas komplizierter ausgefallen Ausdruecke
278 				//dienen dazu auch ueber Eintraege auf der selben (!) Position
279 				//traveln zu koennen. Wenn einer Zeit hat mag er sie mal
280 				//optimieren.
281 
282 			case TOX_SAME_PRV:
283 				if( pTOXMark->GetText() != rCurTOXMark.GetText() )
284 					break;
285 				/* no break here */
286 			case TOX_PRV:
287 				if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
288 					  aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
289 					 (aAbsIdx == aAbsNew &&
290 					  (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
291 					   (!pNew ||
292 						(pNew && (aPrevPos < aAbsIdx ||
293 								  sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
294 					 (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
295 					  sal_uLong(pTOXMark) > sal_uLong(pNew)) )
296 				{
297 					pNew = pTOXMark;
298 					aPrevPos = aAbsNew;
299 					if ( aAbsNew >= aMax )
300 					{
301 						aMax = aAbsNew;
302 						pMax = pTOXMark;
303 					}
304 				}
305 				break;
306 
307 			case TOX_SAME_NXT:
308 				if( pTOXMark->GetText() != rCurTOXMark.GetText() )
309 					break;
310 				/* no break here */
311 			case TOX_NXT:
312 				if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
313 					  aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
314 					 (aAbsIdx == aAbsNew &&
315 					  (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
316 					   (!pNew ||
317 						(pNew && (aNextPos > aAbsIdx ||
318 								  sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
319 					 (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
320 					  sal_uLong(pTOXMark) < sal_uLong(pNew)) )
321 				{
322 					pNew = pTOXMark;
323 					aNextPos = aAbsNew;
324 					if ( aAbsNew <= aMin )
325 					{
326 						aMin = aAbsNew;
327 						pMin = pTOXMark;
328 					}
329 				}
330 				break;
331 			}
332 		}
333 	}
334 
335 
336 	// kein Nachfolger wurde gefunden
337 	// Min oder Max benutzen
338 	if(!pNew)
339 	{
340 		switch(eDir)
341 		{
342 		case TOX_PRV:
343 		case TOX_SAME_PRV:
344 			pNew = pMax;
345 			break;
346 		case TOX_NXT:
347 		case TOX_SAME_NXT:
348 			pNew = pMin;
349 			break;
350 		default:
351 			pNew = &rCurTOXMark;
352 		}
353 	}
354 	return *pNew;
355 }
356 
357 
358 const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
359 												const SwTOXBase& rTOX,
360 												const SfxItemSet* pSet,
361 												sal_Bool bExpand )
362 {
363     GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
364 
365 	String sSectNm( rTOX.GetTOXName() );
366 	sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
367 	SwPaM aPam( rPos );
368     SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
369     SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
370         InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
371     if (pNewSection)
372     {
373         SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
374         pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
375 
376 		if( bExpand )
377         {
378             // OD 19.03.2003 #106329# - add value for 2nd parameter = true to
379             // indicate, that a creation of a new table of content has to be performed.
380             // Value of 1st parameter = default value.
381             pNewSection->Update( 0, true );
382         }
383 		else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
384 		// insert title of TOX
385 		{
386 			// then insert the headline section
387 			SwNodeIndex aIdx( *pSectNd, +1 );
388 
389 			SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
390 							GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
391 
392             String sNm( pNewSection->GetTOXName() );
393 // ??Resource
394 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
395 
396             SwSectionData headerData( TOX_HEADER_SECTION, sNm );
397 
398 			SwNodeIndex aStt( *pHeadNd ); aIdx--;
399 			SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
400             GetNodes().InsertTextSection(
401                     aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
402         }
403     }
404 
405     GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
406 
407     return pNewSection;
408 }
409 
410 
411 
412 const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
413 												const SwTOXBase& rTOX,
414 												const SfxItemSet* pSet )
415 {
416 	// check for recursiv TOX
417 	SwNode* pNd = GetNodes()[ nSttNd ];
418 	SwSectionNode* pSectNd = pNd->FindSectionNode();
419 	while( pSectNd )
420 	{
421 		SectionType eT = pSectNd->GetSection().GetType();
422 		if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
423 			return 0;
424         pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
425 	}
426 
427 	String sSectNm( rTOX.GetTOXName() );
428 	sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
429 
430     SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
431 
432 	SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
433 	SwSectionFmt* pFmt = MakeSectionFmt( 0 );
434 	if(pSet)
435         pFmt->SetFmtAttr(*pSet);
436 
437 //	--aEnd;		// im InsertSection ist Ende inclusive
438 
439     SwSectionNode *const pNewSectionNode =
440         GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
441     if (!pNewSectionNode)
442     {
443 		DelSectionFmt( pFmt );
444         return 0;
445     }
446 
447     SwTOXBaseSection *const pNewSection(
448         dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
449     pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
450     return pNewSection;
451 }
452 
453 /*--------------------------------------------------------------------
454 	 Beschreibung: Aktuelles Verzeichnis ermitteln
455  --------------------------------------------------------------------*/
456 
457 const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
458 {
459 	const SwNode& rNd = rPos.nNode.GetNode();
460 	const SwSectionNode* pSectNd = rNd.FindSectionNode();
461 	while( pSectNd )
462 	{
463 		SectionType eT = pSectNd->GetSection().GetType();
464 		if( TOX_CONTENT_SECTION == eT )
465 		{
466 			ASSERT( pSectNd->GetSection().ISA( SwTOXBaseSection ),
467 					"keine TOXBaseSection!" );
468 			SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
469 												pSectNd->GetSection();
470 			return &rTOXSect;
471 		}
472         pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
473 	}
474 	return 0;
475 }
476 
477 const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
478 {
479 	ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
480 	const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
481 	SwSectionFmt* pFmt = rTOXSect.GetFmt();
482 	ASSERT( pFmt, "invalid TOXBaseSection!" );
483 	return pFmt->GetAttrSet();
484 }
485 
486 const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate )
487 {
488     SwTOXBase** prBase = 0;
489 	switch(eTyp)
490 	{
491 	case  TOX_CONTENT: 			prBase = &pDefTOXBases->pContBase; break;
492 	case  TOX_INDEX:            prBase = &pDefTOXBases->pIdxBase;  break;
493 	case  TOX_USER:             prBase = &pDefTOXBases->pUserBase; break;
494 	case  TOX_TABLES:           prBase = &pDefTOXBases->pTblBase;  break;
495 	case  TOX_OBJECTS:          prBase = &pDefTOXBases->pObjBase;  break;
496 	case  TOX_ILLUSTRATIONS:    prBase = &pDefTOXBases->pIllBase;  break;
497 	case  TOX_AUTHORITIES:		prBase = &pDefTOXBases->pAuthBase; break;
498 	}
499 	if(!(*prBase) && bCreate)
500 	{
501 		SwForm aForm(eTyp);
502 		const SwTOXType* pType = GetTOXType(eTyp, 0);
503 		(*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
504 	}
505 	return (*prBase);
506 }
507 
508 void	SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
509 {
510     SwTOXBase** prBase = 0;
511 	switch(rBase.GetType())
512 	{
513 	case  TOX_CONTENT: 			prBase = &pDefTOXBases->pContBase; break;
514 	case  TOX_INDEX:            prBase = &pDefTOXBases->pIdxBase;  break;
515 	case  TOX_USER:             prBase = &pDefTOXBases->pUserBase; break;
516 	case  TOX_TABLES:           prBase = &pDefTOXBases->pTblBase;  break;
517 	case  TOX_OBJECTS:          prBase = &pDefTOXBases->pObjBase;  break;
518 	case  TOX_ILLUSTRATIONS:    prBase = &pDefTOXBases->pIllBase;  break;
519 	case  TOX_AUTHORITIES:		prBase = &pDefTOXBases->pAuthBase; break;
520 	}
521 	if(*prBase)
522 		delete (*prBase);
523 	(*prBase) = new SwTOXBase(rBase);
524 }
525 
526 /*--------------------------------------------------------------------
527 	 Beschreibung: Verzeichnis loeschen
528  --------------------------------------------------------------------*/
529 
530 
531 sal_Bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes )
532 {
533     // its only delete the TOX, not the nodes
534     sal_Bool bRet = sal_False;
535     ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
536 
537     const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
538     SwSectionFmt* pFmt = rTOXSect.GetFmt();
539     if( pFmt )
540     {
541         GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
542 
543 		/* Save the start node of the TOX' section. */
544 		SwSectionNode * pMyNode = pFmt->GetSectionNode();
545 		/* Save start node of section's surrounding. */
546         SwNode * pStartNd = pMyNode->StartOfSectionNode();
547 
548 		/* Look for point where to move the cursors in the area to
549 		   delete to. This is done by first searching forward from the
550 		   end of the TOX' section. If no content node is found behind
551 		   the TOX one is searched before it. If this is not
552 		   successfull, too, insert new text node behind the end of
553 		   the TOX' section. The cursors from the TOX' section will be
554 		   moved to the content node found or the new text node. */
555 
556 		/* Set PaM to end of TOX' section and search following content node.
557 
558 		   aSearchPam will contain the point where to move the cursors
559 		   to. */
560 		SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
561         SwPosition aEndPos(*pStartNd->EndOfSectionNode());
562 		if (! aSearchPam.Move() /* no content node found */
563 			|| *aSearchPam.GetPoint() >= aEndPos /* content node found
564 													outside surrounding */
565 			)
566 		{
567 			/* Set PaM to beginning of TOX' section and search previous
568 			   content node */
569 			SwPaM aTmpPam(*pMyNode);
570 			aSearchPam = aTmpPam;
571             SwPosition aStartPos(*pStartNd);
572 
573 			if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
574 				 || *aSearchPam.GetPoint() <= aStartPos  /* content node
575 															found outside
576 															surrounding */
577 				 )
578 			{
579 				/* There is no content node in the surrounding of
580 				   TOX'. Append text node behind TOX' section. */
581 
582                 SwPosition aInsPos(*pMyNode->EndOfSectionNode());
583 				AppendTxtNode(aInsPos);
584 
585 				SwPaM aTmpPam1(aInsPos);
586 				aSearchPam = aTmpPam1;
587 			}
588 		}
589 
590 
591 		/* PaM containing the TOX. */
592 		SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
593 
594 		/* Move cursors contained in TOX to point determined above. */
595 		PaMCorrAbs(aPam, *aSearchPam.GetPoint());
596 
597 		if( !bDelNodes )
598 		{
599 			SwSections aArr( 0, 4 );
600 			sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
601 			for( sal_uInt16 n = 0; n < nCnt; ++n )
602 			{
603 				SwSection* pSect = aArr[ n ];
604 				if( TOX_HEADER_SECTION == pSect->GetType() )
605 				{
606 					DelSectionFmt( pSect->GetFmt(), bDelNodes );
607 				}
608 			}
609 		}
610 
611 		DelSectionFmt( pFmt, bDelNodes );
612 
613         GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
614 		bRet = sal_True;
615     }
616 
617     return bRet;
618 }
619 
620 /*--------------------------------------------------------------------
621 	 Beschreibung:	Verzeichnistypen verwalten
622  --------------------------------------------------------------------*/
623 
624 sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
625 {
626 	const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
627 	sal_uInt16 nCnt = 0;
628 	for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
629 		if( eTyp == (*ppTTypes)->GetType() )
630 			++nCnt;
631 	return nCnt;
632 }
633 
634 const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
635 {
636 	const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
637 	sal_uInt16 nCnt = 0;
638 	for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
639 		if( eTyp == (*ppTTypes)->GetType() && nCnt++ == nId )
640 			return (*ppTTypes);
641 	return 0;
642 }
643 
644 
645 const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
646 {
647 	SwTOXType * pNew = new SwTOXType( rTyp );
648 	pTOXTypes->Insert( pNew, pTOXTypes->Count() );
649 	return pNew;
650 }
651 
652 String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
653 									const String* pChkStr ) const
654 {
655 	sal_uInt16 n;
656 	const SwSectionNode* pSectNd;
657 	const SwSection* pSect;
658 
659 	if(pChkStr && !pChkStr->Len())
660 		pChkStr = 0;
661 	String aName( rType.GetTypeName() );
662 	xub_StrLen nNmLen = aName.Len();
663 
664     sal_uInt16 nNum = 0;
665     sal_uInt16 nTmp = 0;
666     sal_uInt16 nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
667 	sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
668 	memset( pSetFlags, 0, nFlagSize );
669 
670 	for( n = 0; n < pSectionFmtTbl->Count(); ++n )
671 		if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
672 			 TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
673 		{
674             const String& rNm = pSect->GetSectionName();
675 			if( rNm.Match( aName ) == nNmLen )
676 			{
677 				// Nummer bestimmen und das Flag setzen
678 				nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
679 				if( nNum-- && nNum < pSectionFmtTbl->Count() )
680 					pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
681 			}
682 			if( pChkStr && pChkStr->Equals( rNm ) )
683 				pChkStr = 0;
684 		}
685 
686 	if( !pChkStr )
687 	{
688 		// alle Nummern entsprechend geflag, also bestimme die richtige Nummer
689 		nNum = pSectionFmtTbl->Count();
690 		for( n = 0; n < nFlagSize; ++n )
691 			if( 0xff != ( nTmp = pSetFlags[ n ] ))
692 			{
693 				// also die Nummer bestimmen
694 				nNum = n * 8;
695 				while( nTmp & 1 )
696 					++nNum, nTmp >>= 1;
697 				break;
698 			}
699 	}
700 	delete [] pSetFlags;
701 	if( pChkStr )
702 		return *pChkStr;
703 	return aName += String::CreateFromInt32( ++nNum );
704 }
705 
706 sal_Bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
707 {
708 	ASSERT( rTOXBase.ISA( SwTOXBaseSection ),
709 					"keine TOXBaseSection!" );
710 	SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
711 
712 	String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
713 	sal_Bool bRet = sTmp == rName;
714 	if(bRet)
715 	{
716 		pTOX->SetTOXName(rName);
717         pTOX->SetSectionName(rName);
718 		SetModified();
719 	}
720 	return bRet;
721 }
722 
723 
724 const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
725 {
726 	const SwNode* pNd = &rNd;
727 	if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
728 	{
729 		// then find the "Anchor" (Body) position
730 		Point aPt;
731 		SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
732 		const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
733 
734 		if( pFrm )
735 		{
736 			SwPosition aPos( *pNd );
737 			pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
738 			ASSERT( pNd,	"wo steht der Absatz" );
739 		}
740 	}
741 	return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
742 }
743 
744 
745 /*--------------------------------------------------------------------
746 	 Beschreibung: Verzeichnis-Klasse
747  --------------------------------------------------------------------*/
748 
749 SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
750     : SwTOXBase( rBase )
751     , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
752 {
753 	SetProtect( rBase.IsProtected() );
754     SetSectionName( GetTOXName() );
755 }
756 
757 
758 SwTOXBaseSection::~SwTOXBaseSection()
759 {
760 }
761 
762 
763 sal_Bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart ) const
764 {
765 	sal_Bool bRet = sal_False;
766 	const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
767 	if( pSectNd )
768 	{
769 		SwCntntNode* pCNd;
770 		xub_StrLen nC = 0;
771 		if( bAtStart )
772 		{
773 			rPos.nNode = *pSectNd;
774 			pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
775 		}
776 		else
777 		{
778 			rPos.nNode = *pSectNd->EndOfSectionNode();
779 			pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
780 			if( pCNd ) nC = pCNd->Len();
781 		}
782 		rPos.nContent.Assign( pCNd, nC );
783 		bRet = sal_True;
784 	}
785 	return bRet;
786 }
787 
788 /*--------------------------------------------------------------------
789 	 Beschreibung: Verzeichnisinhalt zusammensammeln
790  --------------------------------------------------------------------*/
791 
792 void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
793                               const bool        _bNewTOX )//swmodtest 080307
794 {
795 	const SwSectionNode* pSectNd;
796 	if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
797 		!GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
798 		!pSectNd->GetNodes().IsDocNodes() ||
799 		IsHiddenFlag() )
800 		return;
801 
802 	SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
803 
804     DBG_ASSERT(pDoc != NULL, "Where is the document?");
805 
806 	if(pAttr && pDoc && GetFmt())
807 		pDoc->ChgFmt(*GetFmt(), *pAttr);
808 
809     // OD 18.03.2003 #106329# - determine default page description, which
810     // will be used by the content nodes, if no approriate one is found.
811     const SwPageDesc* pDefaultPageDesc;
812     {
813         pDefaultPageDesc =
814             pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
815         if ( !_bNewTOX && !pDefaultPageDesc )
816         {
817             // determine page description of table-of-content
818             sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
819             sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
820             pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
821             if ( nPgDescNdIdx < pSectNd->GetIndex() )
822             {
823                 pDefaultPageDesc = 0;
824             }
825         }
826         // OD 28.04.2003 #109166# - consider end node of content section in the
827         // node array.
828         if ( !pDefaultPageDesc &&
829              ( pSectNd->EndOfSectionNode()->GetIndex() <
830                  (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
831            )
832         {
833             // determine page description of content after table-of-content
834             SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
835             const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
836             const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
837             const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
838             if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
839                     eBreak == SVX_BREAK_PAGE_BOTH )
840                )
841             {
842                 pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
843             }
844         }
845         // OD 28.04.2003 #109166# - consider start node of content section in
846         // the node array.
847         if ( !pDefaultPageDesc &&
848              ( pSectNd->GetIndex() >
849                  (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
850            )
851         {
852             // determine page description of content before table-of-content
853             SwNodeIndex aIdx( *pSectNd );
854             pDefaultPageDesc =
855                 pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
856 
857         }
858         if ( !pDefaultPageDesc )
859         {
860             // determine default page description
861             pDefaultPageDesc =
862                 &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
863         }
864     }
865 
866     pDoc->SetModified();
867 
868 	// get current Language
869     SwTOXInternational aIntl(  GetLanguage(),
870                                TOX_INDEX == GetTOXType()->GetType() ?
871                                GetOptions() : 0,
872                                GetSortAlgorithm() );
873 
874 	aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
875 
876 	// find the first layout node for this TOX, if it only find the content
877 	// in his own chapter
878 	const SwTxtNode* pOwnChapterNode = IsFromChapter()
879 			? ::lcl_FindChapterNode( *pSectNd, 0 )
880 			: 0;
881 
882 	SwNode2Layout aN2L( *pSectNd );
883 	((SwSectionNode*)pSectNd)->DelFrms();
884 
885 	// remove old content an insert one empty textnode (to hold the layout!)
886 	SwTxtNode* pFirstEmptyNd;
887 	{
888 		pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
889 
890 		SwNodeIndex aSttIdx( *pSectNd, +1 );
891 		SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
892 		pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
893 						pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
894 
895 		{
896 			// Task 70995 - save and restore PageDesc and Break Attributes
897 			SwNodeIndex aNxtIdx( aSttIdx );
898 			const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
899 			if( !pCNd )
900 				pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
901             if( pCNd->HasSwAttrSet() )
902 			{
903 				SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
904 				aBrkSet.Put( *pCNd->GetpSwAttrSet() );
905 				if( aBrkSet.Count() )
906                     pFirstEmptyNd->SetAttr( aBrkSet );
907 			}
908 		}
909 		aEndIdx--;
910 		SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
911 		pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
912 
913 		// delete all before
914 		DelFlyInRange( aSttIdx, aEndIdx );
915 		_DelBookmarks( aSttIdx, aEndIdx );
916 
917 		pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
918 
919 	}
920 
921 	//
922 	// insert title of TOX
923 	if( GetTitle().Len() )
924 	{
925 		// then insert the headline section
926 		SwNodeIndex aIdx( *pSectNd, +1 );
927 
928 		SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
929 								GetTxtFmtColl( FORM_TITLE ) );
930         pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
931 
932 		String sNm( GetTOXName() );
933 // ??Resource
934 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
935 
936         SwSectionData headerData( TOX_HEADER_SECTION, sNm );
937 
938 		SwNodeIndex aStt( *pHeadNd ); aIdx--;
939 		SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
940         pDoc->GetNodes().InsertTextSection(
941                 aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
942 	}
943 
944 	// jetzt waere ein prima Zeitpunkt, um die Numerierung zu updaten
945 	pDoc->UpdateNumRule();
946 
947     if( GetCreateType() & nsSwTOXElement::TOX_MARK )
948 		UpdateMarks( aIntl, pOwnChapterNode );
949 
950     if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
951 		UpdateOutline( pOwnChapterNode );
952 
953     if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
954 		UpdateTemplate( pOwnChapterNode );
955 
956     if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
957 			TOX_OBJECTS == SwTOXBase::GetType())
958         UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
959 
960     if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
961 			(TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
962 		UpdateTable( pOwnChapterNode );
963 
964     if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
965 		(TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
966         UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
967 
968 	if( GetSequenceName().Len() && !IsFromObjectNames() &&
969 		(TOX_TABLES == SwTOXBase::GetType() ||
970 		 TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
971 		UpdateSequence( pOwnChapterNode );
972 
973     if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
974         UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
975 
976 	if(TOX_AUTHORITIES == SwTOXBase::GetType())
977 		UpdateAuthorities( aIntl );
978 
979 	// Bei Bedarf Alphadelimitter einfuegen (nur bei Stichwoertern)
980 	//
981 	if( TOX_INDEX == SwTOXBase::GetType() &&
982         ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
983 		InsertAlphaDelimitter( aIntl );
984 
985 	// sortierte Liste aller Verzeichnismarken und Verzeichnisbereiche
986 	void* p = 0;
987 	String* pStr = 0;
988 	sal_uInt16 nCnt = 0, nFormMax = GetTOXForm().GetFormMax();
989 	SvStringsDtor aStrArr( (sal_uInt8)nFormMax );
990 	SvPtrarr aCollArr( (sal_uInt8)nFormMax );
991 	for( ; nCnt < nFormMax; ++nCnt )
992 	{
993 		aCollArr.Insert( p, nCnt );
994 		aStrArr.Insert( pStr, nCnt );
995 	}
996 
997 	SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
998 	for( nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
999 	{
1000 		::SetProgressState( 0, pDoc->GetDocShell() );
1001 
1002 		// setze den Text in das Verzeichniss
1003 		sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
1004 		SwTxtFmtColl* pColl = (SwTxtFmtColl*)aCollArr[ nLvl ];
1005 		if( !pColl )
1006 		{
1007 			pColl = GetTxtFmtColl( nLvl );
1008 			aCollArr.Remove( nLvl );
1009 			p = pColl;
1010 			aCollArr.Insert( p , nLvl );
1011 		}
1012 
1013 		// Generierung: dynamische TabStops setzen
1014 		SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
1015 		aSortArr[ nCnt ]->pTOXNd = pTOXNd;
1016 
1017 		// Generierung: Form auswerten und Platzhalter
1018 		//				fuer die Seitennummer eintragen
1019 		//if it is a TOX_INDEX and the SwForm IsCommaSeparated()
1020 		// then a range of entries must be generated into one paragraph
1021 		sal_uInt16 nRange = 1;
1022 		if(TOX_INDEX == SwTOXBase::GetType() &&
1023 				GetTOXForm().IsCommaSeparated() &&
1024 				aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1025 		{
1026 			const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1027 			const String sPrimKey = rMark.GetPrimaryKey();
1028 			const String sSecKey = rMark.GetSecondaryKey();
1029 			const SwTOXMark* pNextMark = 0;
1030 			while(aSortArr.Count() > (nCnt + nRange)&&
1031 					aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1032 					0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1033 					pNextMark->GetPrimaryKey() == sPrimKey &&
1034 					pNextMark->GetSecondaryKey() == sSecKey)
1035 				nRange++;
1036 		}
1037         // OD 18.03.2003 #106329# - pass node index of table-of-content section
1038         // and default page description to method <GenerateText(..)>.
1039         GenerateText( nCnt, nRange, aStrArr, pSectNd->GetIndex(), pDefaultPageDesc );
1040 		nCnt += nRange - 1;
1041 	}
1042 
1043 	// delete the first dummy node and remove all Cursor into the prev node
1044 	aInsPos = *pFirstEmptyNd;
1045 	{
1046 		SwPaM aCorPam( *pFirstEmptyNd );
1047 		aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
1048 		if( !aCorPam.Move( fnMoveForward ) )
1049 			aCorPam.Move( fnMoveBackward );
1050 		SwNodeIndex aEndIdx( aInsPos, 1 );
1051 		pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
1052 
1053 		// Task 70995 - save and restore PageDesc and Break Attributes
1054         if( pFirstEmptyNd->HasSwAttrSet() )
1055 		{
1056 			if( GetTitle().Len() )
1057 				aEndIdx = *pSectNd;
1058 			else
1059 				aEndIdx = *pFirstEmptyNd;
1060 			SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
1061             if( pCNd ) // Robust against defect documents, e.g. i60336
1062                 pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
1063 		}
1064 	}
1065 
1066 	// now create the new Frames
1067 	sal_uLong nIdx = pSectNd->GetIndex();
1068 	// don't delete if index is empty
1069 	if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1070 		pDoc->GetNodes().Delete( aInsPos, 1 );
1071 
1072 	aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1073 	std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1074 	for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); pLayoutIter++)
1075 	{
1076 		SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
1077 	}//swmod 080310
1078 
1079 	SetProtect( SwTOXBase::IsProtected() );
1080 }
1081 
1082 /*--------------------------------------------------------------------
1083 	 Beschreibung: AlphaDelimitter einfuegen
1084  --------------------------------------------------------------------*/
1085 
1086 
1087 void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1088 {
1089 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1090 	String sDeli, sLastDeli;
1091 	sal_uInt16	i = 0;
1092 	while( i < aSortArr.Count() )
1093 	{
1094 		::SetProgressState( 0, pDoc->GetDocShell() );
1095 
1096 		sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1097 
1098 		// Alpha-Delimitter ueberlesen
1099 		if( nLevel == FORM_ALPHA_DELIMITTER )
1100 			continue;
1101 
1102         String sMyString, sMyStringReading;
1103         aSortArr[i]->GetTxt( sMyString, sMyStringReading );
1104 
1105         sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
1106                                    aSortArr[i]->GetLocale() );
1107 
1108 		// Delimitter schon vorhanden ??
1109 		if( sDeli.Len() && sLastDeli != sDeli )
1110 		{
1111 			// alle kleiner Blank wollen wir nicht haben -> sind Sonderzeichen
1112 			if( ' ' <= sDeli.GetChar( 0 ) )
1113 			{
1114                 SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
1115                                                      rIntl, aSortArr[i]->GetLocale() );
1116 				aSortArr.Insert( pCst, i++ );
1117 			}
1118 			sLastDeli = sDeli;
1119 		}
1120 
1121 		// Skippen bis gleibhes oder kleineres Level erreicht ist
1122 		do {
1123 			i++;
1124 		} while (i < aSortArr.Count() && aSortArr[i]->GetLevel() > nLevel);
1125 	}
1126 }
1127 
1128 /*--------------------------------------------------------------------
1129 	 Beschreibung: Template  auswerten
1130  --------------------------------------------------------------------*/
1131 
1132 SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
1133 {
1134 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1135 	const String& rName = GetTOXForm().GetTemplate( nLevel );
1136 	SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
1137 	if( !pColl )
1138 	{
1139         sal_uInt16 nPoolFmt = 0;
1140 		const TOXTypes eMyType = SwTOXBase::GetType();
1141 		switch( eMyType )
1142 		{
1143 		case TOX_INDEX:			nPoolFmt = RES_POOLCOLL_TOX_IDXH; 		break;
1144 		case TOX_USER:
1145 			if( nLevel < 6 )
1146 				nPoolFmt = RES_POOLCOLL_TOX_USERH;
1147 			else
1148 				nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
1149 			break;
1150 		case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; 	break;
1151 		case TOX_OBJECTS:		nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; 	break;
1152 		case TOX_TABLES:		nPoolFmt = RES_POOLCOLL_TOX_TABLESH; 	break;
1153 		case TOX_AUTHORITIES:	nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1154 
1155 		case TOX_CONTENT:
1156 			// im Content Bereich gibt es einen Sprung!
1157 			if( nLevel < 6 )
1158 				nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
1159 			else
1160 				nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
1161 			break;
1162 		}
1163 
1164 		if(eMyType == TOX_AUTHORITIES && nLevel)
1165 			nPoolFmt = nPoolFmt + 1;
1166 		else if(eMyType == TOX_INDEX && nLevel)
1167 		{
1168 			//pool: Level 1,2,3, Delimiter
1169 			//SwForm: Delimiter, Level 1,2,3
1170 			nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1171 		}
1172 		else
1173 			nPoolFmt = nPoolFmt + nLevel;
1174 		pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
1175 	}
1176 	return pColl;
1177 }
1178 
1179 
1180 /*--------------------------------------------------------------------
1181 	 Beschreibung: Aus Markierungen erzeugen
1182  --------------------------------------------------------------------*/
1183 
1184 void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1185 									const SwTxtNode* pOwnChapterNode )
1186 {
1187 	const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
1188 	if( !pType->GetDepends() )
1189 		return;
1190 
1191 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1192 	TOXTypes eTOXTyp = GetTOXType()->GetType();
1193 	SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1194 
1195 	SwTxtTOXMark* pTxtMark;
1196 	SwTOXMark* pMark;
1197 	for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1198 	{
1199 		::SetProgressState( 0, pDoc->GetDocShell() );
1200 
1201 		if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1202 			0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
1203 		{
1204 			const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
1205 			// nur TOXMarks einfuegen die im Doc stehen
1206 			// nicht die, die im UNDO stehen
1207 			//
1208 			// if selected use marks from the same chapter only
1209 			if( pTOXSrc->GetNodes().IsDocNodes() &&
1210 				pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
1211                 pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1212                (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1213                !pTOXSrc->HasHiddenParaField() &&
1214                !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
1215 			{
1216 				SwTOXSortTabBase* pBase = 0;
1217 				if(TOX_INDEX == eTOXTyp)
1218 				{
1219 					// Stichwortverzeichnismarkierung
1220                     lang::Locale aLocale;
1221                     if ( pBreakIt->GetBreakIter().is() )
1222                     {
1223                         aLocale = pBreakIt->GetLocale(
1224                                         pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
1225                     }
1226 
1227 					pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1228                                             GetOptions(), FORM_ENTRY, rIntl, aLocale );
1229 					InsertSorted(pBase);
1230                     if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1231 						pTxtMark->GetTOXMark().GetPrimaryKey().Len())
1232 					{
1233 						pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1234                                                 GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1235 						InsertSorted(pBase);
1236 						if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
1237 						{
1238 							pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1239                                                     GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1240 							InsertSorted(pBase);
1241 						}
1242 					}
1243 				}
1244 				else if( TOX_USER == eTOXTyp ||
1245 					pMark->GetLevel() <= GetLevel())
1246 				{	// Inhaltsberzeichnismarkierung
1247 					// also used for user marks
1248 					pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
1249 					InsertSorted(pBase);
1250 				}
1251 			}
1252 		}
1253 	}
1254 }
1255 
1256 
1257 /*--------------------------------------------------------------------
1258 	 Beschreibung:	Verzeichnisinhalt aus Gliederungsebene generieren
1259  --------------------------------------------------------------------*/
1260 
1261 
1262 void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
1263 {
1264 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1265 	SwNodes& rNds = pDoc->GetNodes();
1266 
1267 	const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1268 	for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
1269 	{
1270 		::SetProgressState( 0, pDoc->GetDocShell() );
1271 		SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
1272 		if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
1273 			//sal_uInt16(pTxtNd->GetTxtColl()->GetOutlineLevel()+1) <= GetLevel() &&	//#outline level,zhaojianwei
1274 			sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() &&	//<-end,zhaojianwei
1275 			pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1276            !pTxtNd->HasHiddenParaField() &&
1277            !pTxtNd->HasHiddenCharAttribute( true ) &&
1278             ( !IsFromChapter() ||
1279 			   ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
1280 		{
1281             SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1282 			InsertSorted( pNew );
1283 		}
1284 	}
1285 }
1286 
1287 /*--------------------------------------------------------------------
1288 	 Beschreibung: Verzeichnisinhalt aus Vorlagenbereichen generieren
1289  --------------------------------------------------------------------*/
1290 
1291 void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
1292 {
1293 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1294 	for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1295 	{
1296 		String sTmpStyleNames = GetStyleNames(i);
1297 		sal_uInt16 nTokenCount = sTmpStyleNames.GetTokenCount(TOX_STYLE_DELIMITER);
1298 		for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
1299 		{
1300 			SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
1301 									sTmpStyleNames.GetToken( nStyle,
1302 													TOX_STYLE_DELIMITER ));
1303 			//TODO: no outline Collections in content indexes if OutlineLevels are already included
1304 			if( !pColl ||
1305 				( TOX_CONTENT == SwTOXBase::GetType() &&
1306                   GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1307 				  //NO_NUMBERING != pColl->GetOutlineLevel() ) )//#outline level,zhaojianwei
1308 					pColl->IsAssignedToListLevelOfOutlineStyle()) )//<-end,zhaojianwei
1309 				  continue;
1310 
1311 			SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
1312 			for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
1313 			{
1314 				::SetProgressState( 0, pDoc->GetDocShell() );
1315 
1316 				if( pTxtNd->GetTxt().Len() && pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1317 					pTxtNd->GetNodes().IsDocNodes() &&
1318 					( !IsFromChapter() || pOwnChapterNode ==
1319 						::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
1320 				{
1321                     SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1322 					InsertSorted(pNew);
1323 				}
1324 			}
1325 		}
1326 	}
1327 }
1328 
1329 /* -----------------14.07.99 09:59-------------------
1330 	Description: generate content from sequence fields
1331  --------------------------------------------------*/
1332 void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
1333 {
1334 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1335 	SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
1336 	if(!pSeqFld)
1337 		return;
1338 
1339 	SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
1340 	for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1341 	{
1342 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1343 		if(!pTxtFld)
1344 			continue;
1345 		const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1346 		::SetProgressState( 0, pDoc->GetDocShell() );
1347 
1348 		if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1349 			rTxtNode.GetNodes().IsDocNodes() &&
1350 			( !IsFromChapter() ||
1351 				::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
1352 		{
1353             SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
1354 			//set indexes if the number or the reference text are to be displayed
1355 			if( GetCaptionDisplay() == CAPTION_TEXT )
1356 			{
1357 				pNew->SetStartIndex(
1358 					SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
1359 			}
1360 			else if(GetCaptionDisplay() == CAPTION_NUMBER)
1361 			{
1362 				pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
1363 			}
1364 			InsertSorted(pNew);
1365 		}
1366 	}
1367 }
1368 
1369 void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1370 {
1371 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1372 	SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
1373 	if(!pAuthFld)
1374 		return;
1375 
1376 	SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
1377 	for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1378 	{
1379 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1380 		//undo
1381 		if(!pTxtFld)
1382 			continue;
1383 		const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1384 		::SetProgressState( 0, pDoc->GetDocShell() );
1385 
1386 //		const SwTxtNode* pChapterCompareNode = 0;
1387 
1388 		if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1389 			rTxtNode.GetNodes().IsDocNodes() /*&&
1390 			(!IsFromChapter() || pChapterCompareNode == pOwnChapterNode) */)
1391 		{
1392             //#106485# the body node has to be used!
1393             SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
1394             SwPosition aFldPos(rTxtNode);
1395             const SwTxtNode* pTxtNode = 0;
1396             if(pFrm && !pFrm->IsInDocBody())
1397                 pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
1398             if(!pTxtNode)
1399                 pTxtNode = &rTxtNode;
1400             SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
1401 
1402 			InsertSorted(pNew);
1403 		}
1404 	}
1405 }
1406 
1407 long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1408 {
1409 	static struct _SoObjType {
1410 		long nFlag;
1411 		// GlobalNameId
1412 		struct _GlobalNameIds {
1413 			sal_uInt32 n1;
1414 			sal_uInt16 n2, n3;
1415 			sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1416         } aGlNmIds[4];
1417 	} aArr[] = {
1418         { nsSwTOOElements::TOO_MATH,
1419           { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1420             {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1421         { nsSwTOOElements::TOO_CHART,
1422           { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1423             {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1424         { nsSwTOOElements::TOO_CALC,
1425           { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1426             {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1427         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1428           { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1429             {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1430         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1431           { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1432         { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1433             {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1434 	};
1435 
1436 	long nRet = 0;
1437 	for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1438         for ( int n = 0; n < 4; ++n )
1439 		{
1440 			const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1441 			if( !rId.n1 )
1442 				break;
1443 			SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1444 						rId.b8, rId.b9, rId.b10, rId.b11,
1445 						rId.b12, rId.b13, rId.b14, rId.b15 );
1446 			if( rFactoryNm == aGlbNm )
1447 			{
1448 				nRet = pArr->nFlag;
1449 				break;
1450 			}
1451 		}
1452 
1453 	return nRet;
1454 }
1455 
1456 void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
1457 									const SwTxtNode* pOwnChapterNode )
1458 {
1459 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1460 	SwNodes& rNds = pDoc->GetNodes();
1461 	// auf den 1. Node der 1. Section
1462 	sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1463 		 nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1464 
1465 	while( nIdx < nEndIdx )
1466 	{
1467 		::SetProgressState( 0, pDoc->GetDocShell() );
1468 
1469 		SwNode* pNd = rNds[ nIdx ];
1470 		SwCntntNode* pCNd = 0;
1471 		switch( eMyType )
1472 		{
1473         case nsSwTOXElement::TOX_FRAME:
1474 			if( !pNd->IsNoTxtNode() )
1475 			{
1476 				pCNd = pNd->GetCntntNode();
1477 				if( !pCNd )
1478 				{
1479 					SwNodeIndex aTmp( *pNd );
1480 					pCNd = rNds.GoNext( &aTmp );
1481 				}
1482 			}
1483 			break;
1484         case nsSwTOXElement::TOX_GRAPHIC:
1485 			if( pNd->IsGrfNode() )
1486 				pCNd = (SwCntntNode*)pNd;
1487 			break;
1488         case nsSwTOXElement::TOX_OLE:
1489 			if( pNd->IsOLENode() )
1490 			{
1491 				sal_Bool bInclude = sal_True;
1492 				if(TOX_OBJECTS == SwTOXBase::GetType())
1493 				{
1494 					SwOLENode* pOLENode = pNd->GetOLENode();
1495 					long nMyOLEOptions = GetOLEOptions();
1496 					SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1497 
1498 					if( rOLEObj.IsOleRef() )	//Noch nicht geladen
1499 					{
1500                         SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1501                         long nObj = ::lcl_IsSOObject( aTmpName );
1502                         bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1503                                                     || (0 != (nMyOLEOptions & nObj));
1504 					}
1505 					else
1506 					{
1507 						DBG_ERROR("OLE-object nicht geladen?");
1508 						bInclude = sal_False;
1509 					}
1510 				}
1511 
1512 				if(bInclude)
1513 					pCNd = (SwCntntNode*)pNd;
1514 			}
1515 			break;
1516         default: break;
1517 		}
1518 
1519 		if( pCNd )
1520 		{
1521 			//find node in body text
1522             int nSetLevel = USHRT_MAX;
1523 
1524             //#111105# tables of tables|illustrations|objects don't support hierarchies
1525             if( IsLevelFromChapter() &&
1526                     TOX_TABLES != SwTOXBase::GetType() &&
1527                     TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1528                     TOX_OBJECTS != SwTOXBase::GetType() )
1529 			{
1530 				const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1531 														MAXLEVEL - 1 );
1532 				if( pOutlNd )
1533 				{
1534 					//sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1535 					//if( nTmp < NO_NUMBERING )
1536 					//	nSetLevel = nTmp + 1;
1537 					if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1538 						nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
1539 				}
1540 			}
1541 
1542 			if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
1543 					::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1544 			{
1545 				SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1546                             ( USHRT_MAX != nSetLevel )
1547                             ? static_cast<sal_uInt16>(nSetLevel)
1548                             : FORM_ALPHA_DELIMITTER );
1549 				InsertSorted( pNew );
1550 			}
1551 		}
1552 
1553         nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2;  // 2 == End-/StartNode
1554 	}
1555 }
1556 
1557 /*--------------------------------------------------------------------
1558 	 Beschreibung:	Tabelleneintraege zusammensuchen
1559  --------------------------------------------------------------------*/
1560 
1561 void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
1562 {
1563 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1564 	SwNodes& rNds = pDoc->GetNodes();
1565 	const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
1566 
1567 	for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
1568 	{
1569 		::SetProgressState( 0, pDoc->GetDocShell() );
1570 
1571 		SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
1572 		SwTableBox* pFBox;
1573 		if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
1574 			pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1575 		{
1576 			const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
1577 			SwNodeIndex aCntntIdx( *pTblNd, 1 );
1578 
1579 			SwCntntNode* pCNd;
1580 			while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
1581 				aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
1582 			{
1583 				if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
1584 					::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1585 				{
1586 					SwTOXTable * pNew = new SwTOXTable( *pCNd );
1587                     if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1588                     {
1589                         const SwTxtNode* pOutlNd =
1590                             ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1591                         if( pOutlNd )
1592                         {
1593 							//sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1594 							//if( nTmp < NO_NUMBERING )
1595 							//	pNew->SetLevel( nTmp + 1 );
1596                             if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1597 							{
1598                                 const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
1599                                 pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
1600 							}
1601                         }
1602                     }
1603                     InsertSorted(pNew);
1604 					break;
1605 				}
1606 			}
1607 		}
1608 	}
1609 }
1610 
1611 /*--------------------------------------------------------------------
1612 	 Beschreibung:	String generieren anhand der Form
1613 					SonderZeichen 0-31 und 255 entfernen
1614  --------------------------------------------------------------------*/
1615 
1616 String lcl_GetNumString( const SwTOXSortTabBase& rBase, sal_Bool bUsePrefix, sal_uInt8 nLevel )
1617 {
1618 	String sRet;
1619 
1620 	if( !rBase.pTxtMark && rBase.aTOXSources.Count() > 0 )
1621 	{	// nur wenn es keine Marke ist
1622 		const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
1623 		if( pNd )
1624 		{
1625 			const SwNumRule* pRule = pNd->GetNumRule();
1626 
1627             if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
1628                 sRet = pNd->GetNumString(bUsePrefix, nLevel);
1629         }
1630 	}
1631 	return sRet;
1632 }
1633 
1634 // OD 18.03.2003 #106329# - add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc>
1635 // in order to control, which page description is used, no appropriate one is found.
1636 void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
1637                                      sal_uInt16 nCount,
1638                                      SvStringsDtor& ,
1639                                      const sal_uInt32   _nTOXSectNdIdx,
1640                                      const SwPageDesc*  _pDefaultPageDesc )
1641 {
1642 	LinkStructArr	aLinkArr;
1643 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1644 	::SetProgressState( 0, pDoc->GetDocShell() );
1645 
1646 	//pTOXNd is only set at the first mark
1647 	SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
1648 	String& rTxt = (String&)pTOXNd->GetTxt();
1649 	rTxt.Erase();
1650 	for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
1651 	{
1652 		if(nIndex > nArrayIdx)
1653 			rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
1654 		// String mit dem Pattern aus der Form initialisieren
1655 		const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
1656 		sal_uInt16 nLvl = rBase.GetLevel();
1657 		ASSERT( nLvl < GetTOXForm().GetFormMax(), "ungueltiges FORM_LEVEL");
1658 
1659         SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1660 		xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
1661         String  sLinkCharacterStyle; //default to "Default" character style - which is none
1662 		String sURL;
1663 		// create an enumerator
1664         // #i21237#
1665         SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
1666         SwFormTokens::iterator aIt = aPattern.begin();
1667 		// remove text from node
1668 		while(aIt != aPattern.end()) // #i21237#
1669 		{
1670 			SwFormToken aToken = *aIt; // #i21237#
1671 			xub_StrLen nStartCharStyle = rTxt.Len();
1672 			switch( aToken.eTokenType )
1673 			{
1674 			case TOKEN_ENTRY_NO:
1675 				// fuer Inhaltsverzeichnis Numerierung
1676                 rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
1677 				break;
1678 
1679 			case TOKEN_ENTRY_TEXT:
1680 				{
1681 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1682 					rBase.FillText( *pTOXNd, aIdx );
1683 				}
1684 				break;
1685 
1686 			case TOKEN_ENTRY:
1687 				{
1688 					// fuer Inhaltsverzeichnis Numerierung
1689 					rTxt.Insert( lcl_GetNumString( rBase, sal_True, MAXLEVEL ));
1690 
1691 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1692 					rBase.FillText( *pTOXNd, aIdx );
1693 				}
1694 				break;
1695 
1696 			case TOKEN_TAB_STOP:
1697                 if (aToken.bWithTab) // #i21237#
1698                     rTxt.Append('\t');
1699 				//
1700 
1701 				if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
1702 				{
1703 					const SvxLRSpaceItem& rLR =
1704                         (SvxLRSpaceItem&)pTOXNd->
1705                         SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
1706 
1707 					long nTabPosition = aToken.nTabStopPosition;
1708 					if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
1709 						nTabPosition -= rLR.GetTxtLeft();
1710 					aTStops.Insert( SvxTabStop( nTabPosition,
1711                                                 aToken.eTabAlign,
1712 												cDfltDecimalChar,
1713 												aToken.cTabFillChar ));
1714 				}
1715 				else
1716 				{
1717 					const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
1718 								SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
1719 
1720 					sal_Bool bCallFindRect = sal_True;
1721 					long nRightMargin;
1722 					if( pPageDesc )
1723 					{
1724 						const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
1725 						if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
1726 							pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
1727 							// dann muss man ueber den PageDesc gehen
1728 							bCallFindRect = sal_False;
1729 					}
1730 
1731 					SwRect aNdRect;
1732 					if( bCallFindRect )
1733 						aNdRect = pTOXNd->FindLayoutRect( sal_True );
1734 
1735 					if( aNdRect.IsEmpty() )
1736 					{
1737 						// dann hilft alles nichts, wir muessen ueber die Seiten-
1738 						// vorlage gehen.
1739                         // OD 18.03.2003 #106329# - call
1740                         sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
1741                         sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
1742                         pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
1743                         if ( !pPageDesc ||
1744                              *pPgDescNdIdx < _nTOXSectNdIdx )
1745                         {
1746                             // use default page description, if none is found
1747                             // or the found one is given by a node before the
1748                             // table-of-content section.
1749                             pPageDesc = _pDefaultPageDesc;
1750                         }
1751 
1752 						const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
1753 						nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
1754 								 		rPgDscFmt.GetLRSpace().GetLeft() -
1755 								 		rPgDscFmt.GetLRSpace().GetRight();
1756 					}
1757 					else
1758 						nRightMargin = aNdRect.Width();
1759                     //#i24363# tab stops relative to indent
1760                     if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
1761                     {
1762                         //left margin of paragraph style
1763                         const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
1764                         nRightMargin -= rLRSpace.GetLeft();
1765                         nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
1766                     }
1767 
1768                     aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
1769 												cDfltDecimalChar,
1770 												aToken.cTabFillChar ));
1771 				}
1772 				break;
1773 
1774 			case TOKEN_TEXT:
1775 				rTxt.Append( aToken.sText );
1776 				break;
1777 
1778 			case TOKEN_PAGE_NUMS:
1779 					// Platzhalter fuer Seitennummer(n) es wird nur der erste beachtet
1780 					//
1781 				{
1782 					// Die Anzahl der gleichen Eintrage bestimmt die Seitennummern-Pattern
1783 					//
1784 					sal_uInt16 nSize = rBase.aTOXSources.Count();
1785 					if( nSize > 0 )
1786 					{
1787 						String aInsStr( cNumRepl );
1788 						for(sal_uInt16 i=1; i < nSize; ++i)
1789 						{
1790 							aInsStr.AppendAscii( sPageDeli );
1791 							aInsStr += cNumRepl;
1792 						}
1793 						aInsStr += cEndPageNum;
1794 						rTxt.Append( aInsStr );
1795 					}
1796 //						// Tab entfernen, wenn keine Seitennummer
1797 //					else if( rTxt.Len() && '\t' == rTxt.GetChar( rTxt.Len() - 1 ))
1798 //						rTxt.Erase( rTxt.Len()-1, 1 );
1799 				}
1800 				break;
1801 
1802 			case TOKEN_CHAPTER_INFO:
1803 				{
1804 					// ein bischen trickreich: suche irgend einen Frame
1805 					const SwTOXSource* pTOXSource = 0;
1806 					if(rBase.aTOXSources.Count())
1807 						pTOXSource = &rBase.aTOXSources[0];
1808 
1809                     // --> OD 2008-02-14 #i53420#
1810 //                    if( pTOXSource && pTOXSource->pNd
1811 //                        pTOXSource->pNd->IsTxtNode() )
1812                     if ( pTOXSource && pTOXSource->pNd &&
1813                          pTOXSource->pNd->IsCntntNode() )
1814                     // <--
1815 					{
1816 						const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1817 						if( pFrm )
1818 						{
1819 							SwChapterFieldType aFldTyp;
1820 							SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
1821                             aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
1822                             // --> OD 2008-02-14 #i53420#
1823 //                            aFld.ChangeExpansion( pFrm, (SwTxtNode*)pTOXSource->pNd, sal_True );
1824                             aFld.ChangeExpansion( pFrm,
1825                                 dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
1826                                 sal_True );
1827                             // <--
1828                             //---> i89791
1829                             // OD 2008-06-26 - continue to support CF_NUMBER
1830                             // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
1831                             // written by OOo 3.x in the same way as OOo 2.x
1832                             // would handle them.
1833                             if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
1834                                  CF_NUMBER == aToken.nChapterFormat )
1835                                 rTxt.Insert(aFld.GetNumber()); //get the string number without pre/postfix
1836                             else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
1837                                       CF_NUM_TITLE == aToken.nChapterFormat )
1838                             //<---
1839 							{
1840 								rTxt += aFld.GetNumber();
1841 								rTxt += ' ';
1842 								rTxt += aFld.GetTitle();
1843 							}
1844 							else if(CF_TITLE == aToken.nChapterFormat)
1845 								rTxt += aFld.GetTitle();
1846 						}
1847 					}
1848 				}
1849 				break;
1850 
1851 			case TOKEN_LINK_START:
1852 				nLinkStartPosition = rTxt.Len();
1853                 sLinkCharacterStyle = aToken.sCharStyleName;
1854             break;
1855 
1856 			case TOKEN_LINK_END:
1857 					//TODO: only paired start/end tokens are valid
1858 				if( STRING_NOTFOUND != nLinkStartPosition)
1859 				{
1860 					SwIndex aIdx( pTOXNd, nLinkStartPosition );
1861 					//pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
1862 					xub_StrLen nEnd = rTxt.Len();
1863 
1864 					if( !sURL.Len() )
1865 					{
1866 						sURL = rBase.GetURL();
1867 						if( !sURL.Len() )
1868 							break;
1869 					}
1870                     LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
1871                                                     nEnd);
1872                     pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
1873                     pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
1874                     if(sLinkCharacterStyle.Len())
1875                     {
1876                         sal_uInt16 nPoolId =
1877                             SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1878                         pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
1879                         pNewLink->aINetFmt.SetINetFmtId(nPoolId);
1880                     }
1881                     else
1882                     {
1883                         pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
1884                         pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
1885                     }
1886                     aLinkArr.Insert( pNewLink, aLinkArr.Count() );
1887 					nLinkStartPosition = STRING_NOTFOUND;
1888                     sLinkCharacterStyle.Erase();
1889 				}
1890 				break;
1891 
1892 			case TOKEN_AUTHORITY:
1893 				{
1894 					ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
1895 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1896 					rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
1897 				}
1898 				break;
1899             case TOKEN_END: break;
1900 			}
1901 
1902 			if( aToken.sCharStyleName.Len() )
1903 			{
1904 				SwCharFmt* pCharFmt;
1905 				if(	USHRT_MAX != aToken.nPoolId )
1906 					pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
1907 				else
1908 					pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
1909 
1910                 if (pCharFmt)
1911                 {
1912                     SwFmtCharFmt aFmt( pCharFmt );
1913                     pTOXNd->InsertItem( aFmt, nStartCharStyle,
1914                         rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
1915                 }
1916             }
1917 
1918             aIt++; // #i21237#
1919 		}
1920 
1921         pTOXNd->SetAttr( aTStops );
1922 	}
1923 
1924 	if(aLinkArr.Count())
1925 		for(sal_uInt16 i = 0; i < aLinkArr.Count(); ++i )
1926 		{
1927 			LinkStruct* pTmp = aLinkArr.GetObject(i);
1928             pTOXNd->InsertItem( pTmp->aINetFmt, pTmp->nStartTextPos,
1929 							pTmp->nEndTextPos);
1930 		}
1931 }
1932 
1933 /*--------------------------------------------------------------------
1934 	 Beschreibung: Seitennummer errechnen und nach dem Formatieren
1935 				   eintragen
1936  --------------------------------------------------------------------*/
1937 
1938 void SwTOXBaseSection::UpdatePageNum()
1939 {
1940 	if( !aSortArr.Count() )
1941 		return ;
1942 
1943 	// die aktuellen Seitennummern ins Verzeichnis eintragen
1944 	SwPageFrm*	pAktPage	= 0;
1945 	sal_uInt16		nPage		= 0;
1946 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1947 
1948     SwTOXInternational aIntl( GetLanguage(),
1949                               TOX_INDEX == GetTOXType()->GetType() ?
1950                               GetOptions() : 0,
1951                               GetSortAlgorithm() );
1952 
1953 	for( sal_uInt16 nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
1954 	{
1955 		// Schleife ueber alle SourceNodes
1956 		SvUShorts aNums;		//Die Seitennummern
1957 		SvPtrarr  aDescs;		//Die PageDescriptoren passend zu den Seitennummern.
1958 		SvUShorts* pMainNums = 0; // contains page numbers of main entries
1959 
1960 		// process run in lines
1961 		sal_uInt16 nRange = 0;
1962 		if(GetTOXForm().IsCommaSeparated() &&
1963 				aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1964 		{
1965 			const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1966 			const String sPrimKey = rMark.GetPrimaryKey();
1967 			const String sSecKey = rMark.GetSecondaryKey();
1968 			const SwTOXMark* pNextMark = 0;
1969 			while(aSortArr.Count() > (nCnt + nRange)&&
1970 					aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1971 					0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1972 					pNextMark->GetPrimaryKey() == sPrimKey &&
1973 					pNextMark->GetSecondaryKey() == sSecKey)
1974 				nRange++;
1975 		}
1976 		else
1977 			nRange = 1;
1978 
1979 		for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
1980 		{
1981 			SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
1982 			sal_uInt16 nSize = pSortBase->aTOXSources.Count();
1983 			sal_uInt16 i;
1984 			for( sal_uInt16 j = 0; j < nSize; ++j )
1985 			{
1986 				::SetProgressState( 0, pDoc->GetDocShell() );
1987 
1988 				SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1989 				if( rTOXSource.pNd )
1990 				{
1991 					SwCntntFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1992                     ASSERT( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
1993                     if( !pFrm )
1994                         continue;
1995 					if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
1996 					{
1997 						// dann suche den richtigen heraus
1998 						SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
1999 						while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
2000 								&& rTOXSource.nPos >= pNext->GetOfst() )
2001 							pFrm = pNext;
2002 					}
2003 
2004 					SwPageFrm*	pTmpPage = pFrm->FindPageFrm();
2005 					if( pTmpPage != pAktPage )
2006 					{
2007 						nPage		= pTmpPage->GetVirtPageNum();
2008 						pAktPage	= pTmpPage;
2009 					}
2010 
2011 					// sortiert einfuegen
2012 					for( i = 0; i < aNums.Count() && aNums[i] < nPage; ++i )
2013 						;
2014 
2015 					if( i >= aNums.Count() || aNums[ i ] != nPage )
2016 					{
2017 						aNums.Insert( nPage, i );
2018 						aDescs.Insert( (void*)pAktPage->GetPageDesc(), i );
2019 					}
2020 					// is it a main entry?
2021 					if(TOX_SORT_INDEX == pSortBase->GetType() &&
2022 						rTOXSource.bMainEntry)
2023 					{
2024 						if(!pMainNums)
2025 							pMainNums = new SvUShorts;
2026 						pMainNums->Insert(nPage, pMainNums->Count());
2027 					}
2028 				}
2029 			}
2030 			// einfuegen der Seitennummer in den Verzeichnis-Text-Node
2031 			const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
2032 			if(pBase->pTOXNd)
2033 			{
2034 				const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
2035 				ASSERT( pTxtNd, "kein TextNode, falsches Verzeichnis" );
2036 
2037 				_UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
2038 								aIntl );
2039 			}
2040 			DELETEZ(pMainNums);
2041 			aNums.Remove(0, aNums.Count());
2042 		}
2043 	}
2044 	// nach dem Setzen der richtigen Seitennummer, das Mapping-Array
2045 	// wieder loeschen !!
2046 	aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
2047 }
2048 
2049 
2050 /*--------------------------------------------------------------------
2051 	 Beschreibung: Austausch der Seitennummer-Platzhalter
2052  --------------------------------------------------------------------*/
2053 
2054 // search for the page no in the array of main entry page numbers
2055 sal_Bool lcl_HasMainEntry( const SvUShorts* pMainEntryNums, sal_uInt16 nToFind )
2056 {
2057 	for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->Count(); ++i)
2058 		if(nToFind == (*pMainEntryNums)[i])
2059 			return sal_True;
2060 	return sal_False;
2061 }
2062 
2063 void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
2064 									const SvUShorts& rNums,
2065 									const SvPtrarr & rDescs,
2066 									const SvUShorts* pMainEntryNums,
2067 									const SwTOXInternational& rIntl )
2068 {
2069 	//collect starts end ends of main entry character style
2070 	SvUShorts* pCharStyleIdx = pMainEntryNums ? new SvUShorts : 0;
2071 
2072 	String sSrchStr( cNumRepl );
2073 	sSrchStr.AppendAscii( sPageDeli ) += cNumRepl;
2074 	xub_StrLen nStartPos = pNd->GetTxt().Search( sSrchStr );
2075 	( sSrchStr = cNumRepl ) += cEndPageNum;
2076 	xub_StrLen nEndPos = pNd->GetTxt().Search( sSrchStr );
2077 	sal_uInt16 i;
2078 
2079 	if( STRING_NOTFOUND == nEndPos || !rNums.Count() )
2080 		return;
2081 
2082 	if( STRING_NOTFOUND == nStartPos || nStartPos > nEndPos)
2083 		nStartPos = nEndPos;
2084 
2085 	sal_uInt16 nOld = rNums[0],
2086 		   nBeg = nOld,
2087 		   nCount  = 0;
2088 	String aNumStr( SvxNumberType( ((SwPageDesc*)rDescs[0])->GetNumType() ).
2089 					GetNumStr( nBeg ) );
2090 	if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
2091 	{
2092 		sal_uInt16 nTemp = 0;
2093 		pCharStyleIdx->Insert( nTemp, pCharStyleIdx->Count());
2094 	}
2095 
2096 	// Platzhalter loeschen
2097 	SwIndex aPos(pNd, nStartPos);
2098 	SwCharFmt* pPageNoCharFmt = 0;
2099 	SwpHints* pHints = pNd->GetpSwpHints();
2100 	if(pHints)
2101 		for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
2102 		{
2103 			SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
2104 			xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
2105 			if(	nStartPos >= *pAttr->GetStart() &&
2106 				(nStartPos + 2) <= nTmpEnd &&
2107 				pAttr->Which() == RES_TXTATR_CHARFMT)
2108 			{
2109 				pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
2110 				break;
2111 			}
2112 		}
2113     pNd->EraseText(aPos, nEndPos - nStartPos + 2);
2114 
2115 	for( i = 1; i < rNums.Count(); ++i)
2116 	{
2117 		SvxNumberType aType( ((SwPageDesc*)rDescs[i])->GetNumType() );
2118 		if( TOX_INDEX == SwTOXBase::GetType() )
2119 		{	// Zusammenfassen f. ff.
2120 			// Alle folgenden aufaddieren
2121 			// break up if main entry starts or ends and
2122 			// insert a char style index
2123 			sal_Bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
2124 					!= lcl_HasMainEntry(pMainEntryNums, rNums[i]);
2125 
2126 			if(nOld == rNums[i]-1 && !bMainEntryChanges &&
2127                 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
2128 				nCount++;
2129 			else
2130 			{
2131 				// ff. f. alten Wert flushen
2132                 if(GetOptions() & nsSwTOIOptions::TOI_FF)
2133 				{
2134 					if ( nCount >= 1 )
2135 						aNumStr += rIntl.GetFollowingText( nCount > 1 );
2136 				}
2137 				else
2138 				{
2139 					if(nCount >= 2 )
2140 						aNumStr += '-';
2141 					else if(nCount == 1 )
2142 						aNumStr.AppendAscii( sPageDeli );
2143 //#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
2144 					if(nCount)
2145 						aNumStr += aType.GetNumStr( nBeg + nCount );
2146 				}
2147 
2148 				// neuen String anlegen
2149 				nBeg	 = rNums[i];
2150 				aNumStr.AppendAscii( sPageDeli );
2151 				//the change of the character style must apply after sPageDeli is appended
2152 				if(pCharStyleIdx && bMainEntryChanges)
2153 					pCharStyleIdx->Insert(aNumStr.Len(),
2154 													pCharStyleIdx->Count());
2155 				aNumStr += aType.GetNumStr( nBeg );
2156 				nCount	 = 0;
2157 			}
2158 			nOld = rNums[i];
2159 		}
2160 		else
2161 		{	// Alle Nummern eintragen
2162 			aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
2163 			if(i != (rNums.Count()-1))
2164 				aNumStr.AppendAscii( sPageDeli );
2165 		}
2166 	}
2167 	// Bei Ende und ff. alten Wert flushen
2168 	if( TOX_INDEX == SwTOXBase::GetType() )
2169 	{
2170         if(GetOptions() & nsSwTOIOptions::TOI_FF)
2171 		{
2172 			if( nCount >= 1 )
2173 				aNumStr += rIntl.GetFollowingText( nCount > 1 );
2174 		}
2175 		else
2176 		{
2177 			if(nCount >= 2)
2178 				aNumStr +='-';
2179 			else if(nCount == 1)
2180 				aNumStr.AppendAscii( sPageDeli );
2181 //#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
2182 			if(nCount)
2183 				aNumStr += SvxNumberType( ((SwPageDesc*)rDescs[i-1])->
2184 								GetNumType() ).GetNumStr( nBeg+nCount );
2185 		}
2186 	}
2187     pNd->InsertText( aNumStr, aPos,
2188            static_cast<IDocumentContentOperations::InsertFlags>(
2189                IDocumentContentOperations::INS_EMPTYEXPAND |
2190                IDocumentContentOperations::INS_FORCEHINTEXPAND) );
2191 	if(pPageNoCharFmt)
2192 	{
2193         SwFmtCharFmt aCharFmt( pPageNoCharFmt );
2194         pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
2195     }
2196 
2197 	//now the main entries should get there character style
2198 	if(pCharStyleIdx && pCharStyleIdx->Count() && GetMainEntryCharStyle().Len())
2199 	{
2200 		// eventually the last index must me appended
2201 		if(pCharStyleIdx->Count()&0x01)
2202 			pCharStyleIdx->Insert(aNumStr.Len(), pCharStyleIdx->Count());
2203 
2204 		//search by name
2205 		SwDoc* pDoc = pNd->GetDoc();
2206 		sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
2207 		SwCharFmt* pCharFmt = 0;
2208 		if(USHRT_MAX != nPoolId)
2209 			pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
2210 		else
2211 			pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
2212 		if(!pCharFmt)
2213 			pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
2214 
2215 		//find the page numbers in aNumStr and set the character style
2216 		xub_StrLen nOffset = pNd->GetTxt().Len() - aNumStr.Len();
2217 		SwFmtCharFmt aCharFmt(pCharFmt);
2218 		for(sal_uInt16 j = 0; j < pCharStyleIdx->Count(); j += 2)
2219 		{
2220 			xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
2221 			xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1]  + nOffset;
2222             pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
2223 		}
2224 
2225 	}
2226 	delete pCharStyleIdx;
2227 }
2228 
2229 
2230 /*--------------------------------------------------------------------
2231 	 Beschreibung: Sortiert einfuegen in das SortArr
2232  --------------------------------------------------------------------*/
2233 
2234 void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
2235 {
2236 	Range aRange(0, aSortArr.Count());
2237 	if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
2238 	{
2239 		const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
2240 		// Schluessel auswerten
2241 		// Den Bereich ermitteln, in dem einzufuegen ist
2242         if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
2243 			rMark.GetPrimaryKey().Len() )
2244 		{
2245             aRange = GetKeyRange( rMark.GetPrimaryKey(),
2246                                   rMark.GetPrimaryKeyReading(),
2247                                   *pNew, FORM_PRIMARY_KEY, aRange );
2248 
2249             if( rMark.GetSecondaryKey().Len() )
2250                 aRange = GetKeyRange( rMark.GetSecondaryKey(),
2251                                       rMark.GetSecondaryKeyReading(),
2252                                       *pNew, FORM_SECONDARY_KEY, aRange );
2253 		}
2254 	}
2255 	//search for identical entries and remove the trailing one
2256 	if(TOX_AUTHORITIES == SwTOXBase::GetType())
2257 	{
2258 		for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2259 		{
2260 			SwTOXSortTabBase* pOld = aSortArr[i];
2261 			if(*pOld == *pNew)
2262 			{
2263 				if(*pOld < *pNew)
2264 				{
2265 					delete pNew;
2266 					return;
2267 				}
2268 				else
2269 				{
2270 					// remove the old content
2271 					aSortArr.DeleteAndDestroy( i, 1 );
2272 					aRange.Max()--;
2273 					break;
2274 				}
2275 			}
2276 		}
2277 	}
2278 
2279 	// find position and insert
2280 	//
2281 	short i;
2282 
2283 	for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2284 	{	// nur auf gleicher Ebene pruefen
2285 		//
2286 		SwTOXSortTabBase* pOld = aSortArr[i];
2287 		if(*pOld == *pNew)
2288 		{
2289 			if(TOX_AUTHORITIES != SwTOXBase::GetType())
2290 			{
2291 				// Eigener Eintrag fuer Doppelte oder Keywords
2292 				//
2293 				if( pOld->GetType() == TOX_SORT_CUSTOM &&
2294                     pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
2295 					continue;
2296 
2297                 if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
2298 				{	// Eigener Eintrag
2299 					aSortArr.Insert(pNew, i );
2300 					return;
2301 				}
2302 				// Eintrag schon vorhanden in Referenzliste aufnehmen
2303 				pOld->aTOXSources.Insert( pNew->aTOXSources[0],
2304 											pOld->aTOXSources.Count() );
2305 
2306 				delete pNew;
2307 				return;
2308 			}
2309 #ifdef DBG_UTIL
2310 			else
2311 				DBG_ERROR("Bibliography entries cannot be found here");
2312 #endif
2313 		}
2314 		if(*pNew < *pOld)
2315 			break;
2316 	}
2317 	// SubLevel Skippen
2318 	while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
2319 		  aSortArr[i]->GetLevel() > pNew->GetLevel() )
2320 		i++;
2321 
2322 	// An Position i wird eingefuegt
2323 	aSortArr.Insert(pNew, i );
2324 }
2325 
2326 /*--------------------------------------------------------------------
2327 	 Beschreibung: Schluessel-Bereich suchen und evtl einfuegen
2328  --------------------------------------------------------------------*/
2329 
2330 Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
2331                                     const SwTOXSortTabBase& rNew,
2332                                     sal_uInt16 nLevel, const Range& rRange )
2333 {
2334     const SwTOXInternational& rIntl = *rNew.pTOXIntl;
2335 	String sToCompare(rStr);
2336     String sToCompareReading(rStrReading);
2337 
2338     if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
2339 	{
2340 		String sUpper( rIntl.ToUpper( sToCompare, 0 ));
2341 		sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
2342 	}
2343 
2344 	ASSERT(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
2345 
2346 	const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
2347 	const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
2348 
2349     sal_uInt16 i;
2350 
2351 	for( i = nMin; i < nMax; ++i)
2352 	{
2353 		SwTOXSortTabBase* pBase = aSortArr[i];
2354 
2355         String sMyString, sMyStringReading;
2356         pBase->GetTxt( sMyString, sMyStringReading );
2357 
2358         if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
2359                            sToCompare, sToCompareReading, rNew.GetLocale() )  &&
2360                     pBase->GetLevel() == nLevel )
2361 			break;
2362 	}
2363 	if(i == nMax)
2364 	{	// Falls nicht vorhanden erzeugen und einfuegen
2365 		//
2366         SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
2367                                              rNew.GetLocale() );
2368 		for(i = nMin; i < nMax; ++i)
2369 		{
2370 			if(nLevel == aSortArr[i]->GetLevel() &&  *pKey < *(aSortArr[i]))
2371 				break;
2372 		}
2373 		aSortArr.Insert(pKey, i );
2374 	}
2375 	sal_uInt16 nStart = i+1;
2376 	sal_uInt16 nEnd   = aSortArr.Count();
2377 
2378 	// Ende des Bereiches suchen
2379 	for(i = nStart; i < aSortArr.Count(); ++i)
2380 	{
2381 		if(aSortArr[i]->GetLevel() <= nLevel)
2382 		{	nEnd = i;
2383 			break;
2384 		}
2385 	}
2386 	return Range(nStart, nEnd);
2387 }
2388 
2389 
2390 sal_Bool SwTOXBase::IsTOXBaseInReadonly() const
2391 {
2392 	const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2393 	sal_Bool bRet = sal_False;
2394 	const SwSectionNode* pSectNode;
2395 	if(pSect && pSect->GetFmt() &&
2396 			0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
2397 	{
2398 		const SwDocShell* pDocSh;
2399 		bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
2400 													pDocSh->IsReadOnly()) ||
2401             (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
2402 					pSectNode->GetSection().IsProtectFlag());
2403 
2404 	}
2405 	return bRet;
2406 }
2407 
2408 const SfxItemSet* SwTOXBase::GetAttrSet() const
2409 {
2410 	const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2411 	if(pSect && pSect->GetFmt())
2412 		return &pSect->GetFmt()->GetAttrSet();
2413 	return 0;
2414 }
2415 
2416 void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
2417 {
2418 	SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2419 	if( pSect && pSect->GetFmt() )
2420         pSect->GetFmt()->SetFmtAttr( rSet );
2421 }
2422 
2423 sal_Bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
2424 {
2425 	switch( rInfo.Which() )
2426 	{
2427 	case RES_CONTENT_VISIBLE:
2428 		{
2429 			SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2430 			if( pSect && pSect->GetFmt() )
2431 				pSect->GetFmt()->GetInfo( rInfo );
2432 		}
2433 		return sal_False;
2434 	}
2435 	return sal_True;
2436 }
2437 
2438