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