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