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