1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
30 #include <txttxmrk.hxx>
31 #include <fmtinfmt.hxx>
32 #include <fmtpdsc.hxx>
34 #include <fmtfsize.hxx>
36 #include <pagedesc.hxx>
38 #include <IDocumentUndoRedo.hxx>
39 #include <pagefrm.hxx>
41 #include <swtable.hxx>
45 #include <poolfmt.hxx>
47 #include <rootfrm.hxx>
48 #include <UndoAttribute.hxx>
52 #include <charfmt.hxx>
53 #include <fchrfmt.hxx>
60 #include <node2lay.hxx>
61 #include <SwStyleNameMapper.hxx>
62 #include <breakit.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
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
),
86 typedef std::vector
<LinkStruct
*> LinkStructArr
;
88 sal_uInt16
SwDoc::GetTOIKeys( SwTOIKeyType eTyp
, std::vector
<String
>& rArr
) const
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() )
106 if( TOI_PRIMARY
== eTyp
)
107 pStr
= &((SwTOXMark
*)pItem
)->GetPrimaryKey();
109 pStr
= &((SwTOXMark
*)pItem
)->GetSecondaryKey();
112 rArr
.push_back( *pStr
);
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() )
127 const SwpHints
& rHts
= *pTxtNd
->GetpSwpHints();
128 const SwTxtAttr
* pHt
;
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() )
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!
150 SwTOXMark
* pTMark
= (SwTOXMark
*) &pHt
->GetTOXMark();
151 rArr
.push_back( pTMark
);
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();
188 /// Travel between table of content Marks
189 class CompareNodeCntnt
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();
235 SwTOXMark::InsertTOXMarks( aMarks
, *pType
);
237 const SwTOXMark
* pTOXMark
;
238 const SwCntntFrm
* pCFrm
;
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() );
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.
256 if( pTOXMark
->GetText() != rCurTOXMark
.GetText() )
260 if ( (aAbsNew
< aAbsIdx
&& aAbsNew
> aPrevPos
&&
261 aPrevPos
!= aAbsIdx
&& aAbsNew
!= aAbsIdx
) ||
262 (aAbsIdx
== aAbsNew
&&
263 (sal_uLong(&rCurTOXMark
) > sal_uLong(pTOXMark
) &&
265 (pNew
&& (aPrevPos
< aAbsIdx
||
266 sal_uLong(pNew
) < sal_uLong(pTOXMark
)))))) ||
267 (aPrevPos
== aAbsNew
&& aAbsIdx
!= aAbsNew
&&
268 sal_uLong(pTOXMark
) > sal_uLong(pNew
)) )
272 if ( aAbsNew
>= aMax
)
281 if( pTOXMark
->GetText() != rCurTOXMark
.GetText() )
285 if ( (aAbsNew
> aAbsIdx
&& aAbsNew
< aNextPos
&&
286 aNextPos
!= aAbsIdx
&& aAbsNew
!= aAbsIdx
) ||
287 (aAbsIdx
== aAbsNew
&&
288 (sal_uLong(&rCurTOXMark
) < sal_uLong(pTOXMark
) &&
290 (pNew
&& (aNextPos
> aAbsIdx
||
291 sal_uLong(pNew
) > sal_uLong(pTOXMark
)))))) ||
292 (aNextPos
== aAbsNew
&& aAbsIdx
!= aAbsNew
&&
293 sal_uLong(pTOXMark
) < sal_uLong(pNew
)) )
297 if ( aAbsNew
<= aMin
)
309 // We couldn't find a successor
310 // Use minimum or maximum
330 const SwTOXBaseSection
* SwDoc::InsertTableOf( const SwPosition
& rPos
,
331 const SwTOXBase
& rTOX
,
332 const SfxItemSet
* pSet
,
335 GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX
, NULL
);
337 String
sSectNm( rTOX
.GetTOXName() );
338 sSectNm
= GetUniqueTOXBaseName( *rTOX
.GetTOXType(), &sSectNm
);
340 SwSectionData
aSectionData( TOX_CONTENT_SECTION
, sSectNm
);
341 SwTOXBaseSection
*const pNewSection
= dynamic_cast<SwTOXBaseSection
*>(
342 InsertSwSection( aPam
, aSectionData
, & rTOX
, pSet
, false ));
345 SwSectionNode
*const pSectNd
= pNewSection
->GetFmt()->GetSectionNode();
346 pNewSection
->SetTOXName(sSectNm
); // rTOX may have had no name...
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() );
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
);
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();
391 SectionType eT
= pSectNd
->GetSection().GetType();
392 if( TOX_HEADER_SECTION
== eT
|| TOX_CONTENT_SECTION
== eT
)
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 );
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
);
417 SwTOXBaseSection
*const pNewSection(
418 dynamic_cast<SwTOXBaseSection
*>(& pNewSectionNode
->GetSection()));
419 pNewSection
->SetTOXName(sSectNm
); // rTOX may have had no name...
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();
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();
439 pSectNd
= pSectNd
->StartOfSectionNode()->FindSectionNode();
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;
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
)
469 const SwTOXType
* pType
= GetTOXType(eTyp
, 0);
470 (*prBase
) = new SwTOXBase(pType
, aForm
, 0, pType
->GetTypeName());
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;
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
498 OSL_ENSURE( rTOXBase
.ISA( SwTOXBaseSection
), "no TOXBaseSection!" );
500 const SwTOXBaseSection
& rTOXSect
= (const SwTOXBaseSection
&)rTOXBase
;
501 SwSectionFmt
* pFmt
= rTOXSect
.GetFmt();
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
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
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
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());
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
);
582 /// Manage table of content types
583 sal_uInt16
SwDoc::GetTOXTypeCount(TOXTypes eTyp
) const
586 for( sal_uInt16 n
= 0; n
< mpTOXTypes
->size(); ++n
)
587 if( eTyp
== (*mpTOXTypes
)[n
]->GetType() )
592 const SwTOXType
* SwDoc::GetTOXType( TOXTypes eTyp
, sal_uInt16 nId
) const
595 for( sal_uInt16 n
= 0; n
< mpTOXTypes
->size(); ++n
)
596 if( eTyp
== (*mpTOXTypes
)[n
]->GetType() && nCnt
++ == nId
)
597 return (*mpTOXTypes
)[n
];
601 const SwTOXType
* SwDoc::InsertTOXType( const SwTOXType
& rTyp
)
603 SwTOXType
* pNew
= new SwTOXType( rTyp
);
604 mpTOXTypes
->push_back( pNew
);
608 String
SwDoc::GetUniqueTOXBaseName( const SwTOXType
& rType
,
609 const String
* pChkStr
) const
612 const SwSectionNode
* pSectNd
;
613 const SwSection
* pSect
;
615 if(pChkStr
&& !pChkStr
->Len())
617 String
aName( rType
.GetTypeName() );
618 xub_StrLen nNmLen
= aName
.Len();
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
) )
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
] ))
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
;
672 pTOX
->SetTOXName(rName
);
673 pTOX
->SetSectionName(rName
);
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
686 SwNode2Layout
aNode2Layout( *pNd
, pNd
->GetIndex() );
687 const SwFrm
* pFrm
= aNode2Layout
.GetFrm( &aPt
, 0, sal_False
);
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
)
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
716 const SwSectionNode
* pSectNd
= GetFmt()->GetSectionNode();
723 rPos
.nNode
= *pSectNd
;
724 pCNd
= pSectNd
->GetDoc()->GetNodes().GoNext( &rPos
.nNode
);
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
);
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() ||
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
;
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
);
800 pSectNd
->GetNodes().GoPrevious( &aIdx
)->FindPageDesc( sal_False
);
803 if ( !pDefaultPageDesc
)
805 // determine default page description
806 pDefaultPageDesc
= &pDoc
->GetPageDesc( 0 );
812 // get current Language
813 SwTOXInternational
aIntl( GetLanguage(),
814 TOX_INDEX
== GetTOXType()->GetType() ?
816 GetSortAlgorithm() );
818 for (SwTOXSortTabBases::const_iterator it
= aSortArr
.begin(); it
!= aSortArr
.end(); ++it
)
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 )
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();
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
);
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() );
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
];
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
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
)
969 // pass node index of table-of-content section and default page description
970 // to method <GenerateText(..)>.
971 GenerateText( nCnt
, nRange
, pSectNd
->GetIndex(), pDefaultPageDesc
);
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() )
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() );
1011 SetProtect( SwTOXBase::IsProtected() );
1014 void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational
& rIntl
)
1016 SwDoc
* pDoc
= (SwDoc
*)GetFmt()->GetDoc();
1017 String sDeli
, sLastDeli
;
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
)
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
);
1049 // Skip until we get to the same or a lower Level
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;
1064 sal_uInt16 nPoolFmt
= 0;
1065 const TOXTypes eMyType
= SwTOXBase::GetType();
1068 case TOX_INDEX
: nPoolFmt
= RES_POOLCOLL_TOX_IDXH
; break;
1071 nPoolFmt
= RES_POOLCOLL_TOX_USERH
;
1073 nPoolFmt
= RES_POOLCOLL_TOX_USER6
- 6;
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;
1081 // There's a jump in the ContentArea!
1083 nPoolFmt
= RES_POOLCOLL_TOX_CNTNTH
;
1085 nPoolFmt
= RES_POOLCOLL_TOX_CNTNT6
- 6;
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;
1098 nPoolFmt
= nPoolFmt
+ nLevel
;
1099 pColl
= pDoc
->GetTxtCollFromPool( nPoolFmt
);
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() )
1112 SwDoc
* pDoc
= (SwDoc
*)GetFmt()->GetDoc();
1113 TOXTypes eTOXTyp
= GetTOXType()->GetType();
1114 SwIterator
<SwTOXMark
,SwTOXType
> aIter( *pType
);
1116 SwTxtTOXMark
* pTxtMark
;
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
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
)
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
1217 ( TOX_CONTENT
== SwTOXBase::GetType() &&
1218 GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL
&&
1219 pColl
->IsAssignedToListLevelOfOutlineStyle()) )
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 );
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);
1249 SwIterator
<SwFmtFld
,SwFieldType
> aIter( *pSeqFld
);
1250 for( SwFmtFld
* pFmtFld
= aIter
.First(); pFmtFld
; pFmtFld
= aIter
.Next() )
1252 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
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);
1284 void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational
& rIntl
)
1286 SwDoc
* pDoc
= (SwDoc
*)GetFmt()->GetDoc();
1287 SwFieldType
* pAuthFld
= pDoc
->GetFldType(RES_AUTHORITY
, aEmptyStr
, false);
1291 SwIterator
<SwFmtFld
,SwFieldType
> aIter( *pAuthFld
);
1292 for( SwFmtFld
* pFmtFld
= aIter
.First(); pFmtFld
; pFmtFld
= aIter
.Next() )
1294 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
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
);
1312 pTxtNode
= &rTxtNode
;
1313 SwTOXAuthority
* pNew
= new SwTOXAuthority( *pTxtNode
, *pFmtFld
, rIntl
);
1320 static long lcl_IsSOObject( const SvGlobalName
& rFactoryNm
)
1322 static struct _SoObjType
{
1325 struct _GlobalNameIds
{
1328 sal_uInt8 b8
, b9
, b10
, b11
, b12
, b13
, b14
, b15
;
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} } }
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
];
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
)
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;
1386 case nsSwTOXElement::TOX_FRAME
:
1387 if( !pNd
->IsNoTxtNode() )
1389 pCNd
= pNd
->GetCntntNode();
1392 SwNodeIndex
aTmp( *pNd
);
1393 pCNd
= rNds
.GoNext( &aTmp
);
1397 case nsSwTOXElement::TOX_GRAPHIC
:
1398 if( pNd
->IsGrfNode() )
1399 pCNd
= (SwCntntNode
*)pNd
;
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
));
1420 OSL_FAIL("OLE Object no loaded?");
1426 pCNd
= (SwCntntNode
*)pNd
;
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
,
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
] );
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 );
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 );
1500 if( pOutlNd
->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1502 const int nTmp
= pOutlNd
->GetTxtColl()->GetAttrOutlineLevel();
1503 pNew
->SetLevel( static_cast<sal_uInt16
>(nTmp
) );//<-end ,zhaojianwei
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
)
1521 if( !rBase
.pTxtMark
&& !rBase
.aTOXSources
.empty() )
1522 { // only if it's not a Mark
1523 const SwTxtNode
* pNd
= rBase
.aTOXSources
[0].pNd
->GetTxtNode();
1526 const SwNumRule
* pRule
= pNd
->GetNumRule();
1528 if( pRule
&& pNd
->GetActualListLevel() < MAXLEVEL
)
1529 sRet
= pNd
->GetNumString(bUsePrefix
, nLevel
);
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
)
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
) == ' ' )
1551 sRet
.SetChar(i
- nOffset
, sRet
.GetChar(i
));
1554 if (sRet
.GetChar(sRet
.Len() - 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
,
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();
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
1589 // create an enumerator
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)) );
1605 case TOKEN_ENTRY_TEXT
:
1607 SwIndex
aIdx( pTOXNd
, rTxt
.Len() );
1608 rBase
.FillText( *pTOXNd
, aIdx
);
1609 rTxt
= lcl_RemoveLineBreaks(rTxt
);
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
);
1624 case TOKEN_TAB_STOP
:
1625 if (aToken
.bWithTab
) // #i21237#
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
,
1640 aToken
.cTabFillChar
));
1644 const SwPageDesc
* pPageDesc
= ((SwFmtPageDesc
&)pTOXNd
->
1645 SwCntntNode::GetAttr( RES_PAGEDESC
)).GetPageDesc();
1647 bool bCallFindRect
= true;
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;
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
);
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();
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
,
1695 aToken
.cTabFillChar
));
1700 rTxt
.Append( aToken
.sText
);
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();
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
);
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];
1730 if ( pTOXSource
&& pTOXSource
->pNd
&&
1731 pTOXSource
->pNd
->IsCntntNode() )
1733 const SwCntntFrm
* pFrm
= pTOXSource
->pNd
->getLayoutFrm( pDoc
->GetCurrentLayout() );
1736 SwChapterFieldType aFldTyp
;
1737 SwChapterField
aFld( &aFldTyp
, aToken
.nChapterFormat
);
1738 aFld
.SetLevel( static_cast<sal_uInt8
>(aToken
.nOutlineLevel
- 1) );
1740 aFld
.ChangeExpansion( pFrm
,
1741 dynamic_cast<const SwCntntNode
*>(pTOXSource
->pNd
),
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();
1756 rTxt
+= aFld
.GetTitle();
1758 else if(CF_TITLE
== aToken
.nChapterFormat
)
1759 rTxt
+= aFld
.GetTitle();
1765 case TOKEN_LINK_START
:
1766 nLinkStartPosition
= rTxt
.Len();
1767 sLinkCharacterStyle
= aToken
.sCharStyleName
;
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();
1780 sURL
= rBase
.GetURL();
1784 LinkStruct
* pNewLink
= new LinkStruct(sURL
, nLinkStartPosition
,
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
);
1797 pNewLink
->aINetFmt
.SetVisitedFmtId(USHRT_MAX
);
1798 pNewLink
->aINetFmt
.SetINetFmtId(USHRT_MAX
);
1800 aLinkArr
.push_back(pNewLink
);
1801 nLinkStartPosition
= STRING_NOTFOUND
;
1802 sLinkCharacterStyle
.Erase();
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
) );
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
);
1822 pCharFmt
= pDoc
->FindCharFmtByName( aToken
.sCharStyleName
);
1826 SwFmtCharFmt
aFmt( pCharFmt
);
1827 pTOXNd
->InsertItem( aFmt
, nStartCharStyle
,
1828 rTxt
.Len(), nsSetAttrMode::SETATTR_DONTEXPAND
);
1835 pTOXNd
->SetAttr( aTStops
);
1838 for(LinkStructArr::const_iterator i
= aLinkArr
.begin(); i
!= aLinkArr
.end(); ++i
)
1840 pTOXNd
->InsertItem((*i
)->aINetFmt
, (*i
)->nStartTextPos
,
1845 /// Calculate PageNumber and insert after formatting
1846 void SwTOXBaseSection::UpdatePageNum()
1848 if( aSortArr
.empty() )
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() ?
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
)
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");
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() )
1911 SwPageFrm
* pTmpPage
= pFrm
->FindPageFrm();
1912 if( pTmpPage
!= pAktPage
)
1914 nPage
= pTmpPage
->GetVirtPageNum();
1915 pAktPage
= pTmpPage
;
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
)
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
];
1942 const SwTxtNode
* pTxtNd
= pBase
->pTOXNd
->GetTxtNode();
1943 OSL_ENSURE( pTxtNd
, "no TextNode, wrong TOC" );
1945 _UpdatePageNum( (SwTxtNode
*)pTxtNd
, aNums
, aDescs
, pMainNums
,
1952 // Delete the mapping array after setting the right PageNumber
1953 for (SwTOXSortTabBases::const_iterator it
= aSortArr
.begin(); it
!= aSortArr
.end(); ++it
)
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
])
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
);
1985 if (-1 == nEndPos
|| rNums
.empty())
1988 if (-1 == nStartPos
|| nStartPos
> nEndPos
)
1989 nStartPos
= nEndPos
;
1991 sal_uInt16 nOld
= rNums
[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();
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();
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
)))
2037 // Flush for the following old values
2038 if(GetOptions() & nsSwTOIOptions::TOI_FF
)
2041 aNumStr
+= rIntl
.GetFollowingText( nCount
> 1 );
2047 else if(nCount
== 1 )
2048 aNumStr
.AppendAscii( sPageDeli
);
2049 //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
2051 aNumStr
+= aType
.GetNumStr( nBeg
+ nCount
);
2054 // Create new String
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
);
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
)
2080 aNumStr
+= rIntl
.GetFollowingText( nCount
> 1 );
2086 else if(nCount
== 1)
2087 aNumStr
.AppendAscii( sPageDeli
);
2088 //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
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
) );
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());
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
);
2117 pCharFmt
= pDoc
->FindCharFmtByName( GetMainEntryCharStyle() );
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();
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
];
2171 // remove the old content
2173 aSortArr
.erase( aSortArr
.begin() + i
);
2181 // find position and insert
2184 for( i
= (short)aRange
.Min(); i
< (short)aRange
.Max(); ++i
)
2185 { // Only check for same level
2186 SwTOXSortTabBase
* pOld
= aSortArr
[i
];
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
)
2196 if(!(pNew
->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY
))
2198 aSortArr
.insert(aSortArr
.begin() + i
, pNew
);
2201 // If the own entry is already present, add it to the references list
2202 pOld
->aTOXSources
.push_back(pNew
->aTOXSources
[0]);
2207 #if OSL_DEBUG_LEVEL > 0
2209 OSL_FAIL("Bibliography entries cannot be found here");
2216 while( TOX_INDEX
== SwTOXBase::GetType() && i
< aRange
.Max() &&
2217 aSortArr
[i
]->GetLevel() > pNew
->GetLevel() )
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();
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
)
2259 { // If not already present, create and insert
2260 SwTOXCustom
* pKey
= new SwTOXCustom( sToCompare
, sToCompareReading
, nLevel
, rIntl
,
2262 for(i
= nMin
; i
< nMax
; ++i
)
2264 if(nLevel
== aSortArr
[i
]->GetLevel() && *pKey
< *(aSortArr
[i
]))
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
)
2280 return Range(nStart
, nEnd
);
2283 bool SwTOXBase::IsTOXBaseInReadonly() const
2285 const SwTOXBaseSection
*pSect
= dynamic_cast<const SwTOXBaseSection
*>(this);
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());
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();
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
);
2331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */