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