Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/doc/doctxm.cxx
Warning:line 1674, column 59
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name doctxm.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/doc/doctxm.cxx
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
74using namespace ::com::sun::star;
75
76template<typename T, typename... Args> static
77typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
78MakeSwTOXSortTabBase(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
85void 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.
116sal_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
154void 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
197namespace {
198
199/// Travel between table of content Marks
200class CompareNodeContent
201{
202 sal_uLong m_nNode;
203 sal_Int32 m_nContent;
204public:
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
228const 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
346SwTOXBaseSection* 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
356SwTOXBaseSection* 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
409void 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
448SwTOXBase* 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
468const 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
477const 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
503void 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
524bool 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
611sal_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
620const 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
629const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
630{
631 SwTOXType * pNew = new SwTOXType( rTyp );
632 mpTOXTypes->emplace_back( pNew );
633 return pNew;
634}
635
636OUString 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
705bool 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
721static 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
743SwTOXBaseSection::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
751SwTOXBaseSection::~SwTOXBaseSection()
752{
753}
754
755bool 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
770void 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
1078void 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
1121SwTextFormatColl* 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
1170void 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
1196void 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
1235void 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
1262void 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
1305void 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
1349void 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
1384static 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
1428void 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
1534void 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
1587void SwTOXBaseSection::UpdatePageNum()
1588{
1589 if( m_aSortArr.empty() )
1
Assuming the condition is false
2
Taking false branch
1590 return ;
1591
1592 // Insert the current PageNumber into the TOC
1593 SwPageFrame* pCurrentPage = nullptr;
3
'pCurrentPage' initialized to a null pointer value
1594 sal_uInt16 nPage = 0;
1595 SwDoc* pDoc = GetFormat()->GetDoc();
1596
1597 SwTOXInternational aIntl( GetLanguage(),
1598 TOX_INDEX == GetTOXType()->GetType() ?
4
Assuming the condition is false
5
'?' condition is false
1599 GetOptions() : SwTOIOptions::NONE,
1600 GetSortAlgorithm() );
1601
1602 for( size_t nCnt = 0; nCnt < m_aSortArr.size(); ++nCnt )
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
1603 {
1604 // Loop over all SourceNodes
1605
1606 // process run in lines
1607 size_t nRange = 0;
1608 if(GetTOXForm().IsCommaSeparated() &&
8
Assuming the condition is false
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)
9
Loop condition is true. Entering loop body
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)
10
Assuming 'j' is < 'nSize'
11
Loop condition is true. Entering loop body
1633 {
1634 ::SetProgressState( 0, pDoc->GetDocShell() );
1635
1636 SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1637 if( rTOXSource.pNd )
12
Assuming field 'pNd' is non-null
13
Taking true branch
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
)
;
14
Assuming 'pFrame' is non-null
15
Taking false branch
16
Loop condition is false. Exiting loop
1641 if( !pFrame
16.1
'pFrame' is non-null
)
17
Taking false branch
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 )
18
Assuming 'pTmpPage' is equal to 'pCurrentPage'
19
Taking false branch
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 )
20
Assuming the condition is false
1669 ;
1670
1671 if( i >= aNums.size() || aNums[ i ] != nPage )
21
Assuming the condition is true
1672 {
1673 aNums.insert(aNums.begin() + i, nPage);
1674 aDescs.insert(aDescs.begin() + i, pCurrentPage->GetPageDesc() );
22
Called C++ object pointer is null
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.
1702static 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
1713void 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
1871void 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
1958Range 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
2012bool 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
2036const 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
2044void 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: */