xref: /trunk/main/sw/source/core/doc/doctxm.cxx (revision 782a276c8a1bedc2d3a53e8b896490eb36cd15c8)
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->End() ) ||
161                 *pEndIdx <= nAktPos )
162                 continue;       // weiter suchen
163         }
164         else if( nSttIdx > nAktPos )
165             // ist Start vom Hint groesser als rPos, dann abbrechen. Denn
166             // die Attribute sind nach Start sortiert !
167             break;
168 
169         const SwTOXMark* pTMark = &pHt->GetTOXMark();
170         rArr.Insert( pTMark, rArr.Count() );
171     }
172     return rArr.Count();
173 }
174 
175 /*--------------------------------------------------------------------
176      Beschreibung: Marke loeschen
177  --------------------------------------------------------------------*/
178 
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_uInt16 nMark=0; nMark<aMarks.Count(); nMark++ )
266     {
267         pTOXMark = aMarks[nMark];
268         if( pTOXMark != &rCurTOXMark &&
269             0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
270             0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
271             0 != ( pCFrm = pTOXSrc->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False )) &&
272             ( bInReadOnly || !pCFrm->IsProtected() ))
273         {
274             CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
275             switch( eDir )
276             {
277                 //Die untenstehenden etwas komplizierter ausgefallen Ausdruecke
278                 //dienen dazu auch ueber Eintraege auf der selben (!) Position
279                 //traveln zu koennen. Wenn einer Zeit hat mag er sie mal
280                 //optimieren.
281 
282             case TOX_SAME_PRV:
283                 if( pTOXMark->GetText() != rCurTOXMark.GetText() )
284                     break;
285                 /* no break here */
286             case TOX_PRV:
287                 if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
288                       aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
289                      (aAbsIdx == aAbsNew &&
290                       (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
291                        (!pNew ||
292                         (pNew && (aPrevPos < aAbsIdx ||
293                                   sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
294                      (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
295                       sal_uLong(pTOXMark) > sal_uLong(pNew)) )
296                 {
297                     pNew = pTOXMark;
298                     aPrevPos = aAbsNew;
299                     if ( aAbsNew >= aMax )
300                     {
301                         aMax = aAbsNew;
302                         pMax = pTOXMark;
303                     }
304                 }
305                 break;
306 
307             case TOX_SAME_NXT:
308                 if( pTOXMark->GetText() != rCurTOXMark.GetText() )
309                     break;
310                 /* no break here */
311             case TOX_NXT:
312                 if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
313                       aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
314                      (aAbsIdx == aAbsNew &&
315                       (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
316                        (!pNew ||
317                         (pNew && (aNextPos > aAbsIdx ||
318                                   sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
319                      (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
320                       sal_uLong(pTOXMark) < sal_uLong(pNew)) )
321                 {
322                     pNew = pTOXMark;
323                     aNextPos = aAbsNew;
324                     if ( aAbsNew <= aMin )
325                     {
326                         aMin = aAbsNew;
327                         pMin = pTOXMark;
328                     }
329                 }
330                 break;
331             }
332         }
333     }
334 
335 
336     // kein Nachfolger wurde gefunden
337     // Min oder Max benutzen
338     if(!pNew)
339     {
340         switch(eDir)
341         {
342         case TOX_PRV:
343         case TOX_SAME_PRV:
344             pNew = pMax;
345             break;
346         case TOX_NXT:
347         case TOX_SAME_NXT:
348             pNew = pMin;
349             break;
350         default:
351             pNew = &rCurTOXMark;
352         }
353     }
354     return *pNew;
355 }
356 
357 
358 const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
359                                                 const SwTOXBase& rTOX,
360                                                 const SfxItemSet* pSet,
361                                                 sal_Bool bExpand )
362 {
363     GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
364 
365     String sSectNm( rTOX.GetTOXName() );
366     sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
367     SwPaM aPam( rPos );
368     SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
369     SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
370         InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
371     if (pNewSection)
372     {
373         SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
374         pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
375 
376         if( bExpand )
377         {
378             // OD 19.03.2003 #106329# - add value for 2nd parameter = true to
379             // indicate, that a creation of a new table of content has to be performed.
380             // Value of 1st parameter = default value.
381             pNewSection->Update( 0, true );
382         }
383         else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
384         // insert title of TOX
385         {
386             // then insert the headline section
387             SwNodeIndex aIdx( *pSectNd, +1 );
388 
389             SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
390                             GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
391 
392             String sNm( pNewSection->GetTOXName() );
393 // ??Resource
394 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
395 
396             SwSectionData headerData( TOX_HEADER_SECTION, sNm );
397 
398             SwNodeIndex aStt( *pHeadNd ); aIdx--;
399             SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
400             GetNodes().InsertTextSection(
401                     aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
402         }
403     }
404 
405     GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
406 
407     return pNewSection;
408 }
409 
410 
411 
412 const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
413                                                 const SwTOXBase& rTOX,
414                                                 const SfxItemSet* pSet )
415 {
416     // check for recursiv TOX
417     SwNode* pNd = GetNodes()[ nSttNd ];
418     SwSectionNode* pSectNd = pNd->FindSectionNode();
419     while( pSectNd )
420     {
421         SectionType eT = pSectNd->GetSection().GetType();
422         if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
423             return 0;
424         pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
425     }
426 
427     String sSectNm( rTOX.GetTOXName() );
428     sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
429 
430     SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
431 
432     SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
433     SwSectionFmt* pFmt = MakeSectionFmt( 0 );
434     if(pSet)
435         pFmt->SetFmtAttr(*pSet);
436 
437 //  --aEnd;     // im InsertSection ist Ende inclusive
438 
439     SwSectionNode *const pNewSectionNode =
440         GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
441     if (!pNewSectionNode)
442     {
443         DelSectionFmt( pFmt );
444         return 0;
445     }
446 
447     SwTOXBaseSection *const pNewSection(
448         dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
449     pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
450     return pNewSection;
451 }
452 
453 /*--------------------------------------------------------------------
454      Beschreibung: Aktuelles Verzeichnis ermitteln
455  --------------------------------------------------------------------*/
456 
457 const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
458 {
459     const SwNode& rNd = rPos.nNode.GetNode();
460     const SwSectionNode* pSectNd = rNd.FindSectionNode();
461     while( pSectNd )
462     {
463         SectionType eT = pSectNd->GetSection().GetType();
464         if( TOX_CONTENT_SECTION == eT )
465         {
466             ASSERT( pSectNd->GetSection().ISA( SwTOXBaseSection ),
467                     "keine TOXBaseSection!" );
468             SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
469                                                 pSectNd->GetSection();
470             return &rTOXSect;
471         }
472         pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
473     }
474     return 0;
475 }
476 
477 const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
478 {
479     ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
480     const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
481     SwSectionFmt* pFmt = rTOXSect.GetFmt();
482     ASSERT( pFmt, "invalid TOXBaseSection!" );
483     return pFmt->GetAttrSet();
484 }
485 
486 const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate )
487 {
488     SwTOXBase** prBase = 0;
489     switch(eTyp)
490     {
491     case  TOX_CONTENT:          prBase = &pDefTOXBases->pContBase; break;
492     case  TOX_INDEX:            prBase = &pDefTOXBases->pIdxBase;  break;
493     case  TOX_USER:             prBase = &pDefTOXBases->pUserBase; break;
494     case  TOX_TABLES:           prBase = &pDefTOXBases->pTblBase;  break;
495     case  TOX_OBJECTS:          prBase = &pDefTOXBases->pObjBase;  break;
496     case  TOX_ILLUSTRATIONS:    prBase = &pDefTOXBases->pIllBase;  break;
497     case  TOX_AUTHORITIES:      prBase = &pDefTOXBases->pAuthBase; break;
498     }
499     if(!(*prBase) && bCreate)
500     {
501         SwForm aForm(eTyp);
502         const SwTOXType* pType = GetTOXType(eTyp, 0);
503         (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
504     }
505     return (*prBase);
506 }
507 
508 void    SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
509 {
510     SwTOXBase** prBase = 0;
511     switch(rBase.GetType())
512     {
513     case  TOX_CONTENT:          prBase = &pDefTOXBases->pContBase; break;
514     case  TOX_INDEX:            prBase = &pDefTOXBases->pIdxBase;  break;
515     case  TOX_USER:             prBase = &pDefTOXBases->pUserBase; break;
516     case  TOX_TABLES:           prBase = &pDefTOXBases->pTblBase;  break;
517     case  TOX_OBJECTS:          prBase = &pDefTOXBases->pObjBase;  break;
518     case  TOX_ILLUSTRATIONS:    prBase = &pDefTOXBases->pIllBase;  break;
519     case  TOX_AUTHORITIES:      prBase = &pDefTOXBases->pAuthBase; break;
520     }
521     if(*prBase)
522         delete (*prBase);
523     (*prBase) = new SwTOXBase(rBase);
524 }
525 
526 /*--------------------------------------------------------------------
527      Beschreibung: Verzeichnis loeschen
528  --------------------------------------------------------------------*/
529 
530 
531 sal_Bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes )
532 {
533     // its only delete the TOX, not the nodes
534     sal_Bool bRet = sal_False;
535     ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
536 
537     const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
538     SwSectionFmt* pFmt = rTOXSect.GetFmt();
539     if( pFmt )
540     {
541         GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
542 
543         /* Save the start node of the TOX' section. */
544         SwSectionNode * pMyNode = pFmt->GetSectionNode();
545         /* Save start node of section's surrounding. */
546         SwNode * pStartNd = pMyNode->StartOfSectionNode();
547 
548         /* Look for point where to move the cursors in the area to
549            delete to. This is done by first searching forward from the
550            end of the TOX' section. If no content node is found behind
551            the TOX one is searched before it. If this is not
552            successfull, too, insert new text node behind the end of
553            the TOX' section. The cursors from the TOX' section will be
554            moved to the content node found or the new text node. */
555 
556         /* Set PaM to end of TOX' section and search following content node.
557 
558            aSearchPam will contain the point where to move the cursors
559            to. */
560         SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
561         SwPosition aEndPos(*pStartNd->EndOfSectionNode());
562         if (! aSearchPam.Move() /* no content node found */
563             || *aSearchPam.GetPoint() >= aEndPos /* content node found
564                                                     outside surrounding */
565             )
566         {
567             /* Set PaM to beginning of TOX' section and search previous
568                content node */
569             SwPaM aTmpPam(*pMyNode);
570             aSearchPam = aTmpPam;
571             SwPosition aStartPos(*pStartNd);
572 
573             if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
574                  || *aSearchPam.GetPoint() <= aStartPos  /* content node
575                                                             found outside
576                                                             surrounding */
577                  )
578             {
579                 /* There is no content node in the surrounding of
580                    TOX'. Append text node behind TOX' section. */
581 
582                 SwPosition aInsPos(*pMyNode->EndOfSectionNode());
583                 AppendTxtNode(aInsPos);
584 
585                 SwPaM aTmpPam1(aInsPos);
586                 aSearchPam = aTmpPam1;
587             }
588         }
589 
590 
591         /* PaM containing the TOX. */
592         SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
593 
594         /* Move cursors contained in TOX to point determined above. */
595         PaMCorrAbs(aPam, *aSearchPam.GetPoint());
596 
597         if( !bDelNodes )
598         {
599             SwSections aArr( 0, 4 );
600             sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
601             for( sal_uInt16 n = 0; n < nCnt; ++n )
602             {
603                 SwSection* pSect = aArr[ n ];
604                 if( TOX_HEADER_SECTION == pSect->GetType() )
605                 {
606                     DelSectionFmt( pSect->GetFmt(), bDelNodes );
607                 }
608             }
609         }
610 
611         DelSectionFmt( pFmt, bDelNodes );
612 
613         GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
614         bRet = sal_True;
615     }
616 
617     return bRet;
618 }
619 
620 /*--------------------------------------------------------------------
621      Beschreibung:  Verzeichnistypen verwalten
622  --------------------------------------------------------------------*/
623 
624 sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
625 {
626     const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
627     sal_uInt16 nCnt = 0;
628     for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
629         if( eTyp == (*ppTTypes)->GetType() )
630             ++nCnt;
631     return nCnt;
632 }
633 
634 const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
635 {
636     const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
637     sal_uInt16 nCnt = 0;
638     for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
639         if( eTyp == (*ppTTypes)->GetType() && nCnt++ == nId )
640             return (*ppTTypes);
641     return 0;
642 }
643 
644 
645 const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
646 {
647     SwTOXType * pNew = new SwTOXType( rTyp );
648     pTOXTypes->Insert( pNew, pTOXTypes->Count() );
649     return pNew;
650 }
651 
652 String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
653                                     const String* pChkStr ) const
654 {
655     sal_uInt16 n;
656     const SwSectionNode* pSectNd;
657     const SwSection* pSect;
658 
659     if(pChkStr && !pChkStr->Len())
660         pChkStr = 0;
661     String aName( rType.GetTypeName() );
662     xub_StrLen nNmLen = aName.Len();
663 
664     sal_uInt16 nNum = 0;
665     sal_uInt16 nTmp = 0;
666     sal_uInt16 nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
667     sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
668     memset( pSetFlags, 0, nFlagSize );
669 
670     for( n = 0; n < pSectionFmtTbl->Count(); ++n )
671         if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
672              TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
673         {
674             const String& rNm = pSect->GetSectionName();
675             if( rNm.Match( aName ) == nNmLen )
676             {
677                 // Nummer bestimmen und das Flag setzen
678                 nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
679                 if( nNum-- && nNum < pSectionFmtTbl->Count() )
680                     pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
681             }
682             if( pChkStr && pChkStr->Equals( rNm ) )
683                 pChkStr = 0;
684         }
685 
686     if( !pChkStr )
687     {
688         // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
689         nNum = pSectionFmtTbl->Count();
690         for( n = 0; n < nFlagSize; ++n )
691             if( 0xff != ( nTmp = pSetFlags[ n ] ))
692             {
693                 // also die Nummer bestimmen
694                 nNum = n * 8;
695                 while( nTmp & 1 )
696                     ++nNum, nTmp >>= 1;
697                 break;
698             }
699     }
700     delete [] pSetFlags;
701     if( pChkStr )
702         return *pChkStr;
703     return aName += String::CreateFromInt32( ++nNum );
704 }
705 
706 sal_Bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
707 {
708     ASSERT( rTOXBase.ISA( SwTOXBaseSection ),
709                     "keine TOXBaseSection!" );
710     SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
711 
712     String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
713     sal_Bool bRet = sTmp == rName;
714     if(bRet)
715     {
716         pTOX->SetTOXName(rName);
717         pTOX->SetSectionName(rName);
718         SetModified();
719     }
720     return bRet;
721 }
722 
723 
724 const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
725 {
726     const SwNode* pNd = &rNd;
727     if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
728     {
729         // then find the "Anchor" (Body) position
730         Point aPt;
731         SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
732         const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
733 
734         if( pFrm )
735         {
736             SwPosition aPos( *pNd );
737             pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
738             ASSERT( pNd,    "wo steht der Absatz" );
739         }
740     }
741     return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
742 }
743 
744 
745 /*--------------------------------------------------------------------
746      Beschreibung: Verzeichnis-Klasse
747  --------------------------------------------------------------------*/
748 
749 SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
750     : SwTOXBase( rBase )
751     , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
752 {
753     SetProtect( rBase.IsProtected() );
754     SetSectionName( GetTOXName() );
755 }
756 
757 
758 SwTOXBaseSection::~SwTOXBaseSection()
759 {
760     aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );  // i120680
761 }
762 
763 
764 sal_Bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart ) const
765 {
766     sal_Bool bRet = sal_False;
767     const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
768     if( pSectNd )
769     {
770         SwCntntNode* pCNd;
771         xub_StrLen nC = 0;
772         if( bAtStart )
773         {
774             rPos.nNode = *pSectNd;
775             pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
776         }
777         else
778         {
779             rPos.nNode = *pSectNd->EndOfSectionNode();
780             pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
781             if( pCNd ) nC = pCNd->Len();
782         }
783         rPos.nContent.Assign( pCNd, nC );
784         bRet = sal_True;
785     }
786     return bRet;
787 }
788 
789 /*--------------------------------------------------------------------
790      Beschreibung: Verzeichnisinhalt zusammensammeln
791  --------------------------------------------------------------------*/
792 
793 void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
794                               const bool        _bNewTOX )//swmodtest 080307
795 {
796     const SwSectionNode* pSectNd;
797     if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
798         !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
799         !pSectNd->GetNodes().IsDocNodes() ||
800         IsHiddenFlag() )
801     {
802         return;
803     }
804 
805     if ( !mbKeepExpression )
806     {
807         maMSTOCExpression = String();
808     }
809 
810     SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
811 
812     DBG_ASSERT(pDoc != NULL, "Where is the document?");
813 
814     if(pAttr && pDoc && GetFmt())
815         pDoc->ChgFmt(*GetFmt(), *pAttr);
816 
817     // OD 18.03.2003 #106329# - determine default page description, which
818     // will be used by the content nodes, if no approriate one is found.
819     const SwPageDesc* pDefaultPageDesc;
820     {
821         pDefaultPageDesc =
822             pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
823         if ( !_bNewTOX && !pDefaultPageDesc )
824         {
825             // determine page description of table-of-content
826             sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
827             sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
828             pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
829             if ( nPgDescNdIdx < pSectNd->GetIndex() )
830             {
831                 pDefaultPageDesc = 0;
832             }
833         }
834         // OD 28.04.2003 #109166# - consider end node of content section in the
835         // node array.
836         if ( !pDefaultPageDesc &&
837              ( pSectNd->EndOfSectionNode()->GetIndex() <
838                  (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
839            )
840         {
841             // determine page description of content after table-of-content
842             SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
843             const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
844             const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
845             const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
846             if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
847                     eBreak == SVX_BREAK_PAGE_BOTH )
848                )
849             {
850                 pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
851             }
852         }
853         // OD 28.04.2003 #109166# - consider start node of content section in
854         // the node array.
855         if ( !pDefaultPageDesc &&
856              ( pSectNd->GetIndex() >
857                  (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
858            )
859         {
860             // determine page description of content before table-of-content
861             SwNodeIndex aIdx( *pSectNd );
862             pDefaultPageDesc =
863                 pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
864 
865         }
866         if ( !pDefaultPageDesc )
867         {
868             // determine default page description
869             pDefaultPageDesc =
870                 &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
871         }
872     }
873 
874     pDoc->SetModified();
875 
876     // get current Language
877     SwTOXInternational aIntl(  GetLanguage(),
878                                TOX_INDEX == GetTOXType()->GetType() ?
879                                GetOptions() : 0,
880                                GetSortAlgorithm() );
881 
882     aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
883 
884     // find the first layout node for this TOX, if it only find the content
885     // in his own chapter
886     const SwTxtNode* pOwnChapterNode = IsFromChapter()
887             ? ::lcl_FindChapterNode( *pSectNd, 0 )
888             : 0;
889 
890     SwNode2Layout aN2L( *pSectNd );
891     ((SwSectionNode*)pSectNd)->DelFrms();
892 
893     // remove old content an insert one empty textnode (to hold the layout!)
894     SwTxtNode* pFirstEmptyNd;
895     {
896         pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
897 
898         SwNodeIndex aSttIdx( *pSectNd, +1 );
899         SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
900         pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
901                         pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
902 
903         {
904             // Task 70995 - save and restore PageDesc and Break Attributes
905             SwNodeIndex aNxtIdx( aSttIdx );
906             const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
907             if( !pCNd )
908                 pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
909             if( pCNd->HasSwAttrSet() )
910             {
911                 SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
912                 aBrkSet.Put( *pCNd->GetpSwAttrSet() );
913                 if( aBrkSet.Count() )
914                     pFirstEmptyNd->SetAttr( aBrkSet );
915             }
916         }
917         aEndIdx--;
918         SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
919         pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
920 
921         // delete all before
922         DelFlyInRange( aSttIdx, aEndIdx );
923         _DelBookmarks( aSttIdx, aEndIdx );
924 
925         pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
926 
927     }
928 
929     //
930     // insert title of TOX
931     if( GetTitle().Len() )
932     {
933         // then insert the headline section
934         SwNodeIndex aIdx( *pSectNd, +1 );
935 
936         SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
937                                 GetTxtFmtColl( FORM_TITLE ) );
938         pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
939 
940         String sNm( GetTOXName() );
941 // ??Resource
942 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
943 
944         SwSectionData headerData( TOX_HEADER_SECTION, sNm );
945 
946         SwNodeIndex aStt( *pHeadNd ); aIdx--;
947         SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
948         pDoc->GetNodes().InsertTextSection(
949                 aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
950     }
951 
952     // jetzt waere ein prima Zeitpunkt, um die Numerierung zu updaten
953     pDoc->UpdateNumRule();
954 
955     if( GetCreateType() & nsSwTOXElement::TOX_MARK )
956         UpdateMarks( aIntl, pOwnChapterNode );
957 
958     if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
959         UpdateOutline( pOwnChapterNode );
960 
961     if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
962         UpdateTemplate( pOwnChapterNode );
963 
964     if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
965             TOX_OBJECTS == SwTOXBase::GetType())
966         UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
967 
968     if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
969             (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
970         UpdateTable( pOwnChapterNode );
971 
972     if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
973         (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
974         UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
975 
976     if( GetSequenceName().Len() && !IsFromObjectNames() &&
977         (TOX_TABLES == SwTOXBase::GetType() ||
978          TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
979         UpdateSequence( pOwnChapterNode );
980 
981     if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
982         UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
983 
984     if(TOX_AUTHORITIES == SwTOXBase::GetType())
985         UpdateAuthorities( aIntl );
986 
987     // Bei Bedarf Alphadelimitter einfuegen (nur bei Stichwoertern)
988     //
989     if( TOX_INDEX == SwTOXBase::GetType() &&
990         ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
991         InsertAlphaDelimitter( aIntl );
992 
993     // sortierte Liste aller Verzeichnismarken und Verzeichnisbereiche
994     void* p = 0;
995     String* pStr = 0;
996     sal_uInt16 nCnt = 0, nFormMax = GetTOXForm().GetFormMax();
997     SvStringsDtor aStrArr( (sal_uInt8)nFormMax );
998     SvPtrarr aCollArr( (sal_uInt8)nFormMax );
999     for( ; nCnt < nFormMax; ++nCnt )
1000     {
1001         aCollArr.Insert( p, nCnt );
1002         aStrArr.Insert( pStr, nCnt );
1003     }
1004 
1005     SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
1006     for( nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
1007     {
1008         ::SetProgressState( 0, pDoc->GetDocShell() );
1009 
1010         // setze den Text in das Verzeichniss
1011         sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
1012         SwTxtFmtColl* pColl = (SwTxtFmtColl*)aCollArr[ nLvl ];
1013         if( !pColl )
1014         {
1015             pColl = GetTxtFmtColl( nLvl );
1016             aCollArr.Remove( nLvl );
1017             p = pColl;
1018             aCollArr.Insert( p , nLvl );
1019         }
1020 
1021         // Generierung: dynamische TabStops setzen
1022         SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
1023         aSortArr[ nCnt ]->pTOXNd = pTOXNd;
1024 
1025         // Generierung: Form auswerten und Platzhalter
1026         //              fuer die Seitennummer eintragen
1027         //if it is a TOX_INDEX and the SwForm IsCommaSeparated()
1028         // then a range of entries must be generated into one paragraph
1029         sal_uInt16 nRange = 1;
1030         if(TOX_INDEX == SwTOXBase::GetType() &&
1031                 GetTOXForm().IsCommaSeparated() &&
1032                 aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1033         {
1034             const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1035             const String sPrimKey = rMark.GetPrimaryKey();
1036             const String sSecKey = rMark.GetSecondaryKey();
1037             const SwTOXMark* pNextMark = 0;
1038             while(aSortArr.Count() > (nCnt + nRange)&&
1039                     aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1040                     0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1041                     pNextMark->GetPrimaryKey() == sPrimKey &&
1042                     pNextMark->GetSecondaryKey() == sSecKey)
1043                 nRange++;
1044         }
1045         // OD 18.03.2003 #106329# - pass node index of table-of-content section
1046         // and default page description to method <GenerateText(..)>.
1047         GenerateText( nCnt, nRange, aStrArr, pSectNd->GetIndex(), pDefaultPageDesc );
1048         nCnt += nRange - 1;
1049     }
1050 
1051     // delete the first dummy node and remove all Cursor into the prev node
1052     aInsPos = *pFirstEmptyNd;
1053     {
1054         SwPaM aCorPam( *pFirstEmptyNd );
1055         aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
1056         if( !aCorPam.Move( fnMoveForward ) )
1057             aCorPam.Move( fnMoveBackward );
1058         SwNodeIndex aEndIdx( aInsPos, 1 );
1059         pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
1060 
1061         // Task 70995 - save and restore PageDesc and Break Attributes
1062         if( pFirstEmptyNd->HasSwAttrSet() )
1063         {
1064             if( GetTitle().Len() )
1065                 aEndIdx = *pSectNd;
1066             else
1067                 aEndIdx = *pFirstEmptyNd;
1068             SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
1069             if( pCNd ) // Robust against defect documents, e.g. i60336
1070                 pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
1071         }
1072     }
1073 
1074     // now create the new Frames
1075     sal_uLong nIdx = pSectNd->GetIndex();
1076     // don't delete if index is empty
1077     if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1078         pDoc->GetNodes().Delete( aInsPos, 1 );
1079 
1080     aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1081     std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1082     for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); pLayoutIter++)
1083     {
1084         SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
1085     }//swmod 080310
1086 
1087     SetProtect( SwTOXBase::IsProtected() );
1088 }
1089 
1090 /*--------------------------------------------------------------------
1091      Beschreibung: AlphaDelimitter einfuegen
1092  --------------------------------------------------------------------*/
1093 
1094 
1095 void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1096 {
1097     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1098     String sDeli, sLastDeli;
1099     sal_uInt16  i = 0;
1100     while( i < aSortArr.Count() )
1101     {
1102         ::SetProgressState( 0, pDoc->GetDocShell() );
1103 
1104         sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1105 
1106         // Alpha-Delimitter ueberlesen
1107         if( nLevel == FORM_ALPHA_DELIMITTER )
1108             continue;
1109 
1110         String sMyString, sMyStringReading;
1111         aSortArr[i]->GetTxt( sMyString, sMyStringReading );
1112 
1113         sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
1114                                    aSortArr[i]->GetLocale() );
1115 
1116         // Delimitter schon vorhanden ??
1117         if( sDeli.Len() && sLastDeli != sDeli )
1118         {
1119             // alle kleiner Blank wollen wir nicht haben -> sind Sonderzeichen
1120             if( ' ' <= sDeli.GetChar( 0 ) )
1121             {
1122                 SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
1123                                                      rIntl, aSortArr[i]->GetLocale() );
1124                 aSortArr.Insert( pCst, i++ );
1125             }
1126             sLastDeli = sDeli;
1127         }
1128 
1129         // Skippen bis gleibhes oder kleineres Level erreicht ist
1130         do {
1131             i++;
1132         } while (i < aSortArr.Count() && aSortArr[i]->GetLevel() > nLevel);
1133     }
1134 }
1135 
1136 /*--------------------------------------------------------------------
1137      Beschreibung: Template  auswerten
1138  --------------------------------------------------------------------*/
1139 
1140 SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
1141 {
1142     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1143     const String& rName = GetTOXForm().GetTemplate( nLevel );
1144     SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
1145     if( !pColl )
1146     {
1147         sal_uInt16 nPoolFmt = 0;
1148         const TOXTypes eMyType = SwTOXBase::GetType();
1149         switch( eMyType )
1150         {
1151         case TOX_INDEX:         nPoolFmt = RES_POOLCOLL_TOX_IDXH;       break;
1152         case TOX_USER:
1153             if( nLevel < 6 )
1154                 nPoolFmt = RES_POOLCOLL_TOX_USERH;
1155             else
1156                 nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
1157             break;
1158         case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH;     break;
1159         case TOX_OBJECTS:       nPoolFmt = RES_POOLCOLL_TOX_OBJECTH;    break;
1160         case TOX_TABLES:        nPoolFmt = RES_POOLCOLL_TOX_TABLESH;    break;
1161         case TOX_AUTHORITIES:   nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1162 
1163         case TOX_CONTENT:
1164             // im Content Bereich gibt es einen Sprung!
1165             if( nLevel < 6 )
1166                 nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
1167             else
1168                 nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
1169             break;
1170         }
1171 
1172         if(eMyType == TOX_AUTHORITIES && nLevel)
1173             nPoolFmt = nPoolFmt + 1;
1174         else if(eMyType == TOX_INDEX && nLevel)
1175         {
1176             //pool: Level 1,2,3, Delimiter
1177             //SwForm: Delimiter, Level 1,2,3
1178             nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1179         }
1180         else
1181             nPoolFmt = nPoolFmt + nLevel;
1182         pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
1183     }
1184     return pColl;
1185 }
1186 
1187 
1188 /*--------------------------------------------------------------------
1189      Beschreibung: Aus Markierungen erzeugen
1190  --------------------------------------------------------------------*/
1191 
1192 void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1193                                     const SwTxtNode* pOwnChapterNode )
1194 {
1195     const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
1196     if( !pType->GetDepends() )
1197         return;
1198 
1199     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1200     TOXTypes eTOXTyp = GetTOXType()->GetType();
1201     SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1202 
1203     SwTxtTOXMark* pTxtMark;
1204     SwTOXMark* pMark;
1205     for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1206     {
1207         ::SetProgressState( 0, pDoc->GetDocShell() );
1208 
1209         if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1210             0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
1211         {
1212             const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
1213             // nur TOXMarks einfuegen die im Doc stehen
1214             // nicht die, die im UNDO stehen
1215             //
1216             // if selected use marks from the same chapter only
1217             if( pTOXSrc->GetNodes().IsDocNodes() &&
1218                 pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
1219                 pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1220                (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1221                !pTOXSrc->HasHiddenParaField() &&
1222                !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
1223             {
1224                 SwTOXSortTabBase* pBase = 0;
1225                 if(TOX_INDEX == eTOXTyp)
1226                 {
1227                     // Stichwortverzeichnismarkierung
1228                     lang::Locale aLocale;
1229                     if ( pBreakIt->GetBreakIter().is() )
1230                     {
1231                         aLocale = pBreakIt->GetLocale(
1232                                         pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
1233                     }
1234 
1235                     pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1236                                             GetOptions(), FORM_ENTRY, rIntl, aLocale );
1237                     InsertSorted(pBase);
1238                     if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1239                         pTxtMark->GetTOXMark().GetPrimaryKey().Len())
1240                     {
1241                         pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1242                                                 GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1243                         InsertSorted(pBase);
1244                         if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
1245                         {
1246                             pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1247                                                     GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1248                             InsertSorted(pBase);
1249                         }
1250                     }
1251                 }
1252                 else if( TOX_USER == eTOXTyp ||
1253                     pMark->GetLevel() <= GetLevel())
1254                 {   // Inhaltsberzeichnismarkierung
1255                     // also used for user marks
1256                     pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
1257                     InsertSorted(pBase);
1258                 }
1259             }
1260         }
1261     }
1262 }
1263 
1264 
1265 /*--------------------------------------------------------------------
1266      Beschreibung:  Verzeichnisinhalt aus Gliederungsebene generieren
1267  --------------------------------------------------------------------*/
1268 
1269 
1270 void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
1271 {
1272     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1273     SwNodes& rNds = pDoc->GetNodes();
1274 
1275     const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1276     for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
1277     {
1278         ::SetProgressState( 0, pDoc->GetDocShell() );
1279         SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
1280         if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
1281             //sal_uInt16(pTxtNd->GetTxtColl()->GetOutlineLevel()+1) <= GetLevel() &&    //#outline level,zhaojianwei
1282             sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() && //<-end,zhaojianwei
1283             pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1284            !pTxtNd->HasHiddenParaField() &&
1285            !pTxtNd->HasHiddenCharAttribute( true ) &&
1286             ( !IsFromChapter() ||
1287                ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
1288         {
1289             SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1290             InsertSorted( pNew );
1291         }
1292     }
1293 }
1294 
1295 /*--------------------------------------------------------------------
1296      Beschreibung: Verzeichnisinhalt aus Vorlagenbereichen generieren
1297  --------------------------------------------------------------------*/
1298 
1299 void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
1300 {
1301     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1302     for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1303     {
1304         String sTmpStyleNames = GetStyleNames(i);
1305         sal_uInt16 nTokenCount = sTmpStyleNames.GetTokenCount(TOX_STYLE_DELIMITER);
1306         for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
1307         {
1308             SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
1309                                     sTmpStyleNames.GetToken( nStyle,
1310                                                     TOX_STYLE_DELIMITER ));
1311             //TODO: no outline Collections in content indexes if OutlineLevels are already included
1312             if( !pColl ||
1313                 ( TOX_CONTENT == SwTOXBase::GetType() &&
1314                   GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1315                   //NO_NUMBERING != pColl->GetOutlineLevel() ) )//#outline level,zhaojianwei
1316                     pColl->IsAssignedToListLevelOfOutlineStyle()) )//<-end,zhaojianwei
1317                   continue;
1318 
1319             SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
1320             for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
1321             {
1322                 ::SetProgressState( 0, pDoc->GetDocShell() );
1323 
1324                 if( pTxtNd->GetTxt().Len() && pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1325                     pTxtNd->GetNodes().IsDocNodes() &&
1326                     ( !IsFromChapter() || pOwnChapterNode ==
1327                         ::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
1328                 {
1329                     SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1330                     InsertSorted(pNew);
1331                 }
1332             }
1333         }
1334     }
1335 }
1336 
1337 /* -----------------14.07.99 09:59-------------------
1338     Description: generate content from sequence fields
1339  --------------------------------------------------*/
1340 void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
1341 {
1342     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1343     SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
1344     if(!pSeqFld)
1345         return;
1346 
1347     SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
1348     for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1349     {
1350         const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1351         if(!pTxtFld)
1352             continue;
1353         const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1354         ::SetProgressState( 0, pDoc->GetDocShell() );
1355 
1356         if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1357             rTxtNode.GetNodes().IsDocNodes() &&
1358             ( !IsFromChapter() ||
1359                 ::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
1360         {
1361             SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
1362             //set indexes if the number or the reference text are to be displayed
1363             if( GetCaptionDisplay() == CAPTION_TEXT )
1364             {
1365                 pNew->SetStartIndex(
1366                     SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
1367             }
1368             else if(GetCaptionDisplay() == CAPTION_NUMBER)
1369             {
1370                 pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
1371             }
1372             InsertSorted(pNew);
1373         }
1374     }
1375 }
1376 
1377 void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1378 {
1379     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1380     SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
1381     if(!pAuthFld)
1382         return;
1383 
1384     SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
1385     for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1386     {
1387         const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1388         //undo
1389         if(!pTxtFld)
1390             continue;
1391         const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1392         ::SetProgressState( 0, pDoc->GetDocShell() );
1393 
1394 //      const SwTxtNode* pChapterCompareNode = 0;
1395 
1396         if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1397             rTxtNode.GetNodes().IsDocNodes() /*&&
1398             (!IsFromChapter() || pChapterCompareNode == pOwnChapterNode) */)
1399         {
1400             //#106485# the body node has to be used!
1401             SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
1402             SwPosition aFldPos(rTxtNode);
1403             const SwTxtNode* pTxtNode = 0;
1404             if(pFrm && !pFrm->IsInDocBody())
1405                 pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
1406             if(!pTxtNode)
1407                 pTxtNode = &rTxtNode;
1408             SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
1409 
1410             InsertSorted(pNew);
1411         }
1412     }
1413 }
1414 
1415 long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1416 {
1417     static struct _SoObjType {
1418         long nFlag;
1419         // GlobalNameId
1420         struct _GlobalNameIds {
1421             sal_uInt32 n1;
1422             sal_uInt16 n2, n3;
1423             sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1424         } aGlNmIds[4];
1425     } aArr[] = {
1426         { nsSwTOOElements::TOO_MATH,
1427           { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1428             {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1429         { nsSwTOOElements::TOO_CHART,
1430           { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1431             {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1432         { nsSwTOOElements::TOO_CALC,
1433           { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1434             {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1435         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1436           { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1437             {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1438         { nsSwTOOElements::TOO_DRAW_IMPRESS,
1439           { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1440         { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1441             {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1442     };
1443 
1444     long nRet = 0;
1445     for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1446         for ( int n = 0; n < 4; ++n )
1447         {
1448             const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1449             if( !rId.n1 )
1450                 break;
1451             SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1452                         rId.b8, rId.b9, rId.b10, rId.b11,
1453                         rId.b12, rId.b13, rId.b14, rId.b15 );
1454             if( rFactoryNm == aGlbNm )
1455             {
1456                 nRet = pArr->nFlag;
1457                 break;
1458             }
1459         }
1460 
1461     return nRet;
1462 }
1463 
1464 void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
1465                                     const SwTxtNode* pOwnChapterNode )
1466 {
1467     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1468     SwNodes& rNds = pDoc->GetNodes();
1469     // auf den 1. Node der 1. Section
1470     sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1471          nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1472 
1473     while( nIdx < nEndIdx )
1474     {
1475         ::SetProgressState( 0, pDoc->GetDocShell() );
1476 
1477         SwNode* pNd = rNds[ nIdx ];
1478         SwCntntNode* pCNd = 0;
1479         switch( eMyType )
1480         {
1481         case nsSwTOXElement::TOX_FRAME:
1482             if( !pNd->IsNoTxtNode() )
1483             {
1484                 pCNd = pNd->GetCntntNode();
1485                 if( !pCNd )
1486                 {
1487                     SwNodeIndex aTmp( *pNd );
1488                     pCNd = rNds.GoNext( &aTmp );
1489                 }
1490             }
1491             break;
1492         case nsSwTOXElement::TOX_GRAPHIC:
1493             if( pNd->IsGrfNode() )
1494                 pCNd = (SwCntntNode*)pNd;
1495             break;
1496         case nsSwTOXElement::TOX_OLE:
1497             if( pNd->IsOLENode() )
1498             {
1499                 sal_Bool bInclude = sal_True;
1500                 if(TOX_OBJECTS == SwTOXBase::GetType())
1501                 {
1502                     SwOLENode* pOLENode = pNd->GetOLENode();
1503                     long nMyOLEOptions = GetOLEOptions();
1504                     SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1505 
1506                     if( rOLEObj.IsOleRef() )    //Noch nicht geladen
1507                     {
1508                         SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1509                         long nObj = ::lcl_IsSOObject( aTmpName );
1510                         bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1511                                                     || (0 != (nMyOLEOptions & nObj));
1512                     }
1513                     else
1514                     {
1515                         DBG_ERROR("OLE-object nicht geladen?");
1516                         bInclude = sal_False;
1517                     }
1518                 }
1519 
1520                 if(bInclude)
1521                     pCNd = (SwCntntNode*)pNd;
1522             }
1523             break;
1524         default: break;
1525         }
1526 
1527         if( pCNd )
1528         {
1529             //find node in body text
1530             int nSetLevel = USHRT_MAX;
1531 
1532             //#111105# tables of tables|illustrations|objects don't support hierarchies
1533             if( IsLevelFromChapter() &&
1534                     TOX_TABLES != SwTOXBase::GetType() &&
1535                     TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1536                     TOX_OBJECTS != SwTOXBase::GetType() )
1537             {
1538                 const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1539                                                         MAXLEVEL - 1 );
1540                 if( pOutlNd )
1541                 {
1542                     //sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1543                     //if( nTmp < NO_NUMBERING )
1544                     //  nSetLevel = nTmp + 1;
1545                     if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1546                         nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
1547                 }
1548             }
1549 
1550             if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
1551                     ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1552             {
1553                 SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1554                             ( USHRT_MAX != nSetLevel )
1555                             ? static_cast<sal_uInt16>(nSetLevel)
1556                             : FORM_ALPHA_DELIMITTER );
1557                 InsertSorted( pNew );
1558             }
1559         }
1560 
1561         nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2;  // 2 == End-/StartNode
1562     }
1563 }
1564 
1565 /*--------------------------------------------------------------------
1566      Beschreibung:  Tabelleneintraege zusammensuchen
1567  --------------------------------------------------------------------*/
1568 
1569 void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
1570 {
1571     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1572     SwNodes& rNds = pDoc->GetNodes();
1573     const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
1574 
1575     for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
1576     {
1577         ::SetProgressState( 0, pDoc->GetDocShell() );
1578 
1579         SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
1580         SwTableBox* pFBox;
1581         if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
1582             pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1583         {
1584             const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
1585             SwNodeIndex aCntntIdx( *pTblNd, 1 );
1586 
1587             SwCntntNode* pCNd;
1588             while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
1589                 aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
1590             {
1591                 if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
1592                     ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1593                 {
1594                     SwTOXTable * pNew = new SwTOXTable( *pCNd );
1595                     if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1596                     {
1597                         const SwTxtNode* pOutlNd =
1598                             ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1599                         if( pOutlNd )
1600                         {
1601                             //sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
1602                             //if( nTmp < NO_NUMBERING )
1603                             //  pNew->SetLevel( nTmp + 1 );
1604                             if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1605                             {
1606                                 const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
1607                                 pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
1608                             }
1609                         }
1610                     }
1611                     InsertSorted(pNew);
1612                     break;
1613                 }
1614             }
1615         }
1616     }
1617 }
1618 
1619 /*--------------------------------------------------------------------
1620      Beschreibung:  String generieren anhand der Form
1621                     SonderZeichen 0-31 und 255 entfernen
1622  --------------------------------------------------------------------*/
1623 
1624 String lcl_GetNumString( const SwTOXSortTabBase& rBase, sal_Bool bUsePrefix, sal_uInt8 nLevel )
1625 {
1626     String sRet;
1627 
1628     if( !rBase.pTxtMark && rBase.aTOXSources.Count() > 0 )
1629     {   // nur wenn es keine Marke ist
1630         const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
1631         if( pNd )
1632         {
1633             const SwNumRule* pRule = pNd->GetNumRule();
1634 
1635             if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
1636                 sRet = pNd->GetNumString(bUsePrefix, nLevel);
1637         }
1638     }
1639     return sRet;
1640 }
1641 
1642 // OD 18.03.2003 #106329# - add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc>
1643 // in order to control, which page description is used, no appropriate one is found.
1644 void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
1645                                      sal_uInt16 nCount,
1646                                      SvStringsDtor& ,
1647                                      const sal_uInt32   _nTOXSectNdIdx,
1648                                      const SwPageDesc*  _pDefaultPageDesc )
1649 {
1650     LinkStructArr   aLinkArr;
1651     SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1652     ::SetProgressState( 0, pDoc->GetDocShell() );
1653 
1654     //pTOXNd is only set at the first mark
1655     SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
1656     String& rTxt = (String&)pTOXNd->GetTxt();
1657     rTxt.Erase();
1658     for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
1659     {
1660         if(nIndex > nArrayIdx)
1661             rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
1662         // String mit dem Pattern aus der Form initialisieren
1663         const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
1664         sal_uInt16 nLvl = rBase.GetLevel();
1665         ASSERT( nLvl < GetTOXForm().GetFormMax(), "ungueltiges FORM_LEVEL");
1666 
1667         SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1668         xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
1669         String  sLinkCharacterStyle; //default to "Default" character style - which is none
1670         String sURL;
1671         // create an enumerator
1672         // #i21237#
1673         SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
1674         SwFormTokens::iterator aIt = aPattern.begin();
1675         // remove text from node
1676         while(aIt != aPattern.end()) // #i21237#
1677         {
1678             SwFormToken aToken = *aIt; // #i21237#
1679             xub_StrLen nStartCharStyle = rTxt.Len();
1680             switch( aToken.eTokenType )
1681             {
1682             case TOKEN_ENTRY_NO:
1683                 // fuer Inhaltsverzeichnis Numerierung
1684                 rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
1685                 break;
1686 
1687             case TOKEN_ENTRY_TEXT:
1688                 {
1689                     SwIndex aIdx( pTOXNd, rTxt.Len() );
1690                     rBase.FillText( *pTOXNd, aIdx );
1691                 }
1692                 break;
1693 
1694             case TOKEN_ENTRY:
1695                 {
1696                     // fuer Inhaltsverzeichnis Numerierung
1697                     rTxt.Insert( lcl_GetNumString( rBase, sal_True, MAXLEVEL ));
1698 
1699                     SwIndex aIdx( pTOXNd, rTxt.Len() );
1700                     rBase.FillText( *pTOXNd, aIdx );
1701                 }
1702                 break;
1703 
1704             case TOKEN_TAB_STOP:
1705                 if (aToken.bWithTab) // #i21237#
1706                     rTxt.Append('\t');
1707                 //
1708 
1709                 if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
1710                 {
1711                     const SvxLRSpaceItem& rLR =
1712                         (SvxLRSpaceItem&)pTOXNd->
1713                         SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
1714 
1715                     long nTabPosition = aToken.nTabStopPosition;
1716                     if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
1717                         nTabPosition -= rLR.GetTxtLeft();
1718                     aTStops.Insert( SvxTabStop( nTabPosition,
1719                                                 aToken.eTabAlign,
1720                                                 cDfltDecimalChar,
1721                                                 aToken.cTabFillChar ));
1722                 }
1723                 else
1724                 {
1725                     const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
1726                                 SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
1727 
1728                     sal_Bool bCallFindRect = sal_True;
1729                     long nRightMargin;
1730                     if( pPageDesc )
1731                     {
1732                         const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
1733                         if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
1734                             pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
1735                             // dann muss man ueber den PageDesc gehen
1736                             bCallFindRect = sal_False;
1737                     }
1738 
1739                     SwRect aNdRect;
1740                     if( bCallFindRect )
1741                         aNdRect = pTOXNd->FindLayoutRect( sal_True );
1742 
1743                     if( aNdRect.IsEmpty() )
1744                     {
1745                         // dann hilft alles nichts, wir muessen ueber die Seiten-
1746                         // vorlage gehen.
1747                         // OD 18.03.2003 #106329# - call
1748                         sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
1749                         sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
1750                         pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
1751                         if ( !pPageDesc ||
1752                              *pPgDescNdIdx < _nTOXSectNdIdx )
1753                         {
1754                             // use default page description, if none is found
1755                             // or the found one is given by a node before the
1756                             // table-of-content section.
1757                             pPageDesc = _pDefaultPageDesc;
1758                         }
1759 
1760                         const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
1761                         nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
1762                                         rPgDscFmt.GetLRSpace().GetLeft() -
1763                                         rPgDscFmt.GetLRSpace().GetRight();
1764                     }
1765                     else
1766                         nRightMargin = aNdRect.Width();
1767                     //#i24363# tab stops relative to indent
1768                     if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
1769                     {
1770                         //left margin of paragraph style
1771                         const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
1772                         nRightMargin -= rLRSpace.GetLeft();
1773                         nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
1774                     }
1775 
1776                     aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
1777                                                 cDfltDecimalChar,
1778                                                 aToken.cTabFillChar ));
1779                 }
1780                 break;
1781 
1782             case TOKEN_TEXT:
1783                 rTxt.Append( aToken.sText );
1784                 break;
1785 
1786             case TOKEN_PAGE_NUMS:
1787                     // Platzhalter fuer Seitennummer(n) es wird nur der erste beachtet
1788                     //
1789                 {
1790                     // Die Anzahl der gleichen Eintrage bestimmt die Seitennummern-Pattern
1791                     //
1792                     sal_uInt16 nSize = rBase.aTOXSources.Count();
1793                     if( nSize > 0 )
1794                     {
1795                         String aInsStr( cNumRepl );
1796                         for(sal_uInt16 i=1; i < nSize; ++i)
1797                         {
1798                             aInsStr.AppendAscii( sPageDeli );
1799                             aInsStr += cNumRepl;
1800                         }
1801                         aInsStr += cEndPageNum;
1802                         rTxt.Append( aInsStr );
1803                     }
1804 //                      // Tab entfernen, wenn keine Seitennummer
1805 //                  else if( rTxt.Len() && '\t' == rTxt.GetChar( rTxt.Len() - 1 ))
1806 //                      rTxt.Erase( rTxt.Len()-1, 1 );
1807                 }
1808                 break;
1809 
1810             case TOKEN_CHAPTER_INFO:
1811                 {
1812                     // ein bischen trickreich: suche irgend einen Frame
1813                     const SwTOXSource* pTOXSource = 0;
1814                     if(rBase.aTOXSources.Count())
1815                         pTOXSource = &rBase.aTOXSources[0];
1816 
1817                     // --> OD 2008-02-14 #i53420#
1818 //                    if( pTOXSource && pTOXSource->pNd
1819 //                        pTOXSource->pNd->IsTxtNode() )
1820                     if ( pTOXSource && pTOXSource->pNd &&
1821                          pTOXSource->pNd->IsCntntNode() )
1822                     // <--
1823                     {
1824                         const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1825                         if( pFrm )
1826                         {
1827                             SwChapterFieldType aFldTyp;
1828                             SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
1829                             aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
1830                             // --> OD 2008-02-14 #i53420#
1831 //                            aFld.ChangeExpansion( pFrm, (SwTxtNode*)pTOXSource->pNd, sal_True );
1832                             aFld.ChangeExpansion( pFrm,
1833                                 dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
1834                                 sal_True );
1835                             // <--
1836                             //---> i89791
1837                             // OD 2008-06-26 - continue to support CF_NUMBER
1838                             // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
1839                             // written by OOo 3.x in the same way as OOo 2.x
1840                             // would handle them.
1841                             if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
1842                                  CF_NUMBER == aToken.nChapterFormat )
1843                                 rTxt.Insert(aFld.GetNumber()); //get the string number without pre/postfix
1844                             else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
1845                                       CF_NUM_TITLE == aToken.nChapterFormat )
1846                             //<---
1847                             {
1848                                 rTxt += aFld.GetNumber();
1849                                 rTxt += ' ';
1850                                 rTxt += aFld.GetTitle();
1851                             }
1852                             else if(CF_TITLE == aToken.nChapterFormat)
1853                                 rTxt += aFld.GetTitle();
1854                         }
1855                     }
1856                 }
1857                 break;
1858 
1859             case TOKEN_LINK_START:
1860                 nLinkStartPosition = rTxt.Len();
1861                 sLinkCharacterStyle = aToken.sCharStyleName;
1862             break;
1863 
1864             case TOKEN_LINK_END:
1865                     //TODO: only paired start/end tokens are valid
1866                 if( STRING_NOTFOUND != nLinkStartPosition)
1867                 {
1868                     SwIndex aIdx( pTOXNd, nLinkStartPosition );
1869                     //pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
1870                     xub_StrLen nEnd = rTxt.Len();
1871 
1872                     if( !sURL.Len() )
1873                     {
1874                         sURL = rBase.GetURL();
1875                         if( !sURL.Len() )
1876                             break;
1877                     }
1878                     LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
1879                                                     nEnd);
1880                     const sal_uInt16 nPoolId =
1881                             sLinkCharacterStyle.Len() == 0
1882                             ? USHRT_MAX
1883                             : SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1884                     pNewLink->aINetFmt.SetVisitedFmtAndId( sLinkCharacterStyle, nPoolId );
1885                     pNewLink->aINetFmt.SetINetFmtAndId( sLinkCharacterStyle, nPoolId );
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             const xub_StrLen nTmpEnd = pAttr->End() ? *pAttr->End() : 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