Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx
Warning:line 549, column 30
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 doclay.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/doclay.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 <hintids.hxx>
21#include <sot/exchange.hxx>
22#include <svx/svdpage.hxx>
23#include <editeng/keepitem.hxx>
24#include <editeng/ulspitem.hxx>
25#include <editeng/lrspitem.hxx>
26#include <editeng/boxitem.hxx>
27#include <editeng/shaditem.hxx>
28#include <editeng/protitem.hxx>
29#include <editeng/opaqitem.hxx>
30#include <svx/svdouno.hxx>
31#include <editeng/frmdiritem.hxx>
32#include <swmodule.hxx>
33#include <modcfg.hxx>
34#include <com/sun/star/beans/XPropertySet.hpp>
35#include <com/sun/star/embed/XEmbeddedObject.hpp>
36#include <SwStyleNameMapper.hxx>
37#include <drawdoc.hxx>
38#include <fchrfmt.hxx>
39#include <frmatr.hxx>
40#include <txatbase.hxx>
41#include <fmtfld.hxx>
42#include <fmtornt.hxx>
43#include <fmtcntnt.hxx>
44#include <fmtanchr.hxx>
45#include <fmtfsize.hxx>
46#include <fmtsrnd.hxx>
47#include <fmtflcnt.hxx>
48#include <frmfmt.hxx>
49#include <pam.hxx>
50#include <ndtxt.hxx>
51#include <ndnotxt.hxx>
52#include <ndole.hxx>
53#include <doc.hxx>
54#include <IDocumentUndoRedo.hxx>
55#include <IDocumentRedlineAccess.hxx>
56#include <DocumentSettingManager.hxx>
57#include <IDocumentDrawModelAccess.hxx>
58#include <IDocumentFieldsAccess.hxx>
59#include <IDocumentState.hxx>
60#include <IDocumentLayoutAccess.hxx>
61#include <IDocumentStylePoolAccess.hxx>
62#include <rootfrm.hxx>
63#include <pagefrm.hxx>
64#include <cntfrm.hxx>
65#include <txtfrm.hxx>
66#include <notxtfrm.hxx>
67#include <flyfrm.hxx>
68#include <dflyobj.hxx>
69#include <dcontact.hxx>
70#include <swundo.hxx>
71#include <flypos.hxx>
72#include <UndoInsert.hxx>
73#include <expfld.hxx>
74#include <poolfmt.hxx>
75#include <docary.hxx>
76#include <swtable.hxx>
77#include <tblsel.hxx>
78#include <txtftn.hxx>
79#include <ftnidx.hxx>
80#include <ftninfo.hxx>
81#include <pagedesc.hxx>
82#include <strings.hrc>
83#include <frameformats.hxx>
84#include <tools/datetimeutils.hxx>
85
86#include <sortedobjs.hxx>
87
88#include <vector>
89
90using namespace ::com::sun::star;
91
92#define DEF_FLY_WIDTH2268 2268 // Default width for FlyFrames (2268 == 4cm)
93
94static bool lcl_IsItemSet(const SwContentNode & rNode, sal_uInt16 which)
95{
96 bool bResult = false;
97
98 if (SfxItemState::SET == rNode.GetSwAttrSet().GetItemState(which))
99 bResult = true;
100
101 return bResult;
102}
103
104SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, bool bMoveWithinDoc,
105 bool bInsInPage )
106{
107 // #i52858# - method name changed
108 SdrPage *pPg = getIDocumentDrawModelAccess().GetOrCreateDrawModel()->GetPage( 0 );
109 if( !pPg )
110 {
111 pPg = getIDocumentDrawModelAccess().GetDrawModel()->AllocPage( false );
112 getIDocumentDrawModelAccess().GetDrawModel()->InsertPage( pPg );
113 }
114
115 // TTTT Clone directly to target SdrModel
116 SdrObject *pObj(rObj.CloneSdrObject(*getIDocumentDrawModelAccess().GetDrawModel()));
117
118 if( bMoveWithinDoc && SdrInventor::FmForm == pObj->GetObjInventor() )
119 {
120 // We need to preserve the Name for Controls
121 uno::Reference< awt::XControlModel > xModel = static_cast<SdrUnoObj*>(pObj)->GetUnoControlModel();
122 uno::Any aVal;
123 uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
124 const OUString sName("Name");
125 if( xSet.is() )
126 aVal = xSet->getPropertyValue( sName );
127 if( bInsInPage )
128 pPg->InsertObjectThenMakeNameUnique( pObj );
129 if( xSet.is() )
130 xSet->setPropertyValue( sName, aVal );
131 }
132 else if( bInsInPage )
133 pPg->InsertObjectThenMakeNameUnique( pObj );
134
135 // For drawing objects: set layer of cloned object to invisible layer
136 SdrLayerID nLayerIdForClone = rObj.GetLayer();
137 if ( dynamic_cast<const SwFlyDrawObj*>( pObj) == nullptr &&
138 dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr &&
139 typeid(SdrObject) != typeid(pObj) )
140 {
141 if ( getIDocumentDrawModelAccess().IsVisibleLayerId( nLayerIdForClone ) )
142 {
143 nLayerIdForClone = getIDocumentDrawModelAccess().GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
144 }
145 }
146 pObj->SetLayer( nLayerIdForClone );
147
148 return pObj;
149}
150
151SwFlyFrameFormat* SwDoc::MakeFlySection_( const SwPosition& rAnchPos,
152 const SwContentNode& rNode,
153 RndStdIds eRequestId,
154 const SfxItemSet* pFlySet,
155 SwFrameFormat* pFrameFormat )
156{
157 if( !pFrameFormat )
158 pFrameFormat = getIDocumentStylePoolAccess().GetFrameFormatFromPool( RES_POOLFRM_FRAME );
159
160 OUString sName;
161 if( !mbInReading )
162 switch( rNode.GetNodeType() )
163 {
164 case SwNodeType::Grf: sName = GetUniqueGrfName(); break;
165 case SwNodeType::Ole: sName = GetUniqueOLEName(); break;
166 default: sName = GetUniqueFrameName(); break;
167 }
168 SwFlyFrameFormat* pFormat = MakeFlyFrameFormat( sName, pFrameFormat );
169
170 // Create content and connect to the format.
171 // Create ContentNode and put it into the autotext selection.
172 SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
173 GetNodes().GetEndOfAutotext() );
174 GetNodes().SectionDown( &aRange, SwFlyStartNode );
175
176 pFormat->SetFormatAttr( SwFormatContent( rNode.StartOfSectionNode() ));
177
178 const SwFormatAnchor* pAnchor = nullptr;
179 if( pFlySet )
180 {
181 pFlySet->GetItemState( RES_ANCHOR, false,
182 reinterpret_cast<const SfxPoolItem**>(&pAnchor) );
183 if( SfxItemState::SET == pFlySet->GetItemState( RES_CNTNT, false ))
184 {
185 SfxItemSet aTmpSet( *pFlySet );
186 aTmpSet.ClearItem( RES_CNTNT );
187 pFormat->SetFormatAttr( aTmpSet );
188 }
189 else
190 pFormat->SetFormatAttr( *pFlySet );
191 }
192
193 // Anchor not yet set?
194 RndStdIds eAnchorId;
195 // #i107811# Assure that at-page anchored fly frames have a page num or a
196 // content anchor set.
197 if ( !pAnchor ||
198 ( RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId() &&
199 !pAnchor->GetContentAnchor() ) ||
200 ( RndStdIds::FLY_AT_PAGE == pAnchor->GetAnchorId() &&
201 !pAnchor->GetContentAnchor() &&
202 pAnchor->GetPageNum() == 0 ) )
203 {
204 // set it again, needed for Undo
205 SwFormatAnchor aAnch( pFormat->GetAnchor() );
206 if (pAnchor && (RndStdIds::FLY_AT_FLY == pAnchor->GetAnchorId()))
207 {
208 SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
209 aAnch.SetAnchor( &aPos );
210 eAnchorId = RndStdIds::FLY_AT_FLY;
211 }
212 else
213 {
214 if( eRequestId != aAnch.GetAnchorId() &&
215 SfxItemState::SET != pFormat->GetItemState( RES_ANCHOR ) )
216 {
217 aAnch.SetType( eRequestId );
218 }
219
220 eAnchorId = aAnch.GetAnchorId();
221 if ( RndStdIds::FLY_AT_PAGE != eAnchorId || !pAnchor || aAnch.GetPageNum() == 0)
222 {
223 aAnch.SetAnchor( &rAnchPos );
224 }
225 }
226 pFormat->SetFormatAttr( aAnch );
227 }
228 else
229 eAnchorId = pFormat->GetAnchor().GetAnchorId();
230
231 if ( RndStdIds::FLY_AS_CHAR == eAnchorId )
232 {
233 const sal_Int32 nStt = rAnchPos.nContent.GetIndex();
234 SwTextNode * pTextNode = rAnchPos.nNode.GetNode().GetTextNode();
235
236 OSL_ENSURE(pTextNode!= nullptr, "There should be a SwTextNode!")do { if (true && (!(pTextNode!= nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "236" ": "), "%s", "There should be a SwTextNode!"); } }
while (false)
;
237
238 if (pTextNode != nullptr)
239 {
240 SwFormatFlyCnt aFormat( pFormat );
241 // may fail if there's no space left or header/ftr
242 if (!pTextNode->InsertItem(aFormat, nStt, nStt))
243 { // pFormat is dead now
244 return nullptr;
245 }
246 }
247 }
248
249 if( SfxItemState::SET != pFormat->GetAttrSet().GetItemState( RES_FRM_SIZE ))
250 {
251 SwFormatFrameSize aFormatSize( SwFrameSize::Variable, 0, DEF_FLY_WIDTH2268 );
252 const SwNoTextNode* pNoTextNode = rNode.GetNoTextNode();
253 if( pNoTextNode )
254 {
255 // Set size
256 Size aSize( pNoTextNode->GetTwipSize() );
257 if( MINFLY23 > aSize.Width() )
258 aSize.setWidth( DEF_FLY_WIDTH2268 );
259 aFormatSize.SetWidth( aSize.Width() );
260 if( aSize.Height() )
261 {
262 aFormatSize.SetHeight( aSize.Height() );
263 aFormatSize.SetHeightSizeType( SwFrameSize::Fixed );
264 }
265 }
266 pFormat->SetFormatAttr( aFormatSize );
267 }
268
269 // Set up frames
270 if( getIDocumentLayoutAccess().GetCurrentViewShell() )
271 pFormat->MakeFrames(); // ???
272
273 if (GetIDocumentUndoRedo().DoesUndo())
274 {
275 sal_uLong nNodeIdx = rAnchPos.nNode.GetIndex();
276 const sal_Int32 nCntIdx = rAnchPos.nContent.GetIndex();
277 GetIDocumentUndoRedo().AppendUndo(
278 std::make_unique<SwUndoInsLayFormat>( pFormat, nNodeIdx, nCntIdx ));
279 }
280
281 getIDocumentState().SetModified();
282 return pFormat;
283}
284
285SwFlyFrameFormat* SwDoc::MakeFlySection( RndStdIds eAnchorType,
286 const SwPosition* pAnchorPos,
287 const SfxItemSet* pFlySet,
288 SwFrameFormat* pFrameFormat, bool bCalledFromShell )
289{
290 SwFlyFrameFormat* pFormat = nullptr;
291 if ( !pAnchorPos && (RndStdIds::FLY_AT_PAGE != eAnchorType) )
292 {
293 const SwFormatAnchor* pAnch;
294 if( (pFlySet && SfxItemState::SET == pFlySet->GetItemState(
295 RES_ANCHOR, false, reinterpret_cast<const SfxPoolItem**>(&pAnch) )) ||
296 ( pFrameFormat && SfxItemState::SET == pFrameFormat->GetItemState(
297 RES_ANCHOR, true, reinterpret_cast<const SfxPoolItem**>(&pAnch) )) )
298 {
299 if ( RndStdIds::FLY_AT_PAGE != pAnch->GetAnchorId() )
300 {
301 pAnchorPos = pAnch->GetContentAnchor();
302 }
303 }
304 }
305
306 if (pAnchorPos)
307 {
308 if( !pFrameFormat )
309 pFrameFormat = getIDocumentStylePoolAccess().GetFrameFormatFromPool( RES_POOLFRM_FRAME );
310
311 sal_uInt16 nCollId = static_cast<sal_uInt16>(
312 GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
313
314 /* If there is no adjust item in the paragraph style for the content node of the new fly section
315 propagate an existing adjust item at the anchor to the new content node. */
316 SwContentNode * pNewTextNd = GetNodes().MakeTextNode
317 (SwNodeIndex( GetNodes().GetEndOfAutotext()),
318 getIDocumentStylePoolAccess().GetTextCollFromPool( nCollId ));
319 SwContentNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetContentNode();
320 // pAnchorNode from cursor must be valid, unless a whole table is selected (in which
321 // case the node is not a content node, and pAnchorNode is nullptr). In the latter case,
322 // bCalledFromShell is false.
323 assert(!bCalledFromShell || pAnchorNode)(static_cast <bool> (!bCalledFromShell || pAnchorNode) ?
void (0) : __assert_fail ("!bCalledFromShell || pAnchorNode"
, "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 323, __extension__ __PRETTY_FUNCTION__))
;
324
325 const SfxPoolItem * pItem = nullptr;
326
327 if (bCalledFromShell && !lcl_IsItemSet(*pNewTextNd, RES_PARATR_ADJUST) &&
328 SfxItemState::SET == pAnchorNode->GetSwAttrSet().
329 GetItemState(RES_PARATR_ADJUST, true, &pItem))
330 {
331 pNewTextNd->SetAttr(*pItem);
332 }
333
334 pFormat = MakeFlySection_( *pAnchorPos, *pNewTextNd,
335 eAnchorType, pFlySet, pFrameFormat );
336 }
337 return pFormat;
338}
339
340SwFlyFrameFormat* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
341 const SwSelBoxes* pSelBoxes,
342 SwFrameFormat *pParent )
343{
344 const SwFormatAnchor& rAnch = rSet.Get( RES_ANCHOR );
345
346 GetIDocumentUndoRedo().StartUndo( SwUndoId::INSLAYFMT, nullptr );
347
348 SwFlyFrameFormat* pFormat = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
349 &rSet, pParent );
350
351 // If content is selected, it becomes the new frame's content.
352 // Namely, it is moved into the NodeArray's appropriate section.
353
354 if( pFormat )
355 {
356 do { // middle check loop
357 const SwFormatContent &rContent = pFormat->GetContent();
358 OSL_ENSURE( rContent.GetContentIdx(), "No content prepared." )do { if (true && (!(rContent.GetContentIdx()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "358" ": "), "%s", "No content prepared."); } } while (false
)
;
359 SwNodeIndex aIndex( *(rContent.GetContentIdx()), 1 );
360 SwContentNode *pNode = aIndex.GetNode().GetContentNode();
361
362 // Attention: Do not create an index on the stack, or we
363 // cannot delete ContentNode in the end!
364 SwPosition aPos( aIndex );
365 aPos.nContent.Assign( pNode, 0 );
366
367 if( pSelBoxes && !pSelBoxes->empty() )
368 {
369 // Table selection
370 // Copy parts of a table: create a table with the same width as the
371 // original one and move (copy and delete) the selected boxes.
372 // The size is corrected on a percentage basis.
373
374 SwTableNode* pTableNd = const_cast<SwTableNode*>((*pSelBoxes)[0]->
375 GetSttNd()->FindTableNode());
376 if( !pTableNd )
377 break;
378
379 SwTable& rTable = pTableNd->GetTable();
380
381 // Did we select the whole table?
382 if( pSelBoxes->size() == rTable.GetTabSortBoxes().size() )
383 {
384 // move the whole table
385 SwNodeRange aRg( *pTableNd, 0, *pTableNd->EndOfSectionNode(), 1 );
386
387 // If we move the whole table and it is located within a
388 // FlyFrame, the we create a TextNode after it.
389 // So that this FlyFrame is preserved.
390 if( aRg.aEnd.GetNode().IsEndNode() )
391 GetNodes().MakeTextNode( aRg.aStart,
392 GetDfltTextFormatColl() );
393
394 getIDocumentContentOperations().MoveNodeRange( aRg, aPos.nNode, SwMoveFlags::DEFAULT );
395 }
396 else
397 {
398 rTable.MakeCopy(*this, aPos, *pSelBoxes);
399 // Don't delete a part of a table with row span!!
400 // You could delete the content instead -> ToDo
401 //rTable.DeleteSel( this, *pSelBoxes, 0, 0, true, true );
402 }
403
404 // If the table is within the frame, then copy without the following TextNode
405 aIndex = rContent.GetContentIdx()->GetNode().EndOfSectionIndex() - 1;
406 OSL_ENSURE( aIndex.GetNode().GetTextNode(),do { if (true && (!(aIndex.GetNode().GetTextNode())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "407" ": "), "%s", "a TextNode should be here"); } } while
(false)
407 "a TextNode should be here" )do { if (true && (!(aIndex.GetNode().GetTextNode())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "407" ": "), "%s", "a TextNode should be here"); } } while
(false)
;
408 aPos.nContent.Assign( nullptr, 0 ); // Deregister index!
409 GetNodes().Delete( aIndex );
410
411 // This is a hack: whilst FlyFrames/Headers/Footers are not undoable we delete all Undo objects
412 if( GetIDocumentUndoRedo().DoesUndo() )
413 {
414 GetIDocumentUndoRedo().DelAllUndoObj();
415 }
416 }
417 else
418 {
419 // copy all Pams and then delete all
420 bool bOldFlag = mbCopyIsMove;
421 bool const bOldUndo = GetIDocumentUndoRedo().DoesUndo();
422 bool const bOldRedlineMove(getIDocumentRedlineAccess().IsRedlineMove());
423 mbCopyIsMove = true;
424 GetIDocumentUndoRedo().DoUndo(false);
425 getIDocumentRedlineAccess().SetRedlineMove(true);
426 for(const SwPaM& rTmp : rPam.GetRingContainer())
427 {
428 if( rTmp.HasMark() &&
429 *rTmp.GetPoint() != *rTmp.GetMark() )
430 {
431 // aPos is the newly created fly section, so definitely outside rPam, it's pointless to check that again.
432 getIDocumentContentOperations().CopyRange(*const_cast<SwPaM*>(&rTmp), aPos, SwCopyFlags::IsMoveToFly);
433 }
434 }
435 getIDocumentRedlineAccess().SetRedlineMove(bOldRedlineMove);
436 mbCopyIsMove = bOldFlag;
437 GetIDocumentUndoRedo().DoUndo(bOldUndo);
438
439 for(const SwPaM& rTmp : rPam.GetRingContainer())
440 {
441 if( rTmp.HasMark() &&
442 *rTmp.GetPoint() != *rTmp.GetMark() )
443 {
444 getIDocumentContentOperations().DeleteAndJoin( *const_cast<SwPaM*>(&rTmp) );
445 }
446 }
447 }
448 } while( false );
449 }
450
451 getIDocumentState().SetModified();
452
453 GetIDocumentUndoRedo().EndUndo( SwUndoId::INSLAYFMT, nullptr );
454
455 return pFormat;
456}
457
458
459/*
460 * paragraph frames - o.k. if the PaM includes the paragraph from the beginning
461 * to the beginning of the next paragraph at least
462 * frames at character - o.k. if the PaM starts at least at the same position
463 * as the frame
464 */
465static bool lcl_TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
466 RndStdIds nAnchorId )
467{
468 bool bOk = false;
469 const SwPaM* pTmp = pPam;
470 do {
471 const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
472 const SwPosition* pPaMStart = pTmp->Start();
473 const SwPosition* pPaMEnd = pTmp->End();
474 const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
475 const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
476 if (RndStdIds::FLY_AT_PARA == nAnchorId)
477 bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
478 (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
479 (nPamEndIndex > nFlyIndex));
480 else
481 {
482 const sal_Int32 nFlyContentIndex = pFlyPos->nContent.GetIndex();
483 const sal_Int32 nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
484 bOk = (nPamStartIndex < nFlyIndex &&
485 (( nPamEndIndex > nFlyIndex )||
486 ((nPamEndIndex == nFlyIndex) &&
487 (nPamEndContentIndex > nFlyContentIndex))) )
488 ||
489 (((nPamStartIndex == nFlyIndex) &&
490 (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
491 ((nPamEndIndex > nFlyIndex) ||
492 (nPamEndContentIndex > nFlyContentIndex )));
493 }
494
495 if( bOk )
496 break;
497 pTmp = pTmp->GetNext();
498 } while( pPam != pTmp );
499 return bOk;
500}
501
502SwPosFlyFrames SwDoc::GetAllFlyFormats( const SwPaM* pCmpRange, bool bDrawAlso,
503 bool bAsCharAlso ) const
504{
505 SwPosFlyFrames aRetval;
506
507 // collect all anchored somehow to paragraphs
508 for( auto pFly : *GetSpzFrameFormats() )
509 {
510 bool bDrawFormat = bDrawAlso && RES_DRAWFRMFMT == pFly->Which();
511 bool bFlyFormat = RES_FLYFRMFMT == pFly->Which();
512 if( bFlyFormat || bDrawFormat )
513 {
514 const SwFormatAnchor& rAnchor = pFly->GetAnchor();
515 SwPosition const*const pAPos = rAnchor.GetContentAnchor();
516 if (pAPos &&
517 ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) ||
518 (RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId()) ||
519 (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
520 ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) && bAsCharAlso)))
521 {
522 if( pCmpRange &&
523 !lcl_TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
524 continue; // not a valid FlyFrame
525 aRetval.insert(std::make_shared<SwPosFlyFrame>(pAPos->nNode, pFly, aRetval.size()));
526 }
527 }
528 }
529
530 // If we don't have a layout we can't get page anchored FlyFrames.
531 // Also, page anchored FlyFrames are only returned if no range is specified.
532 if( !getIDocumentLayoutAccess().GetCurrentViewShell() || pCmpRange )
1
Assuming the condition is false
2
Assuming 'pCmpRange' is null
3
Taking false branch
533 {
534 return aRetval;
535 }
536
537 const SwPageFrame *pPage = static_cast<const SwPageFrame*>(getIDocumentLayoutAccess().GetCurrentLayout()->GetLower());
538 while( pPage )
4
Loop condition is true. Entering loop body
539 {
540 if( pPage->GetSortedObjs() )
5
Assuming the condition is true
6
Taking true branch
541 {
542 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
543 for(SwAnchoredObject* pAnchoredObj : rObjs)
7
'pAnchoredObj' initialized here
544 {
545 SwFrameFormat *pFly;
546 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr )
8
Assuming pointer value is null
9
Taking false branch
547 pFly = &(pAnchoredObj->GetFrameFormat());
548 else if ( bDrawAlso )
10
Assuming 'bDrawAlso' is true
11
Taking true branch
549 pFly = &(pAnchoredObj->GetFrameFormat());
12
Called C++ object pointer is null
550 else
551 continue;
552
553 const SwFormatAnchor& rAnchor = pFly->GetAnchor();
554 if ((RndStdIds::FLY_AT_PARA != rAnchor.GetAnchorId()) &&
555 (RndStdIds::FLY_AT_FLY != rAnchor.GetAnchorId()) &&
556 (RndStdIds::FLY_AT_CHAR != rAnchor.GetAnchorId()))
557 {
558 const SwContentFrame * pContentFrame = pPage->FindFirstBodyContent();
559 if ( !pContentFrame )
560 {
561 // Oops! An empty page.
562 // In order not to lose the whole frame (RTF) we
563 // look for the last Content before the page.
564 const SwPageFrame *pPrv = static_cast<const SwPageFrame*>(pPage->GetPrev());
565 while ( !pContentFrame && pPrv )
566 {
567 pContentFrame = pPrv->FindFirstBodyContent();
568 pPrv = static_cast<const SwPageFrame*>(pPrv->GetPrev());
569 }
570 }
571 if ( pContentFrame )
572 {
573 SwNodeIndex aIdx( pContentFrame->IsTextFrame()
574 ? *static_cast<SwTextFrame const*>(pContentFrame)->GetTextNodeFirst()
575 : *static_cast<SwNoTextFrame const*>(pContentFrame)->GetNode() );
576 aRetval.insert(std::make_shared<SwPosFlyFrame>(aIdx, pFly, aRetval.size()));
577 }
578 }
579 }
580 }
581 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
582 }
583
584 return aRetval;
585}
586
587/* #i6447# changed behaviour if lcl_CpyAttr:
588
589 If the old item set contains the item to set (no inheritance) copy the item
590 into the new set.
591
592 If the old item set contains the item by inheritance and the new set
593 contains the item, too:
594 If the two items differ copy the item from the old set to the new set.
595
596 Otherwise the new set will not be changed.
597*/
598static void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
599{
600 const SfxPoolItem *pOldItem = nullptr;
601
602 rOldSet.GetItemState( nWhich, false, &pOldItem);
603 if (pOldItem != nullptr)
604 rNewSet.Put( *pOldItem );
605 else
606 {
607 pOldItem = rOldSet.GetItem( nWhich );
608 if (pOldItem != nullptr)
609 {
610 const SfxPoolItem *pNewItem = rNewSet.GetItem( nWhich );
611 if (pNewItem != nullptr)
612 {
613 if (*pOldItem != *pNewItem)
614 rNewSet.Put( *pOldItem );
615 }
616 else {
617 OSL_FAIL("What am I doing 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/doclay.cxx"
":" "617" ": "), "%s", "What am I doing here?"); } } while (
false)
;
618 }
619 }
620 else {
621 OSL_FAIL("What am I doing 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/doclay.cxx"
":" "621" ": "), "%s", "What am I doing here?"); } } while (
false)
;
622 }
623 }
624
625}
626
627static SwFlyFrameFormat *
628lcl_InsertLabel(SwDoc & rDoc, SwTextFormatColls *const pTextFormatCollTable,
629 SwUndoInsertLabel *const pUndo,
630 SwLabelType const eType, OUString const& rText, OUString const& rSeparator,
631 const OUString& rNumberingSeparator,
632 const bool bBefore, const sal_uInt16 nId, const sal_uLong nNdIdx,
633 const OUString& rCharacterStyle,
634 const bool bCpyBrd )
635{
636 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
637
638 bool bTable = false; // To save some code.
639
640 // Get the field first, because we retrieve the TextColl via the field's name
641 OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.getIDocumentFieldsAccess().GetFieldTypes()->size(),do { if (true && (!(nId == (32767 *2 +1) || nId < rDoc
.getIDocumentFieldsAccess().GetFieldTypes()->size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "642" ": "), "%s", "FieldType index out of bounds."); } }
while (false)
642 "FieldType index out of bounds." )do { if (true && (!(nId == (32767 *2 +1) || nId < rDoc
.getIDocumentFieldsAccess().GetFieldTypes()->size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "642" ": "), "%s", "FieldType index out of bounds."); } }
while (false)
;
643 SwFieldType *pType = (nId != USHRT_MAX(32767 *2 +1)) ? (*rDoc.getIDocumentFieldsAccess().GetFieldTypes())[nId].get() : nullptr;
644 OSL_ENSURE(!pType || pType->Which() == SwFieldIds::SetExp, "wrong Id for Label")do { if (true && (!(!pType || pType->Which() == SwFieldIds
::SetExp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "644" ": "), "%s", "wrong Id for Label"); } } while (false
)
;
645
646 SwTextFormatColl * pColl = nullptr;
647 if( pType )
648 {
649 for( auto i = pTextFormatCollTable->size(); i; )
650 {
651 if( (*pTextFormatCollTable)[ --i ]->GetName()==pType->GetName() )
652 {
653 pColl = (*pTextFormatCollTable)[i];
654 break;
655 }
656 }
657 OSL_ENSURE( pColl, "no text collection found" )do { if (true && (!(pColl))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "657" ": "), "%s", "no text collection found"); } } while
(false)
;
658 }
659
660 if( !pColl )
661 {
662 pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_LABEL );
663 }
664
665 SwTextNode *pNew = nullptr;
666 SwFlyFrameFormat* pNewFormat = nullptr;
667
668 switch ( eType )
669 {
670 case SwLabelType::Table:
671 bTable = true;
672 [[fallthrough]];
673 case SwLabelType::Fly:
674 // At the FlySection's Beginning/End insert the corresponding Node with its Field.
675 // The Frame is created automatically.
676 {
677 SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode();
678 OSL_ENSURE( pSttNd, "No StartNode in InsertLabel." )do { if (true && (!(pSttNd))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "678" ": "), "%s", "No StartNode in InsertLabel."); } } while
(false)
;
679 sal_uLong nNode;
680 if( bBefore )
681 {
682 nNode = pSttNd->GetIndex();
683 if( !bTable )
684 ++nNode;
685 }
686 else
687 {
688 nNode = pSttNd->EndOfSectionIndex();
689 if( bTable )
690 ++nNode;
691 }
692
693 if( pUndo )
694 pUndo->SetNodePos( nNode );
695
696 // Create Node for labeling paragraph.
697 SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
698 pNew = rDoc.GetNodes().MakeTextNode( aIdx, pColl );
699 }
700 break;
701
702 case SwLabelType::Object:
703 {
704 // Destroy Frame,
705 // insert new Frame,
706 // insert the corresponding Node with Field into the new Frame,
707 // insert the old Frame with the Object (Picture/OLE) paragraph-bound into the new Frame,
708 // create Frames.
709
710 // Get the FlyFrame's Format and decouple the Layout.
711 SwFrameFormat *pOldFormat = rDoc.GetNodes()[nNdIdx]->GetFlyFormat();
712 OSL_ENSURE( pOldFormat, "Couldn't find the Fly's Format." )do { if (true && (!(pOldFormat))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "712" ": "), "%s", "Couldn't find the Fly's Format."); }
} while (false)
;
713 // #i115719#
714 // <title> and <description> attributes are lost when calling <DelFrames()>.
715 // Thus, keep them and restore them after the calling <MakeFrames()>
716 const bool bIsSwFlyFrameFormatInstance( dynamic_cast<SwFlyFrameFormat*>(pOldFormat) != nullptr );
717 const OUString sTitle( bIsSwFlyFrameFormatInstance
718 ? static_cast<SwFlyFrameFormat*>(pOldFormat)->GetObjTitle()
719 : OUString() );
720 const OUString sDescription( bIsSwFlyFrameFormatInstance
721 ? static_cast<SwFlyFrameFormat*>(pOldFormat)->GetObjDescription()
722 : OUString() );
723 pOldFormat->DelFrames();
724
725 pNewFormat = rDoc.MakeFlyFrameFormat( rDoc.GetUniqueFrameName(),
726 rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool(RES_POOLFRM_FRAME) );
727
728 /* #i6447#: Only the selected items are copied from the old
729 format. */
730 std::unique_ptr<SfxItemSet> pNewSet = pNewFormat->GetAttrSet().Clone();
731
732 // Copy only the set attributes.
733 // The others should apply from the Templates.
734 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_PRINT );
735 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_OPAQUE );
736 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_PROTECT );
737 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_SURROUND );
738 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_VERT_ORIENT );
739 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_HORI_ORIENT );
740 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_LR_SPACE );
741 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_UL_SPACE );
742 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_BACKGROUND );
743 if( bCpyBrd )
744 {
745 // If there's no BoxItem at graphic, but the new Format has one, then set the
746 // default item in the new Set. Because the graphic's size has never changed!
747 const SfxPoolItem *pItem;
748 if( SfxItemState::SET == pOldFormat->GetAttrSet().
749 GetItemState( RES_BOX, true, &pItem ))
750 pNewSet->Put( *pItem );
751 else if( SfxItemState::SET == pNewFormat->GetAttrSet().
752 GetItemState( RES_BOX ))
753 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
754
755 if( SfxItemState::SET == pOldFormat->GetAttrSet().
756 GetItemState( RES_SHADOW, true, &pItem ))
757 pNewSet->Put( *pItem );
758 else if( SfxItemState::SET == pNewFormat->GetAttrSet().
759 GetItemState( RES_SHADOW ))
760 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
761 }
762 else
763 {
764 // Hard-set the attributes, because they could come from the Template
765 // and then size calculations could not be correct anymore.
766 pNewSet->Put( SvxBoxItem(RES_BOX) );
767 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
768 }
769
770 // Always transfer the anchor, which is a hard attribute anyways.
771 pNewSet->Put( pOldFormat->GetAnchor() );
772
773 // The new one should be changeable in its height.
774 std::unique_ptr<SwFormatFrameSize> aFrameSize(pOldFormat->GetFrameSize().Clone());
775 aFrameSize->SetHeightSizeType( SwFrameSize::Minimum );
776 pNewSet->Put( std::move(aFrameSize) );
777
778 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection(
779 SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
780 SwFlyStartNode, pColl );
781 pNewSet->Put( SwFormatContent( pSttNd ));
782
783 pNewFormat->SetFormatAttr( *pNewSet );
784
785 // InContents need to be treated in a special way:
786 // The TextAttribute needs to be destroyed.
787 // Unfortunately, this also destroys the Format next to the Frames.
788 // To avoid this, we disconnect the attribute from the Format.
789
790 const SwFormatAnchor& rAnchor = pNewFormat->GetAnchor();
791 if ( RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId() )
792 {
793 const SwPosition *pPos = rAnchor.GetContentAnchor();
794 SwTextNode *pTextNode = pPos->nNode.GetNode().GetTextNode();
795 OSL_ENSURE( pTextNode->HasHints(), "Missing FlyInCnt-Hint." )do { if (true && (!(pTextNode->HasHints()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "795" ": "), "%s", "Missing FlyInCnt-Hint."); } } while (
false)
;
796 const sal_Int32 nIdx = pPos->nContent.GetIndex();
797 SwTextAttr * const pHint =
798 pTextNode->GetTextAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
799
800 assert(pHint && "Missing Hint.")(static_cast <bool> (pHint && "Missing Hint.") ?
void (0) : __assert_fail ("pHint && \"Missing Hint.\""
, "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 800, __extension__ __PRETTY_FUNCTION__))
;
801
802 OSL_ENSURE( pHint->Which() == RES_TXTATR_FLYCNT,do { if (true && (!(pHint->Which() == RES_TXTATR_FLYCNT
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "803" ": "), "%s", "Missing FlyInCnt-Hint."); } } while (
false)
803 "Missing FlyInCnt-Hint." )do { if (true && (!(pHint->Which() == RES_TXTATR_FLYCNT
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "803" ": "), "%s", "Missing FlyInCnt-Hint."); } } while (
false)
;
804 OSL_ENSURE( pHint->GetFlyCnt().GetFrameFormat() == pOldFormat,do { if (true && (!(pHint->GetFlyCnt().GetFrameFormat
() == pOldFormat))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "805" ": "), "%s", "Wrong TextFlyCnt-Hint."); } } while (
false)
805 "Wrong TextFlyCnt-Hint." )do { if (true && (!(pHint->GetFlyCnt().GetFrameFormat
() == pOldFormat))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "805" ": "), "%s", "Wrong TextFlyCnt-Hint."); } } while (
false)
;
806
807 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt()).SetFlyFormat(
808 pNewFormat );
809 }
810
811 // The old one should not have a flow and it should be adjusted to above and
812 // middle.
813 // Also, the width should be 100% and it should also adjust the height, if changed.
814 pNewSet->ClearItem();
815
816 pNewSet->Put( SwFormatSurround( css::text::WrapTextMode_NONE ) );
817 pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, true ) );
818
819 sal_Int16 eVert = bBefore ? text::VertOrientation::BOTTOM : text::VertOrientation::TOP;
820 pNewSet->Put( SwFormatVertOrient( 0, eVert ) );
821 pNewSet->Put( SwFormatHoriOrient( 0, text::HoriOrientation::CENTER ) );
822
823 aFrameSize.reset(pOldFormat->GetFrameSize().Clone());
824
825 SwOLENode* pOleNode = rDoc.GetNodes()[nNdIdx + 1]->GetOLENode();
826 bool isMath = false;
827 if(pOleNode)
828 {
829 svt::EmbeddedObjectRef& xRef = pOleNode->GetOLEObj().GetObject();
830 if(xRef.is())
831 {
832 SvGlobalName aCLSID( xRef->getClassID() );
833 isMath = ( SotExchange::IsMath( aCLSID ) != 0 );
834 }
835 }
836 aFrameSize->SetWidthPercent(isMath ? 0 : 100);
837 aFrameSize->SetHeightPercent(SwFormatFrameSize::SYNCED);
838 pNewSet->Put( std::move(aFrameSize) );
839
840 // Hard-set the attributes, because they could come from the Template
841 // and then size calculations could not be correct anymore.
842 if( bCpyBrd )
843 {
844 pNewSet->Put( SvxBoxItem(RES_BOX) );
845 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
846 }
847 pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
848 pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
849
850 // The old one is paragraph-bound to the paragraph in the new one.
851 SwFormatAnchor aAnch( RndStdIds::FLY_AT_PARA );
852 SwNodeIndex aAnchIdx( *pNewFormat->GetContent().GetContentIdx(), 1 );
853 pNew = aAnchIdx.GetNode().GetTextNode();
854 SwPosition aPos( aAnchIdx );
855 aAnch.SetAnchor( &aPos );
856 pNewSet->Put( aAnch );
857
858 if( pUndo )
859 pUndo->SetFlys( *pOldFormat, *pNewSet, *pNewFormat );
860 else
861 pOldFormat->SetFormatAttr( *pNewSet );
862
863 pNewSet.reset();
864
865 // Have only the FlyFrames created.
866 // We leave this to established methods (especially for InCntFlys).
867 pNewFormat->MakeFrames();
868 // #i115719#
869 if ( bIsSwFlyFrameFormatInstance )
870 {
871 static_cast<SwFlyFrameFormat*>(pOldFormat)->SetObjTitle( sTitle );
872 static_cast<SwFlyFrameFormat*>(pOldFormat)->SetObjDescription( sDescription );
873 }
874 }
875 break;
876
877 default:
878 OSL_ENSURE(false, "unknown LabelType?")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "878" ": "), "%s", "unknown LabelType?"); } } while (false
)
;
879 }
880 OSL_ENSURE( pNew, "No Label inserted" )do { if (true && (!(pNew))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "880" ": "), "%s", "No Label inserted"); } } while (false
)
;
881 if( pNew )
882 {
883 // #i61007# order of captions
884 bool bOrderNumberingFirst = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetModuleConfig()->IsCaptionOrderNumberingFirst();
885 // Work up OUString
886 OUString aText;
887 if( bOrderNumberingFirst )
888 {
889 aText = rNumberingSeparator;
890 }
891 if( pType)
892 {
893 aText += pType->GetName();
894 if( !bOrderNumberingFirst )
895 aText += " ";
896 }
897 sal_Int32 nIdx = aText.getLength();
898 if( !rText.isEmpty() )
899 {
900 aText += rSeparator;
901 }
902 const sal_Int32 nSepIdx = aText.getLength();
903 aText += rText;
904
905 // Insert string
906 SwIndex aIdx( pNew, 0 );
907 pNew->InsertText( aText, aIdx );
908
909 // Insert field
910 if(pType)
911 {
912 SwSetExpField aField( static_cast<SwSetExpFieldType*>(pType), OUString(), SVX_NUM_ARABIC);
913 if( bOrderNumberingFirst )
914 nIdx = 0;
915 SwFormatField aFormat( aField );
916 pNew->InsertItem( aFormat, nIdx, nIdx );
917 if(!rCharacterStyle.isEmpty())
918 {
919 SwCharFormat* pCharFormat = rDoc.FindCharFormatByName(rCharacterStyle);
920 if( !pCharFormat )
921 {
922 const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, SwGetPoolIdFromName::ChrFmt);
923 pCharFormat = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( nMyId );
924 }
925 if (pCharFormat)
926 {
927 SwFormatCharFormat aCharFormat( pCharFormat );
928 pNew->InsertItem( aCharFormat, 0,
929 nSepIdx + 1, SetAttrMode::DONTEXPAND );
930 }
931 }
932 }
933
934 if ( bTable )
935 {
936 if ( bBefore )
937 {
938 if ( !pNew->GetSwAttrSet().GetKeep().GetValue() )
939 pNew->SetAttr( SvxFormatKeepItem( true, RES_KEEP ) );
940 }
941 else
942 {
943 SwTableNode *const pNd =
944 rDoc.GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
945 SwTable &rTable = pNd->GetTable();
946 if ( !rTable.GetFrameFormat()->GetKeep().GetValue() )
947 rTable.GetFrameFormat()->SetFormatAttr( SvxFormatKeepItem( true, RES_KEEP ) );
948 if ( pUndo )
949 pUndo->SetUndoKeep();
950 }
951 }
952 rDoc.getIDocumentState().SetModified();
953 }
954
955 return pNewFormat;
956}
957
958SwFlyFrameFormat *
959SwDoc::InsertLabel(
960 SwLabelType const eType, OUString const& rText, OUString const& rSeparator,
961 OUString const& rNumberingSeparator,
962 bool const bBefore, sal_uInt16 const nId, sal_uLong const nNdIdx,
963 OUString const& rCharacterStyle,
964 bool const bCpyBrd )
965{
966 std::unique_ptr<SwUndoInsertLabel> pUndo;
967 if (GetIDocumentUndoRedo().DoesUndo())
968 {
969 pUndo.reset(new SwUndoInsertLabel(
970 eType, rText, rSeparator, rNumberingSeparator,
971 bBefore, nId, rCharacterStyle, bCpyBrd, this ));
972 }
973
974 SwFlyFrameFormat *const pNewFormat = lcl_InsertLabel(*this, mpTextFormatCollTable.get(), pUndo.get(),
975 eType, rText, rSeparator, rNumberingSeparator, bBefore,
976 nId, nNdIdx, rCharacterStyle, bCpyBrd);
977
978 if (pUndo)
979 {
980 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
981 }
982 else
983 {
984 GetIDocumentUndoRedo().DelAllUndoObj();
985 }
986
987 return pNewFormat;
988}
989
990static SwFlyFrameFormat *
991lcl_InsertDrawLabel( SwDoc & rDoc, SwTextFormatColls *const pTextFormatCollTable,
992 SwUndoInsertLabel *const pUndo, SwDrawFrameFormat *const pOldFormat,
993 OUString const& rText,
994 const OUString& rSeparator,
995 const OUString& rNumberSeparator,
996 const sal_uInt16 nId,
997 const OUString& rCharacterStyle,
998 SdrObject& rSdrObj )
999{
1000 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1001 ::sw::DrawUndoGuard const drawUndoGuard(rDoc.GetIDocumentUndoRedo());
1002
1003 // Because we get by the TextColl's name, we need to create the field first.
1004 OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.getIDocumentFieldsAccess().GetFieldTypes()->size(),do { if (true && (!(nId == (32767 *2 +1) || nId < rDoc
.getIDocumentFieldsAccess().GetFieldTypes()->size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1005" ": "), "%s", "FieldType index out of bounds"); } }
while (false)
1005 "FieldType index out of bounds" )do { if (true && (!(nId == (32767 *2 +1) || nId < rDoc
.getIDocumentFieldsAccess().GetFieldTypes()->size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1005" ": "), "%s", "FieldType index out of bounds"); } }
while (false)
;
1006 SwFieldType *pType = nId != USHRT_MAX(32767 *2 +1) ? (*rDoc.getIDocumentFieldsAccess().GetFieldTypes())[nId].get() : nullptr;
1007 OSL_ENSURE( !pType || pType->Which() == SwFieldIds::SetExp, "Wrong label id" )do { if (true && (!(!pType || pType->Which() == SwFieldIds
::SetExp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1007" ": "), "%s", "Wrong label id"); } } while (false)
;
1008
1009 SwTextFormatColl *pColl = nullptr;
1010 if( pType )
1011 {
1012 for( auto i = pTextFormatCollTable->size(); i; )
1013 {
1014 if( (*pTextFormatCollTable)[ --i ]->GetName()==pType->GetName() )
1015 {
1016 pColl = (*pTextFormatCollTable)[i];
1017 break;
1018 }
1019 }
1020 OSL_ENSURE( pColl, "no text collection found" )do { if (true && (!(pColl))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1020" ": "), "%s", "no text collection found"); } } while
(false)
;
1021 }
1022
1023 if( !pColl )
1024 {
1025 pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_LABEL );
1026 }
1027
1028 SwTextNode* pNew = nullptr;
1029 SwFlyFrameFormat* pNewFormat = nullptr;
1030
1031 // Destroy Frame,
1032 // insert new Frame,
1033 // insert the corresponding Node with Field into the new Frame,
1034 // insert the old Frame with the Object (Picture/OLE) paragraph-bound into the new Frame,
1035 // create Frames.
1036
1037 // Keep layer ID of drawing object before removing
1038 // its frames.
1039 // Note: The layer ID is passed to the undo and have to be the correct value.
1040 // Removing the frames of the drawing object changes its layer.
1041 const SdrLayerID nLayerId = rSdrObj.GetLayer();
1042
1043 pOldFormat->DelFrames();
1044
1045 // InContents need to be treated in a special way:
1046 // The TextAttribute needs to be destroyed.
1047 // Unfortunately, this also destroys the Format next to the Frames.
1048 // To avoid this, we disconnect the attribute from the Format.
1049 std::unique_ptr<SfxItemSet> pNewSet = pOldFormat->GetAttrSet().Clone( false );
1050
1051 // Protect the Frame's size and position
1052 if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
1053 {
1054 SvxProtectItem aProtect(RES_PROTECT);
1055 aProtect.SetContentProtect( false );
1056 aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
1057 aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
1058 pNewSet->Put( aProtect );
1059 }
1060
1061 // Take over the text wrap
1062 lcl_CpyAttr( *pNewSet, pOldFormat->GetAttrSet(), RES_SURROUND );
1063
1064 // Send the frame to the back, if needed.
1065 // Consider the 'invisible' hell layer.
1066 if ( rDoc.getIDocumentDrawModelAccess().GetHellId() != nLayerId &&
1067 rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId() != nLayerId )
1068 {
1069 SvxOpaqueItem aOpaque( RES_OPAQUE );
1070 aOpaque.SetValue( true );
1071 pNewSet->Put( aOpaque );
1072 }
1073
1074 // Take over position
1075 // #i26791# - use directly drawing object's positioning attributes
1076 pNewSet->Put( pOldFormat->GetHoriOrient() );
1077 pNewSet->Put( pOldFormat->GetVertOrient() );
1078
1079 pNewSet->Put( pOldFormat->GetAnchor() );
1080
1081 // The new one should be variable in its height!
1082 Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
1083 SwFormatFrameSize aFrameSize( SwFrameSize::Minimum, aSz.Width(), aSz.Height() );
1084 pNewSet->Put( aFrameSize );
1085
1086 // Apply the margin to the new Frame.
1087 // Don't set a border, use the one from the Template.
1088 pNewSet->Put( pOldFormat->GetLRSpace() );
1089 pNewSet->Put( pOldFormat->GetULSpace() );
1090
1091 SwStartNode* pSttNd =
1092 rDoc.GetNodes().MakeTextSection(
1093 SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
1094 SwFlyStartNode, pColl );
1095
1096 pNewFormat = rDoc.MakeFlyFrameFormat( rDoc.GetUniqueFrameName(),
1097 rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool( RES_POOLFRM_FRAME ) );
1098
1099 // Set border and shadow to default if the template contains any.
1100 if( SfxItemState::SET == pNewFormat->GetAttrSet().GetItemState( RES_BOX ))
1101 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1102
1103 if( SfxItemState::SET == pNewFormat->GetAttrSet().GetItemState(RES_SHADOW))
1104 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1105
1106 pNewFormat->SetFormatAttr( SwFormatContent( pSttNd ));
1107 pNewFormat->SetFormatAttr( *pNewSet );
1108
1109 const SwFormatAnchor& rAnchor = pNewFormat->GetAnchor();
1110 if ( RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId() )
1111 {
1112 const SwPosition *pPos = rAnchor.GetContentAnchor();
1113 SwTextNode *pTextNode = pPos->nNode.GetNode().GetTextNode();
1114 OSL_ENSURE( pTextNode->HasHints(), "Missing FlyInCnt-Hint." )do { if (true && (!(pTextNode->HasHints()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1114" ": "), "%s", "Missing FlyInCnt-Hint."); } } while
(false)
;
1115 const sal_Int32 nIdx = pPos->nContent.GetIndex();
1116 SwTextAttr * const pHint =
1117 pTextNode->GetTextAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
1118
1119 assert(pHint && "Missing Hint.")(static_cast <bool> (pHint && "Missing Hint.") ?
void (0) : __assert_fail ("pHint && \"Missing Hint.\""
, "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 1119, __extension__ __PRETTY_FUNCTION__))
;
1120
1121#if OSL_DEBUG_LEVEL1 > 0
1122 OSL_ENSURE( pHint->Which() == RES_TXTATR_FLYCNT,do { if (true && (!(pHint->Which() == RES_TXTATR_FLYCNT
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1123" ": "), "%s", "Missing FlyInCnt-Hint."); } } while
(false)
1123 "Missing FlyInCnt-Hint." )do { if (true && (!(pHint->Which() == RES_TXTATR_FLYCNT
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1123" ": "), "%s", "Missing FlyInCnt-Hint."); } } while
(false)
;
1124 OSL_ENSURE( pHint->GetFlyCnt().do { if (true && (!(pHint->GetFlyCnt(). GetFrameFormat
() == static_cast<SwFrameFormat*>(pOldFormat)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1126" ": "), "%s", "Wrong TextFlyCnt-Hint."); } } while
(false)
1125 GetFrameFormat() == static_cast<SwFrameFormat*>(pOldFormat),do { if (true && (!(pHint->GetFlyCnt(). GetFrameFormat
() == static_cast<SwFrameFormat*>(pOldFormat)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1126" ": "), "%s", "Wrong TextFlyCnt-Hint."); } } while
(false)
1126 "Wrong TextFlyCnt-Hint." )do { if (true && (!(pHint->GetFlyCnt(). GetFrameFormat
() == static_cast<SwFrameFormat*>(pOldFormat)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1126" ": "), "%s", "Wrong TextFlyCnt-Hint."); } } while
(false)
;
1127#endif
1128 const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt()).SetFlyFormat( pNewFormat );
1129 }
1130
1131 // The old one should not have a flow
1132 // and it should be adjusted to above and middle.
1133 pNewSet->ClearItem();
1134
1135 pNewSet->Put( SwFormatSurround( css::text::WrapTextMode_NONE ) );
1136 if (nLayerId == rDoc.getIDocumentDrawModelAccess().GetHellId())
1137 {
1138 // Consider drawing objects in the 'invisible' hell layer
1139 rSdrObj.SetLayer( rDoc.getIDocumentDrawModelAccess().GetHeavenId() );
1140 }
1141 else if (nLayerId == rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId())
1142 {
1143 rSdrObj.SetLayer( rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId() );
1144 }
1145 pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
1146 pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
1147
1148 // #i26791# - set position of the drawing object, which is labeled.
1149 pNewSet->Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
1150 pNewSet->Put( SwFormatHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
1151
1152 // The old one is paragraph-bound to the new one's paragraph.
1153 SwFormatAnchor aAnch( RndStdIds::FLY_AT_PARA );
1154 SwNodeIndex aAnchIdx( *pNewFormat->GetContent().GetContentIdx(), 1 );
1155 pNew = aAnchIdx.GetNode().GetTextNode();
1156 SwPosition aPos( aAnchIdx );
1157 aAnch.SetAnchor( &aPos );
1158 pNewSet->Put( aAnch );
1159
1160 if( pUndo )
1161 {
1162 pUndo->SetFlys( *pOldFormat, *pNewSet, *pNewFormat );
1163 // #i26791# - position no longer needed
1164 pUndo->SetDrawObj( nLayerId );
1165 }
1166 else
1167 pOldFormat->SetFormatAttr( *pNewSet );
1168
1169 pNewSet.reset();
1170
1171 // Have only the FlyFrames created.
1172 // We leave this to established methods (especially for InCntFlys).
1173 pNewFormat->MakeFrames();
1174
1175 OSL_ENSURE( pNew, "No Label inserted" )do { if (true && (!(pNew))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1175" ": "), "%s", "No Label inserted"); } } while (false
)
;
1176
1177 if( pNew )
1178 {
1179 //#i61007# order of captions
1180 bool bOrderNumberingFirst = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1181
1182 // prepare string
1183 OUString aText;
1184 if( bOrderNumberingFirst )
1185 {
1186 aText = rNumberSeparator;
1187 }
1188 if ( pType )
1189 {
1190 aText += pType->GetName();
1191 if( !bOrderNumberingFirst )
1192 aText += " ";
1193 }
1194 sal_Int32 nIdx = aText.getLength();
1195 aText += rSeparator;
1196 const sal_Int32 nSepIdx = aText.getLength();
1197 aText += rText;
1198
1199 // insert text
1200 SwIndex aIdx( pNew, 0 );
1201 pNew->InsertText( aText, aIdx );
1202
1203 // insert field
1204 if ( pType )
1205 {
1206 SwSetExpField aField( static_cast<SwSetExpFieldType*>(pType), OUString(), SVX_NUM_ARABIC );
1207 if( bOrderNumberingFirst )
1208 nIdx = 0;
1209 SwFormatField aFormat( aField );
1210 pNew->InsertItem( aFormat, nIdx, nIdx );
1211 if ( !rCharacterStyle.isEmpty() )
1212 {
1213 SwCharFormat * pCharFormat = rDoc.FindCharFormatByName(rCharacterStyle);
1214 if ( !pCharFormat )
1215 {
1216 const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, SwGetPoolIdFromName::ChrFmt );
1217 pCharFormat = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( nMyId );
1218 }
1219 if ( pCharFormat )
1220 {
1221 SwFormatCharFormat aCharFormat( pCharFormat );
1222 pNew->InsertItem( aCharFormat, 0, nSepIdx + 1,
1223 SetAttrMode::DONTEXPAND );
1224 }
1225 }
1226 }
1227 }
1228
1229 return pNewFormat;
1230}
1231
1232SwFlyFrameFormat* SwDoc::InsertDrawLabel(
1233 OUString const& rText,
1234 OUString const& rSeparator,
1235 OUString const& rNumberSeparator,
1236 sal_uInt16 const nId,
1237 OUString const& rCharacterStyle,
1238 SdrObject& rSdrObj )
1239{
1240 SwDrawContact *const pContact =
1241 static_cast<SwDrawContact*>(GetUserCall( &rSdrObj ));
1242 if (!pContact)
1243 return nullptr;
1244 OSL_ENSURE( RES_DRAWFRMFMT == pContact->GetFormat()->Which(),do { if (true && (!(RES_DRAWFRMFMT == pContact->GetFormat
()->Which()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1245" ": "), "%s", "InsertDrawLabel(): not a DrawFrameFormat"
); } } while (false)
1245 "InsertDrawLabel(): not a DrawFrameFormat" )do { if (true && (!(RES_DRAWFRMFMT == pContact->GetFormat
()->Which()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1245" ": "), "%s", "InsertDrawLabel(): not a DrawFrameFormat"
); } } while (false)
;
1246
1247 SwDrawFrameFormat* pOldFormat = static_cast<SwDrawFrameFormat *>(pContact->GetFormat());
1248 if (!pOldFormat)
1249 return nullptr;
1250
1251 std::unique_ptr<SwUndoInsertLabel> pUndo;
1252 if (GetIDocumentUndoRedo().DoesUndo())
1253 {
1254 GetIDocumentUndoRedo().ClearRedo();
1255 pUndo.reset(new SwUndoInsertLabel(
1256 SwLabelType::Draw, rText, rSeparator, rNumberSeparator, false,
1257 nId, rCharacterStyle, false, this ));
1258 }
1259
1260 SwFlyFrameFormat *const pNewFormat = lcl_InsertDrawLabel(
1261 *this, mpTextFormatCollTable.get(), pUndo.get(), pOldFormat,
1262 rText, rSeparator, rNumberSeparator, nId, rCharacterStyle, rSdrObj);
1263
1264 if (pUndo)
1265 {
1266 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
1267 }
1268 else
1269 {
1270 GetIDocumentUndoRedo().DelAllUndoObj();
1271 }
1272
1273 return pNewFormat;
1274}
1275
1276static void lcl_collectUsedNums(std::vector<unsigned int>& rSetFlags, sal_Int32 nNmLen, const OUString& rName, const OUString& rCmpName)
1277{
1278 if (rName.startsWith(rCmpName))
1279 {
1280 // Only get and set the Flag
1281 const sal_Int32 nNum = rName.copy(nNmLen).toInt32() - 1;
1282 if (nNum >= 0)
1283 rSetFlags.push_back(nNum);
1284 }
1285}
1286
1287static void lcl_collectUsedNums(std::vector<unsigned int>& rSetFlags, sal_Int32 nNmLen, const SdrObject& rObj, const OUString& rCmpName)
1288{
1289 OUString sName = rObj.GetName();
1290 lcl_collectUsedNums(rSetFlags, nNmLen, sName, rCmpName);
1291 // tdf#122487 take groups into account, iterate and recurse through their
1292 // contents for name collision check
1293 if (!rObj.IsGroupObject())
1294 return;
1295
1296 const SdrObjList* pSub(rObj.GetSubList());
1297 assert(pSub && "IsGroupObject is implemented as GetSubList != nullptr")(static_cast <bool> (pSub && "IsGroupObject is implemented as GetSubList != nullptr"
) ? void (0) : __assert_fail ("pSub && \"IsGroupObject is implemented as GetSubList != nullptr\""
, "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 1297, __extension__ __PRETTY_FUNCTION__))
;
1298 const size_t nCount = pSub->GetObjCount();
1299 for (size_t i = 0; i < nCount; ++i)
1300 {
1301 SdrObject* pObj = pSub->GetObj(i);
1302 if (!pObj)
1303 continue;
1304 lcl_collectUsedNums(rSetFlags, nNmLen, *pObj, rCmpName);
1305 }
1306}
1307
1308namespace
1309{
1310 int first_available_number(std::vector<unsigned int>& numbers)
1311 {
1312 std::sort(numbers.begin(), numbers.end());
1313 auto last = std::unique(numbers.begin(), numbers.end());
1314 numbers.erase(last, numbers.end());
1315
1316 for (size_t i = 0; i < numbers.size(); ++i)
1317 {
1318 if (numbers[i] != i)
1319 return i;
1320 }
1321
1322 return numbers.size();
1323 }
1324}
1325
1326static OUString lcl_GetUniqueFlyName(const SwDoc& rDoc, const char* pDefStrId, sal_uInt16 eType)
1327{
1328 assert(eType >= RES_FMT_BEGIN && eType < RES_FMT_END)(static_cast <bool> (eType >= RES_FMT_BEGIN &&
eType < RES_FMT_END) ? void (0) : __assert_fail ("eType >= RES_FMT_BEGIN && eType < RES_FMT_END"
, "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 1328, __extension__ __PRETTY_FUNCTION__))
;
1329 if (rDoc.IsInMailMerge())
1330 {
1331 OUString newName = "MailMergeFly"
1332 + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)) )
1333 + OUString::number( rDoc.GetSpzFrameFormats()->size() + 1 );
1334 return newName;
1335 }
1336
1337 OUString aName(SwResId(pDefStrId));
1338 sal_Int32 nNmLen = aName.getLength();
1339
1340 const SwFrameFormats& rFormats = *rDoc.GetSpzFrameFormats();
1341
1342 std::vector<unsigned int> aUsedNums;
1343 aUsedNums.reserve(rFormats.size());
1344
1345 for( SwFrameFormats::size_type n = 0; n < rFormats.size(); ++n )
1346 {
1347 const SwFrameFormat* pFlyFormat = rFormats[ n ];
1348 if (eType != pFlyFormat->Which())
1349 continue;
1350 if (eType == RES_DRAWFRMFMT)
1351 {
1352 const SdrObject *pObj = pFlyFormat->FindSdrObject();
1353 if (pObj)
1354 lcl_collectUsedNums(aUsedNums, nNmLen, *pObj, aName);
1355 }
1356
1357 OUString sName = pFlyFormat->GetName();
1358 lcl_collectUsedNums(aUsedNums, nNmLen, sName, aName);
1359 }
1360
1361 // All numbers are flagged accordingly, so determine the right one
1362 SwFrameFormats::size_type nNum = first_available_number(aUsedNums) + 1;
1363 return aName + OUString::number(nNum);
1364}
1365
1366OUString SwDoc::GetUniqueGrfName() const
1367{
1368 return lcl_GetUniqueFlyName(*this, STR_GRAPHIC_DEFNAMEreinterpret_cast<char const *>("STR_GRAPHIC_DEFNAME" "\004"
u8"Image")
, RES_FLYFRMFMT);
1369}
1370
1371OUString SwDoc::GetUniqueOLEName() const
1372{
1373 return lcl_GetUniqueFlyName(*this, STR_OBJECT_DEFNAMEreinterpret_cast<char const *>("STR_OBJECT_DEFNAME" "\004"
u8"Object")
, RES_FLYFRMFMT);
1374}
1375
1376OUString SwDoc::GetUniqueFrameName() const
1377{
1378 return lcl_GetUniqueFlyName(*this, STR_FRAME_DEFNAMEreinterpret_cast<char const *>("STR_FRAME_DEFNAME" "\004"
u8"Frame")
, RES_FLYFRMFMT);
1379}
1380
1381OUString SwDoc::GetUniqueShapeName() const
1382{
1383 return lcl_GetUniqueFlyName(*this, STR_SHAPE_DEFNAMEreinterpret_cast<char const *>("STR_SHAPE_DEFNAME" "\004"
u8"Shape")
, RES_DRAWFRMFMT);
1384}
1385
1386OUString SwDoc::GetUniqueDrawObjectName() const
1387{
1388 return lcl_GetUniqueFlyName(*this, "DrawObject", RES_DRAWFRMFMT);
1389}
1390
1391const SwFlyFrameFormat* SwDoc::FindFlyByName( const OUString& rName, SwNodeType nNdTyp ) const
1392{
1393 auto range = GetSpzFrameFormats()->rangeFind( RES_FLYFRMFMT, rName );
1394 for( auto it = range.first; it != range.second; it++ )
1395 {
1396 const SwFrameFormat* pFlyFormat = *it;
1397 if( RES_FLYFRMFMT != pFlyFormat->Which() || pFlyFormat->GetName() != rName )
1398 continue;
1399 const SwNodeIndex* pIdx = pFlyFormat->GetContent().GetContentIdx();
1400 if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
1401 {
1402 if( nNdTyp != SwNodeType::NONE )
1403 {
1404 // query for the right NodeType
1405 const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
1406 if( nNdTyp == SwNodeType::Text
1407 ? !pNd->IsNoTextNode()
1408 : nNdTyp == pNd->GetNodeType() )
1409 return static_cast<const SwFlyFrameFormat*>(pFlyFormat);
1410 }
1411 else
1412 return static_cast<const SwFlyFrameFormat*>(pFlyFormat);
1413 }
1414 }
1415 return nullptr;
1416}
1417
1418void SwDoc::SetFlyName( SwFlyFrameFormat& rFormat, const OUString& rName )
1419{
1420 OUString sName( rName );
1421 if( sName.isEmpty() || FindFlyByName( sName ) )
1422 {
1423 const char* pTyp = STR_FRAME_DEFNAMEreinterpret_cast<char const *>("STR_FRAME_DEFNAME" "\004"
u8"Frame")
;
1424 const SwNodeIndex* pIdx = rFormat.GetContent().GetContentIdx();
1425 if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
1426 {
1427 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
1428 {
1429 case SwNodeType::Grf:
1430 pTyp = STR_GRAPHIC_DEFNAMEreinterpret_cast<char const *>("STR_GRAPHIC_DEFNAME" "\004"
u8"Image")
;
1431 break;
1432 case SwNodeType::Ole:
1433 pTyp = STR_OBJECT_DEFNAMEreinterpret_cast<char const *>("STR_OBJECT_DEFNAME" "\004"
u8"Object")
;
1434 break;
1435 default: break;
1436 }
1437 }
1438 sName = lcl_GetUniqueFlyName(*this, pTyp, RES_FLYFRMFMT);
1439 }
1440 rFormat.SetName( sName, true );
1441 getIDocumentState().SetModified();
1442}
1443
1444void SwDoc::SetAllUniqueFlyNames()
1445{
1446 sal_Int32 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
1447
1448 const OUString sFlyNm(SwResId(STR_FRAME_DEFNAMEreinterpret_cast<char const *>("STR_FRAME_DEFNAME" "\004"
u8"Frame")
));
1449 const OUString sGrfNm(SwResId(STR_GRAPHIC_DEFNAMEreinterpret_cast<char const *>("STR_GRAPHIC_DEFNAME" "\004"
u8"Image")
));
1450 const OUString sOLENm(SwResId(STR_OBJECT_DEFNAMEreinterpret_cast<char const *>("STR_OBJECT_DEFNAME" "\004"
u8"Object")
));
1451
1452 n = GetSpzFrameFormats()->size();
1453 if( 255 < n )
1454 n = 255;
1455 SwFrameFormatsV aArr;
1456 aArr.reserve( n );
1457 SwFrameFormat* pFlyFormat;
1458 bool bContainsAtPageObjWithContentAnchor = false;
1459
1460 for( n = GetSpzFrameFormats()->size(); n; )
1461 {
1462 pFlyFormat = (*GetSpzFrameFormats())[ --n ];
1463 if( RES_FLYFRMFMT == pFlyFormat->Which() )
1464 {
1465 const OUString& aNm = pFlyFormat->GetName();
1466 if ( !aNm.isEmpty() )
1467 {
1468 sal_Int32 *pNum = nullptr;
1469 sal_Int32 nLen = 0;
1470 if ( aNm.startsWith(sGrfNm) )
1471 {
1472 nLen = sGrfNm.getLength();
1473 pNum = &nGrfNum;
1474 }
1475 else if( aNm.startsWith(sFlyNm) )
1476 {
1477 nLen = sFlyNm.getLength();
1478 pNum = &nFlyNum;
1479 }
1480 else if( aNm.startsWith(sOLENm) )
1481 {
1482 nLen = sOLENm.getLength();
1483 pNum = &nOLENum;
1484 }
1485
1486 if ( pNum )
1487 {
1488 const sal_Int32 nNewLen = aNm.copy( nLen ).toInt32();
1489 if (*pNum < nNewLen)
1490 *pNum = nNewLen;
1491 }
1492 }
1493 else
1494 // we want to set that afterwards
1495 aArr.push_back( pFlyFormat );
1496
1497 }
1498 if ( !bContainsAtPageObjWithContentAnchor )
1499 {
1500 const SwFormatAnchor& rAnchor = pFlyFormat->GetAnchor();
1501 if ( (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId()) &&
1502 rAnchor.GetContentAnchor() )
1503 {
1504 bContainsAtPageObjWithContentAnchor = true;
1505 }
1506 }
1507 }
1508 SetContainsAtPageObjWithContentAnchor( bContainsAtPageObjWithContentAnchor );
1509
1510 for( n = aArr.size(); n; )
1511 {
1512 pFlyFormat = aArr[ --n ];
1513 const SwNodeIndex* pIdx = pFlyFormat->GetContent().GetContentIdx();
1514 if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
1515 {
1516 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
1517 {
1518 case SwNodeType::Grf:
1519 pFlyFormat->SetName( sGrfNm + OUString::number( ++nGrfNum ));
1520 break;
1521 case SwNodeType::Ole:
1522 pFlyFormat->SetName( sOLENm + OUString::number( ++nOLENum ));
1523 break;
1524 default:
1525 pFlyFormat->SetName( sFlyNm + OUString::number( ++nFlyNum ));
1526 break;
1527 }
1528 }
1529 }
1530 aArr.clear();
1531
1532 if( GetFootnoteIdxs().empty() )
1533 return;
1534
1535 SwTextFootnote::SetUniqueSeqRefNo( *this );
1536 // #i52775# Chapter footnotes did not get updated correctly.
1537 // Calling UpdateAllFootnote() instead of UpdateFootnote() solves this problem,
1538 // but I do not dare to call UpdateAllFootnote() in all cases: Safety first.
1539 if ( FTNNUM_CHAPTER == GetFootnoteInfo().m_eNum )
1540 {
1541 GetFootnoteIdxs().UpdateAllFootnote();
1542 }
1543 else
1544 {
1545 SwNodeIndex aTmp( GetNodes() );
1546 GetFootnoteIdxs().UpdateFootnote( aTmp );
1547 }
1548}
1549
1550bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
1551{
1552 // That can also be a Fly in a Fly in the Header.
1553 // Is also used by sw3io, to determine if a Redline object is
1554 // in the Header or Footer.
1555 // Because Redlines are also attached to Start and EndNode,
1556 // the Index must not necessarily be from a ContentNode.
1557 SwNode* pNd = &rIdx.GetNode();
1558 const SwNode* pFlyNd = pNd->FindFlyStartNode();
1559 while( pFlyNd )
1560 {
1561 // get up by using the Anchor
1562#if OSL_DEBUG_LEVEL1 > 0
1563 std::vector<const SwFrameFormat*> checkFormats;
1564 for( auto pFormat : *GetSpzFrameFormats() )
1565 {
1566 const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx();
1567 if( pIdx && pFlyNd == &pIdx->GetNode() )
1568 checkFormats.push_back( pFormat );
1569 }
1570#endif
1571 std::vector<SwFrameFormat*> const*const pFlys(pFlyNd->GetAnchoredFlys());
1572 bool bFound(false);
1573 for (size_t i = 0; pFlys && i < pFlys->size(); ++i)
1574 {
1575 const SwFrameFormat *const pFormat = (*pFlys)[i];
1576 const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx();
1577 if( pIdx && pFlyNd == &pIdx->GetNode() )
1578 {
1579#if OSL_DEBUG_LEVEL1 > 0
1580 auto checkPos = std::find(
1581 checkFormats.begin(), checkFormats.end(), pFormat );
1582 assert( checkPos != checkFormats.end())(static_cast <bool> (checkPos != checkFormats.end()) ? void
(0) : __assert_fail ("checkPos != checkFormats.end()", "/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
, 1582, __extension__ __PRETTY_FUNCTION__))
;
1583 checkFormats.erase( checkPos );
1584#endif
1585 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1586 if ((RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId()) ||
1587 !rAnchor.GetContentAnchor() )
1588 {
1589 return false;
1590 }
1591
1592 pNd = &rAnchor.GetContentAnchor()->nNode.GetNode();
1593 pFlyNd = pNd->FindFlyStartNode();
1594 bFound = true;
1595 break;
1596 }
1597 }
1598 if (!bFound)
1599 {
1600 OSL_ENSURE(mbInReading, "Found a FlySection but not a Format!")do { if (true && (!(mbInReading))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/doc/doclay.cxx"
":" "1600" ": "), "%s", "Found a FlySection but not a Format!"
); } } while (false)
;
1601 return false;
1602 }
1603 }
1604
1605 return nullptr != pNd->FindHeaderStartNode() ||
1606 nullptr != pNd->FindFooterStartNode();
1607}
1608
1609SvxFrameDirection SwDoc::GetTextDirection( const SwPosition& rPos,
1610 const Point* pPt ) const
1611{
1612 SvxFrameDirection nRet = SvxFrameDirection::Unknown;
1613
1614 SwContentNode *pNd = rPos.nNode.GetNode().GetContentNode();
1615
1616 // #i42921# - use new method <SwContentNode::GetTextDirection(..)>
1617 if ( pNd )
1618 {
1619 nRet = pNd->GetTextDirection( rPos, pPt );
1620 }
1621 if ( nRet == SvxFrameDirection::Unknown )
1622 {
1623 const SvxFrameDirectionItem* pItem = nullptr;
1624 if( pNd )
1625 {
1626 // Are we in a FlyFrame? Then look at that for the correct attribute
1627 const SwFrameFormat* pFlyFormat = pNd->GetFlyFormat();
1628 while( pFlyFormat )
1629 {
1630 pItem = &pFlyFormat->GetFrameDir();
1631 if( SvxFrameDirection::Environment == pItem->GetValue() )
1632 {
1633 pItem = nullptr;
1634 const SwFormatAnchor* pAnchor = &pFlyFormat->GetAnchor();
1635 if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
1636 pAnchor->GetContentAnchor())
1637 {
1638 pFlyFormat = pAnchor->GetContentAnchor()->nNode.
1639 GetNode().GetFlyFormat();
1640 }
1641 else
1642 pFlyFormat = nullptr;
1643 }
1644 else
1645 pFlyFormat = nullptr;
1646 }
1647
1648 if( !pItem )
1649 {
1650 const SwPageDesc* pPgDsc = pNd->FindPageDesc();
1651 if( pPgDsc )
1652 pItem = &pPgDsc->GetMaster().GetFrameDir();
1653 }
1654 }
1655 if( !pItem )
1656 pItem = &GetAttrPool().GetDefaultItem( RES_FRAMEDIR );
1657 nRet = pItem->GetValue();
1658 }
1659 return nRet;
1660}
1661
1662bool SwDoc::IsInVerticalText( const SwPosition& rPos ) const
1663{
1664 const SvxFrameDirection nDir = GetTextDirection( rPos );
1665 return SvxFrameDirection::Vertical_RL_TB == nDir || SvxFrameDirection::Vertical_LR_TB == nDir;
1666}
1667
1668o3tl::sorted_vector<SwRootFrame*> SwDoc::GetAllLayouts()
1669{
1670 o3tl::sorted_vector<SwRootFrame*> aAllLayouts;
1671 SwViewShell *pStart = getIDocumentLayoutAccess().GetCurrentViewShell();
1672 if(pStart)
1673 {
1674 for(const SwViewShell& rShell : pStart->GetRingContainer())
1675 {
1676 if(rShell.GetLayout())
1677 aAllLayouts.insert(rShell.GetLayout());
1678 }
1679 }
1680 return aAllLayouts;
1681}
1682
1683/* vim:set shiftwidth=4 softtabstop=4 expandtab: */