xref: /aoo41x/main/sw/source/core/doc/doctxm.cxx (revision f66c5aaf)
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     aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );  // i120680
761 }
762 
763 
764 sal_Bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart ) const
765 {
766 	sal_Bool bRet = sal_False;
767 	const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
768 	if( pSectNd )
769 	{
770 		SwCntntNode* pCNd;
771 		xub_StrLen nC = 0;
772 		if( bAtStart )
773 		{
774 			rPos.nNode = *pSectNd;
775 			pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
776 		}
777 		else
778 		{
779 			rPos.nNode = *pSectNd->EndOfSectionNode();
780 			pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
781 			if( pCNd ) nC = pCNd->Len();
782 		}
783 		rPos.nContent.Assign( pCNd, nC );
784 		bRet = sal_True;
785 	}
786 	return bRet;
787 }
788 
789 /*--------------------------------------------------------------------
790 	 Beschreibung: Verzeichnisinhalt zusammensammeln
791  --------------------------------------------------------------------*/
792 
793 void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
794                               const bool        _bNewTOX )//swmodtest 080307
795 {
796     const SwSectionNode* pSectNd;
797     if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
798         !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
799         !pSectNd->GetNodes().IsDocNodes() ||
800         IsHiddenFlag() )
801     {
802         return;
803     }
804 
805     if ( !mbKeepExpression )
806     {
807         maMSTOCExpression = String();
808     }
809 
810     SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
811 
812     DBG_ASSERT(pDoc != NULL, "Where is the document?");
813 
814     if(pAttr && pDoc && GetFmt())
815         pDoc->ChgFmt(*GetFmt(), *pAttr);
816 
817     // OD 18.03.2003 #106329# - determine default page description, which
818     // will be used by the content nodes, if no approriate one is found.
819     const SwPageDesc* pDefaultPageDesc;
820     {
821         pDefaultPageDesc =
822             pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
823         if ( !_bNewTOX && !pDefaultPageDesc )
824         {
825             // determine page description of table-of-content
826             sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
827             sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
828             pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
829             if ( nPgDescNdIdx < pSectNd->GetIndex() )
830             {
831                 pDefaultPageDesc = 0;
832             }
833         }
834         // OD 28.04.2003 #109166# - consider end node of content section in the
835         // node array.
836         if ( !pDefaultPageDesc &&
837              ( pSectNd->EndOfSectionNode()->GetIndex() <
838                  (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
839            )
840         {
841             // determine page description of content after table-of-content
842             SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
843             const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
844             const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
845             const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
846             if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
847                     eBreak == SVX_BREAK_PAGE_BOTH )
848                )
849             {
850                 pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
851             }
852         }
853         // OD 28.04.2003 #109166# - consider start node of content section in
854         // the node array.
855         if ( !pDefaultPageDesc &&
856              ( pSectNd->GetIndex() >
857                  (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
858            )
859         {
860             // determine page description of content before table-of-content
861             SwNodeIndex aIdx( *pSectNd );
862             pDefaultPageDesc =
863                 pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
864 
865         }
866         if ( !pDefaultPageDesc )
867         {
868             // determine default page description
869             pDefaultPageDesc =
870                 &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
871         }
872     }
873 
874     pDoc->SetModified();
875 
876 	// get current Language
877     SwTOXInternational aIntl(  GetLanguage(),
878                                TOX_INDEX == GetTOXType()->GetType() ?
879                                GetOptions() : 0,
880                                GetSortAlgorithm() );
881 
882 	aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
883 
884 	// find the first layout node for this TOX, if it only find the content
885 	// in his own chapter
886 	const SwTxtNode* pOwnChapterNode = IsFromChapter()
887 			? ::lcl_FindChapterNode( *pSectNd, 0 )
888 			: 0;
889 
890 	SwNode2Layout aN2L( *pSectNd );
891 	((SwSectionNode*)pSectNd)->DelFrms();
892 
893 	// remove old content an insert one empty textnode (to hold the layout!)
894 	SwTxtNode* pFirstEmptyNd;
895 	{
896 		pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
897 
898 		SwNodeIndex aSttIdx( *pSectNd, +1 );
899 		SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
900 		pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
901 						pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
902 
903 		{
904 			// Task 70995 - save and restore PageDesc and Break Attributes
905 			SwNodeIndex aNxtIdx( aSttIdx );
906 			const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
907 			if( !pCNd )
908 				pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
909             if( pCNd->HasSwAttrSet() )
910 			{
911 				SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
912 				aBrkSet.Put( *pCNd->GetpSwAttrSet() );
913 				if( aBrkSet.Count() )
914                     pFirstEmptyNd->SetAttr( aBrkSet );
915 			}
916 		}
917 		aEndIdx--;
918 		SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
919 		pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
920 
921 		// delete all before
922 		DelFlyInRange( aSttIdx, aEndIdx );
923 		_DelBookmarks( aSttIdx, aEndIdx );
924 
925 		pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
926 
927 	}
928 
929 	//
930 	// insert title of TOX
931 	if( GetTitle().Len() )
932 	{
933 		// then insert the headline section
934 		SwNodeIndex aIdx( *pSectNd, +1 );
935 
936 		SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
937 								GetTxtFmtColl( FORM_TITLE ) );
938         pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
939 
940 		String sNm( GetTOXName() );
941 // ??Resource
942 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
943 
944         SwSectionData headerData( TOX_HEADER_SECTION, sNm );
945 
946 		SwNodeIndex aStt( *pHeadNd ); aIdx--;
947 		SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
948         pDoc->GetNodes().InsertTextSection(
949                 aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
950 	}
951 
952 	// jetzt waere ein prima Zeitpunkt, um die Numerierung zu updaten
953 	pDoc->UpdateNumRule();
954 
955     if( GetCreateType() & nsSwTOXElement::TOX_MARK )
956 		UpdateMarks( aIntl, pOwnChapterNode );
957 
958     if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
959 		UpdateOutline( pOwnChapterNode );
960 
961     if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
962 		UpdateTemplate( pOwnChapterNode );
963 
964     if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
965 			TOX_OBJECTS == SwTOXBase::GetType())
966         UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
967 
968     if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
969 			(TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
970 		UpdateTable( pOwnChapterNode );
971 
972     if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
973 		(TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
974         UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
975 
976 	if( GetSequenceName().Len() && !IsFromObjectNames() &&
977 		(TOX_TABLES == SwTOXBase::GetType() ||
978 		 TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
979 		UpdateSequence( pOwnChapterNode );
980 
981     if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
982         UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
983 
984 	if(TOX_AUTHORITIES == SwTOXBase::GetType())
985 		UpdateAuthorities( aIntl );
986 
987 	// Bei Bedarf Alphadelimitter einfuegen (nur bei Stichwoertern)
988 	//
989 	if( TOX_INDEX == SwTOXBase::GetType() &&
990         ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
991 		InsertAlphaDelimitter( aIntl );
992 
993 	// sortierte Liste aller Verzeichnismarken und Verzeichnisbereiche
994 	void* p = 0;
995 	String* pStr = 0;
996 	sal_uInt16 nCnt = 0, nFormMax = GetTOXForm().GetFormMax();
997 	SvStringsDtor aStrArr( (sal_uInt8)nFormMax );
998 	SvPtrarr aCollArr( (sal_uInt8)nFormMax );
999 	for( ; nCnt < nFormMax; ++nCnt )
1000 	{
1001 		aCollArr.Insert( p, nCnt );
1002 		aStrArr.Insert( pStr, nCnt );
1003 	}
1004 
1005 	SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
1006 	for( nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
1007 	{
1008 		::SetProgressState( 0, pDoc->GetDocShell() );
1009 
1010 		// setze den Text in das Verzeichniss
1011 		sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
1012 		SwTxtFmtColl* pColl = (SwTxtFmtColl*)aCollArr[ nLvl ];
1013 		if( !pColl )
1014 		{
1015 			pColl = GetTxtFmtColl( nLvl );
1016 			aCollArr.Remove( nLvl );
1017 			p = pColl;
1018 			aCollArr.Insert( p , nLvl );
1019 		}
1020 
1021 		// Generierung: dynamische TabStops setzen
1022 		SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
1023 		aSortArr[ nCnt ]->pTOXNd = pTOXNd;
1024 
1025 		// Generierung: Form auswerten und Platzhalter
1026 		//				fuer die Seitennummer eintragen
1027 		//if it is a TOX_INDEX and the SwForm IsCommaSeparated()
1028 		// then a range of entries must be generated into one paragraph
1029 		sal_uInt16 nRange = 1;
1030 		if(TOX_INDEX == SwTOXBase::GetType() &&
1031 				GetTOXForm().IsCommaSeparated() &&
1032 				aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1033 		{
1034 			const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1035 			const String sPrimKey = rMark.GetPrimaryKey();
1036 			const String sSecKey = rMark.GetSecondaryKey();
1037 			const SwTOXMark* pNextMark = 0;
1038 			while(aSortArr.Count() > (nCnt + nRange)&&
1039 					aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1040 					0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1041 					pNextMark->GetPrimaryKey() == sPrimKey &&
1042 					pNextMark->GetSecondaryKey() == sSecKey)
1043 				nRange++;
1044 		}
1045         // OD 18.03.2003 #106329# - pass node index of table-of-content section
1046         // and default page description to method <GenerateText(..)>.
1047         GenerateText( nCnt, nRange, aStrArr, pSectNd->GetIndex(), pDefaultPageDesc );
1048 		nCnt += nRange - 1;
1049 	}
1050 
1051 	// delete the first dummy node and remove all Cursor into the prev node
1052 	aInsPos = *pFirstEmptyNd;
1053 	{
1054 		SwPaM aCorPam( *pFirstEmptyNd );
1055 		aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
1056 		if( !aCorPam.Move( fnMoveForward ) )
1057 			aCorPam.Move( fnMoveBackward );
1058 		SwNodeIndex aEndIdx( aInsPos, 1 );
1059 		pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
1060 
1061 		// Task 70995 - save and restore PageDesc and Break Attributes
1062         if( pFirstEmptyNd->HasSwAttrSet() )
1063 		{
1064 			if( GetTitle().Len() )
1065 				aEndIdx = *pSectNd;
1066 			else
1067 				aEndIdx = *pFirstEmptyNd;
1068 			SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
1069             if( pCNd ) // Robust against defect documents, e.g. i60336
1070                 pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
1071 		}
1072 	}
1073 
1074 	// now create the new Frames
1075 	sal_uLong nIdx = pSectNd->GetIndex();
1076 	// don't delete if index is empty
1077 	if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1078 		pDoc->GetNodes().Delete( aInsPos, 1 );
1079 
1080 	aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1081 	std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1082 	for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); pLayoutIter++)
1083 	{
1084 		SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
1085 	}//swmod 080310
1086 
1087 	SetProtect( SwTOXBase::IsProtected() );
1088 }
1089 
1090 /*--------------------------------------------------------------------
1091 	 Beschreibung: AlphaDelimitter einfuegen
1092  --------------------------------------------------------------------*/
1093 
1094 
1095 void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1096 {
1097 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1098 	String sDeli, sLastDeli;
1099 	sal_uInt16	i = 0;
1100 	while( i < aSortArr.Count() )
1101 	{
1102 		::SetProgressState( 0, pDoc->GetDocShell() );
1103 
1104 		sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1105 
1106 		// Alpha-Delimitter ueberlesen
1107 		if( nLevel == FORM_ALPHA_DELIMITTER )
1108 			continue;
1109 
1110         String sMyString, sMyStringReading;
1111         aSortArr[i]->GetTxt( sMyString, sMyStringReading );
1112 
1113         sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
1114                                    aSortArr[i]->GetLocale() );
1115 
1116 		// Delimitter schon vorhanden ??
1117 		if( sDeli.Len() && sLastDeli != sDeli )
1118 		{
1119 			// alle kleiner Blank wollen wir nicht haben -> sind Sonderzeichen
1120 			if( ' ' <= sDeli.GetChar( 0 ) )
1121 			{
1122                 SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
1123                                                      rIntl, aSortArr[i]->GetLocale() );
1124 				aSortArr.Insert( pCst, i++ );
1125 			}
1126 			sLastDeli = sDeli;
1127 		}
1128 
1129 		// Skippen bis gleibhes oder kleineres Level erreicht ist
1130 		do {
1131 			i++;
1132 		} while (i < aSortArr.Count() && aSortArr[i]->GetLevel() > nLevel);
1133 	}
1134 }
1135 
1136 /*--------------------------------------------------------------------
1137 	 Beschreibung: Template  auswerten
1138  --------------------------------------------------------------------*/
1139 
1140 SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
1141 {
1142 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1143 	const String& rName = GetTOXForm().GetTemplate( nLevel );
1144 	SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
1145 	if( !pColl )
1146 	{
1147         sal_uInt16 nPoolFmt = 0;
1148 		const TOXTypes eMyType = SwTOXBase::GetType();
1149 		switch( eMyType )
1150 		{
1151 		case TOX_INDEX:			nPoolFmt = RES_POOLCOLL_TOX_IDXH; 		break;
1152 		case TOX_USER:
1153 			if( nLevel < 6 )
1154 				nPoolFmt = RES_POOLCOLL_TOX_USERH;
1155 			else
1156 				nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
1157 			break;
1158 		case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; 	break;
1159 		case TOX_OBJECTS:		nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; 	break;
1160 		case TOX_TABLES:		nPoolFmt = RES_POOLCOLL_TOX_TABLESH; 	break;
1161 		case TOX_AUTHORITIES:	nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1162 
1163 		case TOX_CONTENT:
1164 			// im Content Bereich gibt es einen Sprung!
1165 			if( nLevel < 6 )
1166 				nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
1167 			else
1168 				nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
1169 			break;
1170 		}
1171 
1172 		if(eMyType == TOX_AUTHORITIES && nLevel)
1173 			nPoolFmt = nPoolFmt + 1;
1174 		else if(eMyType == TOX_INDEX && nLevel)
1175 		{
1176 			//pool: Level 1,2,3, Delimiter
1177 			//SwForm: Delimiter, Level 1,2,3
1178 			nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1179 		}
1180 		else
1181 			nPoolFmt = nPoolFmt + nLevel;
1182 		pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
1183 	}
1184 	return pColl;
1185 }
1186 
1187 
1188 /*--------------------------------------------------------------------
1189 	 Beschreibung: Aus Markierungen erzeugen
1190  --------------------------------------------------------------------*/
1191 
1192 void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1193 									const SwTxtNode* pOwnChapterNode )
1194 {
1195 	const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
1196 	if( !pType->GetDepends() )
1197 		return;
1198 
1199 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1200 	TOXTypes eTOXTyp = GetTOXType()->GetType();
1201 	SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1202 
1203 	SwTxtTOXMark* pTxtMark;
1204 	SwTOXMark* pMark;
1205 	for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1206 	{
1207 		::SetProgressState( 0, pDoc->GetDocShell() );
1208 
1209 		if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1210 			0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
1211 		{
1212 			const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
1213 			// nur TOXMarks einfuegen die im Doc stehen
1214 			// nicht die, die im UNDO stehen
1215 			//
1216 			// if selected use marks from the same chapter only
1217 			if( pTOXSrc->GetNodes().IsDocNodes() &&
1218 				pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
1219                 pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1220                (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1221                !pTOXSrc->HasHiddenParaField() &&
1222                !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
1223 			{
1224 				SwTOXSortTabBase* pBase = 0;
1225 				if(TOX_INDEX == eTOXTyp)
1226 				{
1227 					// Stichwortverzeichnismarkierung
1228                     lang::Locale aLocale;
1229                     if ( pBreakIt->GetBreakIter().is() )
1230                     {
1231                         aLocale = pBreakIt->GetLocale(
1232                                         pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
1233                     }
1234 
1235 					pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1236                                             GetOptions(), FORM_ENTRY, rIntl, aLocale );
1237 					InsertSorted(pBase);
1238                     if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1239 						pTxtMark->GetTOXMark().GetPrimaryKey().Len())
1240 					{
1241 						pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1242                                                 GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1243 						InsertSorted(pBase);
1244 						if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
1245 						{
1246 							pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1247                                                     GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1248 							InsertSorted(pBase);
1249 						}
1250 					}
1251 				}
1252 				else if( TOX_USER == eTOXTyp ||
1253 					pMark->GetLevel() <= GetLevel())
1254 				{	// Inhaltsberzeichnismarkierung
1255 					// also used for user marks
1256 					pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
1257 					InsertSorted(pBase);
1258 				}
1259 			}
1260 		}
1261 	}
1262 }
1263 
1264 
1265 /*--------------------------------------------------------------------
1266 	 Beschreibung:	Verzeichnisinhalt aus Gliederungsebene generieren
1267  --------------------------------------------------------------------*/
1268 
1269 
1270 void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
1271 {
1272 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1273 	SwNodes& rNds = pDoc->GetNodes();
1274 
1275 	const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1276 	for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
1277 	{
1278 		::SetProgressState( 0, pDoc->GetDocShell() );
1279 		SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
1280 		if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
1281 			//sal_uInt16(pTxtNd->GetTxtColl()->GetOutlineLevel()+1) <= GetLevel() &&	//#outline level,zhaojianwei
1282 			sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() &&	//<-end,zhaojianwei
1283 			pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1284            !pTxtNd->HasHiddenParaField() &&
1285            !pTxtNd->HasHiddenCharAttribute( true ) &&
1286             ( !IsFromChapter() ||
1287 			   ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
1288 		{
1289             SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1290 			InsertSorted( pNew );
1291 		}
1292 	}
1293 }
1294 
1295 /*--------------------------------------------------------------------
1296 	 Beschreibung: Verzeichnisinhalt aus Vorlagenbereichen generieren
1297  --------------------------------------------------------------------*/
1298 
1299 void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
1300 {
1301 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1302 	for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1303 	{
1304 		String sTmpStyleNames = GetStyleNames(i);
1305 		sal_uInt16 nTokenCount = sTmpStyleNames.GetTokenCount(TOX_STYLE_DELIMITER);
1306 		for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
1307 		{
1308 			SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
1309 									sTmpStyleNames.GetToken( nStyle,
1310 													TOX_STYLE_DELIMITER ));
1311 			//TODO: no outline Collections in content indexes if OutlineLevels are already included
1312 			if( !pColl ||
1313 				( TOX_CONTENT == SwTOXBase::GetType() &&
1314                   GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1315 				  //NO_NUMBERING != pColl->GetOutlineLevel() ) )//#outline level,zhaojianwei
1316 					pColl->IsAssignedToListLevelOfOutlineStyle()) )//<-end,zhaojianwei
1317 				  continue;
1318 
1319 			SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
1320 			for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
1321 			{
1322 				::SetProgressState( 0, pDoc->GetDocShell() );
1323 
1324 				if( pTxtNd->GetTxt().Len() && pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1325 					pTxtNd->GetNodes().IsDocNodes() &&
1326 					( !IsFromChapter() || pOwnChapterNode ==
1327 						::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
1328 				{
1329                     SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1330 					InsertSorted(pNew);
1331 				}
1332 			}
1333 		}
1334 	}
1335 }
1336 
1337 /* -----------------14.07.99 09:59-------------------
1338 	Description: generate content from sequence fields
1339  --------------------------------------------------*/
1340 void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
1341 {
1342 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1343 	SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
1344 	if(!pSeqFld)
1345 		return;
1346 
1347 	SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
1348 	for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1349 	{
1350 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1351 		if(!pTxtFld)
1352 			continue;
1353 		const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1354 		::SetProgressState( 0, pDoc->GetDocShell() );
1355 
1356 		if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1357 			rTxtNode.GetNodes().IsDocNodes() &&
1358 			( !IsFromChapter() ||
1359 				::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
1360 		{
1361             SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
1362 			//set indexes if the number or the reference text are to be displayed
1363 			if( GetCaptionDisplay() == CAPTION_TEXT )
1364 			{
1365 				pNew->SetStartIndex(
1366 					SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
1367 			}
1368 			else if(GetCaptionDisplay() == CAPTION_NUMBER)
1369 			{
1370 				pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
1371 			}
1372 			InsertSorted(pNew);
1373 		}
1374 	}
1375 }
1376 
1377 void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1378 {
1379 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1380 	SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
1381 	if(!pAuthFld)
1382 		return;
1383 
1384 	SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
1385 	for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1386 	{
1387 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1388 		//undo
1389 		if(!pTxtFld)
1390 			continue;
1391 		const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1392 		::SetProgressState( 0, pDoc->GetDocShell() );
1393 
1394 //		const SwTxtNode* pChapterCompareNode = 0;
1395 
1396 		if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1397 			rTxtNode.GetNodes().IsDocNodes() /*&&
1398 			(!IsFromChapter() || pChapterCompareNode == pOwnChapterNode) */)
1399 		{
1400             //#106485# the body node has to be used!
1401             SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
1402             SwPosition aFldPos(rTxtNode);
1403             const SwTxtNode* pTxtNode = 0;
1404             if(pFrm && !pFrm->IsInDocBody())
1405                 pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
1406             if(!pTxtNode)
1407                 pTxtNode = &rTxtNode;
1408             SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
1409 
1410 			InsertSorted(pNew);
1411 		}
1412 	}
1413 }
1414 
1415 long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1416 {
1417 	static struct _SoObjType {
1418 		long nFlag;
1419 		// GlobalNameId
1420 		struct _GlobalNameIds {
1421 			sal_uInt32 n1;
1422 			sal_uInt16 n2, n3;
1423 			sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1424         } aGlNmIds[4];
1425 	} aArr[] = {
1426         { nsSwTOOElements::TOO_MATH,
1427           { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1428             {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1429         { nsSwTOOElements::TOO_CHART,
1430           { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1431             {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1432         { nsSwTOOElements::TOO_CALC,
1433           { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1434             {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1435         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1436           { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1437             {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1438         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1439           { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1440         { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1441             {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1442 	};
1443 
1444 	long nRet = 0;
1445 	for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1446         for ( int n = 0; n < 4; ++n )
1447 		{
1448 			const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1449 			if( !rId.n1 )
1450 				break;
1451 			SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1452 						rId.b8, rId.b9, rId.b10, rId.b11,
1453 						rId.b12, rId.b13, rId.b14, rId.b15 );
1454 			if( rFactoryNm == aGlbNm )
1455 			{
1456 				nRet = pArr->nFlag;
1457 				break;
1458 			}
1459 		}
1460 
1461 	return nRet;
1462 }
1463 
1464 void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
1465 									const SwTxtNode* pOwnChapterNode )
1466 {
1467 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1468 	SwNodes& rNds = pDoc->GetNodes();
1469 	// auf den 1. Node der 1. Section
1470 	sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1471 		 nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1472 
1473 	while( nIdx < nEndIdx )
1474 	{
1475 		::SetProgressState( 0, pDoc->GetDocShell() );
1476 
1477 		SwNode* pNd = rNds[ nIdx ];
1478 		SwCntntNode* pCNd = 0;
1479 		switch( eMyType )
1480 		{
1481         case nsSwTOXElement::TOX_FRAME:
1482 			if( !pNd->IsNoTxtNode() )
1483 			{
1484 				pCNd = pNd->GetCntntNode();
1485 				if( !pCNd )
1486 				{
1487 					SwNodeIndex aTmp( *pNd );
1488 					pCNd = rNds.GoNext( &aTmp );
1489 				}
1490 			}
1491 			break;
1492         case nsSwTOXElement::TOX_GRAPHIC:
1493 			if( pNd->IsGrfNode() )
1494 				pCNd = (SwCntntNode*)pNd;
1495 			break;
1496         case nsSwTOXElement::TOX_OLE:
1497 			if( pNd->IsOLENode() )
1498 			{
1499 				sal_Bool bInclude = sal_True;
1500 				if(TOX_OBJECTS == SwTOXBase::GetType())
1501 				{
1502 					SwOLENode* pOLENode = pNd->GetOLENode();
1503 					long nMyOLEOptions = GetOLEOptions();
1504 					SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1505 
1506 					if( rOLEObj.IsOleRef() )	//Noch nicht geladen
1507 					{
1508                         SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1509                         long nObj = ::lcl_IsSOObject( aTmpName );
1510                         bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1511                                                     || (0 != (nMyOLEOptions & nObj));
1512 					}
1513 					else
1514 					{
1515 						DBG_ERROR("OLE-object nicht geladen?");
1516 						bInclude = sal_False;
1517 					}
1518 				}
1519 
1520 				if(bInclude)
1521 					pCNd = (SwCntntNode*)pNd;
1522 			}
1523 			break;
1524         default: break;
1525 		}
1526 
1527 		if( pCNd )
1528 		{
1529 			//find node in body text
1530             int nSetLevel = USHRT_MAX;
1531 
1532             //#111105# tables of tables|illustrations|objects don't support hierarchies
1533             if( IsLevelFromChapter() &&
1534                     TOX_TABLES != SwTOXBase::GetType() &&
1535                     TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1536                     TOX_OBJECTS != SwTOXBase::GetType() )
1537 			{
1538 				const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1539 														MAXLEVEL - 1 );
1540 				if( pOutlNd )
1541 				{
1542 					//sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1543 					//if( nTmp < NO_NUMBERING )
1544 					//	nSetLevel = nTmp + 1;
1545 					if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1546 						nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
1547 				}
1548 			}
1549 
1550 			if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
1551 					::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1552 			{
1553 				SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1554                             ( USHRT_MAX != nSetLevel )
1555                             ? static_cast<sal_uInt16>(nSetLevel)
1556                             : FORM_ALPHA_DELIMITTER );
1557 				InsertSorted( pNew );
1558 			}
1559 		}
1560 
1561         nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2;  // 2 == End-/StartNode
1562 	}
1563 }
1564 
1565 /*--------------------------------------------------------------------
1566 	 Beschreibung:	Tabelleneintraege zusammensuchen
1567  --------------------------------------------------------------------*/
1568 
1569 void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
1570 {
1571 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1572 	SwNodes& rNds = pDoc->GetNodes();
1573 	const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
1574 
1575 	for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
1576 	{
1577 		::SetProgressState( 0, pDoc->GetDocShell() );
1578 
1579 		SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
1580 		SwTableBox* pFBox;
1581 		if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
1582 			pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1583 		{
1584 			const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
1585 			SwNodeIndex aCntntIdx( *pTblNd, 1 );
1586 
1587 			SwCntntNode* pCNd;
1588 			while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
1589 				aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
1590 			{
1591 				if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
1592 					::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1593 				{
1594 					SwTOXTable * pNew = new SwTOXTable( *pCNd );
1595                     if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1596                     {
1597                         const SwTxtNode* pOutlNd =
1598                             ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1599                         if( pOutlNd )
1600                         {
1601 							//sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1602 							//if( nTmp < NO_NUMBERING )
1603 							//	pNew->SetLevel( nTmp + 1 );
1604                             if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1605 							{
1606                                 const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
1607                                 pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
1608 							}
1609                         }
1610                     }
1611                     InsertSorted(pNew);
1612 					break;
1613 				}
1614 			}
1615 		}
1616 	}
1617 }
1618 
1619 /*--------------------------------------------------------------------
1620 	 Beschreibung:	String generieren anhand der Form
1621 					SonderZeichen 0-31 und 255 entfernen
1622  --------------------------------------------------------------------*/
1623 
1624 String lcl_GetNumString( const SwTOXSortTabBase& rBase, sal_Bool bUsePrefix, sal_uInt8 nLevel )
1625 {
1626 	String sRet;
1627 
1628 	if( !rBase.pTxtMark && rBase.aTOXSources.Count() > 0 )
1629 	{	// nur wenn es keine Marke ist
1630 		const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
1631 		if( pNd )
1632 		{
1633 			const SwNumRule* pRule = pNd->GetNumRule();
1634 
1635             if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
1636                 sRet = pNd->GetNumString(bUsePrefix, nLevel);
1637         }
1638 	}
1639 	return sRet;
1640 }
1641 
1642 // OD 18.03.2003 #106329# - add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc>
1643 // in order to control, which page description is used, no appropriate one is found.
1644 void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
1645                                      sal_uInt16 nCount,
1646                                      SvStringsDtor& ,
1647                                      const sal_uInt32   _nTOXSectNdIdx,
1648                                      const SwPageDesc*  _pDefaultPageDesc )
1649 {
1650 	LinkStructArr	aLinkArr;
1651 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1652 	::SetProgressState( 0, pDoc->GetDocShell() );
1653 
1654 	//pTOXNd is only set at the first mark
1655 	SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
1656 	String& rTxt = (String&)pTOXNd->GetTxt();
1657 	rTxt.Erase();
1658 	for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
1659 	{
1660 		if(nIndex > nArrayIdx)
1661 			rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
1662 		// String mit dem Pattern aus der Form initialisieren
1663 		const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
1664 		sal_uInt16 nLvl = rBase.GetLevel();
1665 		ASSERT( nLvl < GetTOXForm().GetFormMax(), "ungueltiges FORM_LEVEL");
1666 
1667         SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1668 		xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
1669         String  sLinkCharacterStyle; //default to "Default" character style - which is none
1670 		String sURL;
1671 		// create an enumerator
1672         // #i21237#
1673         SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
1674         SwFormTokens::iterator aIt = aPattern.begin();
1675 		// remove text from node
1676 		while(aIt != aPattern.end()) // #i21237#
1677 		{
1678 			SwFormToken aToken = *aIt; // #i21237#
1679 			xub_StrLen nStartCharStyle = rTxt.Len();
1680 			switch( aToken.eTokenType )
1681 			{
1682 			case TOKEN_ENTRY_NO:
1683 				// fuer Inhaltsverzeichnis Numerierung
1684                 rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
1685 				break;
1686 
1687 			case TOKEN_ENTRY_TEXT:
1688 				{
1689 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1690 					rBase.FillText( *pTOXNd, aIdx );
1691 				}
1692 				break;
1693 
1694 			case TOKEN_ENTRY:
1695 				{
1696 					// fuer Inhaltsverzeichnis Numerierung
1697 					rTxt.Insert( lcl_GetNumString( rBase, sal_True, MAXLEVEL ));
1698 
1699 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1700 					rBase.FillText( *pTOXNd, aIdx );
1701 				}
1702 				break;
1703 
1704 			case TOKEN_TAB_STOP:
1705                 if (aToken.bWithTab) // #i21237#
1706                     rTxt.Append('\t');
1707 				//
1708 
1709 				if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
1710 				{
1711 					const SvxLRSpaceItem& rLR =
1712                         (SvxLRSpaceItem&)pTOXNd->
1713                         SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
1714 
1715 					long nTabPosition = aToken.nTabStopPosition;
1716 					if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
1717 						nTabPosition -= rLR.GetTxtLeft();
1718 					aTStops.Insert( SvxTabStop( nTabPosition,
1719                                                 aToken.eTabAlign,
1720 												cDfltDecimalChar,
1721 												aToken.cTabFillChar ));
1722 				}
1723 				else
1724 				{
1725 					const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
1726 								SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
1727 
1728 					sal_Bool bCallFindRect = sal_True;
1729 					long nRightMargin;
1730 					if( pPageDesc )
1731 					{
1732 						const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
1733 						if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
1734 							pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
1735 							// dann muss man ueber den PageDesc gehen
1736 							bCallFindRect = sal_False;
1737 					}
1738 
1739 					SwRect aNdRect;
1740 					if( bCallFindRect )
1741 						aNdRect = pTOXNd->FindLayoutRect( sal_True );
1742 
1743 					if( aNdRect.IsEmpty() )
1744 					{
1745 						// dann hilft alles nichts, wir muessen ueber die Seiten-
1746 						// vorlage gehen.
1747                         // OD 18.03.2003 #106329# - call
1748                         sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
1749                         sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
1750                         pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
1751                         if ( !pPageDesc ||
1752                              *pPgDescNdIdx < _nTOXSectNdIdx )
1753                         {
1754                             // use default page description, if none is found
1755                             // or the found one is given by a node before the
1756                             // table-of-content section.
1757                             pPageDesc = _pDefaultPageDesc;
1758                         }
1759 
1760 						const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
1761 						nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
1762 								 		rPgDscFmt.GetLRSpace().GetLeft() -
1763 								 		rPgDscFmt.GetLRSpace().GetRight();
1764 					}
1765 					else
1766 						nRightMargin = aNdRect.Width();
1767                     //#i24363# tab stops relative to indent
1768                     if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
1769                     {
1770                         //left margin of paragraph style
1771                         const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
1772                         nRightMargin -= rLRSpace.GetLeft();
1773                         nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
1774                     }
1775 
1776                     aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
1777 												cDfltDecimalChar,
1778 												aToken.cTabFillChar ));
1779 				}
1780 				break;
1781 
1782 			case TOKEN_TEXT:
1783 				rTxt.Append( aToken.sText );
1784 				break;
1785 
1786 			case TOKEN_PAGE_NUMS:
1787 					// Platzhalter fuer Seitennummer(n) es wird nur der erste beachtet
1788 					//
1789 				{
1790 					// Die Anzahl der gleichen Eintrage bestimmt die Seitennummern-Pattern
1791 					//
1792 					sal_uInt16 nSize = rBase.aTOXSources.Count();
1793 					if( nSize > 0 )
1794 					{
1795 						String aInsStr( cNumRepl );
1796 						for(sal_uInt16 i=1; i < nSize; ++i)
1797 						{
1798 							aInsStr.AppendAscii( sPageDeli );
1799 							aInsStr += cNumRepl;
1800 						}
1801 						aInsStr += cEndPageNum;
1802 						rTxt.Append( aInsStr );
1803 					}
1804 //						// Tab entfernen, wenn keine Seitennummer
1805 //					else if( rTxt.Len() && '\t' == rTxt.GetChar( rTxt.Len() - 1 ))
1806 //						rTxt.Erase( rTxt.Len()-1, 1 );
1807 				}
1808 				break;
1809 
1810 			case TOKEN_CHAPTER_INFO:
1811 				{
1812 					// ein bischen trickreich: suche irgend einen Frame
1813 					const SwTOXSource* pTOXSource = 0;
1814 					if(rBase.aTOXSources.Count())
1815 						pTOXSource = &rBase.aTOXSources[0];
1816 
1817                     // --> OD 2008-02-14 #i53420#
1818 //                    if( pTOXSource && pTOXSource->pNd
1819 //                        pTOXSource->pNd->IsTxtNode() )
1820                     if ( pTOXSource && pTOXSource->pNd &&
1821                          pTOXSource->pNd->IsCntntNode() )
1822                     // <--
1823 					{
1824 						const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1825 						if( pFrm )
1826 						{
1827 							SwChapterFieldType aFldTyp;
1828 							SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
1829                             aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
1830                             // --> OD 2008-02-14 #i53420#
1831 //                            aFld.ChangeExpansion( pFrm, (SwTxtNode*)pTOXSource->pNd, sal_True );
1832                             aFld.ChangeExpansion( pFrm,
1833                                 dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
1834                                 sal_True );
1835                             // <--
1836                             //---> i89791
1837                             // OD 2008-06-26 - continue to support CF_NUMBER
1838                             // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
1839                             // written by OOo 3.x in the same way as OOo 2.x
1840                             // would handle them.
1841                             if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
1842                                  CF_NUMBER == aToken.nChapterFormat )
1843                                 rTxt.Insert(aFld.GetNumber()); //get the string number without pre/postfix
1844                             else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
1845                                       CF_NUM_TITLE == aToken.nChapterFormat )
1846                             //<---
1847 							{
1848 								rTxt += aFld.GetNumber();
1849 								rTxt += ' ';
1850 								rTxt += aFld.GetTitle();
1851 							}
1852 							else if(CF_TITLE == aToken.nChapterFormat)
1853 								rTxt += aFld.GetTitle();
1854 						}
1855 					}
1856 				}
1857 				break;
1858 
1859 			case TOKEN_LINK_START:
1860 				nLinkStartPosition = rTxt.Len();
1861                 sLinkCharacterStyle = aToken.sCharStyleName;
1862             break;
1863 
1864 			case TOKEN_LINK_END:
1865 					//TODO: only paired start/end tokens are valid
1866 				if( STRING_NOTFOUND != nLinkStartPosition)
1867 				{
1868 					SwIndex aIdx( pTOXNd, nLinkStartPosition );
1869 					//pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
1870 					xub_StrLen nEnd = rTxt.Len();
1871 
1872 					if( !sURL.Len() )
1873 					{
1874 						sURL = rBase.GetURL();
1875 						if( !sURL.Len() )
1876 							break;
1877 					}
1878                     LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
1879                                                     nEnd);
1880                     pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
1881                     pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
1882                     if(sLinkCharacterStyle.Len())
1883                     {
1884                         sal_uInt16 nPoolId =
1885                             SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1886                         pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
1887                         pNewLink->aINetFmt.SetINetFmtId(nPoolId);
1888                     }
1889                     else
1890                     {
1891                         pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
1892                         pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
1893                     }
1894                     aLinkArr.Insert( pNewLink, aLinkArr.Count() );
1895 					nLinkStartPosition = STRING_NOTFOUND;
1896                     sLinkCharacterStyle.Erase();
1897 				}
1898 				break;
1899 
1900 			case TOKEN_AUTHORITY:
1901 				{
1902 					ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
1903 					SwIndex aIdx( pTOXNd, rTxt.Len() );
1904 					rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
1905 				}
1906 				break;
1907             case TOKEN_END: break;
1908 			}
1909 
1910 			if( aToken.sCharStyleName.Len() )
1911 			{
1912 				SwCharFmt* pCharFmt;
1913 				if(	USHRT_MAX != aToken.nPoolId )
1914 					pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
1915 				else
1916 					pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
1917 
1918                 if (pCharFmt)
1919                 {
1920                     SwFmtCharFmt aFmt( pCharFmt );
1921                     pTOXNd->InsertItem( aFmt, nStartCharStyle,
1922                         rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
1923                 }
1924             }
1925 
1926             aIt++; // #i21237#
1927 		}
1928 
1929         pTOXNd->SetAttr( aTStops );
1930 	}
1931 
1932 	if(aLinkArr.Count())
1933 		for(sal_uInt16 i = 0; i < aLinkArr.Count(); ++i )
1934 		{
1935 			LinkStruct* pTmp = aLinkArr.GetObject(i);
1936             pTOXNd->InsertItem( pTmp->aINetFmt, pTmp->nStartTextPos,
1937 							pTmp->nEndTextPos);
1938 		}
1939 }
1940 
1941 /*--------------------------------------------------------------------
1942 	 Beschreibung: Seitennummer errechnen und nach dem Formatieren
1943 				   eintragen
1944  --------------------------------------------------------------------*/
1945 
1946 void SwTOXBaseSection::UpdatePageNum()
1947 {
1948 	if( !aSortArr.Count() )
1949 		return ;
1950 
1951 	// die aktuellen Seitennummern ins Verzeichnis eintragen
1952 	SwPageFrm*	pAktPage	= 0;
1953 	sal_uInt16		nPage		= 0;
1954 	SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1955 
1956     SwTOXInternational aIntl( GetLanguage(),
1957                               TOX_INDEX == GetTOXType()->GetType() ?
1958                               GetOptions() : 0,
1959                               GetSortAlgorithm() );
1960 
1961 	for( sal_uInt16 nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
1962 	{
1963 		// Schleife ueber alle SourceNodes
1964 		SvUShorts aNums;		//Die Seitennummern
1965 		SvPtrarr  aDescs;		//Die PageDescriptoren passend zu den Seitennummern.
1966 		SvUShorts* pMainNums = 0; // contains page numbers of main entries
1967 
1968 		// process run in lines
1969 		sal_uInt16 nRange = 0;
1970 		if(GetTOXForm().IsCommaSeparated() &&
1971 				aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1972 		{
1973 			const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1974 			const String sPrimKey = rMark.GetPrimaryKey();
1975 			const String sSecKey = rMark.GetSecondaryKey();
1976 			const SwTOXMark* pNextMark = 0;
1977 			while(aSortArr.Count() > (nCnt + nRange)&&
1978 					aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1979 					0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1980 					pNextMark->GetPrimaryKey() == sPrimKey &&
1981 					pNextMark->GetSecondaryKey() == sSecKey)
1982 				nRange++;
1983 		}
1984 		else
1985 			nRange = 1;
1986 
1987 		for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
1988 		{
1989 			SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
1990 			sal_uInt16 nSize = pSortBase->aTOXSources.Count();
1991 			sal_uInt16 i;
1992 			for( sal_uInt16 j = 0; j < nSize; ++j )
1993 			{
1994 				::SetProgressState( 0, pDoc->GetDocShell() );
1995 
1996 				SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1997 				if( rTOXSource.pNd )
1998 				{
1999 					SwCntntFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
2000                     ASSERT( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
2001                     if( !pFrm )
2002                         continue;
2003 					if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
2004 					{
2005 						// dann suche den richtigen heraus
2006 						SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
2007 						while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
2008 								&& rTOXSource.nPos >= pNext->GetOfst() )
2009 							pFrm = pNext;
2010 					}
2011 
2012 					SwPageFrm*	pTmpPage = pFrm->FindPageFrm();
2013 					if( pTmpPage != pAktPage )
2014 					{
2015 						nPage		= pTmpPage->GetVirtPageNum();
2016 						pAktPage	= pTmpPage;
2017 					}
2018 
2019 					// sortiert einfuegen
2020 					for( i = 0; i < aNums.Count() && aNums[i] < nPage; ++i )
2021 						;
2022 
2023 					if( i >= aNums.Count() || aNums[ i ] != nPage )
2024 					{
2025 						aNums.Insert( nPage, i );
2026 						aDescs.Insert( (void*)pAktPage->GetPageDesc(), i );
2027 					}
2028 					// is it a main entry?
2029 					if(TOX_SORT_INDEX == pSortBase->GetType() &&
2030 						rTOXSource.bMainEntry)
2031 					{
2032 						if(!pMainNums)
2033 							pMainNums = new SvUShorts;
2034 						pMainNums->Insert(nPage, pMainNums->Count());
2035 					}
2036 				}
2037 			}
2038 			// einfuegen der Seitennummer in den Verzeichnis-Text-Node
2039 			const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
2040 			if(pBase->pTOXNd)
2041 			{
2042 				const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
2043 				ASSERT( pTxtNd, "kein TextNode, falsches Verzeichnis" );
2044 
2045 				_UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
2046 								aIntl );
2047 			}
2048 			DELETEZ(pMainNums);
2049 			aNums.Remove(0, aNums.Count());
2050 		}
2051 	}
2052 	// nach dem Setzen der richtigen Seitennummer, das Mapping-Array
2053 	// wieder loeschen !!
2054 	aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
2055 }
2056 
2057 
2058 /*--------------------------------------------------------------------
2059 	 Beschreibung: Austausch der Seitennummer-Platzhalter
2060  --------------------------------------------------------------------*/
2061 
2062 // search for the page no in the array of main entry page numbers
2063 sal_Bool lcl_HasMainEntry( const SvUShorts* pMainEntryNums, sal_uInt16 nToFind )
2064 {
2065 	for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->Count(); ++i)
2066 		if(nToFind == (*pMainEntryNums)[i])
2067 			return sal_True;
2068 	return sal_False;
2069 }
2070 
2071 void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
2072 									const SvUShorts& rNums,
2073 									const SvPtrarr & rDescs,
2074 									const SvUShorts* pMainEntryNums,
2075 									const SwTOXInternational& rIntl )
2076 {
2077 	//collect starts end ends of main entry character style
2078 	SvUShorts* pCharStyleIdx = pMainEntryNums ? new SvUShorts : 0;
2079 
2080 	String sSrchStr( cNumRepl );
2081 	sSrchStr.AppendAscii( sPageDeli ) += cNumRepl;
2082 	xub_StrLen nStartPos = pNd->GetTxt().Search( sSrchStr );
2083 	( sSrchStr = cNumRepl ) += cEndPageNum;
2084 	xub_StrLen nEndPos = pNd->GetTxt().Search( sSrchStr );
2085 	sal_uInt16 i;
2086 
2087 	if( STRING_NOTFOUND == nEndPos || !rNums.Count() )
2088 		return;
2089 
2090 	if( STRING_NOTFOUND == nStartPos || nStartPos > nEndPos)
2091 		nStartPos = nEndPos;
2092 
2093 	sal_uInt16 nOld = rNums[0],
2094 		   nBeg = nOld,
2095 		   nCount  = 0;
2096 	String aNumStr( SvxNumberType( ((SwPageDesc*)rDescs[0])->GetNumType() ).
2097 					GetNumStr( nBeg ) );
2098 	if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
2099 	{
2100 		sal_uInt16 nTemp = 0;
2101 		pCharStyleIdx->Insert( nTemp, pCharStyleIdx->Count());
2102 	}
2103 
2104 	// Platzhalter loeschen
2105 	SwIndex aPos(pNd, nStartPos);
2106 	SwCharFmt* pPageNoCharFmt = 0;
2107 	SwpHints* pHints = pNd->GetpSwpHints();
2108 	if(pHints)
2109 		for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
2110 		{
2111 			SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
2112 			xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
2113 			if(	nStartPos >= *pAttr->GetStart() &&
2114 				(nStartPos + 2) <= nTmpEnd &&
2115 				pAttr->Which() == RES_TXTATR_CHARFMT)
2116 			{
2117 				pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
2118 				break;
2119 			}
2120 		}
2121     pNd->EraseText(aPos, nEndPos - nStartPos + 2);
2122 
2123 	for( i = 1; i < rNums.Count(); ++i)
2124 	{
2125 		SvxNumberType aType( ((SwPageDesc*)rDescs[i])->GetNumType() );
2126 		if( TOX_INDEX == SwTOXBase::GetType() )
2127 		{	// Zusammenfassen f. ff.
2128 			// Alle folgenden aufaddieren
2129 			// break up if main entry starts or ends and
2130 			// insert a char style index
2131 			sal_Bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
2132 					!= lcl_HasMainEntry(pMainEntryNums, rNums[i]);
2133 
2134 			if(nOld == rNums[i]-1 && !bMainEntryChanges &&
2135                 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
2136 				nCount++;
2137 			else
2138 			{
2139 				// ff. f. alten Wert flushen
2140                 if(GetOptions() & nsSwTOIOptions::TOI_FF)
2141 				{
2142 					if ( nCount >= 1 )
2143 						aNumStr += rIntl.GetFollowingText( nCount > 1 );
2144 				}
2145 				else
2146 				{
2147 					if(nCount >= 2 )
2148 						aNumStr += '-';
2149 					else if(nCount == 1 )
2150 						aNumStr.AppendAscii( sPageDeli );
2151 //#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
2152 					if(nCount)
2153 						aNumStr += aType.GetNumStr( nBeg + nCount );
2154 				}
2155 
2156 				// neuen String anlegen
2157 				nBeg	 = rNums[i];
2158 				aNumStr.AppendAscii( sPageDeli );
2159 				//the change of the character style must apply after sPageDeli is appended
2160 				if(pCharStyleIdx && bMainEntryChanges)
2161 					pCharStyleIdx->Insert(aNumStr.Len(),
2162 													pCharStyleIdx->Count());
2163 				aNumStr += aType.GetNumStr( nBeg );
2164 				nCount	 = 0;
2165 			}
2166 			nOld = rNums[i];
2167 		}
2168 		else
2169 		{	// Alle Nummern eintragen
2170 			aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
2171 			if(i != (rNums.Count()-1))
2172 				aNumStr.AppendAscii( sPageDeli );
2173 		}
2174 	}
2175 	// Bei Ende und ff. alten Wert flushen
2176 	if( TOX_INDEX == SwTOXBase::GetType() )
2177 	{
2178         if(GetOptions() & nsSwTOIOptions::TOI_FF)
2179 		{
2180 			if( nCount >= 1 )
2181 				aNumStr += rIntl.GetFollowingText( nCount > 1 );
2182 		}
2183 		else
2184 		{
2185 			if(nCount >= 2)
2186 				aNumStr +='-';
2187 			else if(nCount == 1)
2188 				aNumStr.AppendAscii( sPageDeli );
2189 //#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
2190 			if(nCount)
2191 				aNumStr += SvxNumberType( ((SwPageDesc*)rDescs[i-1])->
2192 								GetNumType() ).GetNumStr( nBeg+nCount );
2193 		}
2194 	}
2195     pNd->InsertText( aNumStr, aPos,
2196            static_cast<IDocumentContentOperations::InsertFlags>(
2197                IDocumentContentOperations::INS_EMPTYEXPAND |
2198                IDocumentContentOperations::INS_FORCEHINTEXPAND) );
2199 	if(pPageNoCharFmt)
2200 	{
2201         SwFmtCharFmt aCharFmt( pPageNoCharFmt );
2202         pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
2203     }
2204 
2205 	//now the main entries should get there character style
2206 	if(pCharStyleIdx && pCharStyleIdx->Count() && GetMainEntryCharStyle().Len())
2207 	{
2208 		// eventually the last index must me appended
2209 		if(pCharStyleIdx->Count()&0x01)
2210 			pCharStyleIdx->Insert(aNumStr.Len(), pCharStyleIdx->Count());
2211 
2212 		//search by name
2213 		SwDoc* pDoc = pNd->GetDoc();
2214 		sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
2215 		SwCharFmt* pCharFmt = 0;
2216 		if(USHRT_MAX != nPoolId)
2217 			pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
2218 		else
2219 			pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
2220 		if(!pCharFmt)
2221 			pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
2222 
2223 		//find the page numbers in aNumStr and set the character style
2224 		xub_StrLen nOffset = pNd->GetTxt().Len() - aNumStr.Len();
2225 		SwFmtCharFmt aCharFmt(pCharFmt);
2226 		for(sal_uInt16 j = 0; j < pCharStyleIdx->Count(); j += 2)
2227 		{
2228 			xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
2229 			xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1]  + nOffset;
2230             pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
2231 		}
2232 
2233 	}
2234 	delete pCharStyleIdx;
2235 }
2236 
2237 
2238 /*--------------------------------------------------------------------
2239 	 Beschreibung: Sortiert einfuegen in das SortArr
2240  --------------------------------------------------------------------*/
2241 
2242 void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
2243 {
2244 	Range aRange(0, aSortArr.Count());
2245 	if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
2246 	{
2247 		const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
2248 		// Schluessel auswerten
2249 		// Den Bereich ermitteln, in dem einzufuegen ist
2250         if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
2251 			rMark.GetPrimaryKey().Len() )
2252 		{
2253             aRange = GetKeyRange( rMark.GetPrimaryKey(),
2254                                   rMark.GetPrimaryKeyReading(),
2255                                   *pNew, FORM_PRIMARY_KEY, aRange );
2256 
2257             if( rMark.GetSecondaryKey().Len() )
2258                 aRange = GetKeyRange( rMark.GetSecondaryKey(),
2259                                       rMark.GetSecondaryKeyReading(),
2260                                       *pNew, FORM_SECONDARY_KEY, aRange );
2261 		}
2262 	}
2263 	//search for identical entries and remove the trailing one
2264 	if(TOX_AUTHORITIES == SwTOXBase::GetType())
2265 	{
2266 		for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2267 		{
2268 			SwTOXSortTabBase* pOld = aSortArr[i];
2269 			if(*pOld == *pNew)
2270 			{
2271 				if(*pOld < *pNew)
2272 				{
2273 					delete pNew;
2274 					return;
2275 				}
2276 				else
2277 				{
2278 					// remove the old content
2279 					aSortArr.DeleteAndDestroy( i, 1 );
2280 					aRange.Max()--;
2281 					break;
2282 				}
2283 			}
2284 		}
2285 	}
2286 
2287 	// find position and insert
2288 	//
2289 	short i;
2290 
2291 	for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2292 	{	// nur auf gleicher Ebene pruefen
2293 		//
2294 		SwTOXSortTabBase* pOld = aSortArr[i];
2295 		if(*pOld == *pNew)
2296 		{
2297 			if(TOX_AUTHORITIES != SwTOXBase::GetType())
2298 			{
2299 				// Eigener Eintrag fuer Doppelte oder Keywords
2300 				//
2301 				if( pOld->GetType() == TOX_SORT_CUSTOM &&
2302                     pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
2303 					continue;
2304 
2305                 if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
2306 				{	// Eigener Eintrag
2307 					aSortArr.Insert(pNew, i );
2308 					return;
2309 				}
2310 				// Eintrag schon vorhanden in Referenzliste aufnehmen
2311 				pOld->aTOXSources.Insert( pNew->aTOXSources[0],
2312 											pOld->aTOXSources.Count() );
2313 
2314 				delete pNew;
2315 				return;
2316 			}
2317 #ifdef DBG_UTIL
2318 			else
2319 				DBG_ERROR("Bibliography entries cannot be found here");
2320 #endif
2321 		}
2322 		if(*pNew < *pOld)
2323 			break;
2324 	}
2325 	// SubLevel Skippen
2326 	while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
2327 		  aSortArr[i]->GetLevel() > pNew->GetLevel() )
2328 		i++;
2329 
2330 	// An Position i wird eingefuegt
2331 	aSortArr.Insert(pNew, i );
2332 }
2333 
2334 /*--------------------------------------------------------------------
2335 	 Beschreibung: Schluessel-Bereich suchen und evtl einfuegen
2336  --------------------------------------------------------------------*/
2337 
2338 Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
2339                                     const SwTOXSortTabBase& rNew,
2340                                     sal_uInt16 nLevel, const Range& rRange )
2341 {
2342     const SwTOXInternational& rIntl = *rNew.pTOXIntl;
2343 	String sToCompare(rStr);
2344     String sToCompareReading(rStrReading);
2345 
2346     if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
2347 	{
2348 		String sUpper( rIntl.ToUpper( sToCompare, 0 ));
2349 		sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
2350 	}
2351 
2352 	ASSERT(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
2353 
2354 	const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
2355 	const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
2356 
2357     sal_uInt16 i;
2358 
2359 	for( i = nMin; i < nMax; ++i)
2360 	{
2361 		SwTOXSortTabBase* pBase = aSortArr[i];
2362 
2363         String sMyString, sMyStringReading;
2364         pBase->GetTxt( sMyString, sMyStringReading );
2365 
2366         if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
2367                            sToCompare, sToCompareReading, rNew.GetLocale() )  &&
2368                     pBase->GetLevel() == nLevel )
2369 			break;
2370 	}
2371 	if(i == nMax)
2372 	{	// Falls nicht vorhanden erzeugen und einfuegen
2373 		//
2374         SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
2375                                              rNew.GetLocale() );
2376 		for(i = nMin; i < nMax; ++i)
2377 		{
2378 			if(nLevel == aSortArr[i]->GetLevel() &&  *pKey < *(aSortArr[i]))
2379 				break;
2380 		}
2381 		aSortArr.Insert(pKey, i );
2382 	}
2383 	sal_uInt16 nStart = i+1;
2384 	sal_uInt16 nEnd   = aSortArr.Count();
2385 
2386 	// Ende des Bereiches suchen
2387 	for(i = nStart; i < aSortArr.Count(); ++i)
2388 	{
2389 		if(aSortArr[i]->GetLevel() <= nLevel)
2390 		{	nEnd = i;
2391 			break;
2392 		}
2393 	}
2394 	return Range(nStart, nEnd);
2395 }
2396 
2397 
2398 sal_Bool SwTOXBase::IsTOXBaseInReadonly() const
2399 {
2400 	const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2401 	sal_Bool bRet = sal_False;
2402 	const SwSectionNode* pSectNode;
2403 	if(pSect && pSect->GetFmt() &&
2404 			0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
2405 	{
2406 		const SwDocShell* pDocSh;
2407 		bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
2408 													pDocSh->IsReadOnly()) ||
2409             (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
2410 					pSectNode->GetSection().IsProtectFlag());
2411 
2412 	}
2413 	return bRet;
2414 }
2415 
2416 const SfxItemSet* SwTOXBase::GetAttrSet() const
2417 {
2418 	const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2419 	if(pSect && pSect->GetFmt())
2420 		return &pSect->GetFmt()->GetAttrSet();
2421 	return 0;
2422 }
2423 
2424 void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
2425 {
2426 	SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2427 	if( pSect && pSect->GetFmt() )
2428         pSect->GetFmt()->SetFmtAttr( rSet );
2429 }
2430 
2431 sal_Bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
2432 {
2433 	switch( rInfo.Which() )
2434 	{
2435 	case RES_CONTENT_VISIBLE:
2436 		{
2437 			SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
2438 			if( pSect && pSect->GetFmt() )
2439 				pSect->GetFmt()->GetInfo( rInfo );
2440 		}
2441 		return sal_False;
2442 	}
2443 	return sal_True;
2444 }
2445 
2446