update credits
[LibreOffice.git] / sw / source / core / doc / doctxm.cxx
blob6498585a79fb6acc12553e05e8f27cdb005885f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <limits.h>
21 #include <hintids.hxx>
22 #include <comphelper/string.hxx>
23 #include <editeng/langitem.hxx>
24 #include <editeng/formatbreakitem.hxx>
25 #include <editeng/tstpitem.hxx>
26 #include <editeng/lrspitem.hxx>
27 #include <comphelper/classids.hxx>
28 #include <docsh.hxx>
29 #include <ndole.hxx>
30 #include <txttxmrk.hxx>
31 #include <fmtinfmt.hxx>
32 #include <fmtpdsc.hxx>
33 #include <frmfmt.hxx>
34 #include <fmtfsize.hxx>
35 #include <frmatr.hxx>
36 #include <pagedesc.hxx>
37 #include <doc.hxx>
38 #include <IDocumentUndoRedo.hxx>
39 #include <pagefrm.hxx>
40 #include <ndtxt.hxx>
41 #include <swtable.hxx>
42 #include <doctxm.hxx>
43 #include <txmsrt.hxx>
44 #include <rolbck.hxx>
45 #include <poolfmt.hxx>
46 #include <txtfrm.hxx>
47 #include <rootfrm.hxx>
48 #include <UndoAttribute.hxx>
49 #include <swundo.hxx>
50 #include <mdiexp.hxx>
51 #include <docary.hxx>
52 #include <charfmt.hxx>
53 #include <fchrfmt.hxx>
54 #include <fldbas.hxx>
55 #include <fmtfld.hxx>
56 #include <txtfld.hxx>
57 #include <expfld.hxx>
58 #include <chpfld.hxx>
59 #include <mvsave.hxx>
60 #include <node2lay.hxx>
61 #include <SwStyleNameMapper.hxx>
62 #include <breakit.hxx>
63 #include <editsh.hxx>
64 #include <scriptinfo.hxx>
65 #include <switerator.hxx>
67 using namespace ::com::sun::star;
69 const sal_Unicode cNumRepl = '@';
70 const sal_Unicode cEndPageNum = '~';
71 const sal_Char sPageDeli[] = ", ";
73 TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection ); // for RTTI
75 struct LinkStruct
77 SwFmtINetFmt aINetFmt;
78 xub_StrLen nStartTextPos, nEndTextPos;
80 LinkStruct( const String& rURL, xub_StrLen nStart, xub_StrLen nEnd )
81 : aINetFmt( rURL, aEmptyStr),
82 nStartTextPos( nStart),
83 nEndTextPos(nEnd) {}
86 typedef std::vector<LinkStruct*> LinkStructArr;
88 sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, std::vector<String>& rArr ) const
90 rArr.clear();
92 // Look up all Primary and Secondary via the Pool
93 const SwTxtTOXMark* pMark;
94 const SfxPoolItem* pItem;
95 const SwTOXType* pTOXType;
96 sal_uInt32 i, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
97 for( i = 0; i < nMaxItems; ++i )
98 if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ) ) &&
99 0!= ( pTOXType = ((SwTOXMark*)pItem)->GetTOXType()) &&
100 TOX_INDEX == pTOXType->GetType() &&
101 0 != ( pMark = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
102 pMark->GetpTxtNd() &&
103 pMark->GetpTxtNd()->GetNodes().IsDocNodes() )
105 const String* pStr;
106 if( TOI_PRIMARY == eTyp )
107 pStr = &((SwTOXMark*)pItem)->GetPrimaryKey();
108 else
109 pStr = &((SwTOXMark*)pItem)->GetSecondaryKey();
111 if( pStr->Len() )
112 rArr.push_back( *pStr );
115 return rArr.size();
118 /// Get current table of contents Mark.
119 sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
120 SwTOXMarks& rArr ) const
122 // search on Position rPos for all SwTOXMarks
123 SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
124 if( !pTxtNd || !pTxtNd->GetpSwpHints() )
125 return 0;
127 const SwpHints & rHts = *pTxtNd->GetpSwpHints();
128 const SwTxtAttr* pHt;
129 xub_StrLen nSttIdx;
130 const xub_StrLen *pEndIdx;
132 xub_StrLen nAktPos = rPos.nContent.GetIndex();
134 for( sal_uInt16 n = 0; n < rHts.Count(); ++n )
136 if( RES_TXTATR_TOXMARK != (pHt = rHts[n])->Which() )
137 continue;
138 if( ( nSttIdx = *pHt->GetStart() ) < nAktPos )
140 // also check the end
141 if( 0 == ( pEndIdx = pHt->GetEnd() ) ||
142 *pEndIdx <= nAktPos )
143 continue; // keep searching
145 else if( nSttIdx > nAktPos )
146 // If Hint's Start is greater than rPos, break, because
147 // the attributes are sorted by Start!
148 break;
150 SwTOXMark* pTMark = (SwTOXMark*) &pHt->GetTOXMark();
151 rArr.push_back( pTMark );
153 return rArr.size();
156 /// Delete table of contents Mark
157 void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
159 // hole den TextNode und
160 const SwTxtTOXMark* pTxtTOXMark = pTOXMark->GetTxtTOXMark();
161 OSL_ENSURE( pTxtTOXMark, "No TxtTOXMark, cannot be deleted" );
163 SwTxtNode& rTxtNd = const_cast<SwTxtNode&>(pTxtTOXMark->GetTxtNode());
164 OSL_ENSURE( rTxtNd.GetpSwpHints(), "cannot be deleted" );
166 if (GetIDocumentUndoRedo().DoesUndo())
168 // save attributes for Undo
169 SwUndoResetAttr* pUndo = new SwUndoResetAttr(
170 SwPosition( rTxtNd, SwIndex( &rTxtNd, *pTxtTOXMark->GetStart() ) ),
171 RES_TXTATR_TOXMARK );
172 GetIDocumentUndoRedo().AppendUndo( pUndo );
174 SwRegHistory aRHst( rTxtNd, &pUndo->GetHistory() );
175 rTxtNd.GetpSwpHints()->Register( &aRHst );
178 rTxtNd.DeleteAttribute( const_cast<SwTxtTOXMark*>(pTxtTOXMark) );
180 if (GetIDocumentUndoRedo().DoesUndo())
182 if( rTxtNd.GetpSwpHints() )
183 rTxtNd.GetpSwpHints()->DeRegister();
185 SetModified();
188 /// Travel between table of content Marks
189 class CompareNodeCntnt
191 sal_uLong nNode;
192 xub_StrLen nCntnt;
193 public:
194 CompareNodeCntnt( sal_uLong nNd, xub_StrLen nCnt )
195 : nNode( nNd ), nCntnt( nCnt ) {}
197 int operator==( const CompareNodeCntnt& rCmp ) const
198 { return nNode == rCmp.nNode && nCntnt == rCmp.nCntnt; }
199 int operator!=( const CompareNodeCntnt& rCmp ) const
200 { return nNode != rCmp.nNode || nCntnt != rCmp.nCntnt; }
201 int operator< ( const CompareNodeCntnt& rCmp ) const
202 { return nNode < rCmp.nNode ||
203 ( nNode == rCmp.nNode && nCntnt < rCmp.nCntnt); }
204 int operator<=( const CompareNodeCntnt& rCmp ) const
205 { return nNode < rCmp.nNode ||
206 ( nNode == rCmp.nNode && nCntnt <= rCmp.nCntnt); }
207 int operator> ( const CompareNodeCntnt& rCmp ) const
208 { return nNode > rCmp.nNode ||
209 ( nNode == rCmp.nNode && nCntnt > rCmp.nCntnt); }
210 int operator>=( const CompareNodeCntnt& rCmp ) const
211 { return nNode > rCmp.nNode ||
212 ( nNode == rCmp.nNode && nCntnt >= rCmp.nCntnt); }
215 const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
216 SwTOXSearch eDir, sal_Bool bInReadOnly )
218 const SwTxtTOXMark* pMark = rCurTOXMark.GetTxtTOXMark();
219 OSL_ENSURE(pMark, "pMark==0 invalid TxtTOXMark");
221 const SwTxtNode *pTOXSrc = pMark->GetpTxtNd();
223 CompareNodeCntnt aAbsIdx( pTOXSrc->GetIndex(), *pMark->GetStart() );
224 CompareNodeCntnt aPrevPos( 0, 0 );
225 CompareNodeCntnt aNextPos( ULONG_MAX, STRING_NOTFOUND );
226 CompareNodeCntnt aMax( 0, 0 );
227 CompareNodeCntnt aMin( ULONG_MAX, STRING_NOTFOUND );
229 const SwTOXMark* pNew = 0;
230 const SwTOXMark* pMax = &rCurTOXMark;
231 const SwTOXMark* pMin = &rCurTOXMark;
233 const SwTOXType* pType = rCurTOXMark.GetTOXType();
234 SwTOXMarks aMarks;
235 SwTOXMark::InsertTOXMarks( aMarks, *pType );
237 const SwTOXMark* pTOXMark;
238 const SwCntntFrm* pCFrm;
239 Point aPt;
240 for( sal_Int32 nMark=0; nMark<(sal_Int32)aMarks.size(); nMark++ )
242 pTOXMark = aMarks[nMark];
243 if( pTOXMark != &rCurTOXMark &&
244 0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
245 0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
246 0 != ( pCFrm = pTOXSrc->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False )) &&
247 ( bInReadOnly || !pCFrm->IsProtected() ))
249 CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
250 switch( eDir )
252 // The following (a bit more complicated) statements make it
253 // possible to also travel across Entries on the same (!)
254 // position. If someone has time, please feel free to optimize.
255 case TOX_SAME_PRV:
256 if( pTOXMark->GetText() != rCurTOXMark.GetText() )
257 break;
258 /* no break here */
259 case TOX_PRV:
260 if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
261 aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
262 (aAbsIdx == aAbsNew &&
263 (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
264 (!pNew ||
265 (pNew && (aPrevPos < aAbsIdx ||
266 sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
267 (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
268 sal_uLong(pTOXMark) > sal_uLong(pNew)) )
270 pNew = pTOXMark;
271 aPrevPos = aAbsNew;
272 if ( aAbsNew >= aMax )
274 aMax = aAbsNew;
275 pMax = pTOXMark;
278 break;
280 case TOX_SAME_NXT:
281 if( pTOXMark->GetText() != rCurTOXMark.GetText() )
282 break;
283 /* no break here */
284 case TOX_NXT:
285 if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
286 aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
287 (aAbsIdx == aAbsNew &&
288 (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
289 (!pNew ||
290 (pNew && (aNextPos > aAbsIdx ||
291 sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
292 (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
293 sal_uLong(pTOXMark) < sal_uLong(pNew)) )
295 pNew = pTOXMark;
296 aNextPos = aAbsNew;
297 if ( aAbsNew <= aMin )
299 aMin = aAbsNew;
300 pMin = pTOXMark;
303 break;
309 // We couldn't find a successor
310 // Use minimum or maximum
311 if(!pNew)
313 switch(eDir)
315 case TOX_PRV:
316 case TOX_SAME_PRV:
317 pNew = pMax;
318 break;
319 case TOX_NXT:
320 case TOX_SAME_NXT:
321 pNew = pMin;
322 break;
323 default:
324 pNew = &rCurTOXMark;
327 return *pNew;
330 const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
331 const SwTOXBase& rTOX,
332 const SfxItemSet* pSet,
333 bool bExpand )
335 GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
337 String sSectNm( rTOX.GetTOXName() );
338 sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
339 SwPaM aPam( rPos );
340 SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
341 SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
342 InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
343 if (pNewSection)
345 SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
346 pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
348 if( bExpand )
350 // add value for 2nd parameter = true to
351 // indicate, that a creation of a new table of content has to be performed.
352 // Value of 1st parameter = default value.
353 pNewSection->Update( 0, true );
355 else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
356 // insert title of TOX
358 // then insert the headline section
359 SwNodeIndex aIdx( *pSectNd, +1 );
361 SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
362 GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
364 String sNm( pNewSection->GetTOXName() );
365 // ??Resource
366 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
368 SwSectionData headerData( TOX_HEADER_SECTION, sNm );
370 SwNodeIndex aStt( *pHeadNd ); aIdx--;
371 SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
372 GetNodes().InsertTextSection(
373 aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
377 GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
379 return pNewSection;
382 const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
383 const SwTOXBase& rTOX,
384 const SfxItemSet* pSet )
386 // check for recursiv TOX
387 SwNode* pNd = GetNodes()[ nSttNd ];
388 SwSectionNode* pSectNd = pNd->FindSectionNode();
389 while( pSectNd )
391 SectionType eT = pSectNd->GetSection().GetType();
392 if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
393 return 0;
394 pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
397 String sSectNm( rTOX.GetTOXName() );
398 sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
400 SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
402 SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
403 SwSectionFmt* pFmt = MakeSectionFmt( 0 );
404 if(pSet)
405 pFmt->SetFmtAttr(*pSet);
407 // --aEnd; // End is inclusive in InsertSection
409 SwSectionNode *const pNewSectionNode =
410 GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
411 if (!pNewSectionNode)
413 DelSectionFmt( pFmt );
414 return 0;
417 SwTOXBaseSection *const pNewSection(
418 dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
419 pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
420 return pNewSection;
423 /// Get current table of contents
424 const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
426 const SwNode& rNd = rPos.nNode.GetNode();
427 const SwSectionNode* pSectNd = rNd.FindSectionNode();
428 while( pSectNd )
430 SectionType eT = pSectNd->GetSection().GetType();
431 if( TOX_CONTENT_SECTION == eT )
433 OSL_ENSURE( pSectNd->GetSection().ISA( SwTOXBaseSection ),
434 "no TOXBaseSection!" );
435 SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
436 pSectNd->GetSection();
437 return &rTOXSect;
439 pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
441 return 0;
444 const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
446 OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
447 const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
448 SwSectionFmt* pFmt = rTOXSect.GetFmt();
449 OSL_ENSURE( pFmt, "invalid TOXBaseSection!" );
450 return pFmt->GetAttrSet();
453 const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, bool bCreate )
455 SwTOXBase** prBase = 0;
456 switch(eTyp)
458 case TOX_CONTENT: prBase = &mpDefTOXBases->pContBase; break;
459 case TOX_INDEX: prBase = &mpDefTOXBases->pIdxBase; break;
460 case TOX_USER: prBase = &mpDefTOXBases->pUserBase; break;
461 case TOX_TABLES: prBase = &mpDefTOXBases->pTblBase; break;
462 case TOX_OBJECTS: prBase = &mpDefTOXBases->pObjBase; break;
463 case TOX_ILLUSTRATIONS: prBase = &mpDefTOXBases->pIllBase; break;
464 case TOX_AUTHORITIES: prBase = &mpDefTOXBases->pAuthBase; break;
466 if(!(*prBase) && bCreate)
468 SwForm aForm(eTyp);
469 const SwTOXType* pType = GetTOXType(eTyp, 0);
470 (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
472 return (*prBase);
475 void SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
477 SwTOXBase** prBase = 0;
478 switch(rBase.GetType())
480 case TOX_CONTENT: prBase = &mpDefTOXBases->pContBase; break;
481 case TOX_INDEX: prBase = &mpDefTOXBases->pIdxBase; break;
482 case TOX_USER: prBase = &mpDefTOXBases->pUserBase; break;
483 case TOX_TABLES: prBase = &mpDefTOXBases->pTblBase; break;
484 case TOX_OBJECTS: prBase = &mpDefTOXBases->pObjBase; break;
485 case TOX_ILLUSTRATIONS: prBase = &mpDefTOXBases->pIllBase; break;
486 case TOX_AUTHORITIES: prBase = &mpDefTOXBases->pAuthBase; break;
488 if(*prBase)
489 delete (*prBase);
490 (*prBase) = new SwTOXBase(rBase);
493 /// Delete table of contents
494 bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, bool bDelNodes )
496 // We only delete the TOX, not the Nodes
497 bool bRet = false;
498 OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
500 const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
501 SwSectionFmt* pFmt = rTOXSect.GetFmt();
502 if( pFmt )
504 GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
506 /* Save the start node of the TOX' section. */
507 SwSectionNode * pMyNode = pFmt->GetSectionNode();
508 /* Save start node of section's surrounding. */
509 SwNode * pStartNd = pMyNode->StartOfSectionNode();
511 /* Look for the point where to move the cursors in the area to
512 delete to. This is done by first searching forward from the
513 end of the TOX' section. If no content node is found behind
514 the TOX one is searched before it. If this is not
515 successful, too, insert new text node behind the end of
516 the TOX' section. The cursors from the TOX' section will be
517 moved to the content node found or the new text node. */
519 /* Set PaM to end of TOX' section and search following content node.
520 aSearchPam will contain the point where to move the cursors
521 to. */
522 SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
523 SwPosition aEndPos(*pStartNd->EndOfSectionNode());
524 if (! aSearchPam.Move() /* no content node found */
525 || *aSearchPam.GetPoint() >= aEndPos /* content node found
526 outside surrounding */
529 /* Set PaM to beginning of TOX' section and search previous
530 content node */
531 SwPaM aTmpPam(*pMyNode);
532 aSearchPam = aTmpPam;
533 SwPosition aStartPos(*pStartNd);
535 if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
536 || *aSearchPam.GetPoint() <= aStartPos /* content node
537 found outside
538 surrounding */
541 /* There is no content node in the surrounding of
542 TOX'. Append text node behind TOX' section. */
544 SwPosition aInsPos(*pMyNode->EndOfSectionNode());
545 AppendTxtNode(aInsPos);
547 SwPaM aTmpPam1(aInsPos);
548 aSearchPam = aTmpPam1;
553 /* PaM containing the TOX. */
554 SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
556 /* Move cursors contained in TOX to the above calculated point. */
557 PaMCorrAbs(aPam, *aSearchPam.GetPoint());
559 if( !bDelNodes )
561 SwSections aArr( 0 );
562 sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
563 for( sal_uInt16 n = 0; n < nCnt; ++n )
565 SwSection* pSect = aArr[ n ];
566 if( TOX_HEADER_SECTION == pSect->GetType() )
568 DelSectionFmt( pSect->GetFmt(), bDelNodes );
573 DelSectionFmt( pFmt, bDelNodes );
575 GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
576 bRet = true;
579 return bRet;
582 /// Manage table of content types
583 sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
585 sal_uInt16 nCnt = 0;
586 for( sal_uInt16 n = 0; n < mpTOXTypes->size(); ++n )
587 if( eTyp == (*mpTOXTypes)[n]->GetType() )
588 ++nCnt;
589 return nCnt;
592 const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
594 sal_uInt16 nCnt = 0;
595 for( sal_uInt16 n = 0; n < mpTOXTypes->size(); ++n )
596 if( eTyp == (*mpTOXTypes)[n]->GetType() && nCnt++ == nId )
597 return (*mpTOXTypes)[n];
598 return 0;
601 const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
603 SwTOXType * pNew = new SwTOXType( rTyp );
604 mpTOXTypes->push_back( pNew );
605 return pNew;
608 String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
609 const String* pChkStr ) const
611 sal_uInt16 n;
612 const SwSectionNode* pSectNd;
613 const SwSection* pSect;
615 if(pChkStr && !pChkStr->Len())
616 pChkStr = 0;
617 String aName( rType.GetTypeName() );
618 xub_StrLen nNmLen = aName.Len();
620 sal_uInt16 nNum = 0;
621 sal_uInt16 nTmp = 0;
622 sal_uInt16 nFlagSize = ( mpSectionFmtTbl->size() / 8 ) +2;
623 sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
624 memset( pSetFlags, 0, nFlagSize );
626 for( n = 0; n < mpSectionFmtTbl->size(); ++n )
627 if( 0 != ( pSectNd = (*mpSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
628 TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
630 const String& rNm = pSect->GetSectionName();
631 if( rNm.Match( aName ) == nNmLen )
633 // Calculate number and set the Flag
634 nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
635 if( nNum-- && nNum < mpSectionFmtTbl->size() )
636 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
638 if( pChkStr && pChkStr->Equals( rNm ) )
639 pChkStr = 0;
642 if( !pChkStr )
644 // All Numbers have been flagged accordingly, so get the right Number
645 nNum = mpSectionFmtTbl->size();
646 for( n = 0; n < nFlagSize; ++n )
647 if( 0xff != ( nTmp = pSetFlags[ n ] ))
649 // so get the Number
650 nNum = n * 8;
651 while( nTmp & 1 )
652 ++nNum, nTmp >>= 1;
653 break;
656 delete [] pSetFlags;
657 if( pChkStr )
658 return *pChkStr;
659 return aName += OUString::number( ++nNum );
662 bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
664 OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ),
665 "no TOXBaseSection!" );
666 SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
668 String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
669 bool bRet = sTmp == rName;
670 if(bRet)
672 pTOX->SetTOXName(rName);
673 pTOX->SetSectionName(rName);
674 SetModified();
676 return bRet;
679 static const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
681 const SwNode* pNd = &rNd;
682 if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
684 // then find the "Anchor" (Body) position
685 Point aPt;
686 SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
687 const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
689 if( pFrm )
691 SwPosition aPos( *pNd );
692 pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
693 OSL_ENSURE( pNd, "Where's the paragraph?" );
696 return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
699 // Table of contents class ------------------------------------------
701 SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
702 : SwTOXBase( rBase )
703 , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
705 SetProtect( rBase.IsProtected() );
706 SetSectionName( GetTOXName() );
709 SwTOXBaseSection::~SwTOXBaseSection()
713 bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, bool bAtStart ) const
715 bool bRet = false;
716 const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
717 if( pSectNd )
719 SwCntntNode* pCNd;
720 xub_StrLen nC = 0;
721 if( bAtStart )
723 rPos.nNode = *pSectNd;
724 pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
726 else
728 rPos.nNode = *pSectNd->EndOfSectionNode();
729 pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
730 if( pCNd ) nC = pCNd->Len();
732 rPos.nContent.Assign( pCNd, nC );
733 bRet = true;
735 return bRet;
738 /// Collect table of contents content
739 void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
740 const bool _bNewTOX )//swmodtest 080307
742 const SwSectionNode* pSectNd;
743 if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
744 !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
745 !pSectNd->GetNodes().IsDocNodes() ||
746 IsHiddenFlag() )
747 return;
749 SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
751 OSL_ENSURE(pDoc != NULL, "Where is the document?");
753 if(pAttr && pDoc && GetFmt())
754 pDoc->ChgFmt(*GetFmt(), *pAttr);
756 // determine default page description, which will be used by the content nodes,
757 // if no approriate one is found.
758 const SwPageDesc* pDefaultPageDesc;
760 pDefaultPageDesc =
761 pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
762 if ( !_bNewTOX && !pDefaultPageDesc )
764 // determine page description of table-of-content
765 sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
766 sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
767 pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
768 if ( nPgDescNdIdx < pSectNd->GetIndex() )
770 pDefaultPageDesc = 0;
773 // consider end node of content section in the node array.
774 if ( !pDefaultPageDesc &&
775 ( pSectNd->EndOfSectionNode()->GetIndex() <
776 (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
779 // determine page description of content after table-of-content
780 SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
781 const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
782 const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
783 const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
784 if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
785 eBreak == SVX_BREAK_PAGE_BOTH )
788 pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
791 // consider start node of content section in the node array.
792 if ( !pDefaultPageDesc &&
793 ( pSectNd->GetIndex() >
794 (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
797 // determine page description of content before table-of-content
798 SwNodeIndex aIdx( *pSectNd );
799 pDefaultPageDesc =
800 pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
803 if ( !pDefaultPageDesc )
805 // determine default page description
806 pDefaultPageDesc = &pDoc->GetPageDesc( 0 );
810 pDoc->SetModified();
812 // get current Language
813 SwTOXInternational aIntl( GetLanguage(),
814 TOX_INDEX == GetTOXType()->GetType() ?
815 GetOptions() : 0,
816 GetSortAlgorithm() );
818 for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
819 delete *it;
820 aSortArr.clear();
822 // find the first layout node for this TOX, if it only find the content
823 // in his own chapter
824 const SwTxtNode* pOwnChapterNode = IsFromChapter()
825 ? ::lcl_FindChapterNode( *pSectNd, 0 )
826 : 0;
828 SwNode2Layout aN2L( *pSectNd );
829 ((SwSectionNode*)pSectNd)->DelFrms();
831 // remove old content an insert one empty textnode (to hold the layout!)
832 SwTxtNode* pFirstEmptyNd;
834 pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
836 SwNodeIndex aSttIdx( *pSectNd, +1 );
837 SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
838 pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
839 pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
842 // Task 70995 - save and restore PageDesc and Break Attributes
843 SwNodeIndex aNxtIdx( aSttIdx );
844 const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
845 if( !pCNd )
846 pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
847 if( pCNd->HasSwAttrSet() )
849 SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
850 aBrkSet.Put( *pCNd->GetpSwAttrSet() );
851 if( aBrkSet.Count() )
852 pFirstEmptyNd->SetAttr( aBrkSet );
855 aEndIdx--;
856 SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
857 pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
859 // delete flys in whole range including start node which requires
860 // giving the node before start node as Mark parameter, hence -1.
861 // (flys must be deleted because the anchor nodes are removed)
862 DelFlyInRange( SwNodeIndex(aSttIdx, -1), aEndIdx );
864 pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
868 // insert title of TOX
869 if( GetTitle().Len() )
871 // then insert the headline section
872 SwNodeIndex aIdx( *pSectNd, +1 );
874 SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
875 GetTxtFmtColl( FORM_TITLE ) );
876 pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
878 String sNm( GetTOXName() );
879 // ??Resource
880 sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
882 SwSectionData headerData( TOX_HEADER_SECTION, sNm );
884 SwNodeIndex aStt( *pHeadNd ); aIdx--;
885 SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
886 pDoc->GetNodes().InsertTextSection(
887 aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
890 // This would be a good time to update the Numbering
891 pDoc->UpdateNumRule();
893 if( GetCreateType() & nsSwTOXElement::TOX_MARK )
894 UpdateMarks( aIntl, pOwnChapterNode );
896 if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
897 UpdateOutline( pOwnChapterNode );
899 if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
900 UpdateTemplate( pOwnChapterNode );
902 if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
903 TOX_OBJECTS == SwTOXBase::GetType())
904 UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
906 if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
907 (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
908 UpdateTable( pOwnChapterNode );
910 if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
911 (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
912 UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
914 if( GetSequenceName().Len() && !IsFromObjectNames() &&
915 (TOX_TABLES == SwTOXBase::GetType() ||
916 TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
917 UpdateSequence( pOwnChapterNode );
919 if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
920 UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
922 if(TOX_AUTHORITIES == SwTOXBase::GetType())
923 UpdateAuthorities( aIntl );
925 // Insert AlphaDelimitters if needed (just for keywords)
926 if( TOX_INDEX == SwTOXBase::GetType() &&
927 ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
928 InsertAlphaDelimitter( aIntl );
930 // Sort the List of all TOC Marks and TOC Sections
931 std::vector<SwTxtFmtColl*> aCollArr( GetTOXForm().GetFormMax(), 0 );
932 SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
933 for( sal_uInt16 nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
935 ::SetProgressState( 0, pDoc->GetDocShell() );
937 // Put the Text into the TOC
938 sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
939 SwTxtFmtColl* pColl = aCollArr[ nLvl ];
940 if( !pColl )
942 pColl = GetTxtFmtColl( nLvl );
943 aCollArr[ nLvl ] = pColl;
946 // Generate: Set dynamic TabStops
947 SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
948 aSortArr[ nCnt ]->pTOXNd = pTOXNd;
950 // Generate: Evaluate Form and insert the place holder for the
951 // page number. If it is a TOX_INDEX and the SwForm IsCommaSeparated()
952 // then a range of entries must be generated into one paragraph
953 size_t nRange = 1;
954 if(TOX_INDEX == SwTOXBase::GetType() &&
955 GetTOXForm().IsCommaSeparated() &&
956 aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
958 const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
959 const String sPrimKey = rMark.GetPrimaryKey();
960 const String sSecKey = rMark.GetSecondaryKey();
961 const SwTOXMark* pNextMark = 0;
962 while(aSortArr.size() > (nCnt + nRange)&&
963 aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
964 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
965 pNextMark->GetPrimaryKey() == sPrimKey &&
966 pNextMark->GetSecondaryKey() == sSecKey)
967 nRange++;
969 // pass node index of table-of-content section and default page description
970 // to method <GenerateText(..)>.
971 GenerateText( nCnt, nRange, pSectNd->GetIndex(), pDefaultPageDesc );
972 nCnt += nRange - 1;
975 // delete the first dummy node and remove all Cursor into the previous node
976 aInsPos = *pFirstEmptyNd;
978 SwPaM aCorPam( *pFirstEmptyNd );
979 aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
980 if( !aCorPam.Move( fnMoveForward ) )
981 aCorPam.Move( fnMoveBackward );
982 SwNodeIndex aEndIdx( aInsPos, 1 );
983 pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
985 // Task 70995 - save and restore PageDesc and Break Attributes
986 if( pFirstEmptyNd->HasSwAttrSet() )
988 if( GetTitle().Len() )
989 aEndIdx = *pSectNd;
990 else
991 aEndIdx = *pFirstEmptyNd;
992 SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
993 if( pCNd ) // Robust against defect documents, e.g. i60336
994 pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
998 // now create the new Frames
999 sal_uLong nIdx = pSectNd->GetIndex();
1000 // don't delete if index is empty
1001 if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1002 pDoc->GetNodes().Delete( aInsPos, 1 );
1004 aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1005 std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1006 for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); ++pLayoutIter)
1008 SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
1009 }//swmod 080310
1011 SetProtect( SwTOXBase::IsProtected() );
1014 void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1016 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1017 String sDeli, sLastDeli;
1018 sal_uInt16 i = 0;
1019 while( i < aSortArr.size() )
1021 ::SetProgressState( 0, pDoc->GetDocShell() );
1023 sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1025 // Skip AlphaDelimitter
1026 if( nLevel == FORM_ALPHA_DELIMITTER )
1027 continue;
1029 String sMyString, sMyStringReading;
1030 aSortArr[i]->GetTxt( sMyString, sMyStringReading );
1032 sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
1033 aSortArr[i]->GetLocale() );
1035 // Do we already have a Delimitter?
1036 if( sDeli.Len() && sLastDeli != sDeli )
1038 // We skip all that are less than a small Blank (these are special characters)
1039 if( ' ' <= sDeli.GetChar( 0 ) )
1041 SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
1042 rIntl, aSortArr[i]->GetLocale() );
1043 aSortArr.insert( aSortArr.begin() + i, pCst);
1044 i++;
1046 sLastDeli = sDeli;
1049 // Skip until we get to the same or a lower Level
1050 do {
1051 i++;
1052 } while (i < aSortArr.size() && aSortArr[i]->GetLevel() > nLevel);
1056 /// Evaluate Template
1057 SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
1059 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1060 const String& rName = GetTOXForm().GetTemplate( nLevel );
1061 SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
1062 if( !pColl )
1064 sal_uInt16 nPoolFmt = 0;
1065 const TOXTypes eMyType = SwTOXBase::GetType();
1066 switch( eMyType )
1068 case TOX_INDEX: nPoolFmt = RES_POOLCOLL_TOX_IDXH; break;
1069 case TOX_USER:
1070 if( nLevel < 6 )
1071 nPoolFmt = RES_POOLCOLL_TOX_USERH;
1072 else
1073 nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
1074 break;
1075 case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; break;
1076 case TOX_OBJECTS: nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; break;
1077 case TOX_TABLES: nPoolFmt = RES_POOLCOLL_TOX_TABLESH; break;
1078 case TOX_AUTHORITIES: nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1080 case TOX_CONTENT:
1081 // There's a jump in the ContentArea!
1082 if( nLevel < 6 )
1083 nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
1084 else
1085 nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
1086 break;
1089 if(eMyType == TOX_AUTHORITIES && nLevel)
1090 nPoolFmt = nPoolFmt + 1;
1091 else if(eMyType == TOX_INDEX && nLevel)
1093 // pool: Level 1,2,3, Delimiter
1094 // SwForm: Delimiter, Level 1,2,3
1095 nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1097 else
1098 nPoolFmt = nPoolFmt + nLevel;
1099 pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
1101 return pColl;
1104 /// Create from Marks
1105 void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1106 const SwTxtNode* pOwnChapterNode )
1108 const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
1109 if( !pType->GetDepends() )
1110 return;
1112 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1113 TOXTypes eTOXTyp = GetTOXType()->GetType();
1114 SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1116 SwTxtTOXMark* pTxtMark;
1117 SwTOXMark* pMark;
1118 for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1120 ::SetProgressState( 0, pDoc->GetDocShell() );
1122 if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1123 0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
1125 const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
1126 // Only insert TOXMarks from the Doc, not from the
1127 // UNDO.
1129 // If selected use marks from the same chapter only
1130 if( pTOXSrc->GetNodes().IsDocNodes() &&
1131 pTOXSrc->GetTxt().getLength() && pTOXSrc->GetDepends() &&
1132 pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1133 (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1134 !pTOXSrc->HasHiddenParaField() &&
1135 !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
1137 SwTOXSortTabBase* pBase = 0;
1138 if(TOX_INDEX == eTOXTyp)
1140 // index entry mark
1141 lang::Locale aLocale;
1142 if ( g_pBreakIt->GetBreakIter().is() )
1144 aLocale = g_pBreakIt->GetLocale(
1145 pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
1148 pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1149 GetOptions(), FORM_ENTRY, rIntl, aLocale );
1150 InsertSorted(pBase);
1151 if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1152 pTxtMark->GetTOXMark().GetPrimaryKey().Len())
1154 pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1155 GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1156 InsertSorted(pBase);
1157 if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
1159 pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1160 GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1161 InsertSorted(pBase);
1165 else if( TOX_USER == eTOXTyp ||
1166 pMark->GetLevel() <= GetLevel())
1167 { // table of content mark
1168 // also used for user marks
1169 pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
1170 InsertSorted(pBase);
1177 /// Generate table of contents from outline
1178 void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
1180 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1181 SwNodes& rNds = pDoc->GetNodes();
1183 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1184 for( sal_uInt16 n = 0; n < rOutlNds.size(); ++n )
1186 ::SetProgressState( 0, pDoc->GetDocShell() );
1187 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
1188 if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
1189 sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() &&
1190 pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1191 !pTxtNd->HasHiddenParaField() &&
1192 !pTxtNd->HasHiddenCharAttribute( true ) &&
1193 ( !IsFromChapter() ||
1194 ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
1196 SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1197 InsertSorted( pNew );
1202 /// Generate table of contents from template areas
1203 void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
1205 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1206 for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1208 String sTmpStyleNames = GetStyleNames(i);
1209 sal_uInt16 nTokenCount = comphelper::string::getTokenCount(sTmpStyleNames, TOX_STYLE_DELIMITER);
1210 for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
1212 SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
1213 sTmpStyleNames.GetToken( nStyle,
1214 TOX_STYLE_DELIMITER ));
1215 //TODO: no outline Collections in content indexes if OutlineLevels are already included
1216 if( !pColl ||
1217 ( TOX_CONTENT == SwTOXBase::GetType() &&
1218 GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1219 pColl->IsAssignedToListLevelOfOutlineStyle()) )
1220 continue;
1222 SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
1223 for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
1225 ::SetProgressState( 0, pDoc->GetDocShell() );
1227 if (pTxtNd->GetTxt().getLength() &&
1228 pTxtNd->getLayoutFrm(pDoc->GetCurrentLayout()) &&
1229 pTxtNd->GetNodes().IsDocNodes() &&
1230 ( !IsFromChapter() || pOwnChapterNode ==
1231 ::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
1233 SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1234 InsertSorted(pNew);
1241 /// Generate content from sequence fields
1242 void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
1244 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1245 SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
1246 if(!pSeqFld)
1247 return;
1249 SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
1250 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1252 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1253 if(!pTxtFld)
1254 continue;
1255 const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1256 ::SetProgressState( 0, pDoc->GetDocShell() );
1258 if (rTxtNode.GetTxt().getLength() &&
1259 rTxtNode.getLayoutFrm(pDoc->GetCurrentLayout()) &&
1260 rTxtNode.GetNodes().IsDocNodes() &&
1261 ( !IsFromChapter() ||
1262 ::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
1264 const SwSetExpField* pSeqField = dynamic_cast< const SwSetExpField* >( pFmtFld->GetFld() );
1265 OUString sName = GetSequenceName();
1266 sName += OUString( cSequenceMarkSeparator );
1267 sName += OUString::valueOf( sal_Int32( pSeqField->GetSeqNumber() ) );
1268 SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1, sName );
1269 // set indexes if the number or the reference text are to be displayed
1270 if( GetCaptionDisplay() == CAPTION_TEXT )
1272 pNew->SetStartIndex(
1273 SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
1275 else if(GetCaptionDisplay() == CAPTION_NUMBER)
1277 pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
1279 InsertSorted(pNew);
1284 void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1286 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1287 SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
1288 if(!pAuthFld)
1289 return;
1291 SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
1292 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1294 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1295 // undo
1296 if(!pTxtFld)
1297 continue;
1298 const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1299 ::SetProgressState( 0, pDoc->GetDocShell() );
1301 if (rTxtNode.GetTxt().getLength() &&
1302 rTxtNode.getLayoutFrm(pDoc->GetCurrentLayout()) &&
1303 rTxtNode.GetNodes().IsDocNodes() )
1305 //#106485# the body node has to be used!
1306 SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
1307 SwPosition aFldPos(rTxtNode);
1308 const SwTxtNode* pTxtNode = 0;
1309 if(pFrm && !pFrm->IsInDocBody())
1310 pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
1311 if(!pTxtNode)
1312 pTxtNode = &rTxtNode;
1313 SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
1315 InsertSorted(pNew);
1320 static long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1322 static struct _SoObjType {
1323 long nFlag;
1324 // GlobalNameId
1325 struct _GlobalNameIds {
1326 sal_uInt32 n1;
1327 sal_uInt16 n2, n3;
1328 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1329 } aGlNmIds[4];
1330 } aArr[] = {
1331 { nsSwTOOElements::TOO_MATH,
1332 { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1333 {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1334 { nsSwTOOElements::TOO_CHART,
1335 { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1336 {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1337 { nsSwTOOElements::TOO_CALC,
1338 { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1339 {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1340 { nsSwTOOElements::TOO_DRAW_IMPRESS,
1341 { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1342 {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1343 { nsSwTOOElements::TOO_DRAW_IMPRESS,
1344 { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1345 { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1346 {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1349 long nRet = 0;
1350 for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1351 for ( int n = 0; n < 4; ++n )
1353 const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1354 if( !rId.n1 )
1355 break;
1356 SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1357 rId.b8, rId.b9, rId.b10, rId.b11,
1358 rId.b12, rId.b13, rId.b14, rId.b15 );
1359 if( rFactoryNm == aGlbNm )
1361 nRet = pArr->nFlag;
1362 break;
1366 return nRet;
1369 void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
1370 const SwTxtNode* pOwnChapterNode )
1372 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1373 SwNodes& rNds = pDoc->GetNodes();
1374 // on the 1st Node of the 1st Section
1375 sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1376 nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1378 while( nIdx < nEndIdx )
1380 ::SetProgressState( 0, pDoc->GetDocShell() );
1382 SwNode* pNd = rNds[ nIdx ];
1383 SwCntntNode* pCNd = 0;
1384 switch( eMyType )
1386 case nsSwTOXElement::TOX_FRAME:
1387 if( !pNd->IsNoTxtNode() )
1389 pCNd = pNd->GetCntntNode();
1390 if( !pCNd )
1392 SwNodeIndex aTmp( *pNd );
1393 pCNd = rNds.GoNext( &aTmp );
1396 break;
1397 case nsSwTOXElement::TOX_GRAPHIC:
1398 if( pNd->IsGrfNode() )
1399 pCNd = (SwCntntNode*)pNd;
1400 break;
1401 case nsSwTOXElement::TOX_OLE:
1402 if( pNd->IsOLENode() )
1404 bool bInclude = true;
1405 if(TOX_OBJECTS == SwTOXBase::GetType())
1407 SwOLENode* pOLENode = pNd->GetOLENode();
1408 long nMyOLEOptions = GetOLEOptions();
1409 SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1411 if( rOLEObj.IsOleRef() ) // Not yet loaded
1413 SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1414 long nObj = ::lcl_IsSOObject( aTmpName );
1415 bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1416 || (0 != (nMyOLEOptions & nObj));
1418 else
1420 OSL_FAIL("OLE Object no loaded?");
1421 bInclude = false;
1425 if(bInclude)
1426 pCNd = (SwCntntNode*)pNd;
1428 break;
1429 default: break;
1432 if( pCNd )
1434 // find node in body text
1435 int nSetLevel = USHRT_MAX;
1437 //#111105# tables of tables|illustrations|objects don't support hierarchies
1438 if( IsLevelFromChapter() &&
1439 TOX_TABLES != SwTOXBase::GetType() &&
1440 TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1441 TOX_OBJECTS != SwTOXBase::GetType() )
1443 const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1444 MAXLEVEL - 1 );
1445 if( pOutlNd )
1447 if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1448 nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
1452 if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
1453 ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1455 SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1456 ( USHRT_MAX != nSetLevel )
1457 ? static_cast<sal_uInt16>(nSetLevel)
1458 : FORM_ALPHA_DELIMITTER );
1459 InsertSorted( pNew );
1463 nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2; // 2 == End/Start Node
1467 /// Collect table entries
1468 void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
1470 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1471 SwNodes& rNds = pDoc->GetNodes();
1472 const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
1474 for( sal_uInt16 n = 0; n < rArr.size(); ++n )
1476 ::SetProgressState( 0, pDoc->GetDocShell() );
1478 SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
1479 SwTableBox* pFBox;
1480 if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
1481 pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1483 const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
1484 SwNodeIndex aCntntIdx( *pTblNd, 1 );
1486 SwCntntNode* pCNd;
1487 while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
1488 aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
1490 if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
1491 ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1493 SwTOXTable * pNew = new SwTOXTable( *pCNd );
1494 if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1496 const SwTxtNode* pOutlNd =
1497 ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1498 if( pOutlNd )
1500 if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1502 const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
1503 pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
1507 InsertSorted(pNew);
1508 break;
1515 /// Generate String according to the Form and remove the
1516 /// special characters 0-31 and 255.
1517 static String lcl_GetNumString( const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel )
1519 String sRet;
1521 if( !rBase.pTxtMark && !rBase.aTOXSources.empty() )
1522 { // only if it's not a Mark
1523 const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
1524 if( pNd )
1526 const SwNumRule* pRule = pNd->GetNumRule();
1528 if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
1529 sRet = pNd->GetNumString(bUsePrefix, nLevel);
1532 return sRet;
1535 /// Generate String with newlines changed to spaces, consecutive spaces changed
1536 /// to a single space, and trailing space removed.
1537 String lcl_RemoveLineBreaks( String sRet )
1539 if (!sRet.Len())
1540 return sRet;
1541 xub_StrLen nOffset = 0;
1542 sRet.SearchAndReplaceAll('\n', ' ');
1543 for (xub_StrLen i = 1; i < sRet.Len(); i++)
1545 if ( sRet.GetChar(i - 1) == ' ' && sRet.GetChar(i) == ' ' )
1547 nOffset += 1;
1549 else
1551 sRet.SetChar(i - nOffset, sRet.GetChar(i));
1554 if (sRet.GetChar(sRet.Len() - 1) == ' ')
1556 nOffset += 1;
1558 return sRet.Copy(0, sRet.Len() - nOffset);
1561 // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
1562 // which page description is used, no appropriate one is found.
1563 void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
1564 sal_uInt16 nCount,
1565 const sal_uInt32 _nTOXSectNdIdx,
1566 const SwPageDesc* _pDefaultPageDesc )
1568 LinkStructArr aLinkArr;
1569 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1570 ::SetProgressState( 0, pDoc->GetDocShell() );
1572 // pTOXNd is only set at the first mark
1573 SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
1574 String& rTxt = (String&)pTOXNd->GetTxt();
1575 rTxt.Erase();
1576 for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
1578 if(nIndex > nArrayIdx)
1579 rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
1580 // Initialize String with the Pattern from the form
1581 const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
1582 sal_uInt16 nLvl = rBase.GetLevel();
1583 OSL_ENSURE( nLvl < GetTOXForm().GetFormMax(), "invalid FORM_LEVEL");
1585 SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1586 xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
1587 String sLinkCharacterStyle; // default to "Default" character style - which is none
1588 String sURL;
1589 // create an enumerator
1590 // #i21237#
1591 SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
1592 SwFormTokens::iterator aIt = aPattern.begin();
1593 // remove text from node
1594 while(aIt != aPattern.end()) // #i21237#
1596 SwFormToken aToken = *aIt; // #i21237#
1597 xub_StrLen nStartCharStyle = rTxt.Len();
1598 switch( aToken.eTokenType )
1600 case TOKEN_ENTRY_NO:
1601 // for TOC numbering
1602 rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
1603 break;
1605 case TOKEN_ENTRY_TEXT:
1607 SwIndex aIdx( pTOXNd, rTxt.Len() );
1608 rBase.FillText( *pTOXNd, aIdx );
1609 rTxt = lcl_RemoveLineBreaks(rTxt);
1611 break;
1613 case TOKEN_ENTRY:
1615 // for TOC numbering
1616 rTxt.Insert( lcl_GetNumString( rBase, true, MAXLEVEL ));
1618 SwIndex aIdx( pTOXNd, rTxt.Len() );
1619 rBase.FillText( *pTOXNd, aIdx );
1620 rTxt = lcl_RemoveLineBreaks(rTxt);
1622 break;
1624 case TOKEN_TAB_STOP:
1625 if (aToken.bWithTab) // #i21237#
1626 rTxt.Append('\t');
1628 if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
1630 const SvxLRSpaceItem& rLR =
1631 (SvxLRSpaceItem&)pTOXNd->
1632 SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
1634 long nTabPosition = aToken.nTabStopPosition;
1635 if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
1636 nTabPosition -= rLR.GetTxtLeft();
1637 aTStops.Insert( SvxTabStop( nTabPosition,
1638 aToken.eTabAlign,
1639 cDfltDecimalChar,
1640 aToken.cTabFillChar ));
1642 else
1644 const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
1645 SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
1647 bool bCallFindRect = true;
1648 long nRightMargin;
1649 if( pPageDesc )
1651 const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
1652 if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
1653 pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
1654 // we have to go via the PageDesc here
1655 bCallFindRect = false;
1658 SwRect aNdRect;
1659 if( bCallFindRect )
1660 aNdRect = pTOXNd->FindLayoutRect( sal_True );
1662 if( aNdRect.IsEmpty() )
1664 // Nothing helped so far, so we go via the PageDesc
1665 sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
1666 sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
1667 pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
1668 if ( !pPageDesc ||
1669 *pPgDescNdIdx < _nTOXSectNdIdx )
1671 // Use default page description, if none is found
1672 // or the found one is given by a Node before the
1673 // table-of-content section.
1674 pPageDesc = _pDefaultPageDesc;
1677 const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
1678 nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
1679 rPgDscFmt.GetLRSpace().GetLeft() -
1680 rPgDscFmt.GetLRSpace().GetRight();
1682 else
1683 nRightMargin = aNdRect.Width();
1684 //#i24363# tab stops relative to indent
1685 if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
1687 // left margin of paragraph style
1688 const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
1689 nRightMargin -= rLRSpace.GetLeft();
1690 nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
1693 aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
1694 cDfltDecimalChar,
1695 aToken.cTabFillChar ));
1697 break;
1699 case TOKEN_TEXT:
1700 rTxt.Append( aToken.sText );
1701 break;
1703 case TOKEN_PAGE_NUMS:
1704 // Place holder for the PageNumber; we only respect the first one
1706 // The count of similar entries gives the PagerNumber pattern
1707 size_t nSize = rBase.aTOXSources.size();
1708 if (nSize > 0)
1710 String aInsStr = OUString(cNumRepl);
1711 for (size_t i = 1; i < nSize; ++i)
1713 aInsStr.AppendAscii( sPageDeli );
1714 aInsStr += cNumRepl;
1716 aInsStr += cEndPageNum;
1717 rTxt.Append( aInsStr );
1720 break;
1722 case TOKEN_CHAPTER_INFO:
1724 // A bit tricky: Find a random Frame
1725 const SwTOXSource* pTOXSource = 0;
1726 if (!rBase.aTOXSources.empty())
1727 pTOXSource = &rBase.aTOXSources[0];
1729 // #i53420#
1730 if ( pTOXSource && pTOXSource->pNd &&
1731 pTOXSource->pNd->IsCntntNode() )
1733 const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1734 if( pFrm )
1736 SwChapterFieldType aFldTyp;
1737 SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
1738 aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
1739 // #i53420#
1740 aFld.ChangeExpansion( pFrm,
1741 dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
1742 sal_True );
1743 //---> #i89791#
1744 // continue to support CF_NUMBER
1745 // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
1746 // written by OOo 3.x in the same way as OOo 2.x
1747 // would handle them.
1748 if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
1749 CF_NUMBER == aToken.nChapterFormat )
1750 rTxt.Insert(aFld.GetNumber()); // get the string number without pre/postfix
1751 else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
1752 CF_NUM_TITLE == aToken.nChapterFormat )
1754 rTxt += aFld.GetNumber();
1755 rTxt += ' ';
1756 rTxt += aFld.GetTitle();
1758 else if(CF_TITLE == aToken.nChapterFormat)
1759 rTxt += aFld.GetTitle();
1763 break;
1765 case TOKEN_LINK_START:
1766 nLinkStartPosition = rTxt.Len();
1767 sLinkCharacterStyle = aToken.sCharStyleName;
1768 break;
1770 case TOKEN_LINK_END:
1771 //TODO: only paired start/end tokens are valid
1772 if( STRING_NOTFOUND != nLinkStartPosition)
1774 SwIndex aIdx( pTOXNd, nLinkStartPosition );
1775 // pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
1776 xub_StrLen nEnd = rTxt.Len();
1778 if( !sURL.Len() )
1780 sURL = rBase.GetURL();
1781 if( !sURL.Len() )
1782 break;
1784 LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
1785 nEnd);
1786 pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
1787 pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
1788 if(sLinkCharacterStyle.Len())
1790 sal_uInt16 nPoolId =
1791 SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1792 pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
1793 pNewLink->aINetFmt.SetINetFmtId(nPoolId);
1795 else
1797 pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
1798 pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
1800 aLinkArr.push_back(pNewLink);
1801 nLinkStartPosition = STRING_NOTFOUND;
1802 sLinkCharacterStyle.Erase();
1804 break;
1806 case TOKEN_AUTHORITY:
1808 ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
1809 SwIndex aIdx( pTOXNd, rTxt.Len() );
1810 rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
1812 break;
1813 case TOKEN_END: break;
1816 if( aToken.sCharStyleName.Len() )
1818 SwCharFmt* pCharFmt;
1819 if( USHRT_MAX != aToken.nPoolId )
1820 pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
1821 else
1822 pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
1824 if (pCharFmt)
1826 SwFmtCharFmt aFmt( pCharFmt );
1827 pTOXNd->InsertItem( aFmt, nStartCharStyle,
1828 rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
1832 ++aIt; // #i21237#
1835 pTOXNd->SetAttr( aTStops );
1838 for(LinkStructArr::const_iterator i = aLinkArr.begin(); i != aLinkArr.end(); ++i)
1840 pTOXNd->InsertItem((*i)->aINetFmt, (*i)->nStartTextPos,
1841 (*i)->nEndTextPos);
1845 /// Calculate PageNumber and insert after formatting
1846 void SwTOXBaseSection::UpdatePageNum()
1848 if( aSortArr.empty() )
1849 return ;
1851 // Insert the current PageNumber into the TOC
1852 SwPageFrm* pAktPage = 0;
1853 sal_uInt16 nPage = 0;
1854 SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1856 SwTOXInternational aIntl( GetLanguage(),
1857 TOX_INDEX == GetTOXType()->GetType() ?
1858 GetOptions() : 0,
1859 GetSortAlgorithm() );
1861 for( size_t nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
1863 // Loop over all SourceNodes
1864 std::vector<sal_uInt16> aNums; // the PageNumber
1865 std::vector<SwPageDesc*> aDescs; // The PageDescriptors matching the PageNumbers
1866 std::vector<sal_uInt16> *pMainNums = 0; // contains page numbers of main entries
1868 // process run in lines
1869 sal_uInt16 nRange = 0;
1870 if(GetTOXForm().IsCommaSeparated() &&
1871 aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1873 const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1874 const String sPrimKey = rMark.GetPrimaryKey();
1875 const String sSecKey = rMark.GetSecondaryKey();
1876 const SwTOXMark* pNextMark = 0;
1877 while(aSortArr.size() > (nCnt + nRange)&&
1878 aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1879 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1880 pNextMark->GetPrimaryKey() == sPrimKey &&
1881 pNextMark->GetSecondaryKey() == sSecKey)
1882 nRange++;
1884 else
1885 nRange = 1;
1887 for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
1889 SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
1890 size_t nSize = pSortBase->aTOXSources.size();
1891 for (size_t j = 0; j < nSize; ++j)
1893 ::SetProgressState( 0, pDoc->GetDocShell() );
1895 SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1896 if( rTOXSource.pNd )
1898 SwCntntFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1899 OSL_ENSURE( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
1900 if( !pFrm )
1901 continue;
1902 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
1904 // find the right one
1905 SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
1906 while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
1907 && rTOXSource.nPos >= pNext->GetOfst() )
1908 pFrm = pNext;
1911 SwPageFrm* pTmpPage = pFrm->FindPageFrm();
1912 if( pTmpPage != pAktPage )
1914 nPage = pTmpPage->GetVirtPageNum();
1915 pAktPage = pTmpPage;
1918 // Insert as sorted
1919 sal_uInt16 i;
1920 for( i = 0; i < aNums.size() && aNums[i] < nPage; ++i )
1923 if( i >= aNums.size() || aNums[ i ] != nPage )
1925 aNums.insert(aNums.begin() + i, nPage);
1926 aDescs.insert(aDescs.begin() + i, pAktPage->GetPageDesc() );
1928 // is it a main entry?
1929 if(TOX_SORT_INDEX == pSortBase->GetType() &&
1930 rTOXSource.bMainEntry)
1932 if(!pMainNums)
1933 pMainNums = new std::vector<sal_uInt16>;
1934 pMainNums->push_back(nPage);
1938 // Insert the PageNumber into the TOC TextNode
1939 const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
1940 if(pBase->pTOXNd)
1942 const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
1943 OSL_ENSURE( pTxtNd, "no TextNode, wrong TOC" );
1945 _UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
1946 aIntl );
1948 DELETEZ(pMainNums);
1949 aNums.clear();
1952 // Delete the mapping array after setting the right PageNumber
1953 for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
1954 delete *it;
1955 aSortArr.clear();
1958 /// Replace the PageNumber place holders. Search for the page no. in the array
1959 /// of main entry page numbers.
1960 static bool lcl_HasMainEntry( const std::vector<sal_uInt16>* pMainEntryNums, sal_uInt16 nToFind )
1962 for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->size(); ++i)
1963 if(nToFind == (*pMainEntryNums)[i])
1964 return true;
1965 return false;
1968 void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
1969 const std::vector<sal_uInt16>& rNums,
1970 const std::vector<SwPageDesc*>& rDescs,
1971 const std::vector<sal_uInt16>* pMainEntryNums,
1972 const SwTOXInternational& rIntl )
1974 // collect starts end ends of main entry character style
1975 std::vector<sal_uInt16>* pCharStyleIdx = pMainEntryNums ? new std::vector<sal_uInt16> : 0;
1977 OUString sSrchStr = OUStringBuffer().append(cNumRepl).
1978 append(sPageDeli).append(cNumRepl).makeStringAndClear();
1979 sal_Int32 nStartPos = pNd->GetTxt().indexOf(sSrchStr);
1980 sSrchStr = OUStringBuffer().append(cNumRepl).
1981 append(cEndPageNum).makeStringAndClear();
1982 sal_Int32 nEndPos = pNd->GetTxt().indexOf(sSrchStr);
1983 sal_uInt16 i;
1985 if (-1 == nEndPos || rNums.empty())
1986 return;
1988 if (-1 == nStartPos || nStartPos > nEndPos)
1989 nStartPos = nEndPos;
1991 sal_uInt16 nOld = rNums[0],
1992 nBeg = nOld,
1993 nCount = 0;
1994 String aNumStr( SvxNumberType( rDescs[0]->GetNumType() ).
1995 GetNumStr( nBeg ) );
1996 if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
1998 sal_uInt16 nTemp = 0;
1999 pCharStyleIdx->push_back( nTemp );
2002 // Delete place holder
2003 SwIndex aPos(pNd, nStartPos);
2004 SwCharFmt* pPageNoCharFmt = 0;
2005 SwpHints* pHints = pNd->GetpSwpHints();
2006 if(pHints)
2007 for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
2009 SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
2010 xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
2011 if( nStartPos >= *pAttr->GetStart() &&
2012 (nStartPos + 2) <= nTmpEnd &&
2013 pAttr->Which() == RES_TXTATR_CHARFMT)
2015 pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
2016 break;
2019 pNd->EraseText(aPos, nEndPos - nStartPos + 2);
2021 for( i = 1; i < rNums.size(); ++i)
2023 SvxNumberType aType( rDescs[i]->GetNumType() );
2024 if( TOX_INDEX == SwTOXBase::GetType() )
2025 { // Summarize for the following
2026 // Add up all following
2027 // break up if main entry starts or ends and
2028 // insert a char style index
2029 bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
2030 != lcl_HasMainEntry(pMainEntryNums, rNums[i]);
2032 if(nOld == rNums[i]-1 && !bMainEntryChanges &&
2033 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
2034 nCount++;
2035 else
2037 // Flush for the following old values
2038 if(GetOptions() & nsSwTOIOptions::TOI_FF)
2040 if ( nCount >= 1 )
2041 aNumStr += rIntl.GetFollowingText( nCount > 1 );
2043 else
2045 if(nCount >= 2 )
2046 aNumStr += '-';
2047 else if(nCount == 1 )
2048 aNumStr.AppendAscii( sPageDeli );
2049 //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
2050 if(nCount)
2051 aNumStr += aType.GetNumStr( nBeg + nCount );
2054 // Create new String
2055 nBeg = rNums[i];
2056 aNumStr.AppendAscii( sPageDeli );
2057 //the change of the character style must apply after sPageDeli is appended
2058 if(pCharStyleIdx && bMainEntryChanges)
2060 pCharStyleIdx->push_back(aNumStr.Len());
2062 aNumStr += aType.GetNumStr( nBeg );
2063 nCount = 0;
2065 nOld = rNums[i];
2067 else
2068 { // Insert all Numbers
2069 aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
2070 if(i != (rNums.size()-1))
2071 aNumStr.AppendAscii( sPageDeli );
2074 // Flush when ending and the following old values
2075 if( TOX_INDEX == SwTOXBase::GetType() )
2077 if(GetOptions() & nsSwTOIOptions::TOI_FF)
2079 if( nCount >= 1 )
2080 aNumStr += rIntl.GetFollowingText( nCount > 1 );
2082 else
2084 if(nCount >= 2)
2085 aNumStr +='-';
2086 else if(nCount == 1)
2087 aNumStr.AppendAscii( sPageDeli );
2088 //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
2089 if(nCount)
2090 aNumStr += SvxNumberType( rDescs[i-1]->GetNumType() ).GetNumStr( nBeg+nCount );
2093 pNd->InsertText( aNumStr, aPos,
2094 static_cast<IDocumentContentOperations::InsertFlags>(
2095 IDocumentContentOperations::INS_EMPTYEXPAND |
2096 IDocumentContentOperations::INS_FORCEHINTEXPAND) );
2097 if(pPageNoCharFmt)
2099 SwFmtCharFmt aCharFmt( pPageNoCharFmt );
2100 pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
2103 // The main entries should get their character style
2104 if(pCharStyleIdx && !pCharStyleIdx->empty() && GetMainEntryCharStyle().Len())
2106 // eventually the last index must me appended
2107 if(pCharStyleIdx->size()&0x01)
2108 pCharStyleIdx->push_back(aNumStr.Len());
2110 // search by name
2111 SwDoc* pDoc = pNd->GetDoc();
2112 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
2113 SwCharFmt* pCharFmt = 0;
2114 if(USHRT_MAX != nPoolId)
2115 pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
2116 else
2117 pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
2118 if(!pCharFmt)
2119 pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
2121 // find the page numbers in aNumStr and set the character style
2122 xub_StrLen nOffset = pNd->GetTxt().getLength() - aNumStr.Len();
2123 SwFmtCharFmt aCharFmt(pCharFmt);
2124 for(sal_uInt16 j = 0; j < pCharStyleIdx->size(); j += 2)
2126 xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
2127 xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1] + nOffset;
2128 pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
2132 delete pCharStyleIdx;
2135 void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
2137 Range aRange(0, aSortArr.size());
2138 if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
2140 const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
2141 // Evaluate Key
2142 // Calculate the range where to insert
2143 if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
2144 rMark.GetPrimaryKey().Len() )
2146 aRange = GetKeyRange( rMark.GetPrimaryKey(),
2147 rMark.GetPrimaryKeyReading(),
2148 *pNew, FORM_PRIMARY_KEY, aRange );
2150 if( rMark.GetSecondaryKey().Len() )
2151 aRange = GetKeyRange( rMark.GetSecondaryKey(),
2152 rMark.GetSecondaryKeyReading(),
2153 *pNew, FORM_SECONDARY_KEY, aRange );
2156 // Search for identical entries and remove the trailing one
2157 if(TOX_AUTHORITIES == SwTOXBase::GetType())
2159 for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2161 SwTOXSortTabBase* pOld = aSortArr[i];
2162 if(*pOld == *pNew)
2164 if(*pOld < *pNew)
2166 delete pNew;
2167 return;
2169 else
2171 // remove the old content
2172 delete aSortArr[i];
2173 aSortArr.erase( aSortArr.begin() + i );
2174 aRange.Max()--;
2175 break;
2181 // find position and insert
2182 short i;
2184 for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2185 { // Only check for same level
2186 SwTOXSortTabBase* pOld = aSortArr[i];
2187 if(*pOld == *pNew)
2189 if(TOX_AUTHORITIES != SwTOXBase::GetType())
2191 // Own entry for for double entries or keywords
2192 if( pOld->GetType() == TOX_SORT_CUSTOM &&
2193 pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
2194 continue;
2196 if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
2197 { // Own entry
2198 aSortArr.insert(aSortArr.begin() + i, pNew);
2199 return;
2201 // If the own entry is already present, add it to the references list
2202 pOld->aTOXSources.push_back(pNew->aTOXSources[0]);
2204 delete pNew;
2205 return;
2207 #if OSL_DEBUG_LEVEL > 0
2208 else
2209 OSL_FAIL("Bibliography entries cannot be found here");
2210 #endif
2212 if(*pNew < *pOld)
2213 break;
2215 // Skip SubLevel
2216 while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
2217 aSortArr[i]->GetLevel() > pNew->GetLevel() )
2218 i++;
2220 // Insert at position i
2221 aSortArr.insert(aSortArr.begin()+i, pNew);
2224 /// Find Key Range and insert if possible
2225 Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
2226 const SwTOXSortTabBase& rNew,
2227 sal_uInt16 nLevel, const Range& rRange )
2229 const SwTOXInternational& rIntl = *rNew.pTOXIntl;
2230 String sToCompare(rStr);
2231 String sToCompareReading(rStrReading);
2233 if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
2235 String sUpper( rIntl.ToUpper( sToCompare, 0 ));
2236 sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
2239 OSL_ENSURE(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
2241 const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
2242 const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
2244 sal_uInt16 i;
2246 for( i = nMin; i < nMax; ++i)
2248 SwTOXSortTabBase* pBase = aSortArr[i];
2250 String sMyString, sMyStringReading;
2251 pBase->GetTxt( sMyString, sMyStringReading );
2253 if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
2254 sToCompare, sToCompareReading, rNew.GetLocale() ) &&
2255 pBase->GetLevel() == nLevel )
2256 break;
2258 if(i == nMax)
2259 { // If not already present, create and insert
2260 SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
2261 rNew.GetLocale() );
2262 for(i = nMin; i < nMax; ++i)
2264 if(nLevel == aSortArr[i]->GetLevel() && *pKey < *(aSortArr[i]))
2265 break;
2267 aSortArr.insert(aSortArr.begin() + i, pKey);
2269 sal_uInt16 nStart = i+1;
2270 sal_uInt16 nEnd = aSortArr.size();
2272 // Find end of range
2273 for(i = nStart; i < aSortArr.size(); ++i)
2275 if(aSortArr[i]->GetLevel() <= nLevel)
2276 { nEnd = i;
2277 break;
2280 return Range(nStart, nEnd);
2283 bool SwTOXBase::IsTOXBaseInReadonly() const
2285 const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2286 bool bRet = false;
2287 const SwSectionNode* pSectNode;
2288 if(pSect && pSect->GetFmt() &&
2289 0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
2291 const SwDocShell* pDocSh;
2292 bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
2293 pDocSh->IsReadOnly()) ||
2294 (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
2295 pSectNode->GetSection().IsProtectFlag());
2298 return bRet;
2301 const SfxItemSet* SwTOXBase::GetAttrSet() const
2303 const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2304 if(pSect && pSect->GetFmt())
2305 return &pSect->GetFmt()->GetAttrSet();
2306 return 0;
2309 void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
2311 const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2312 if( pSect && pSect->GetFmt() )
2313 pSect->GetFmt()->SetFmtAttr( rSet );
2316 bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
2318 switch( rInfo.Which() )
2320 case RES_CONTENT_VISIBLE:
2322 const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2323 if( pSect && pSect->GetFmt() )
2324 pSect->GetFmt()->GetInfo( rInfo );
2326 return false;
2328 return true;
2331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */