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