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