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 <DocumentSettingManager.hxx>
40 : #include <IDocumentRedlineAccess.hxx>
41 : #include <IDocumentFieldsAccess.hxx>
42 : #include <IDocumentState.hxx>
43 : #include <IDocumentLayoutAccess.hxx>
44 : #include <IDocumentStylePoolAccess.hxx>
45 : #include <pagefrm.hxx>
46 : #include <ndtxt.hxx>
47 : #include <swtable.hxx>
48 : #include <doctxm.hxx>
49 : #include <txmsrt.hxx>
50 : #include <rolbck.hxx>
51 : #include <poolfmt.hxx>
52 : #include <txtfrm.hxx>
53 : #include <rootfrm.hxx>
54 : #include <UndoAttribute.hxx>
55 : #include <swundo.hxx>
56 : #include <mdiexp.hxx>
57 : #include <docary.hxx>
58 : #include <charfmt.hxx>
59 : #include <fchrfmt.hxx>
60 : #include <fldbas.hxx>
61 : #include <fmtfld.hxx>
62 : #include <txtfld.hxx>
63 : #include <expfld.hxx>
64 : #include <chpfld.hxx>
65 : #include <mvsave.hxx>
66 : #include <node2lay.hxx>
67 : #include <SwStyleNameMapper.hxx>
68 : #include <breakit.hxx>
69 : #include <editsh.hxx>
70 : #include <scriptinfo.hxx>
71 : #include <calbck.hxx>
72 : #include <ToxTextGenerator.hxx>
73 : #include <ToxTabStopTokenHandler.hxx>
74 : #include <tools/datetimeutils.hxx>
75 :
76 : #include <memory>
77 :
78 : using namespace ::com::sun::star;
79 :
80 6192 : TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection ); // for RTTI
81 :
82 0 : sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, std::vector<OUString>& rArr ) const
83 : {
84 0 : rArr.clear();
85 :
86 : // Look up all Primary and Secondary via the Pool
87 0 : const sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
88 0 : for( sal_uInt32 i = 0; i < nMaxItems; ++i )
89 : {
90 0 : const SwTOXMark* pItem = static_cast<const SwTOXMark*>(GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ));
91 0 : if( !pItem )
92 0 : continue;
93 0 : const SwTOXType* pTOXType = pItem->GetTOXType();
94 0 : if ( !pTOXType || pTOXType->GetType()!=TOX_INDEX )
95 0 : continue;
96 0 : const SwTextTOXMark* pMark = pItem->GetTextTOXMark();
97 0 : if ( pMark && pMark->GetpTextNd() &&
98 0 : pMark->GetpTextNd()->GetNodes().IsDocNodes() )
99 : {
100 : const OUString sStr = TOI_PRIMARY == eTyp
101 : ? pItem->GetPrimaryKey()
102 0 : : pItem->GetSecondaryKey();
103 :
104 0 : if( !sStr.isEmpty() )
105 0 : rArr.push_back( sStr );
106 : }
107 : }
108 :
109 0 : return rArr.size();
110 : }
111 :
112 : /// Get current table of contents Mark.
113 690 : sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
114 : SwTOXMarks& rArr )
115 : {
116 : // search on Position rPos for all SwTOXMarks
117 690 : SwTextNode *const pTextNd = rPos.nNode.GetNode().GetTextNode();
118 690 : if( !pTextNd || !pTextNd->GetpSwpHints() )
119 525 : return 0;
120 :
121 165 : const SwpHints & rHts = *pTextNd->GetpSwpHints();
122 : sal_Int32 nSttIdx;
123 : const sal_Int32 *pEndIdx;
124 :
125 165 : const sal_Int32 nAktPos = rPos.nContent.GetIndex();
126 :
127 482 : for( size_t n = 0; n < rHts.Count(); ++n )
128 : {
129 317 : const SwTextAttr* pHt = rHts[n];
130 317 : if( RES_TXTATR_TOXMARK != pHt->Which() )
131 606 : continue;
132 28 : if( ( nSttIdx = pHt->GetStart() ) < nAktPos )
133 : {
134 : // also check the end
135 47 : if( 0 == ( pEndIdx = pHt->End() ) ||
136 19 : *pEndIdx <= nAktPos )
137 28 : continue; // keep searching
138 : }
139 0 : else if( nSttIdx > nAktPos )
140 : // If Hint's Start is greater than rPos, break, because
141 : // the attributes are sorted by Start!
142 0 : break;
143 :
144 0 : SwTOXMark* pTMark = const_cast<SwTOXMark*>(&pHt->GetTOXMark());
145 0 : rArr.push_back( pTMark );
146 : }
147 165 : return rArr.size();
148 : }
149 :
150 : /// Delete table of contents Mark
151 5 : void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
152 : {
153 5 : const SwTextTOXMark* pTextTOXMark = pTOXMark->GetTextTOXMark();
154 : OSL_ENSURE( pTextTOXMark, "No TextTOXMark, cannot be deleted" );
155 :
156 5 : SwTextNode& rTextNd = const_cast<SwTextNode&>(pTextTOXMark->GetTextNode());
157 : OSL_ENSURE( rTextNd.GetpSwpHints(), "cannot be deleted" );
158 :
159 5 : std::unique_ptr<SwRegHistory> aRHst;
160 5 : if (GetIDocumentUndoRedo().DoesUndo())
161 : {
162 : // save attributes for Undo
163 : SwUndoResetAttr* pUndo = new SwUndoResetAttr(
164 5 : SwPosition( rTextNd, SwIndex( &rTextNd, pTextTOXMark->GetStart() ) ),
165 5 : RES_TXTATR_TOXMARK );
166 5 : GetIDocumentUndoRedo().AppendUndo( pUndo );
167 :
168 5 : aRHst.reset(new SwRegHistory(rTextNd, &pUndo->GetHistory()));
169 5 : rTextNd.GetpSwpHints()->Register(aRHst.get());
170 : }
171 :
172 5 : rTextNd.DeleteAttribute( const_cast<SwTextTOXMark*>(pTextTOXMark) );
173 :
174 5 : if (GetIDocumentUndoRedo().DoesUndo())
175 : {
176 5 : if( rTextNd.GetpSwpHints() )
177 1 : rTextNd.GetpSwpHints()->DeRegister();
178 : }
179 5 : getIDocumentState().SetModified();
180 5 : }
181 :
182 : /// Travel between table of content Marks
183 : class CompareNodeContent
184 : {
185 : sal_uLong nNode;
186 : sal_Int32 nContent;
187 : public:
188 0 : CompareNodeContent( sal_uLong nNd, sal_Int32 nCnt )
189 0 : : nNode( nNd ), nContent( nCnt ) {}
190 :
191 0 : bool operator==( const CompareNodeContent& rCmp ) const
192 0 : { return nNode == rCmp.nNode && nContent == rCmp.nContent; }
193 0 : bool operator!=( const CompareNodeContent& rCmp ) const
194 0 : { return nNode != rCmp.nNode || nContent != rCmp.nContent; }
195 0 : bool operator< ( const CompareNodeContent& rCmp ) const
196 0 : { return nNode < rCmp.nNode ||
197 0 : ( nNode == rCmp.nNode && nContent < rCmp.nContent); }
198 0 : bool operator<=( const CompareNodeContent& rCmp ) const
199 0 : { return nNode < rCmp.nNode ||
200 0 : ( nNode == rCmp.nNode && nContent <= rCmp.nContent); }
201 0 : bool operator> ( const CompareNodeContent& rCmp ) const
202 0 : { return nNode > rCmp.nNode ||
203 0 : ( nNode == rCmp.nNode && nContent > rCmp.nContent); }
204 0 : bool operator>=( const CompareNodeContent& rCmp ) const
205 0 : { return nNode > rCmp.nNode ||
206 0 : ( nNode == rCmp.nNode && nContent >= rCmp.nContent); }
207 : };
208 :
209 0 : const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
210 : SwTOXSearch eDir, bool bInReadOnly )
211 : {
212 0 : const SwTextTOXMark* pMark = rCurTOXMark.GetTextTOXMark();
213 : OSL_ENSURE(pMark, "pMark==0 invalid TextTOXMark");
214 :
215 0 : const SwTextNode *pTOXSrc = pMark->GetpTextNd();
216 :
217 0 : CompareNodeContent aAbsIdx( pTOXSrc->GetIndex(), pMark->GetStart() );
218 0 : CompareNodeContent aPrevPos( 0, 0 );
219 0 : CompareNodeContent aNextPos( ULONG_MAX, SAL_MAX_INT32 );
220 0 : CompareNodeContent aMax( 0, 0 );
221 0 : CompareNodeContent aMin( ULONG_MAX, SAL_MAX_INT32 );
222 :
223 0 : const SwTOXMark* pNew = 0;
224 0 : const SwTOXMark* pMax = &rCurTOXMark;
225 0 : const SwTOXMark* pMin = &rCurTOXMark;
226 :
227 0 : const SwTOXType* pType = rCurTOXMark.GetTOXType();
228 0 : SwTOXMarks aMarks;
229 0 : SwTOXMark::InsertTOXMarks( aMarks, *pType );
230 :
231 0 : for( size_t nMark=0; nMark<aMarks.size(); ++nMark )
232 : {
233 0 : const SwTOXMark* pTOXMark = aMarks[nMark];
234 0 : if ( pTOXMark == &rCurTOXMark )
235 0 : continue;
236 :
237 0 : pMark = pTOXMark->GetTextTOXMark();
238 0 : if (!pMark)
239 0 : continue;
240 :
241 0 : pTOXSrc = pMark->GetpTextNd();
242 0 : if (!pTOXSrc)
243 0 : continue;
244 :
245 0 : Point aPt;
246 0 : const SwContentFrm* pCFrm = pTOXSrc->getLayoutFrm( getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, 0, false );
247 0 : if (!pCFrm)
248 0 : continue;
249 :
250 0 : if ( bInReadOnly || !pCFrm->IsProtected() )
251 : {
252 0 : CompareNodeContent aAbsNew( pTOXSrc->GetIndex(), pMark->GetStart() );
253 0 : switch( eDir )
254 : {
255 : // The following (a bit more complicated) statements make it
256 : // possible to also travel across Entries on the same (!)
257 : // position. If someone has time, please feel free to optimize.
258 : case TOX_SAME_PRV:
259 0 : if( pTOXMark->GetText() != rCurTOXMark.GetText() )
260 0 : break;
261 : /* no break here */
262 : case TOX_PRV:
263 0 : if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos) ||
264 0 : (aAbsIdx == aAbsNew &&
265 0 : (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
266 0 : (!pNew ||
267 0 : (pNew && (aPrevPos < aAbsIdx ||
268 0 : sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
269 0 : (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
270 0 : sal_uLong(pTOXMark) > sal_uLong(pNew)) )
271 : {
272 0 : pNew = pTOXMark;
273 0 : aPrevPos = aAbsNew;
274 0 : if ( aAbsNew >= aMax )
275 : {
276 0 : aMax = aAbsNew;
277 0 : pMax = pTOXMark;
278 : }
279 : }
280 0 : break;
281 :
282 : case TOX_SAME_NXT:
283 0 : if( pTOXMark->GetText() != rCurTOXMark.GetText() )
284 0 : break;
285 : /* no break here */
286 : case TOX_NXT:
287 0 : if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos) ||
288 0 : (aAbsIdx == aAbsNew &&
289 0 : (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
290 0 : (!pNew ||
291 0 : (pNew && (aNextPos > aAbsIdx ||
292 0 : sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
293 0 : (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
294 0 : sal_uLong(pTOXMark) < sal_uLong(pNew)) )
295 : {
296 0 : pNew = pTOXMark;
297 0 : aNextPos = aAbsNew;
298 0 : if ( aAbsNew <= aMin )
299 : {
300 0 : aMin = aAbsNew;
301 0 : pMin = pTOXMark;
302 : }
303 : }
304 0 : break;
305 : }
306 : }
307 : }
308 :
309 : // We couldn't find a successor
310 : // Use minimum or maximum
311 0 : if(!pNew)
312 : {
313 0 : switch(eDir)
314 : {
315 : case TOX_PRV:
316 : case TOX_SAME_PRV:
317 0 : pNew = pMax;
318 0 : break;
319 : case TOX_NXT:
320 : case TOX_SAME_NXT:
321 0 : pNew = pMin;
322 0 : break;
323 : default:
324 0 : pNew = &rCurTOXMark;
325 : }
326 : }
327 0 : return *pNew;
328 : }
329 :
330 119 : SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
331 : const SwTOXBase& rTOX,
332 : const SfxItemSet* pSet,
333 : bool bExpand )
334 : {
335 119 : GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
336 :
337 119 : OUString sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), rTOX.GetTOXName() );
338 238 : SwPaM aPam( rPos );
339 238 : SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
340 : SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
341 119 : InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
342 119 : if (pNewSection)
343 : {
344 119 : SwSectionNode *const pSectNd = pNewSection->GetFormat()->GetSectionNode();
345 119 : pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
346 :
347 119 : if( bExpand )
348 : {
349 : // add value for 2nd parameter = true to
350 : // indicate, that a creation of a new table of content has to be performed.
351 : // Value of 1st parameter = default value.
352 0 : pNewSection->Update( 0, true );
353 : }
354 119 : else if( rTOX.GetTitle().getLength()==1 && IsInReading() )
355 : // insert title of TOX
356 : {
357 : // then insert the headline section
358 0 : SwNodeIndex aIdx( *pSectNd, +1 );
359 :
360 0 : SwTextNode* pHeadNd = GetNodes().MakeTextNode( aIdx,
361 0 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
362 :
363 0 : SwSectionData headerData( TOX_HEADER_SECTION, pNewSection->GetTOXName()+"_Head" );
364 :
365 0 : SwNodeIndex aStt( *pHeadNd ); --aIdx;
366 0 : SwSectionFormat* pSectFormat = MakeSectionFormat( 0 );
367 0 : GetNodes().InsertTextSection(
368 0 : aStt, *pSectFormat, headerData, 0, &aIdx, true, false);
369 : }
370 : }
371 :
372 119 : GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
373 :
374 238 : return pNewSection;
375 : }
376 :
377 0 : const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
378 : const SwTOXBase& rTOX,
379 : const SfxItemSet* pSet )
380 : {
381 : // check for recursiv TOX
382 0 : SwNode* pNd = GetNodes()[ nSttNd ];
383 0 : SwSectionNode* pSectNd = pNd->FindSectionNode();
384 0 : while( pSectNd )
385 : {
386 0 : SectionType eT = pSectNd->GetSection().GetType();
387 0 : if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
388 0 : return 0;
389 0 : pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
390 : }
391 :
392 0 : const OUString sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), rTOX.GetTOXName());
393 :
394 0 : SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
395 :
396 0 : SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
397 0 : SwSectionFormat* pFormat = MakeSectionFormat( 0 );
398 0 : if(pSet)
399 0 : pFormat->SetFormatAttr(*pSet);
400 :
401 : SwSectionNode *const pNewSectionNode =
402 0 : GetNodes().InsertTextSection(aStt, *pFormat, aSectionData, &rTOX, &aEnd);
403 0 : if (!pNewSectionNode)
404 : {
405 0 : DelSectionFormat( pFormat );
406 0 : return 0;
407 : }
408 :
409 : SwTOXBaseSection *const pNewSection(
410 0 : dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
411 0 : if (pNewSection)
412 0 : pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
413 0 : return pNewSection;
414 : }
415 :
416 : /// Get current table of contents
417 2498 : SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos )
418 : {
419 2498 : SwNode& rNd = rPos.nNode.GetNode();
420 2498 : SwSectionNode* pSectNd = rNd.FindSectionNode();
421 4996 : while( pSectNd )
422 : {
423 22 : SectionType eT = pSectNd->GetSection().GetType();
424 22 : if( TOX_CONTENT_SECTION == eT )
425 : {
426 : OSL_ENSURE( pSectNd->GetSection().ISA( SwTOXBaseSection ),
427 : "no TOXBaseSection!" );
428 : SwTOXBaseSection& rTOXSect = static_cast<SwTOXBaseSection&>(
429 22 : pSectNd->GetSection());
430 22 : return &rTOXSect;
431 : }
432 0 : pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
433 : }
434 2476 : return 0;
435 : }
436 :
437 117 : const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase)
438 : {
439 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
440 117 : const SwTOXBaseSection& rTOXSect = static_cast<const SwTOXBaseSection&>(rTOXBase);
441 117 : SwSectionFormat const * pFormat = rTOXSect.GetFormat();
442 : OSL_ENSURE( pFormat, "invalid TOXBaseSection!" );
443 117 : return pFormat->GetAttrSet();
444 : }
445 :
446 0 : const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, bool bCreate )
447 : {
448 0 : SwTOXBase** prBase = 0;
449 0 : switch(eTyp)
450 : {
451 0 : case TOX_CONTENT: prBase = &mpDefTOXBases->pContBase; break;
452 0 : case TOX_INDEX: prBase = &mpDefTOXBases->pIdxBase; break;
453 0 : case TOX_USER: prBase = &mpDefTOXBases->pUserBase; break;
454 0 : case TOX_TABLES: prBase = &mpDefTOXBases->pTableBase; break;
455 0 : case TOX_OBJECTS: prBase = &mpDefTOXBases->pObjBase; break;
456 0 : case TOX_ILLUSTRATIONS: prBase = &mpDefTOXBases->pIllBase; break;
457 0 : case TOX_AUTHORITIES: prBase = &mpDefTOXBases->pAuthBase; break;
458 0 : case TOX_BIBLIOGRAPHY: prBase = &mpDefTOXBases->pBiblioBase; break;
459 0 : case TOX_CITATION: /** TODO */break;
460 : }
461 0 : if (!prBase)
462 0 : return NULL;
463 0 : if(!(*prBase) && bCreate)
464 : {
465 0 : SwForm aForm(eTyp);
466 0 : const SwTOXType* pType = GetTOXType(eTyp, 0);
467 0 : (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
468 : }
469 0 : return (*prBase);
470 : }
471 :
472 0 : void SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
473 : {
474 0 : SwTOXBase** prBase = 0;
475 0 : switch(rBase.GetType())
476 : {
477 0 : case TOX_CONTENT: prBase = &mpDefTOXBases->pContBase; break;
478 0 : case TOX_INDEX: prBase = &mpDefTOXBases->pIdxBase; break;
479 0 : case TOX_USER: prBase = &mpDefTOXBases->pUserBase; break;
480 0 : case TOX_TABLES: prBase = &mpDefTOXBases->pTableBase; break;
481 0 : case TOX_OBJECTS: prBase = &mpDefTOXBases->pObjBase; break;
482 0 : case TOX_ILLUSTRATIONS: prBase = &mpDefTOXBases->pIllBase; break;
483 0 : case TOX_AUTHORITIES: prBase = &mpDefTOXBases->pAuthBase; break;
484 0 : case TOX_BIBLIOGRAPHY: prBase = &mpDefTOXBases->pBiblioBase; break;
485 0 : case TOX_CITATION: /** TODO */break;
486 : }
487 0 : if (!prBase)
488 0 : return;
489 0 : delete (*prBase);
490 0 : (*prBase) = new SwTOXBase(rBase);
491 : }
492 :
493 : /// Delete table of contents
494 2 : bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, bool bDelNodes )
495 : {
496 : // We only delete the TOX, not the Nodes
497 2 : bool bRet = false;
498 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
499 :
500 2 : const SwTOXBaseSection& rTOXSect = static_cast<const SwTOXBaseSection&>(rTOXBase);
501 2 : SwSectionFormat const * pFormat = rTOXSect.GetFormat();
502 : /* Save the start node of the TOX' section. */
503 2 : SwSectionNode const * pMyNode = pFormat ? pFormat->GetSectionNode() : NULL;
504 2 : if (pMyNode)
505 : {
506 2 : GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
507 :
508 : /* Save start node of section's surrounding. */
509 2 : SwNode const * pStartNd = pMyNode->StartOfSectionNode();
510 :
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. */
518 :
519 : /* Set PaM to end of TOX' section and search following content node.
520 : aSearchPam will contain the point where to move the cursors
521 : to. */
522 2 : SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
523 4 : SwPosition aEndPos(*pStartNd->EndOfSectionNode());
524 4 : if (! aSearchPam.Move() /* no content node found */
525 2 : || *aSearchPam.GetPoint() >= aEndPos /* content node found
526 : outside surrounding */
527 : )
528 : {
529 : /* Set PaM to beginning of TOX' section and search previous
530 : content node */
531 0 : SwPaM aTmpPam(*pMyNode);
532 0 : aSearchPam = aTmpPam;
533 0 : SwPosition aStartPos(*pStartNd);
534 :
535 0 : if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
536 0 : || *aSearchPam.GetPoint() <= aStartPos /* content node
537 : found outside
538 : surrounding */
539 : )
540 : {
541 : /* There is no content node in the surrounding of
542 : TOX'. Append text node behind TOX' section. */
543 :
544 0 : SwPosition aInsPos(*pMyNode->EndOfSectionNode());
545 0 : getIDocumentContentOperations().AppendTextNode(aInsPos);
546 :
547 0 : SwPaM aTmpPam1(aInsPos);
548 0 : aSearchPam = aTmpPam1;
549 0 : }
550 : }
551 :
552 : /* PaM containing the TOX. */
553 4 : SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
554 :
555 : /* Move cursors contained in TOX to the above calculated point. */
556 2 : PaMCorrAbs(aPam, *aSearchPam.GetPoint());
557 :
558 2 : if( !bDelNodes )
559 : {
560 0 : SwSections aArr( 0 );
561 0 : pFormat->GetChildSections( aArr, SORTSECT_NOT, false );
562 0 : for( const auto pSect : aArr )
563 : {
564 0 : if( TOX_HEADER_SECTION == pSect->GetType() )
565 : {
566 0 : DelSectionFormat( pSect->GetFormat(), bDelNodes );
567 : }
568 0 : }
569 : }
570 :
571 2 : DelSectionFormat( const_cast<SwSectionFormat *>(pFormat), bDelNodes );
572 :
573 2 : GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
574 4 : bRet = true;
575 : }
576 :
577 2 : return bRet;
578 : }
579 :
580 : /// Manage table of content types
581 0 : sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
582 : {
583 0 : sal_uInt16 nCnt = 0;
584 0 : for( auto pTOXType : *mpTOXTypes )
585 0 : if( eTyp == pTOXType->GetType() )
586 0 : ++nCnt;
587 0 : return nCnt;
588 : }
589 :
590 288 : const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
591 : {
592 288 : sal_uInt16 nCnt = 0;
593 636 : for( auto pTOXType : *mpTOXTypes )
594 636 : if( eTyp == pTOXType->GetType() && nCnt++ == nId )
595 288 : return pTOXType;
596 0 : return 0;
597 : }
598 :
599 0 : const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
600 : {
601 0 : SwTOXType * pNew = new SwTOXType( rTyp );
602 0 : mpTOXTypes->push_back( pNew );
603 0 : return pNew;
604 : }
605 :
606 238 : OUString SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
607 : const OUString& sChkStr ) const
608 : {
609 238 : if( IsInMailMerge())
610 : {
611 : OUString newName = "MailMergeTOX"
612 0 : + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
613 0 : + OUString::number( mpSectionFormatTable->size() + 1 );
614 0 : if( !sChkStr.isEmpty())
615 0 : newName += sChkStr;
616 0 : return newName;
617 : }
618 :
619 238 : bool bUseChkStr = !sChkStr.isEmpty();
620 238 : const OUString aName( rType.GetTypeName() );
621 238 : const sal_Int32 nNmLen = aName.getLength();
622 :
623 238 : SwSectionFormats::size_type nNum = 0;
624 238 : const SwSectionFormats::size_type nFlagSize = ( mpSectionFormatTable->size() / 8 ) +2;
625 238 : sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
626 238 : memset( pSetFlags, 0, nFlagSize );
627 :
628 631 : for( auto pSectionFormat : *mpSectionFormatTable )
629 : {
630 393 : const SwSectionNode *pSectNd = pSectionFormat->GetSectionNode( false );
631 393 : if ( !pSectNd )
632 0 : continue;
633 :
634 393 : const SwSection& rSect = pSectNd->GetSection();
635 393 : if (rSect.GetType()==TOX_CONTENT_SECTION)
636 : {
637 225 : const OUString rNm = rSect.GetSectionName();
638 225 : if ( aName.startsWith(rNm) )
639 : {
640 : // Calculate number and set the Flag
641 0 : nNum = rNm.copy( nNmLen ).toInt32();
642 0 : if( nNum-- && nNum < mpSectionFormatTable->size() )
643 0 : pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
644 : }
645 225 : if ( bUseChkStr && sChkStr==rNm )
646 0 : bUseChkStr = false;
647 : }
648 : }
649 :
650 238 : if( !bUseChkStr )
651 : {
652 : // All Numbers have been flagged accordingly, so get the right Number
653 238 : nNum = mpSectionFormatTable->size();
654 238 : for( SwSectionFormats::size_type n = 0; n < nFlagSize; ++n )
655 : {
656 238 : sal_uInt8 nTmp = pSetFlags[ n ];
657 238 : if( nTmp != 0xff )
658 : {
659 : // so get the Number
660 238 : nNum = n * 8;
661 476 : while( nTmp & 1 )
662 : {
663 0 : ++nNum;
664 0 : nTmp >>= 1;
665 : }
666 238 : break;
667 : }
668 : }
669 : }
670 238 : delete [] pSetFlags;
671 238 : if ( bUseChkStr )
672 0 : return sChkStr;
673 238 : return aName + OUString::number( ++nNum );
674 : }
675 :
676 119 : bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const OUString& rName)
677 : {
678 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ),
679 : "no TOXBaseSection!" );
680 119 : SwTOXBaseSection* pTOX = const_cast<SwTOXBaseSection*>(static_cast<const SwTOXBaseSection*>(&rTOXBase));
681 :
682 119 : if (GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), rName) == rName)
683 : {
684 0 : pTOX->SetTOXName(rName);
685 0 : pTOX->SetSectionName(rName);
686 0 : getIDocumentState().SetModified();
687 0 : return true;
688 : }
689 119 : return false;
690 : }
691 :
692 2 : static const SwTextNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
693 : {
694 2 : const SwNode* pNd = &rNd;
695 2 : 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, false );
701 :
702 0 : if( pFrm )
703 : {
704 0 : SwPosition aPos( *pNd );
705 0 : pNd = GetBodyTextNode( *pNd->GetDoc(), aPos, *pFrm );
706 0 : OSL_ENSURE( pNd, "Where's the paragraph?" );
707 0 : }
708 : }
709 2 : return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
710 : }
711 :
712 : // Table of contents class
713 119 : SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFormat & rFormat)
714 : : SwTOXBase( rBase )
715 119 : , SwSection( TOX_CONTENT_SECTION, OUString(), rFormat )
716 : {
717 119 : SetProtect( rBase.IsProtected() );
718 119 : SetSectionName( GetTOXName() );
719 119 : }
720 :
721 357 : SwTOXBaseSection::~SwTOXBaseSection()
722 : {
723 119 : for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
724 0 : delete *it;
725 238 : }
726 :
727 0 : bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, bool bAtStart ) const
728 : {
729 0 : bool bRet = false;
730 0 : const SwSectionNode* pSectNd = GetFormat()->GetSectionNode();
731 0 : if( pSectNd )
732 : {
733 : SwContentNode* pCNd;
734 0 : sal_Int32 nC = 0;
735 0 : if( bAtStart )
736 : {
737 0 : rPos.nNode = *pSectNd;
738 0 : pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
739 : }
740 : else
741 : {
742 0 : rPos.nNode = *pSectNd->EndOfSectionNode();
743 0 : pCNd = SwNodes::GoPrevious( &rPos.nNode );
744 0 : if( pCNd ) nC = pCNd->Len();
745 : }
746 0 : rPos.nContent.Assign( pCNd, nC );
747 0 : bRet = true;
748 : }
749 0 : return bRet;
750 : }
751 :
752 : /// Collect table of contents content
753 4 : void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
754 : const bool _bNewTOX )
755 : {
756 : const SwSectionNode* pSectNd;
757 12 : if( !SwTOXBase::GetRegisteredIn()->HasWriterListeners() ||
758 12 : !GetFormat() || 0 == (pSectNd = GetFormat()->GetSectionNode() ) ||
759 12 : !pSectNd->GetNodes().IsDocNodes() ||
760 4 : IsHiddenFlag() )
761 : {
762 4 : return;
763 : }
764 :
765 4 : if ( !mbKeepExpression )
766 : {
767 0 : maMSTOCExpression.clear();
768 : }
769 :
770 4 : SwDoc* pDoc = const_cast<SwDoc*>(pSectNd->GetDoc());
771 :
772 : assert(pDoc); //Where is the document?
773 :
774 4 : if (pAttr && GetFormat())
775 0 : pDoc->ChgFormat(*GetFormat(), *pAttr);
776 :
777 : // determine default page description, which will be used by the content nodes,
778 : // if no appropriate one is found.
779 : const SwPageDesc* pDefaultPageDesc;
780 : {
781 : pDefaultPageDesc =
782 4 : pSectNd->GetSection().GetFormat()->GetPageDesc().GetPageDesc();
783 4 : if ( !_bNewTOX && !pDefaultPageDesc )
784 : {
785 : // determine page description of table-of-content
786 4 : size_t nPgDescNdIdx = pSectNd->GetIndex() + 1;
787 4 : size_t* pPgDescNdIdx = &nPgDescNdIdx;
788 4 : pDefaultPageDesc = pSectNd->FindPageDesc( false, pPgDescNdIdx );
789 4 : if ( nPgDescNdIdx < pSectNd->GetIndex() )
790 : {
791 0 : pDefaultPageDesc = 0;
792 : }
793 : }
794 : // consider end node of content section in the node array.
795 4 : if ( !pDefaultPageDesc &&
796 0 : ( pSectNd->EndOfSectionNode()->GetIndex() <
797 0 : (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
798 : )
799 : {
800 : // determine page description of content after table-of-content
801 0 : SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
802 0 : const SwContentNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
803 0 : const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
804 0 : const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
805 0 : if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
806 0 : eBreak == SVX_BREAK_PAGE_BOTH )
807 : )
808 : {
809 0 : pDefaultPageDesc = pNdAfterTOX->FindPageDesc( false );
810 0 : }
811 : }
812 : // consider start node of content section in the node array.
813 4 : if ( !pDefaultPageDesc &&
814 0 : ( pSectNd->GetIndex() >
815 0 : (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
816 : )
817 : {
818 : // determine page description of content before table-of-content
819 0 : SwNodeIndex aIdx( *pSectNd );
820 : pDefaultPageDesc =
821 0 : SwNodes::GoPrevious( &aIdx )->FindPageDesc( false );
822 :
823 : }
824 4 : if ( !pDefaultPageDesc )
825 : {
826 : // determine default page description
827 0 : pDefaultPageDesc = &pDoc->GetPageDesc( 0 );
828 : }
829 : }
830 :
831 4 : pDoc->getIDocumentState().SetModified();
832 :
833 : // get current Language
834 4 : SwTOXInternational aIntl( GetLanguage(),
835 4 : TOX_INDEX == GetTOXType()->GetType() ?
836 1 : GetOptions() : 0,
837 13 : GetSortAlgorithm() );
838 :
839 4 : for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
840 0 : delete *it;
841 4 : aSortArr.clear();
842 :
843 : // find the first layout node for this TOX, if it only find the content
844 : // in his own chapter
845 4 : const SwTextNode* pOwnChapterNode = IsFromChapter()
846 1 : ? ::lcl_FindChapterNode( *pSectNd, 0 )
847 5 : : 0;
848 :
849 8 : SwNode2Layout aN2L( *pSectNd );
850 4 : const_cast<SwSectionNode*>(pSectNd)->DelFrms();
851 :
852 : // remove old content an insert one empty textnode (to hold the layout!)
853 : SwTextNode* pFirstEmptyNd;
854 : {
855 4 : pDoc->getIDocumentRedlineAccess().DeleteRedline( *pSectNd, true, USHRT_MAX );
856 :
857 4 : SwNodeIndex aSttIdx( *pSectNd, +1 );
858 8 : SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
859 4 : pFirstEmptyNd = pDoc->GetNodes().MakeTextNode( aEndIdx,
860 8 : pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
861 :
862 : {
863 : // Task 70995 - save and restore PageDesc and Break Attributes
864 4 : SwNodeIndex aNxtIdx( aSttIdx );
865 4 : const SwContentNode* pCNd = aNxtIdx.GetNode().GetContentNode();
866 4 : if( !pCNd )
867 2 : pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
868 4 : if( pCNd->HasSwAttrSet() )
869 : {
870 0 : SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
871 0 : aBrkSet.Put( *pCNd->GetpSwAttrSet() );
872 0 : if( aBrkSet.Count() )
873 0 : pFirstEmptyNd->SetAttr( aBrkSet );
874 4 : }
875 : }
876 4 : --aEndIdx;
877 8 : SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
878 4 : SwDoc::CorrAbs( aSttIdx, aEndIdx, aPos, true );
879 :
880 : // delete flys in whole range including start node which requires
881 : // giving the node before start node as Mark parameter, hence -1.
882 : // (flys must be deleted because the anchor nodes are removed)
883 4 : DelFlyInRange( SwNodeIndex(aSttIdx, -1), aEndIdx );
884 :
885 8 : pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
886 : }
887 :
888 : // insert title of TOX
889 4 : if ( !GetTitle().isEmpty() )
890 : {
891 : // then insert the headline section
892 4 : SwNodeIndex aIdx( *pSectNd, +1 );
893 :
894 4 : SwTextNode* pHeadNd = pDoc->GetNodes().MakeTextNode( aIdx,
895 8 : GetTextFormatColl( FORM_TITLE ) );
896 4 : pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
897 :
898 8 : SwSectionData headerData( TOX_HEADER_SECTION, GetTOXName()+"_Head" );
899 :
900 8 : SwNodeIndex aStt( *pHeadNd ); --aIdx;
901 4 : SwSectionFormat* pSectFormat = pDoc->MakeSectionFormat( 0 );
902 4 : pDoc->GetNodes().InsertTextSection(
903 8 : aStt, *pSectFormat, headerData, 0, &aIdx, true, false);
904 : }
905 :
906 : // This would be a good time to update the Numbering
907 4 : pDoc->UpdateNumRule();
908 :
909 4 : if( GetCreateType() & nsSwTOXElement::TOX_MARK )
910 4 : UpdateMarks( aIntl, pOwnChapterNode );
911 :
912 4 : if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
913 3 : UpdateOutline( pOwnChapterNode );
914 :
915 4 : if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
916 0 : UpdateTemplate( pOwnChapterNode );
917 :
918 8 : if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
919 4 : TOX_OBJECTS == SwTOXBase::GetType())
920 0 : UpdateContent( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
921 :
922 8 : if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
923 4 : (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
924 0 : UpdateTable( pOwnChapterNode );
925 :
926 8 : if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
927 4 : (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
928 0 : UpdateContent( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
929 :
930 4 : if( !GetSequenceName().isEmpty() && !IsFromObjectNames() &&
931 0 : (TOX_TABLES == SwTOXBase::GetType() ||
932 0 : TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
933 0 : UpdateSequence( pOwnChapterNode );
934 :
935 4 : if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
936 0 : UpdateContent( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
937 :
938 4 : if(TOX_AUTHORITIES == SwTOXBase::GetType())
939 0 : UpdateAuthorities( aIntl );
940 :
941 : // Insert AlphaDelimitters if needed (just for keywords)
942 5 : if( TOX_INDEX == SwTOXBase::GetType() &&
943 1 : ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
944 1 : InsertAlphaDelimitter( aIntl );
945 :
946 : // Sort the List of all TOC Marks and TOC Sections
947 8 : std::vector<SwTextFormatColl*> aCollArr( GetTOXForm().GetFormMax(), 0 );
948 8 : SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
949 8 : for( SwTOXSortTabBases::size_type nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
950 : {
951 4 : ::SetProgressState( 0, pDoc->GetDocShell() );
952 :
953 : // Put the Text into the TOC
954 4 : sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
955 4 : SwTextFormatColl* pColl = aCollArr[ nLvl ];
956 4 : if( !pColl )
957 : {
958 3 : pColl = GetTextFormatColl( nLvl );
959 3 : aCollArr[ nLvl ] = pColl;
960 : }
961 :
962 : // Generate: Set dynamic TabStops
963 4 : SwTextNode* pTOXNd = pDoc->GetNodes().MakeTextNode( aInsPos , pColl );
964 4 : aSortArr[ nCnt ]->pTOXNd = pTOXNd;
965 :
966 : // Generate: Evaluate Form and insert the place holder for the
967 : // page number. If it is a TOX_INDEX and the SwForm IsCommaSeparated()
968 : // then a range of entries must be generated into one paragraph
969 4 : size_t nRange = 1;
970 9 : if(TOX_INDEX == SwTOXBase::GetType() &&
971 4 : GetTOXForm().IsCommaSeparated() &&
972 0 : aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
973 : {
974 0 : const SwTOXMark& rMark = aSortArr[nCnt]->pTextMark->GetTOXMark();
975 0 : const OUString sPrimKey = rMark.GetPrimaryKey();
976 0 : const OUString sSecKey = rMark.GetSecondaryKey();
977 0 : const SwTOXMark* pNextMark = 0;
978 0 : while(aSortArr.size() > (nCnt + nRange)&&
979 0 : aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
980 0 : 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTextMark->GetTOXMark())) &&
981 0 : pNextMark->GetPrimaryKey() == sPrimKey &&
982 0 : pNextMark->GetSecondaryKey() == sSecKey)
983 0 : nRange++;
984 : }
985 : // pass node index of table-of-content section and default page description
986 : // to method <GenerateText(..)>.
987 4 : ::SetProgressState( 0, pDoc->GetDocShell() );
988 :
989 : std::shared_ptr<sw::ToxTabStopTokenHandler> tabStopTokenHandler =
990 : std::make_shared<sw::DefaultToxTabStopTokenHandler>(
991 8 : pSectNd->GetIndex(), *pDefaultPageDesc, GetTOXForm().IsRelTabPos(),
992 4 : pDoc->GetDocumentSettingManager().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT) ?
993 : sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_INDENT :
994 12 : sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_PAGE);
995 8 : sw::ToxTextGenerator ttgn(GetTOXForm(), tabStopTokenHandler);
996 4 : ttgn.GenerateText(GetFormat()->GetDoc(), aSortArr, nCnt, nRange);
997 4 : nCnt += nRange - 1;
998 4 : }
999 :
1000 : // delete the first dummy node and remove all Cursor into the previous node
1001 4 : aInsPos = *pFirstEmptyNd;
1002 : {
1003 4 : SwPaM aCorPam( *pFirstEmptyNd );
1004 4 : aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
1005 4 : if( !aCorPam.Move( fnMoveForward ) )
1006 0 : aCorPam.Move( fnMoveBackward );
1007 8 : SwNodeIndex aEndIdx( aInsPos, 1 );
1008 4 : SwDoc::CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), true );
1009 :
1010 : // Task 70995 - save and restore PageDesc and Break Attributes
1011 4 : if( pFirstEmptyNd->HasSwAttrSet() )
1012 : {
1013 0 : if( !GetTitle().isEmpty() )
1014 0 : aEndIdx = *pSectNd;
1015 : else
1016 0 : aEndIdx = *pFirstEmptyNd;
1017 0 : SwContentNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
1018 0 : if( pCNd ) // Robust against defect documents, e.g. i60336
1019 0 : pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
1020 4 : }
1021 : }
1022 :
1023 : // now create the new Frames
1024 4 : sal_uLong nIdx = pSectNd->GetIndex();
1025 : // don't delete if index is empty
1026 4 : if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1027 4 : pDoc->GetNodes().Delete( aInsPos, 1 );
1028 :
1029 4 : aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1030 8 : std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1031 8 : for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); ++pLayoutIter)
1032 : {
1033 4 : SwFrm::CheckPageDescs( static_cast<SwPageFrm*>((*pLayoutIter)->Lower()) );
1034 : }
1035 :
1036 8 : SetProtect( SwTOXBase::IsProtected() );
1037 : }
1038 :
1039 1 : void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1040 : {
1041 1 : SwDoc* pDoc = GetFormat()->GetDoc();
1042 1 : OUString sLastDeli;
1043 1 : SwTOXSortTabBases::size_type i = 0;
1044 3 : while( i < aSortArr.size() )
1045 : {
1046 1 : ::SetProgressState( 0, pDoc->GetDocShell() );
1047 :
1048 1 : sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1049 :
1050 : // Skip AlphaDelimitter
1051 1 : if( nLevel == FORM_ALPHA_DELIMITTER )
1052 0 : continue;
1053 :
1054 1 : const OUString sDeli = rIntl.GetIndexKey( aSortArr[i]->GetText(),
1055 2 : aSortArr[i]->GetLocale() );
1056 :
1057 : // Do we already have a Delimitter?
1058 1 : if( !sDeli.isEmpty() && sLastDeli != sDeli )
1059 : {
1060 : // We skip all that are less than a small Blank (these are special characters)
1061 0 : if( ' ' <= sDeli[0] )
1062 : {
1063 : SwTOXCustom* pCst = new SwTOXCustom( TextAndReading(sDeli, OUString()),
1064 : FORM_ALPHA_DELIMITTER,
1065 0 : rIntl, aSortArr[i]->GetLocale() );
1066 0 : aSortArr.insert( aSortArr.begin() + i, pCst);
1067 0 : i++;
1068 : }
1069 0 : sLastDeli = sDeli;
1070 : }
1071 :
1072 : // Skip until we get to the same or a lower Level
1073 1 : do {
1074 1 : i++;
1075 1 : } while (i < aSortArr.size() && aSortArr[i]->GetLevel() > nLevel);
1076 2 : }
1077 1 : }
1078 :
1079 : /// Evaluate Template
1080 7 : SwTextFormatColl* SwTOXBaseSection::GetTextFormatColl( sal_uInt16 nLevel )
1081 : {
1082 7 : SwDoc* pDoc = GetFormat()->GetDoc();
1083 7 : const OUString& rName = GetTOXForm().GetTemplate( nLevel );
1084 7 : SwTextFormatColl* pColl = !rName.isEmpty() ? pDoc->FindTextFormatCollByName(rName) :0;
1085 7 : if( !pColl )
1086 : {
1087 4 : sal_uInt16 nPoolFormat = 0;
1088 4 : const TOXTypes eMyType = SwTOXBase::GetType();
1089 4 : switch( eMyType )
1090 : {
1091 2 : case TOX_INDEX: nPoolFormat = RES_POOLCOLL_TOX_IDXH; break;
1092 : case TOX_USER:
1093 0 : if( nLevel < 6 )
1094 0 : nPoolFormat = RES_POOLCOLL_TOX_USERH;
1095 : else
1096 0 : nPoolFormat = RES_POOLCOLL_TOX_USER6 - 6;
1097 0 : break;
1098 0 : case TOX_ILLUSTRATIONS: nPoolFormat = RES_POOLCOLL_TOX_ILLUSH; break;
1099 0 : case TOX_OBJECTS: nPoolFormat = RES_POOLCOLL_TOX_OBJECTH; break;
1100 0 : case TOX_TABLES: nPoolFormat = RES_POOLCOLL_TOX_TABLESH; break;
1101 : case TOX_AUTHORITIES:
1102 : case TOX_BIBLIOGRAPHY:
1103 0 : nPoolFormat = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1104 0 : case TOX_CITATION: /** TODO */break;
1105 : case TOX_CONTENT:
1106 : // There's a jump in the ContentArea!
1107 2 : if( nLevel < 6 )
1108 2 : nPoolFormat = RES_POOLCOLL_TOX_CNTNTH;
1109 : else
1110 0 : nPoolFormat = RES_POOLCOLL_TOX_CNTNT6 - 6;
1111 2 : break;
1112 : }
1113 :
1114 4 : if(eMyType == TOX_AUTHORITIES && nLevel)
1115 0 : nPoolFormat = nPoolFormat + 1;
1116 4 : else if(eMyType == TOX_INDEX && nLevel)
1117 : {
1118 : // pool: Level 1,2,3, Delimiter
1119 : // SwForm: Delimiter, Level 1,2,3
1120 1 : nPoolFormat += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1121 : }
1122 : else
1123 3 : nPoolFormat = nPoolFormat + nLevel;
1124 4 : pColl = pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolFormat );
1125 : }
1126 7 : return pColl;
1127 : }
1128 :
1129 : /// Create from Marks
1130 4 : void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1131 : const SwTextNode* pOwnChapterNode )
1132 : {
1133 4 : const SwTOXType* pType = static_cast<SwTOXType*>( SwTOXBase::GetRegisteredIn() );
1134 4 : if( !pType->HasWriterListeners() )
1135 4 : return;
1136 :
1137 4 : SwDoc* pDoc = GetFormat()->GetDoc();
1138 4 : TOXTypes eTOXTyp = GetTOXType()->GetType();
1139 4 : SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1140 :
1141 : SwTextTOXMark* pTextMark;
1142 : SwTOXMark* pMark;
1143 6 : for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1144 : {
1145 2 : ::SetProgressState( 0, pDoc->GetDocShell() );
1146 :
1147 2 : if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1148 : 0 != ( pTextMark = pMark->GetTextTOXMark() ) )
1149 : {
1150 1 : const SwTextNode* pTOXSrc = pTextMark->GetpTextNd();
1151 : // Only insert TOXMarks from the Doc, not from the
1152 : // UNDO.
1153 :
1154 : // If selected use marks from the same chapter only
1155 3 : if( pTOXSrc->GetNodes().IsDocNodes() &&
1156 3 : pTOXSrc->GetText().getLength() && pTOXSrc->HasWriterListeners() &&
1157 2 : pTOXSrc->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) &&
1158 3 : (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1159 3 : !pTOXSrc->HasHiddenParaField() &&
1160 1 : !SwScriptInfo::IsInHiddenRange( *pTOXSrc, pTextMark->GetStart() ) )
1161 : {
1162 1 : SwTOXSortTabBase* pBase = 0;
1163 1 : if(TOX_INDEX == eTOXTyp)
1164 : {
1165 : // index entry mark
1166 1 : lang::Locale aLocale;
1167 1 : if ( g_pBreakIt->GetBreakIter().is() )
1168 : {
1169 : aLocale = g_pBreakIt->GetLocale(
1170 1 : pTOXSrc->GetLang( pTextMark->GetStart() ) );
1171 : }
1172 :
1173 : pBase = new SwTOXIndex( *pTOXSrc, pTextMark,
1174 1 : GetOptions(), FORM_ENTRY, rIntl, aLocale );
1175 1 : InsertSorted(pBase);
1176 4 : if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1177 4 : !pTextMark->GetTOXMark().GetPrimaryKey().isEmpty())
1178 : {
1179 : pBase = new SwTOXIndex( *pTOXSrc, pTextMark,
1180 0 : GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1181 0 : InsertSorted(pBase);
1182 0 : if (!pTextMark->GetTOXMark().GetSecondaryKey().isEmpty())
1183 : {
1184 : pBase = new SwTOXIndex( *pTOXSrc, pTextMark,
1185 0 : GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1186 0 : InsertSorted(pBase);
1187 : }
1188 1 : }
1189 : }
1190 0 : else if( TOX_USER == eTOXTyp ||
1191 0 : pMark->GetLevel() <= GetLevel())
1192 : { // table of content mark
1193 : // also used for user marks
1194 0 : pBase = new SwTOXContent( *pTOXSrc, pTextMark, rIntl );
1195 0 : InsertSorted(pBase);
1196 : }
1197 : }
1198 : }
1199 4 : }
1200 : }
1201 :
1202 : /// Generate table of contents from outline
1203 3 : void SwTOXBaseSection::UpdateOutline( const SwTextNode* pOwnChapterNode )
1204 : {
1205 3 : SwDoc* pDoc = GetFormat()->GetDoc();
1206 3 : SwNodes& rNds = pDoc->GetNodes();
1207 :
1208 3 : const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1209 6 : for( auto pOutlineNode : rOutlNds )
1210 : {
1211 3 : ::SetProgressState( 0, pDoc->GetDocShell() );
1212 3 : SwTextNode* pTextNd = pOutlineNode->GetTextNode();
1213 9 : if( pTextNd && pTextNd->Len() && pTextNd->HasWriterListeners() &&
1214 6 : sal_uInt16( pTextNd->GetAttrOutlineLevel()) <= GetLevel() &&
1215 6 : pTextNd->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) &&
1216 6 : !pTextNd->HasHiddenParaField() &&
1217 12 : !pTextNd->HasHiddenCharAttribute( true ) &&
1218 3 : ( !IsFromChapter() ||
1219 0 : ::lcl_FindChapterNode( *pTextNd, 0 ) == pOwnChapterNode ))
1220 : {
1221 3 : SwTOXPara * pNew = new SwTOXPara( *pTextNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1222 3 : InsertSorted( pNew );
1223 : }
1224 : }
1225 3 : }
1226 :
1227 : /// Generate table of contents from template areas
1228 0 : void SwTOXBaseSection::UpdateTemplate( const SwTextNode* pOwnChapterNode )
1229 : {
1230 0 : SwDoc* pDoc = GetFormat()->GetDoc();
1231 0 : for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1232 : {
1233 0 : const OUString sTmpStyleNames = GetStyleNames(i);
1234 0 : if (sTmpStyleNames.isEmpty())
1235 0 : continue;
1236 :
1237 0 : sal_Int32 nIndex = 0;
1238 0 : while (nIndex >= 0)
1239 : {
1240 : SwTextFormatColl* pColl = pDoc->FindTextFormatCollByName(
1241 0 : sTmpStyleNames.getToken( 0, TOX_STYLE_DELIMITER, nIndex ));
1242 : //TODO: no outline Collections in content indexes if OutlineLevels are already included
1243 0 : if( !pColl ||
1244 0 : ( TOX_CONTENT == SwTOXBase::GetType() &&
1245 0 : GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1246 0 : pColl->IsAssignedToListLevelOfOutlineStyle()) )
1247 0 : continue;
1248 :
1249 0 : SwIterator<SwTextNode,SwFormatColl> aIter( *pColl );
1250 0 : for( SwTextNode* pTextNd = aIter.First(); pTextNd; pTextNd = aIter.Next() )
1251 : {
1252 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1253 :
1254 0 : if (pTextNd->GetText().getLength() &&
1255 0 : pTextNd->getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout()) &&
1256 0 : pTextNd->GetNodes().IsDocNodes() &&
1257 0 : ( !IsFromChapter() || pOwnChapterNode ==
1258 0 : ::lcl_FindChapterNode( *pTextNd, 0 ) ) )
1259 : {
1260 0 : SwTOXPara * pNew = new SwTOXPara( *pTextNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1261 0 : InsertSorted(pNew);
1262 : }
1263 : }
1264 0 : }
1265 0 : }
1266 0 : }
1267 :
1268 : /// Generate content from sequence fields
1269 0 : void SwTOXBaseSection::UpdateSequence( const SwTextNode* pOwnChapterNode )
1270 : {
1271 0 : SwDoc* pDoc = GetFormat()->GetDoc();
1272 0 : SwFieldType* pSeqField = pDoc->getIDocumentFieldsAccess().GetFieldType(RES_SETEXPFLD, GetSequenceName(), false);
1273 0 : if(!pSeqField)
1274 0 : return;
1275 :
1276 0 : SwIterator<SwFormatField,SwFieldType> aIter( *pSeqField );
1277 0 : for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
1278 : {
1279 0 : const SwTextField* pTextField = pFormatField->GetTextField();
1280 0 : if(!pTextField)
1281 0 : continue;
1282 0 : const SwTextNode& rTextNode = pTextField->GetTextNode();
1283 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1284 :
1285 0 : if (rTextNode.GetText().getLength() &&
1286 0 : rTextNode.getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout()) &&
1287 0 : rTextNode.GetNodes().IsDocNodes() &&
1288 0 : ( !IsFromChapter() ||
1289 0 : ::lcl_FindChapterNode( rTextNode, 0 ) == pOwnChapterNode ) )
1290 : {
1291 0 : const SwSetExpField& rSeqField = dynamic_cast<const SwSetExpField&>(*(pFormatField->GetField()));
1292 : const OUString sName = GetSequenceName()
1293 0 : + OUStringLiteral1<cSequenceMarkSeparator>()
1294 0 : + OUString::number( rSeqField.GetSeqNumber() );
1295 0 : SwTOXPara * pNew = new SwTOXPara( rTextNode, nsSwTOXElement::TOX_SEQUENCE, 1, sName );
1296 : // set indexes if the number or the reference text are to be displayed
1297 0 : if( GetCaptionDisplay() == CAPTION_TEXT )
1298 : {
1299 : pNew->SetStartIndex(
1300 0 : SwGetExpField::GetReferenceTextPos( *pFormatField, *pDoc ));
1301 : }
1302 0 : else if(GetCaptionDisplay() == CAPTION_NUMBER)
1303 : {
1304 0 : pNew->SetEndIndex(pTextField->GetStart() + 1);
1305 : }
1306 0 : InsertSorted(pNew);
1307 : }
1308 0 : }
1309 : }
1310 :
1311 0 : void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1312 : {
1313 0 : SwDoc* pDoc = GetFormat()->GetDoc();
1314 0 : SwFieldType* pAuthField = pDoc->getIDocumentFieldsAccess().GetFieldType(RES_AUTHORITY, OUString(), false);
1315 0 : if(!pAuthField)
1316 0 : return;
1317 :
1318 0 : SwIterator<SwFormatField,SwFieldType> aIter( *pAuthField );
1319 0 : for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
1320 : {
1321 0 : const SwTextField* pTextField = pFormatField->GetTextField();
1322 : // undo
1323 0 : if(!pTextField)
1324 0 : continue;
1325 0 : const SwTextNode& rTextNode = pTextField->GetTextNode();
1326 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1327 :
1328 0 : if (rTextNode.GetText().getLength() &&
1329 0 : rTextNode.getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout()) &&
1330 0 : rTextNode.GetNodes().IsDocNodes() )
1331 : {
1332 : //#106485# the body node has to be used!
1333 0 : SwContentFrm *pFrm = rTextNode.getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() );
1334 0 : SwPosition aFieldPos(rTextNode);
1335 0 : const SwTextNode* pTextNode = 0;
1336 0 : if(pFrm && !pFrm->IsInDocBody())
1337 0 : pTextNode = GetBodyTextNode( *pDoc, aFieldPos, *pFrm );
1338 0 : if(!pTextNode)
1339 0 : pTextNode = &rTextNode;
1340 0 : SwTOXAuthority* pNew = new SwTOXAuthority( *pTextNode, *pFormatField, rIntl );
1341 :
1342 0 : InsertSorted(pNew);
1343 : }
1344 0 : }
1345 : }
1346 :
1347 0 : static long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1348 : {
1349 : static struct _SoObjType {
1350 : long nFlag;
1351 : // GlobalNameId
1352 : struct _GlobalNameIds {
1353 : sal_uInt32 n1;
1354 : sal_uInt16 n2, n3;
1355 : sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1356 : } aGlNmIds[4];
1357 : } aArr[] = {
1358 : { nsSwTOOElements::TOO_MATH,
1359 : { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1360 : {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1361 : { nsSwTOOElements::TOO_CHART,
1362 : { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1363 : {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1364 : { nsSwTOOElements::TOO_CALC,
1365 : { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1366 : {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1367 : { nsSwTOOElements::TOO_DRAW_IMPRESS,
1368 : { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1369 : {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1370 : { nsSwTOOElements::TOO_DRAW_IMPRESS,
1371 : { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1372 : { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1373 : {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1374 : };
1375 :
1376 0 : long nRet = 0;
1377 0 : for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1378 0 : for ( int n = 0; n < 4; ++n )
1379 : {
1380 0 : const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1381 0 : if( !rId.n1 )
1382 0 : break;
1383 : SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1384 : rId.b8, rId.b9, rId.b10, rId.b11,
1385 0 : rId.b12, rId.b13, rId.b14, rId.b15 );
1386 0 : if( rFactoryNm == aGlbNm )
1387 : {
1388 0 : nRet = pArr->nFlag;
1389 0 : break;
1390 : }
1391 0 : }
1392 :
1393 0 : return nRet;
1394 : }
1395 :
1396 0 : void SwTOXBaseSection::UpdateContent( SwTOXElement eMyType,
1397 : const SwTextNode* pOwnChapterNode )
1398 : {
1399 0 : SwDoc* pDoc = GetFormat()->GetDoc();
1400 0 : SwNodes& rNds = pDoc->GetNodes();
1401 : // on the 1st Node of the 1st Section
1402 0 : sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1403 0 : nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1404 :
1405 0 : while( nIdx < nEndIdx )
1406 : {
1407 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1408 :
1409 0 : SwNode* pNd = rNds[ nIdx ];
1410 0 : SwContentNode* pCNd = 0;
1411 0 : switch( eMyType )
1412 : {
1413 : case nsSwTOXElement::TOX_FRAME:
1414 0 : if( !pNd->IsNoTextNode() )
1415 : {
1416 0 : pCNd = pNd->GetContentNode();
1417 0 : if( !pCNd )
1418 : {
1419 0 : SwNodeIndex aTmp( *pNd );
1420 0 : pCNd = rNds.GoNext( &aTmp );
1421 : }
1422 : }
1423 0 : break;
1424 : case nsSwTOXElement::TOX_GRAPHIC:
1425 0 : if( pNd->IsGrfNode() )
1426 0 : pCNd = static_cast<SwContentNode*>(pNd);
1427 0 : break;
1428 : case nsSwTOXElement::TOX_OLE:
1429 0 : if( pNd->IsOLENode() )
1430 : {
1431 0 : bool bInclude = true;
1432 0 : if(TOX_OBJECTS == SwTOXBase::GetType())
1433 : {
1434 0 : SwOLENode* pOLENode = pNd->GetOLENode();
1435 0 : long nMyOLEOptions = GetOLEOptions();
1436 0 : SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1437 :
1438 0 : if( rOLEObj.IsOleRef() ) // Not yet loaded
1439 : {
1440 0 : SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1441 0 : long nObj = ::lcl_IsSOObject( aTmpName );
1442 0 : bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1443 0 : || (0 != (nMyOLEOptions & nObj));
1444 : }
1445 : else
1446 : {
1447 : OSL_FAIL("OLE Object no loaded?");
1448 0 : bInclude = false;
1449 : }
1450 : }
1451 :
1452 0 : if(bInclude)
1453 0 : pCNd = static_cast<SwContentNode*>(pNd);
1454 : }
1455 0 : break;
1456 0 : default: break;
1457 : }
1458 :
1459 0 : if( pCNd )
1460 : {
1461 : // find node in body text
1462 0 : int nSetLevel = USHRT_MAX;
1463 :
1464 : //#111105# tables of tables|illustrations|objects don't support hierarchies
1465 0 : if( IsLevelFromChapter() &&
1466 0 : TOX_TABLES != SwTOXBase::GetType() &&
1467 0 : TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1468 0 : TOX_OBJECTS != SwTOXBase::GetType() )
1469 : {
1470 : const SwTextNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1471 0 : MAXLEVEL - 1 );
1472 0 : if( pOutlNd )
1473 : {
1474 0 : if( pOutlNd->GetTextColl()->IsAssignedToListLevelOfOutlineStyle())
1475 : {
1476 0 : nSetLevel = pOutlNd->GetTextColl()->GetAttrOutlineLevel();
1477 : }
1478 : }
1479 : }
1480 :
1481 0 : if( pCNd->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) && ( !IsFromChapter() ||
1482 0 : ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1483 : {
1484 : SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1485 : ( USHRT_MAX != nSetLevel )
1486 : ? static_cast<sal_uInt16>(nSetLevel)
1487 0 : : FORM_ALPHA_DELIMITTER );
1488 0 : InsertSorted( pNew );
1489 : }
1490 : }
1491 :
1492 0 : nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2; // 2 == End/Start Node
1493 : }
1494 0 : }
1495 :
1496 : /// Collect table entries
1497 0 : void SwTOXBaseSection::UpdateTable( const SwTextNode* pOwnChapterNode )
1498 : {
1499 0 : SwDoc* pDoc = GetFormat()->GetDoc();
1500 0 : SwNodes& rNds = pDoc->GetNodes();
1501 0 : const SwFrameFormats& rArr = *pDoc->GetTableFrameFormats();
1502 :
1503 0 : for( auto pFrameFormat : rArr )
1504 : {
1505 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1506 :
1507 0 : SwTable* pTmpTable = SwTable::FindTable( pFrameFormat );
1508 : SwTableBox* pFBox;
1509 0 : if( pTmpTable && 0 != (pFBox = pTmpTable->GetTabSortBoxes()[0] ) &&
1510 0 : pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1511 : {
1512 0 : const SwTableNode* pTableNd = pFBox->GetSttNd()->FindTableNode();
1513 0 : SwNodeIndex aContentIdx( *pTableNd, 1 );
1514 :
1515 : SwContentNode* pCNd;
1516 0 : while( 0 != ( pCNd = rNds.GoNext( &aContentIdx ) ) &&
1517 0 : aContentIdx.GetIndex() < pTableNd->EndOfSectionIndex() )
1518 : {
1519 0 : if( pCNd->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) && (!IsFromChapter() ||
1520 0 : ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1521 : {
1522 0 : SwTOXTable * pNew = new SwTOXTable( *pCNd );
1523 0 : if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1524 : {
1525 : const SwTextNode* pOutlNd =
1526 0 : ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1527 0 : if( pOutlNd )
1528 : {
1529 0 : if( pOutlNd->GetTextColl()->IsAssignedToListLevelOfOutlineStyle())
1530 : {
1531 0 : const int nTmp = pOutlNd->GetTextColl()->GetAttrOutlineLevel();
1532 0 : pNew->SetLevel(static_cast<sal_uInt16>(nTmp));
1533 : }
1534 : }
1535 : }
1536 0 : InsertSorted(pNew);
1537 0 : break;
1538 : }
1539 0 : }
1540 : }
1541 : }
1542 0 : }
1543 :
1544 : /// Calculate PageNumber and insert after formatting
1545 123 : void SwTOXBaseSection::UpdatePageNum()
1546 : {
1547 123 : if( aSortArr.empty() )
1548 243 : return ;
1549 :
1550 : // Insert the current PageNumber into the TOC
1551 3 : SwPageFrm* pAktPage = 0;
1552 3 : sal_uInt16 nPage = 0;
1553 3 : SwDoc* pDoc = GetFormat()->GetDoc();
1554 :
1555 3 : SwTOXInternational aIntl( GetLanguage(),
1556 3 : TOX_INDEX == GetTOXType()->GetType() ?
1557 1 : GetOptions() : 0,
1558 10 : GetSortAlgorithm() );
1559 :
1560 7 : for( SwTOXSortTabBases::size_type nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
1561 : {
1562 : // Loop over all SourceNodes
1563 4 : std::vector<sal_uInt16> aNums; // the PageNumber
1564 8 : std::vector<SwPageDesc*> aDescs; // The PageDescriptors matching the PageNumbers
1565 4 : std::vector<sal_uInt16> *pMainNums = 0; // contains page numbers of main entries
1566 :
1567 : // process run in lines
1568 4 : SwTOXSortTabBases::size_type nRange = 0;
1569 4 : if(GetTOXForm().IsCommaSeparated() &&
1570 0 : aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1571 : {
1572 0 : const SwTOXMark& rMark = aSortArr[nCnt]->pTextMark->GetTOXMark();
1573 0 : const OUString sPrimKey = rMark.GetPrimaryKey();
1574 0 : const OUString sSecKey = rMark.GetSecondaryKey();
1575 0 : const SwTOXMark* pNextMark = 0;
1576 0 : while(aSortArr.size() > (nCnt + nRange)&&
1577 0 : aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1578 0 : 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTextMark->GetTOXMark())) &&
1579 0 : pNextMark->GetPrimaryKey() == sPrimKey &&
1580 0 : pNextMark->GetSecondaryKey() == sSecKey)
1581 0 : nRange++;
1582 : }
1583 : else
1584 4 : nRange = 1;
1585 :
1586 8 : for(SwTOXSortTabBases::size_type nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; ++nRunInEntry)
1587 : {
1588 4 : SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
1589 4 : size_t nSize = pSortBase->aTOXSources.size();
1590 8 : for (size_t j = 0; j < nSize; ++j)
1591 : {
1592 4 : ::SetProgressState( 0, pDoc->GetDocShell() );
1593 :
1594 4 : SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1595 4 : if( rTOXSource.pNd )
1596 : {
1597 4 : SwContentFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() );
1598 : OSL_ENSURE( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
1599 4 : if( !pFrm )
1600 0 : continue;
1601 4 : if( pFrm->IsTextFrm() && static_cast<SwTextFrm*>(pFrm)->HasFollow() )
1602 : {
1603 : // find the right one
1604 : SwTextFrm* pNext;
1605 0 : while( 0 != ( pNext = static_cast<SwTextFrm*>(pFrm->GetFollow()) )
1606 0 : && rTOXSource.nPos >= pNext->GetOfst() )
1607 0 : pFrm = pNext;
1608 : }
1609 :
1610 4 : SwPageFrm* pTmpPage = pFrm->FindPageFrm();
1611 4 : if( pTmpPage != pAktPage )
1612 : {
1613 3 : nPage = pTmpPage->GetVirtPageNum();
1614 3 : pAktPage = pTmpPage;
1615 : }
1616 :
1617 : // Insert as sorted
1618 : std::vector<sal_uInt16>::size_type i;
1619 4 : for( i = 0; i < aNums.size() && aNums[i] < nPage; ++i )
1620 : ;
1621 :
1622 4 : if( i >= aNums.size() || aNums[ i ] != nPage )
1623 : {
1624 4 : aNums.insert(aNums.begin() + i, nPage);
1625 4 : aDescs.insert(aDescs.begin() + i, pAktPage->GetPageDesc() );
1626 : }
1627 : // is it a main entry?
1628 4 : if(TOX_SORT_INDEX == pSortBase->GetType() &&
1629 : rTOXSource.bMainEntry)
1630 : {
1631 0 : if(!pMainNums)
1632 0 : pMainNums = new std::vector<sal_uInt16>;
1633 0 : pMainNums->push_back(nPage);
1634 : }
1635 : }
1636 : }
1637 : // Insert the PageNumber into the TOC TextNode
1638 4 : const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
1639 4 : if(pBase->pTOXNd)
1640 : {
1641 4 : const SwTextNode* pTextNd = pBase->pTOXNd->GetTextNode();
1642 : OSL_ENSURE( pTextNd, "no TextNode, wrong TOC" );
1643 :
1644 : _UpdatePageNum( const_cast<SwTextNode*>(pTextNd), aNums, aDescs, pMainNums,
1645 4 : aIntl );
1646 : }
1647 4 : DELETEZ(pMainNums);
1648 4 : aNums.clear();
1649 : }
1650 4 : }
1651 : // Delete the mapping array after setting the right PageNumber
1652 7 : for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
1653 4 : delete *it;
1654 3 : aSortArr.clear();
1655 : }
1656 :
1657 : /// Replace the PageNumber place holders. Search for the page no. in the array
1658 : /// of main entry page numbers.
1659 0 : static bool lcl_HasMainEntry( const std::vector<sal_uInt16>* pMainEntryNums, sal_uInt16 nToFind )
1660 : {
1661 0 : if (!pMainEntryNums)
1662 0 : return false;
1663 :
1664 0 : for( auto nMainEntry : *pMainEntryNums )
1665 0 : if (nToFind == nMainEntry)
1666 0 : return true;
1667 0 : return false;
1668 : }
1669 :
1670 4 : void SwTOXBaseSection::_UpdatePageNum( SwTextNode* pNd,
1671 : const std::vector<sal_uInt16>& rNums,
1672 : const std::vector<SwPageDesc*>& rDescs,
1673 : const std::vector<sal_uInt16>* pMainEntryNums,
1674 : const SwTOXInternational& rIntl )
1675 : {
1676 : // collect starts end ends of main entry character style
1677 4 : std::unique_ptr< std::vector<sal_uInt16> > xCharStyleIdx(pMainEntryNums ? new std::vector<sal_uInt16> : 0);
1678 :
1679 8 : OUString sSrchStr = OUStringBuffer().append(C_NUM_REPL).
1680 12 : append(S_PAGE_DELI).append(C_NUM_REPL).makeStringAndClear();
1681 4 : sal_Int32 nStartPos = pNd->GetText().indexOf(sSrchStr);
1682 12 : sSrchStr = OUStringBuffer().append(C_NUM_REPL).
1683 12 : append(C_END_PAGE_NUM).makeStringAndClear();
1684 4 : sal_Int32 nEndPos = pNd->GetText().indexOf(sSrchStr);
1685 :
1686 4 : if (-1 == nEndPos || rNums.empty())
1687 4 : return;
1688 :
1689 4 : if (-1 == nStartPos || nStartPos > nEndPos)
1690 4 : nStartPos = nEndPos;
1691 :
1692 4 : sal_uInt16 nOld = rNums[0],
1693 4 : nBeg = nOld,
1694 4 : nCount = 0;
1695 4 : OUString aNumStr( SvxNumberType( rDescs[0]->GetNumType() ).
1696 12 : GetNumStr( nBeg ) );
1697 4 : if( xCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
1698 : {
1699 0 : xCharStyleIdx->push_back( 0 );
1700 : }
1701 :
1702 : // Delete place holder
1703 8 : SwIndex aPos(pNd, nStartPos);
1704 4 : SwCharFormat* pPageNoCharFormat = 0;
1705 4 : SwpHints* pHints = pNd->GetpSwpHints();
1706 4 : if(pHints)
1707 8 : for(size_t nHintIdx = 0; nHintIdx < pHints->GetStartCount(); ++nHintIdx)
1708 : {
1709 5 : SwTextAttr* pAttr = pHints->GetStart(nHintIdx);
1710 5 : const sal_Int32 nTmpEnd = pAttr->End() ? *pAttr->End() : 0;
1711 15 : if( nStartPos >= pAttr->GetStart() &&
1712 8 : (nStartPos + 2) <= nTmpEnd &&
1713 3 : pAttr->Which() == RES_TXTATR_CHARFMT)
1714 : {
1715 0 : pPageNoCharFormat = pAttr->GetCharFormat().GetCharFormat();
1716 0 : break;
1717 : }
1718 : }
1719 4 : pNd->EraseText(aPos, nEndPos - nStartPos + 2);
1720 :
1721 : std::vector<sal_uInt16>::size_type i;
1722 4 : for( i = 1; i < rNums.size(); ++i)
1723 : {
1724 0 : SvxNumberType aType( rDescs[i]->GetNumType() );
1725 0 : if( TOX_INDEX == SwTOXBase::GetType() )
1726 : { // Summarize for the following
1727 : // Add up all following
1728 : // break up if main entry starts or ends and
1729 : // insert a char style index
1730 0 : bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
1731 0 : != lcl_HasMainEntry(pMainEntryNums, rNums[i]);
1732 :
1733 0 : if(nOld == rNums[i]-1 && !bMainEntryChanges &&
1734 0 : 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
1735 0 : nCount++;
1736 : else
1737 : {
1738 : // Flush for the following old values
1739 0 : if(GetOptions() & nsSwTOIOptions::TOI_FF)
1740 : {
1741 0 : if ( nCount >= 1 )
1742 0 : aNumStr += rIntl.GetFollowingText( nCount > 1 );
1743 : }
1744 0 : else if (nCount) //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
1745 : {
1746 0 : if (nCount == 1 )
1747 0 : aNumStr += S_PAGE_DELI;
1748 : else
1749 0 : aNumStr += "-";
1750 :
1751 0 : aNumStr += aType.GetNumStr( nBeg + nCount );
1752 : }
1753 :
1754 : // Create new String
1755 0 : nBeg = rNums[i];
1756 0 : aNumStr += S_PAGE_DELI;
1757 : //the change of the character style must apply after sPageDeli is appended
1758 0 : if (xCharStyleIdx && bMainEntryChanges)
1759 : {
1760 0 : xCharStyleIdx->push_back(aNumStr.getLength());
1761 : }
1762 0 : aNumStr += aType.GetNumStr( nBeg );
1763 0 : nCount = 0;
1764 : }
1765 0 : nOld = rNums[i];
1766 : }
1767 : else
1768 : { // Insert all Numbers
1769 0 : aNumStr += aType.GetNumStr( rNums[i] );
1770 0 : if (i+1 != rNums.size())
1771 0 : aNumStr += S_PAGE_DELI;
1772 : }
1773 0 : }
1774 : // Flush when ending and the following old values
1775 4 : if( TOX_INDEX == SwTOXBase::GetType() )
1776 : {
1777 1 : if(GetOptions() & nsSwTOIOptions::TOI_FF)
1778 : {
1779 1 : if( nCount >= 1 )
1780 0 : aNumStr += rIntl.GetFollowingText( nCount > 1 );
1781 : }
1782 : else
1783 : {
1784 0 : if(nCount >= 2)
1785 0 : aNumStr += "-";
1786 0 : else if(nCount == 1)
1787 0 : aNumStr += S_PAGE_DELI;
1788 : //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
1789 0 : if(nCount)
1790 0 : aNumStr += SvxNumberType( rDescs[i-1]->GetNumType() ).GetNumStr( nBeg+nCount );
1791 : }
1792 : }
1793 4 : pNd->InsertText( aNumStr, aPos, SwInsertFlags::EMPTYEXPAND | SwInsertFlags::FORCEHINTEXPAND );
1794 4 : if(pPageNoCharFormat)
1795 : {
1796 0 : SwFormatCharFormat aCharFormat( pPageNoCharFormat );
1797 0 : pNd->InsertItem(aCharFormat, nStartPos, nStartPos + aNumStr.getLength(), SetAttrMode::DONTEXPAND);
1798 : }
1799 :
1800 : // The main entries should get their character style
1801 4 : if (xCharStyleIdx && !xCharStyleIdx->empty() && !GetMainEntryCharStyle().isEmpty())
1802 : {
1803 : // eventually the last index must me appended
1804 0 : if (xCharStyleIdx->size()&0x01)
1805 0 : xCharStyleIdx->push_back(aNumStr.getLength());
1806 :
1807 : // search by name
1808 0 : SwDoc* pDoc = pNd->GetDoc();
1809 0 : sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1810 0 : SwCharFormat* pCharFormat = 0;
1811 0 : if(USHRT_MAX != nPoolId)
1812 0 : pCharFormat = pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool(nPoolId);
1813 : else
1814 0 : pCharFormat = pDoc->FindCharFormatByName( GetMainEntryCharStyle() );
1815 0 : if(!pCharFormat)
1816 0 : pCharFormat = pDoc->MakeCharFormat(GetMainEntryCharStyle(), 0);
1817 :
1818 : // find the page numbers in aNumStr and set the character style
1819 0 : sal_Int32 nOffset = pNd->GetText().getLength() - aNumStr.getLength();
1820 0 : SwFormatCharFormat aCharFormat(pCharFormat);
1821 0 : for (size_t j = 0; j < xCharStyleIdx->size(); j += 2)
1822 : {
1823 0 : sal_Int32 nStartIdx = (*xCharStyleIdx)[j] + nOffset;
1824 0 : sal_Int32 nEndIdx = (*xCharStyleIdx)[j + 1] + nOffset;
1825 0 : pNd->InsertItem(aCharFormat, nStartIdx, nEndIdx, SetAttrMode::DONTEXPAND);
1826 0 : }
1827 :
1828 4 : }
1829 : }
1830 :
1831 4 : void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
1832 : {
1833 4 : Range aRange(0, aSortArr.size());
1834 4 : if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTextMark )
1835 : {
1836 1 : const SwTOXMark& rMark = pNew->pTextMark->GetTOXMark();
1837 : // Evaluate Key
1838 : // Calculate the range where to insert
1839 3 : if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
1840 1 : !rMark.GetPrimaryKey().isEmpty() )
1841 : {
1842 : aRange = GetKeyRange( rMark.GetPrimaryKey(),
1843 : rMark.GetPrimaryKeyReading(),
1844 0 : *pNew, FORM_PRIMARY_KEY, aRange );
1845 :
1846 0 : if( !rMark.GetSecondaryKey().isEmpty() )
1847 : aRange = GetKeyRange( rMark.GetSecondaryKey(),
1848 : rMark.GetSecondaryKeyReading(),
1849 0 : *pNew, FORM_SECONDARY_KEY, aRange );
1850 : }
1851 : }
1852 : // Search for identical entries and remove the trailing one
1853 4 : if(TOX_AUTHORITIES == SwTOXBase::GetType())
1854 : {
1855 0 : for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
1856 : {
1857 0 : SwTOXSortTabBase* pOld = aSortArr[i];
1858 0 : if(*pOld == *pNew)
1859 : {
1860 0 : if(*pOld < *pNew)
1861 : {
1862 0 : delete pNew;
1863 0 : return;
1864 : }
1865 : else
1866 : {
1867 : // remove the old content
1868 0 : delete aSortArr[i];
1869 0 : aSortArr.erase( aSortArr.begin() + i );
1870 0 : aRange.Max()--;
1871 0 : break;
1872 : }
1873 : }
1874 : }
1875 : }
1876 :
1877 : // find position and insert
1878 : short i;
1879 :
1880 5 : for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
1881 : { // Only check for same level
1882 1 : SwTOXSortTabBase* pOld = aSortArr[i];
1883 1 : if(*pOld == *pNew)
1884 : {
1885 0 : if(TOX_AUTHORITIES != SwTOXBase::GetType())
1886 : {
1887 : // Own entry for double entries or keywords
1888 0 : if( pOld->GetType() == TOX_SORT_CUSTOM &&
1889 0 : SwTOXSortTabBase::GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
1890 0 : continue;
1891 :
1892 0 : if(!(SwTOXSortTabBase::GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
1893 : { // Own entry
1894 0 : aSortArr.insert(aSortArr.begin() + i, pNew);
1895 0 : return;
1896 : }
1897 : // If the own entry is already present, add it to the references list
1898 0 : pOld->aTOXSources.push_back(pNew->aTOXSources[0]);
1899 :
1900 0 : delete pNew;
1901 0 : return;
1902 : }
1903 : #if OSL_DEBUG_LEVEL > 0
1904 : else
1905 : OSL_FAIL("Bibliography entries cannot be found here");
1906 : #endif
1907 : }
1908 1 : if(*pNew < *pOld)
1909 0 : break;
1910 : }
1911 : // Skip SubLevel
1912 8 : while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
1913 0 : aSortArr[i]->GetLevel() > pNew->GetLevel() )
1914 0 : i++;
1915 :
1916 : // Insert at position i
1917 4 : aSortArr.insert(aSortArr.begin()+i, pNew);
1918 : }
1919 :
1920 : /// Find Key Range and insert if possible
1921 0 : Range SwTOXBaseSection::GetKeyRange(const OUString& rStr, const OUString& rStrReading,
1922 : const SwTOXSortTabBase& rNew,
1923 : sal_uInt16 nLevel, const Range& rRange )
1924 : {
1925 0 : const SwTOXInternational& rIntl = *rNew.pTOXIntl;
1926 0 : TextAndReading aToCompare(rStr, rStrReading);
1927 :
1928 0 : if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
1929 : {
1930 0 : aToCompare.sText = rIntl.ToUpper( aToCompare.sText, 0 )
1931 0 : + aToCompare.sText.copy(1);
1932 : }
1933 :
1934 : OSL_ENSURE(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
1935 :
1936 0 : const long nMin = rRange.Min();
1937 0 : const long nMax = rRange.Max();
1938 :
1939 : long i;
1940 :
1941 0 : for( i = nMin; i < nMax; ++i)
1942 : {
1943 0 : SwTOXSortTabBase* pBase = aSortArr[i];
1944 :
1945 0 : if( rIntl.IsEqual( pBase->GetText(), pBase->GetLocale(),
1946 0 : aToCompare, rNew.GetLocale() ) &&
1947 0 : pBase->GetLevel() == nLevel )
1948 0 : break;
1949 : }
1950 0 : if(i == nMax)
1951 : { // If not already present, create and insert
1952 : SwTOXCustom* pKey = new SwTOXCustom( aToCompare, nLevel, rIntl,
1953 0 : rNew.GetLocale() );
1954 0 : for(i = nMin; i < nMax; ++i)
1955 : {
1956 0 : if(nLevel == aSortArr[i]->GetLevel() && *pKey < *(aSortArr[i]))
1957 0 : break;
1958 : }
1959 0 : aSortArr.insert(aSortArr.begin() + i, pKey);
1960 : }
1961 0 : const long nStart = i+1;
1962 0 : const long nEnd = aSortArr.size();
1963 :
1964 : // Find end of range
1965 0 : for(i = nStart; i < nEnd; ++i)
1966 : {
1967 0 : if(aSortArr[i]->GetLevel() <= nLevel)
1968 : {
1969 0 : return Range(nStart, i);
1970 : }
1971 : }
1972 0 : return Range(nStart, nEnd);
1973 : }
1974 :
1975 0 : bool SwTOXBase::IsTOXBaseInReadonly() const
1976 : {
1977 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
1978 0 : if (!pSect || !pSect->GetFormat())
1979 0 : return false;
1980 :
1981 0 : const SwSectionNode* pSectNode = pSect->GetFormat()->GetSectionNode();
1982 0 : if (!pSectNode)
1983 0 : return false;
1984 :
1985 0 : const SwDocShell* pDocSh = pSectNode->GetDoc()->GetDocShell();
1986 0 : if (!pDocSh)
1987 0 : return false;
1988 :
1989 0 : if (pDocSh->IsReadOnly())
1990 0 : return true;
1991 :
1992 0 : pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode();
1993 0 : if (!pSectNode)
1994 0 : return false;
1995 :
1996 0 : return pSectNode->GetSection().IsProtectFlag();
1997 : }
1998 :
1999 0 : const SfxItemSet* SwTOXBase::GetAttrSet() const
2000 : {
2001 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2002 0 : if(pSect && pSect->GetFormat())
2003 0 : return &pSect->GetFormat()->GetAttrSet();
2004 0 : return 0;
2005 : }
2006 :
2007 0 : void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
2008 : {
2009 0 : SwTOXBaseSection *pSect = dynamic_cast<SwTOXBaseSection*>(this);
2010 0 : if( pSect && pSect->GetFormat() )
2011 0 : pSect->GetFormat()->SetFormatAttr( rSet );
2012 0 : }
2013 :
2014 0 : bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
2015 : {
2016 0 : switch( rInfo.Which() )
2017 : {
2018 : case RES_CONTENT_VISIBLE:
2019 : {
2020 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2021 0 : if( pSect && pSect->GetFormat() )
2022 0 : pSect->GetFormat()->GetInfo( rInfo );
2023 : }
2024 0 : return false;
2025 : }
2026 0 : return true;
2027 177 : }
2028 :
2029 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|