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