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