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