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