Bug Summary

File:home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx
Warning:line 741, column 57
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 drawdoc3.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 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -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 SD_DLLIMPLEMENTATION -D SDUI_DLL_NAME="libsduilo.so" -D SYSTEM_LIBXML -D ENABLE_SDREMOTE -D ENABLE_SDREMOTE_BLUETOOTH -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/external/bluez_bluetooth/inc -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/sd/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/slidesorter/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sd/sdi -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -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/sd/source/core/drawdoc3.cxx

/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.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
21#include <memory>
22
23#include <sfx2/docfile.hxx>
24#include <sfx2/docfilt.hxx>
25#include <sfx2/app.hxx>
26#include <svl/itemset.hxx>
27#include <tools/debug.hxx>
28
29#include <sfx2/fcontnr.hxx>
30#include <svl/style.hxx>
31#include <svx/svdpagv.hxx>
32#include <svx/svdundo.hxx>
33#include <vcl/stdtext.hxx>
34#include <vcl/svapp.hxx>
35#include <vcl/weld.hxx>
36#include <xmloff/autolayout.hxx>
37
38#include <strings.hrc>
39#include <drawdoc.hxx>
40#include <sdmod.hxx>
41#include <sdpage.hxx>
42#include <stlpool.hxx>
43#include <sdresid.hxx>
44#include <customshowlist.hxx>
45#include <sdxfer.hxx>
46
47#include <unmovss.hxx>
48#include <unchss.hxx>
49#include <unprlout.hxx>
50#include <DrawDocShell.hxx>
51#include <GraphicDocShell.hxx>
52#include <ViewShell.hxx>
53#include <View.hxx>
54#include <ViewShellBase.hxx>
55#include <strings.hxx>
56
57using namespace ::com::sun::star;
58
59/** Concrete incarnations get called by lcl_IterateBookmarkPages, for
60 every page in the bookmark document/list
61 */
62
63namespace {
64
65class InsertBookmarkAsPage_FindDuplicateLayouts
66{
67public:
68 explicit InsertBookmarkAsPage_FindDuplicateLayouts( std::vector<OUString> &rLayoutsToTransfer )
69 : mrLayoutsToTransfer(rLayoutsToTransfer) {}
70 void operator()( SdDrawDocument&, SdPage const *, bool, SdDrawDocument* );
71private:
72 std::vector<OUString> &mrLayoutsToTransfer;
73};
74
75}
76
77void InsertBookmarkAsPage_FindDuplicateLayouts::operator()( SdDrawDocument& rDoc, SdPage const * pBMMPage, bool bRenameDuplicates, SdDrawDocument* pBookmarkDoc )
78{
79 // now check for duplicate masterpage and layout names
80
81 OUString aLayout( pBMMPage->GetLayoutName() );
82 sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR"~LT~" );
83 if( nIndex != -1 )
84 aLayout = aLayout.copy(0, nIndex);
85
86 std::vector<OUString>::const_iterator pIter =
87 find(mrLayoutsToTransfer.begin(),mrLayoutsToTransfer.end(),aLayout);
88
89 bool bFound = pIter != mrLayoutsToTransfer.end();
90
91 const sal_uInt16 nMPageCount = rDoc.GetMasterPageCount();
92 for (sal_uInt16 nMPage = 0; nMPage < nMPageCount && !bFound; nMPage++)
93 {
94 // Do the layouts already exist within the document?
95 SdPage* pTestPage = static_cast<SdPage*>( rDoc.GetMasterPage(nMPage) );
96 OUString aTest(pTestPage->GetLayoutName());
97 sal_Int32 nIndex2 = aTest.indexOf( SD_LT_SEPARATOR"~LT~" );
98 if( nIndex2 != -1 )
99 aTest = aTest.copy(0, nIndex2);
100
101 if (aTest == aLayout && pBMMPage->GetPageKind() == pTestPage->GetPageKind())
102 {
103 // Ignore Layouts with "Default" these seem to be special - in the sense that there are lot of assumption all over Impress
104 // about this
105 if( bRenameDuplicates && aTest != SdResId( STR_LAYOUT_DEFAULT_NAMEreinterpret_cast<char const *>("STR_LAYOUT_DEFAULT_NAME"
"\004" u8"Default")
) && !(pTestPage->Equals(*pBMMPage)) )
106 {
107 pBookmarkDoc->RenameLayoutTemplate(
108 pBMMPage->GetLayoutName(), pBMMPage->GetName() + "_");
109 aLayout = pBMMPage->GetName();
110
111 break;
112 }
113 else
114 bFound = true;
115 }
116 }
117
118 if (!bFound)
119 mrLayoutsToTransfer.push_back(aLayout);
120}
121
122// Inserts a bookmark as a page
123static void lcl_IterateBookmarkPages( SdDrawDocument &rDoc, SdDrawDocument* pBookmarkDoc,
124 const std::vector<OUString> &rBookmarkList, sal_uInt16 nBMSdPageCount,
125 InsertBookmarkAsPage_FindDuplicateLayouts& rPageIterator, bool bRenameDuplicates )
126{
127
128 // Refactored copy'n'pasted layout name collection from InsertBookmarkAsPage
129
130 int nPos, nEndPos;
131
132 if( rBookmarkList.empty() )
133 {
134 // no list? whole source document
135 nEndPos = nBMSdPageCount;
136 }
137 else
138 {
139 // bookmark list? number of entries
140 nEndPos = rBookmarkList.size();
141 }
142
143 SdPage* pBMPage;
144
145 // iterate over number of pages to insert
146 for (nPos = 0; nPos < nEndPos; ++nPos)
147 {
148 // the master page associated to the nPos'th page to insert
149 SdPage* pBMMPage = nullptr;
150
151 if( rBookmarkList.empty() )
152 {
153 // simply take master page of nPos'th page in source document
154 pBMMPage = static_cast<SdPage*>(&(pBookmarkDoc->GetSdPage(static_cast<sal_uInt16>(nPos), PageKind::Standard)->TRG_GetMasterPage()));
155 }
156 else
157 {
158 // fetch nPos'th entry from bookmark list, and determine master page
159 OUString aBMPgName(rBookmarkList[nPos]);
160 bool bIsMasterPage;
161
162 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage );
163
164 if (nBMPage != SDRPAGE_NOTFOUND0xFFFF)
165 {
166 pBMPage = static_cast<SdPage*>( pBookmarkDoc->GetPage(nBMPage) );
167 }
168 else
169 {
170 pBMPage = nullptr;
171 }
172
173 // enforce that bookmarked page is a standard page and not already a master page
174 if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
175 {
176 const sal_uInt16 nBMSdPage = (nBMPage - 1) / 2;
177 pBMMPage = static_cast<SdPage*> (&(pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard)->TRG_GetMasterPage()));
178 }
179 }
180
181 // successfully determined valid (bookmarked) page?
182 if( pBMMPage )
183 {
184 // yes, call functor
185 rPageIterator( rDoc, pBMMPage, bRenameDuplicates, pBookmarkDoc );
186 }
187 }
188}
189
190// Opens a bookmark document
191SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(SfxMedium* pMedium)
192{
193 bool bOK = true;
194 SdDrawDocument* pBookmarkDoc = nullptr;
195 OUString aBookmarkName = pMedium->GetName();
196 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
197 if ( !pFilter )
198 {
199 pMedium->UseInteractionHandler( true );
200 SfxGetpApp()->GetFilterMatcher().GuessFilter(*pMedium, pFilter);
201 }
202
203 if ( !pFilter )
204 {
205 bOK = false;
206 }
207 else if ( !aBookmarkName.isEmpty() && maBookmarkFile != aBookmarkName )
208 {
209 bool bCreateGraphicShell = pFilter->GetServiceName() == "com.sun.star.drawing.DrawingDocument";
210 bool bCreateImpressShell = pFilter->GetServiceName() == "com.sun.star.presentation.PresentationDocument";
211 if ( bCreateGraphicShell || bCreateImpressShell )
212 {
213 CloseBookmarkDoc();
214
215 // Create a DocShell, as OLE objects might be contained in the
216 // document. (Persist)
217 // If that wasn't the case, we could load the model directly.
218 if ( bCreateGraphicShell )
219 // Draw
220 mxBookmarkDocShRef = new ::sd::GraphicDocShell(SfxObjectCreateMode::STANDARD);
221 else
222 // Impress
223 mxBookmarkDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Impress);
224
225 bOK = mxBookmarkDocShRef->DoLoad(pMedium);
226 if( bOK )
227 {
228 maBookmarkFile = aBookmarkName;
229 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
230 }
231 }
232 }
233
234 DBG_ASSERT(!aBookmarkName.isEmpty(), "Empty document name!")do { if (true && (!(!aBookmarkName.isEmpty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "234" ": "), "%s", "Empty document name!"); } } while (false
)
;
235
236 if (!bOK)
237 {
238 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
239 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERRORreinterpret_cast<char const *>("STR_READ_DATA_ERROR" "\004"
u8"The file could not be loaded!")
)));
240 xErrorBox->run();
241
242 CloseBookmarkDoc();
243 pBookmarkDoc = nullptr;
244 }
245 else if (mxBookmarkDocShRef.is())
246 {
247 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
248 }
249
250 return pBookmarkDoc;
251}
252
253// Opens a bookmark document
254SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(const OUString& rBookmarkFile)
255{
256 SdDrawDocument* pBookmarkDoc = nullptr;
257
258 if (!rBookmarkFile.isEmpty() && maBookmarkFile != rBookmarkFile)
259 {
260 std::unique_ptr<SfxMedium> xMedium(new SfxMedium(rBookmarkFile, StreamMode::READ));
261 pBookmarkDoc = OpenBookmarkDoc(xMedium.release());
262 }
263 else if (mxBookmarkDocShRef.is())
264 {
265 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
266 }
267
268 return pBookmarkDoc;
269}
270
271// Inserts a bookmark (page or object)
272void SdDrawDocument::InsertBookmark(
273 const std::vector<OUString> &rBookmarkList, // List of names of the bookmarks to be inserted
274 std::vector<OUString> &rExchangeList, // List of the names to be used
275 bool bLink, // Insert bookmarks as links?
276 sal_uInt16 nInsertPos, // Insertion position of pages
277 ::sd::DrawDocShell* pBookmarkDocSh, // If set, this is the source document
278 Point const * pObjPos) // Insertion position of objects
279{
280 bool bOK = true;
281 bool bInsertPages = false;
282
283 if (rBookmarkList.empty())
284 {
285 // Insert all pages
286 bInsertPages = true;
287 }
288 else
289 {
290 SdDrawDocument* pBookmarkDoc = nullptr;
291
292 if (pBookmarkDocSh)
293 {
294 pBookmarkDoc = pBookmarkDocSh->GetDoc();
295 }
296 else if ( mxBookmarkDocShRef.is() )
297 {
298 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
299 }
300 else
301 bOK = false;
302
303 bInsertPages = bOK && std::any_of(rBookmarkList.begin(), rBookmarkList.end(),
304 [&pBookmarkDoc](const OUString& rBookmark) {
305 // Is there a page name in the bookmark list?
306 bool bIsMasterPage;
307 return pBookmarkDoc->GetPageByName(rBookmark, bIsMasterPage) != SDRPAGE_NOTFOUND0xFFFF;
308 });
309 }
310
311 bool bCalcObjCount = !rExchangeList.empty();
312
313 if ( bOK && bInsertPages )
314 {
315 // Insert all page bookmarks
316 bOK = InsertBookmarkAsPage(rBookmarkList, &rExchangeList, bLink, false/*bReplace*/,
317 nInsertPos, false/*bNoDialogs*/, pBookmarkDocSh, true/*bCopy*/, true, false);
318 }
319
320 if ( bOK && !rBookmarkList.empty() )
321 {
322 // Insert all object bookmarks
323 InsertBookmarkAsObject(rBookmarkList, rExchangeList,
324 pBookmarkDocSh, pObjPos, bCalcObjCount);
325 }
326}
327
328namespace
329{
330
331void
332lcl_removeUnusedStyles(SfxStyleSheetBasePool* const pStyleSheetPool, StyleSheetCopyResultVector& rStyles)
333{
334 StyleSheetCopyResultVector aUsedStyles;
335 aUsedStyles.reserve(rStyles.size());
336 for (const auto& a : rStyles)
337 {
338 if (a.m_xStyleSheet->IsUsed())
339 aUsedStyles.push_back(a);
340 else
341 pStyleSheetPool->Remove(a.m_xStyleSheet.get());
342 }
343 rStyles = aUsedStyles;
344}
345
346SfxStyleSheet *lcl_findStyle(StyleSheetCopyResultVector& rStyles, const OUString& aStyleName)
347{
348 for (const auto& a : rStyles)
349 {
350 if (a.m_xStyleSheet->GetName().startsWith(aStyleName))
351 return a.m_xStyleSheet.get();
352 }
353 return nullptr;
354}
355
356}
357
358bool SdDrawDocument::InsertBookmarkAsPage(
359 const std::vector<OUString> &rBookmarkList,
360 std::vector<OUString> *pExchangeList, // List of names to be used
361 bool bLink,
362 bool bReplace,
363 sal_uInt16 nInsertPos,
364 bool bNoDialogs,
365 ::sd::DrawDocShell* pBookmarkDocSh,
366 bool bCopy,
367 bool bMergeMasterPages,
368 bool bPreservePageNames)
369{
370 bool bContinue = true;
371 bool bScaleObjects = false;
372 sal_uInt16 nReplacedStandardPages = 0;
373
374 SdDrawDocument* pBookmarkDoc = nullptr;
375 OUString aBookmarkName;
376
377 if (pBookmarkDocSh)
1
Assuming 'pBookmarkDocSh' is null
2
Taking false branch
378 {
379 pBookmarkDoc = pBookmarkDocSh->GetDoc();
380
381 if (pBookmarkDocSh->GetMedium())
382 {
383 aBookmarkName = pBookmarkDocSh->GetMedium()->GetName();
384 }
385 }
386 else if ( mxBookmarkDocShRef.is() )
3
Calling 'SvRef::is'
6
Returning from 'SvRef::is'
7
Taking true branch
387 {
388 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
389 aBookmarkName = maBookmarkFile;
390 }
391 else
392 {
393 return false;
394 }
395
396 const sal_uInt16 nSdPageCount = GetSdPageCount(PageKind::Standard);
397 const sal_uInt16 nBMSdPageCount = pBookmarkDoc->GetSdPageCount(PageKind::Standard);
398 const sal_uInt16 nMPageCount = GetMasterPageCount();
399
400 if (nSdPageCount==0 || nBMSdPageCount==0 || nMPageCount==0)
8
Assuming 'nSdPageCount' is not equal to 0
9
Assuming 'nBMSdPageCount' is not equal to 0
10
Assuming 'nMPageCount' is not equal to 0
11
Taking false branch
401 {
402 return false;
403 }
404
405 // Store the size and some other properties of the first page and notes
406 // page so that inserted pages can be properly scaled even when inserted
407 // before the first page.
408 // Note that the pointers are used later on as general page pointers.
409 SdPage* pRefPage = GetSdPage(0, PageKind::Standard);
410 Size aSize(pRefPage->GetSize());
411 sal_Int32 nLeft = pRefPage->GetLeftBorder();
412 sal_Int32 nRight = pRefPage->GetRightBorder();
413 sal_Int32 nUpper = pRefPage->GetUpperBorder();
414 sal_Int32 nLower = pRefPage->GetLowerBorder();
415 Orientation eOrient = pRefPage->GetOrientation();
416
417 SdPage* pNPage = GetSdPage(0, PageKind::Notes);
418 Size aNSize(pNPage->GetSize());
419 sal_Int32 nNLeft = pNPage->GetLeftBorder();
420 sal_Int32 nNRight = pNPage->GetRightBorder();
421 sal_Int32 nNUpper = pNPage->GetUpperBorder();
422 sal_Int32 nNLower = pNPage->GetLowerBorder();
423 Orientation eNOrient = pNPage->GetOrientation();
424
425 // Adapt page size and margins to those of the later pages?
426 pRefPage = GetSdPage(nSdPageCount - 1, PageKind::Standard);
427
428 if( bNoDialogs )
12
Assuming 'bNoDialogs' is false
13
Taking false branch
429 {
430 // If this is clipboard, then no need to scale objects:
431 // this will make copied masters to differ from the originals,
432 // and thus InsertBookmarkAsPage_FindDuplicateLayouts will
433 // duplicate masters on insert to same document
434 m_bTransportContainer = (SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule
::Draw)) )
->pTransferClip &&
435 SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule
::Draw)) )
->pTransferClip->GetWorkDocument() == this);
436 if (!m_bTransportContainer)
437 {
438 if (rBookmarkList.empty())
439 bScaleObjects = pRefPage->IsScaleObjects();
440 else
441 bScaleObjects = true;
442 }
443 }
444 else
445 {
446 SdPage* pBMPage = pBookmarkDoc->GetSdPage(0,PageKind::Standard);
447
448 if (pBMPage->GetSize() != pRefPage->GetSize() ||
14
Taking true branch
449 pBMPage->GetLeftBorder() != pRefPage->GetLeftBorder() ||
450 pBMPage->GetRightBorder() != pRefPage->GetRightBorder() ||
451 pBMPage->GetUpperBorder() != pRefPage->GetUpperBorder() ||
452 pBMPage->GetLowerBorder() != pRefPage->GetLowerBorder())
453 {
454 OUString aStr(SdResId(STR_SCALE_OBJECTSreinterpret_cast<char const *>("STR_SCALE_OBJECTS" "\004"
u8"The page size of the target document is different than the source document.\n\nDo you want to scale the copied objects to fit the new page size?"
)
));
455 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
456 VclMessageType::Question, VclButtonsType::YesNo,
457 aStr));
458 xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
459 sal_uInt16 nBut = xQueryBox->run();
460
461 bScaleObjects = nBut == RET_YES;
15
Assuming 'nBut' is not equal to RET_YES
462 bContinue = nBut != RET_CANCEL;
16
Assuming 'nBut' is not equal to RET_CANCEL
463
464 if (!bContinue
16.1
'bContinue' is true
16.1
'bContinue' is true
)
17
Taking false branch
465 {
466 return bContinue;
467 }
468 }
469 }
470
471 // Get the necessary presentation stylesheets and transfer them before
472 // the pages, else, the text objects won't reference their styles anymore.
473 SfxUndoManager* pUndoMgr = nullptr;
474 if( mpDocSh )
18
Assuming field 'mpDocSh' is null
19
Taking false branch
475 {
476 pUndoMgr = mpDocSh->GetUndoManager();
477 ViewShellId nViewShellId(-1);
478 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
479 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
480 pUndoMgr->EnterListAction(SdResId(STR_UNDO_INSERTPAGESreinterpret_cast<char const *>("STR_UNDO_INSERTPAGES" "\004"
u8"Insert slides")
), "", 0, nViewShellId);
481 }
482
483 // Refactored copy'n'pasted layout name collection into IterateBookmarkPages
484
485 std::vector<OUString> aLayoutsToTransfer;
486 InsertBookmarkAsPage_FindDuplicateLayouts aSearchFunctor( aLayoutsToTransfer );
487 lcl_IterateBookmarkPages( *this, pBookmarkDoc, rBookmarkList, nBMSdPageCount, aSearchFunctor, ( rBookmarkList.empty() && pBookmarkDoc != this ) );
20
Assuming the condition is false
488
489 // Copy the style that we actually need.
490 SdStyleSheetPool& rBookmarkStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*pBookmarkDoc->GetStyleSheetPool());
491 SdStyleSheetPool& rStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*GetStyleSheetPool());
492
493 // When copying styles, also copy the master pages!
494 if( !aLayoutsToTransfer.empty() )
21
Assuming the condition is false
22
Taking false branch
495 bMergeMasterPages = true;
496
497 for ( const OUString& layoutName : aLayoutsToTransfer )
498 {
499 StyleSheetCopyResultVector aCreatedStyles;
500
501 rStyleSheetPool.CopyLayoutSheets(layoutName, rBookmarkStyleSheetPool,aCreatedStyles);
502
503 if(!aCreatedStyles.empty())
504 {
505 if( pUndoMgr )
506 {
507 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aCreatedStyles, true));
508 }
509 }
510 }
511
512 // Copy styles. This unconditionally copies all styles, even those
513 // that are not used in any of the inserted pages. The unused styles
514 // are then removed at the end of the function, where we also create
515 // undo records for the inserted styles.
516 StyleSheetCopyResultVector aNewGraphicStyles;
517 OUString aRenameStr;
518 if(!bReplace && !bNoDialogs)
23
Assuming 'bReplace' is true
519 aRenameStr = "_";
520 rStyleSheetPool.RenameAndCopyGraphicSheets(rBookmarkStyleSheetPool, aNewGraphicStyles, aRenameStr);
521 StyleSheetCopyResultVector aNewCellStyles;
522 rStyleSheetPool.CopyCellSheets(rBookmarkStyleSheetPool, aNewCellStyles);
523
524 // TODO handle undo of table styles too
525 rStyleSheetPool.CopyTableStyles(rBookmarkStyleSheetPool);
526
527 // Insert document
528
529 const bool bUndo = IsUndoEnabled();
530
531 if( bUndo )
24
Assuming 'bUndo' is false
25
Taking false branch
532 BegUndo(SdResId(STR_UNDO_INSERTPAGESreinterpret_cast<char const *>("STR_UNDO_INSERTPAGES" "\004"
u8"Insert slides")
));
533
534 if (rBookmarkList.empty())
26
Assuming the condition is false
27
Taking false branch
535 {
536 if (nInsertPos >= GetPageCount())
537 {
538 // Add pages to the end
539 nInsertPos = GetPageCount();
540 }
541
542 sal_uInt16 nActualInsertPos = nInsertPos;
543
544 sal_uInt16 nBMSdPage;
545 std::set<sal_uInt16> aRenameSet;
546 std::map<sal_uInt16,OUString> aNameMap;
547
548 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
549 {
550 SdPage* pBMPage = pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard);
551 OUString sName(pBMPage->GetName());
552 bool bIsMasterPage;
553
554 if (bLink)
555 {
556 // Remember the names of all pages
557 aNameMap.insert(std::make_pair(nBMSdPage,sName));
558 }
559
560 // Have to check for duplicate names here, too
561 // don't change name if source and dest model are the same!
562 if( pBookmarkDoc != this &&
563 GetPageByName(sName, bIsMasterPage ) != SDRPAGE_NOTFOUND0xFFFF )
564 {
565 // delay renaming *after* pages are copied (might destroy source otherwise)
566 aRenameSet.insert(nBMSdPage);
567 }
568 }
569
570 Merge(*pBookmarkDoc,
571 1, // Not the handout page
572 0xFFFF, // But all others
573 nActualInsertPos, // Insert at position ...
574 bMergeMasterPages, // Move master pages?
575 false, // But only the master pages used
576 true, // Create an undo action
577 bCopy); // Copy (or merge) pages?
578
579 for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++)
580 {
581 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
582 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
583
584 // delay renaming *after* pages are copied (might destroy source otherwise)
585 if( aRenameSet.find(nBMSdPage) != aRenameSet.end() )
586 {
587 // Page name already in use -> Use default name for default and
588 // notes page
589 pPage->SetName(OUString());
590 pNotesPage->SetName(OUString());
591 }
592
593 if (bLink)
594 {
595 OUString aName(aNameMap[nBMSdPage]);
596
597 // Assemble all link names
598 pPage->SetFileName(aBookmarkName);
599 pPage->SetBookmarkName(aName);
600 }
601
602 nActualInsertPos += 2;
603 }
604 }
605 else
606 {
607 // Insert selected pages
608 SdPage* pBMPage;
609
610 if (nInsertPos >= GetPageCount())
28
Assuming the condition is false
29
Taking false branch
611 {
612 // Add pages to the end
613 bReplace = false;
614 nInsertPos = GetPageCount();
615 }
616
617 sal_uInt16 nActualInsertPos = nInsertPos;
618
619 // Collect the bookmarked pages
620 ::std::vector<SdPage*> aBookmarkedPages (rBookmarkList.size(), nullptr);
621 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
30
Assuming 'nPos' is >= 'n'
31
Loop condition is false. Execution continues on line 633
622 {
623 OUString aPgName(rBookmarkList[nPos]);
624 bool bIsMasterPage;
625 sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aPgName, bIsMasterPage );
626
627 if (nBMPage != SDRPAGE_NOTFOUND0xFFFF)
628 {
629 aBookmarkedPages[nPos] = dynamic_cast<SdPage*>(pBookmarkDoc->GetPage(nBMPage));
630 }
631 }
632
633 for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos)
32
Assuming 'nPos' is < 'n'
33
Loop condition is true. Entering loop body
634 {
635 pBMPage = aBookmarkedPages[nPos];
636 sal_uInt16 nBMPage = pBMPage!=nullptr ? pBMPage->GetPageNum() : SDRPAGE_NOTFOUND0xFFFF;
34
Assuming the condition is true
35
'?' condition is true
637
638 if (pBMPage
35.1
'pBMPage' is non-null
35.1
'pBMPage' is non-null
&& pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage())
36
Assuming the condition is true
37
Assuming the condition is true
38
Taking true branch
639 {
640 // It has to be a default page
641 bool bMustRename = false;
642
643 // delay renaming *after* pages are copied (might destroy source otherwise)
644 // don't change name if source and dest model are the same!
645 // avoid renaming if replacing the same page
646 OUString aPgName(rBookmarkList[nPos]);
647 bool bIsMasterPage;
648 sal_uInt16 nPageSameName = GetPageByName(aPgName, bIsMasterPage);
649 if( pBookmarkDoc != this &&
39
Assuming the condition is false
650 nPageSameName != SDRPAGE_NOTFOUND0xFFFF &&
651 ( !bReplace ||
652 nPageSameName != nActualInsertPos ) )
653 {
654 bMustRename = true;
655 }
656
657 SdPage* pBookmarkPage = pBMPage;
658 if (bReplace
39.1
'bReplace' is true
39.1
'bReplace' is true
)
40
Taking true branch
659 {
660 ReplacePageInCustomShows( dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ), pBookmarkPage );
661 }
662
663 Merge(*pBookmarkDoc,
664 nBMPage, // From page (default page)
665 nBMPage+1, // To page (notes page)
666 nActualInsertPos, // Insert at position
667 bMergeMasterPages, // Move master pages?
668 false, // But only the master pages used
669 true, // Create undo action
670 bCopy); // Copy (or merge) pages?
671
672 if( bReplace
40.1
'bReplace' is true
40.1
'bReplace' is true
)
41
Taking true branch
673 {
674 if( GetPage( nActualInsertPos ) != pBookmarkPage )
42
Assuming the condition is false
43
Taking false branch
675 {
676 // bookmark page was not moved but cloned, so update custom shows again
677 ReplacePageInCustomShows( pBookmarkPage, dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ) );
678 }
679 }
680
681 if( bMustRename
43.1
'bMustRename' is false
43.1
'bMustRename' is false
)
44
Taking false branch
682 {
683 // Page name already in use -> use default name for default and
684 // notes page
685 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
686 pPage->SetName(OUString());
687 SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) );
688 pNotesPage->SetName(OUString());
689 }
690
691 if (bLink)
45
Assuming 'bLink' is false
46
Taking false branch
692 {
693 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
694 pPage->SetFileName(aBookmarkName);
695 pPage->SetBookmarkName(aPgName);
696 }
697
698 if (bReplace
46.1
'bReplace' is true
46.1
'bReplace' is true
)
47
Taking true branch
699 {
700 // Remove page and notes page.
701 const sal_uInt16 nDestPageNum(nActualInsertPos + 2);
702 SdPage* pStandardPage = nullptr;
48
'pStandardPage' initialized to a null pointer value
703
704 if(nDestPageNum < GetPageCount())
49
Assuming the condition is false
50
Taking false branch
705 {
706 pStandardPage = static_cast<SdPage*>(GetPage(nDestPageNum));
707 }
708
709 if (pStandardPage
50.1
'pStandardPage' is null
50.1
'pStandardPage' is null
)
51
Taking false branch
710 {
711 if( bPreservePageNames )
712 {
713 // Take old slide names for inserted pages
714 SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) );
715 pPage->SetName( pStandardPage->GetRealName() );
716 }
717
718 if( bUndo )
719 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage));
720
721 RemovePage(nDestPageNum);
722
723 if( !bUndo )
724 delete pStandardPage;
725 }
726
727 SdPage* pNotesPage = nullptr;
728
729 if(nDestPageNum < GetPageCount())
52
Assuming the condition is true
53
Taking true branch
730 {
731 pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum));
732 }
733
734 if (pNotesPage)
54
Assuming 'pNotesPage' is non-null
55
Taking true branch
735 {
736 if( bPreservePageNames )
56
Assuming 'bPreservePageNames' is true
57
Taking true branch
737 {
738 // Take old slide names for inserted pages
739 SdPage* pNewNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1));
740 if( pNewNotesPage )
58
Assuming 'pNewNotesPage' is non-null
59
Taking true branch
741 pNewNotesPage->SetName( pStandardPage->GetRealName() );
60
Called C++ object pointer is null
742 }
743
744 if( bUndo )
745 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage));
746
747 RemovePage(nDestPageNum);
748
749 if( !bUndo )
750 delete pNotesPage;
751 }
752
753 nReplacedStandardPages++;
754 }
755
756 nActualInsertPos += 2;
757 }
758 }
759 }
760
761 // We might have duplicate master pages now, as the drawing engine does not
762 // recognize duplicates. Remove these now.
763 sal_uInt16 nNewMPageCount = GetMasterPageCount();
764
765 // Go backwards, so the numbers don't become messed up
766 for (sal_uInt16 nPage = nNewMPageCount - 1; nPage >= nMPageCount; nPage--)
767 {
768 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
769 OUString aMPLayout(pRefPage->GetLayoutName());
770 PageKind eKind = pRefPage->GetPageKind();
771
772 // Does this already exist?
773 for (sal_uInt16 nTest = 0; nTest < nMPageCount; nTest++)
774 {
775 SdPage* pTest = static_cast<SdPage*>( GetMasterPage(nTest) );
776 OUString aTest(pTest->GetLayoutName());
777
778 // nInsertPos > 2 is always true when inserting into non-empty models
779 if ( nInsertPos > 2 &&
780 aTest == aMPLayout &&
781 eKind == pTest->GetPageKind() )
782 {
783 if( bUndo )
784 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage));
785
786 RemoveMasterPage(nPage);
787
788 if( !bUndo )
789 delete pRefPage;
790 nNewMPageCount--;
791 break;
792 }
793 }
794 }
795
796 // nInsertPos > 2 is always true when inserting into non-empty models
797 if (nInsertPos > 0)
798 {
799 sal_uInt16 nSdPageStart = (nInsertPos - 1) / 2;
800 sal_uInt16 nSdPageEnd = bReplace
801 ? nSdPageStart + nReplacedStandardPages - 1
802 : GetSdPageCount(PageKind::Standard) - nSdPageCount + nSdPageStart - 1;
803 const bool bRemoveEmptyPresObj =
804 (pBookmarkDoc->GetDocumentType() == DocumentType::Impress) &&
805 (GetDocumentType() == DocumentType::Draw);
806
807 std::vector<OUString>::iterator pExchangeIter;
808
809 if (pExchangeList)
810 pExchangeIter = pExchangeList->begin();
811
812 for (sal_uInt16 nSdPage = nSdPageStart; nSdPage <= nSdPageEnd; nSdPage++)
813 {
814 pRefPage = GetSdPage(nSdPage, PageKind::Standard);
815
816 if (pExchangeList && pExchangeIter != pExchangeList->end())
817 {
818 // Get the name to use from Exchange list
819 OUString aExchangeName(*pExchangeIter);
820 pRefPage->SetName(aExchangeName);
821 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pRefPage));
822
823 SdPage* pNewNotesPage = GetSdPage(nSdPage, PageKind::Notes);
824 pNewNotesPage->SetName(aExchangeName);
825 Broadcast(SdrHint(SdrHintKind::PageOrderChange, pNewNotesPage));
826
827 ++pExchangeIter;
828 }
829
830 OUString aLayout(pRefPage->GetLayoutName());
831 sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR"~LT~" );
832 if( nIndex != -1 )
833 aLayout = aLayout.copy(0, nIndex);
834
835 // update layout and referred master page
836 pRefPage->SetPresentationLayout(aLayout);
837 if( bUndo )
838 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
839
840 if (bScaleObjects)
841 {
842 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
843 pRefPage->ScaleObjects(aSize, aBorderRect, true);
844 }
845 pRefPage->SetSize(aSize);
846 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
847 pRefPage->SetOrientation( eOrient );
848
849 if( bRemoveEmptyPresObj )
850 pRefPage->RemoveEmptyPresentationObjects();
851
852 pRefPage = GetSdPage(nSdPage, PageKind::Notes);
853
854 // update layout and referred master page
855 pRefPage->SetPresentationLayout(aLayout);
856 if( bUndo )
857 AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) );
858
859 if (bScaleObjects)
860 {
861 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
862 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
863 }
864
865 pRefPage->SetSize(aNSize);
866 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
867 pRefPage->SetOrientation( eNOrient );
868
869 if( bRemoveEmptyPresObj )
870 pRefPage->RemoveEmptyPresentationObjects();
871 }
872
873 ///Remove processed elements, to avoid doing hacks in InsertBookmarkAsObject
874 if ( pExchangeList )
875 pExchangeList->erase(pExchangeList->begin(),pExchangeIter);
876
877 for (sal_uInt16 nPage = nMPageCount; nPage < nNewMPageCount; nPage++)
878 {
879 pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) );
880 if (pRefPage->GetPageKind() == PageKind::Standard)
881 {
882 if (bScaleObjects)
883 {
884 ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower);
885 pRefPage->ScaleObjects(aSize, aBorderRect, true);
886 }
887 pRefPage->SetSize(aSize);
888 pRefPage->SetBorder(nLeft, nUpper, nRight, nLower);
889 pRefPage->SetOrientation( eOrient );
890 }
891 else // Can only be notes
892 {
893 if (bScaleObjects)
894 {
895 ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower);
896 pRefPage->ScaleObjects(aNSize, aBorderRect, true);
897 }
898 pRefPage->SetSize(aNSize);
899 pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower);
900 pRefPage->SetOrientation( eNOrient );
901 }
902
903 if( bRemoveEmptyPresObj )
904 pRefPage->RemoveEmptyPresentationObjects();
905 }
906 }
907
908 // Make absolutely sure no double masterpages are there
909 RemoveUnnecessaryMasterPages(nullptr, true);
910
911 // Rename object styles if necessary
912 if(!aRenameStr.isEmpty())
913 {
914 try
915 {
916 for(sal_uInt32 p = nInsertPos; p < sal_uInt32(nInsertPos) + sal_uInt32(nBMSdPageCount); p++)
917 {
918 SdPage *pPg = static_cast<SdPage *>( GetPage(p) );
919 for(size_t i = 0; pPg && (i < pPg->GetObjCount()); ++i)
920 {
921 if(pPg->GetObj(i)->GetStyleSheet())
922 {
923 OUString aStyleName = pPg->GetObj(i)->GetStyleSheet()->GetName();
924 SfxStyleSheet *pSheet = lcl_findStyle(aNewGraphicStyles, aStyleName + aRenameStr);
925 if(pSheet != nullptr)
926 pPg->GetObj(i)->SetStyleSheet(pSheet, true);
927 }
928 }
929 }
930 }
931 catch(...)
932 {
933 OSL_FAIL("Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "933" ": "), "%s", "Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage"
); } } while (false)
;
934 }
935 }
936 // remove copied styles not used on any inserted page and create
937 // undo records
938 // WARNING: SdMoveStyleSheetsUndoAction clears the passed list of
939 // styles, so it cannot be used after this point
940 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewGraphicStyles);
941 if (!aNewGraphicStyles.empty() && pUndoMgr)
942 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aNewGraphicStyles, true));
943 lcl_removeUnusedStyles(GetStyleSheetPool(), aNewCellStyles);
944 if (!aNewCellStyles.empty() && pUndoMgr)
945 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aNewCellStyles, true));
946
947 if( bUndo )
948 EndUndo();
949
950 if (pUndoMgr)
951 pUndoMgr->LeaveListAction();
952
953 return bContinue;
954}
955
956// Inserts a bookmark as an object
957bool SdDrawDocument::InsertBookmarkAsObject(
958 const std::vector<OUString> &rBookmarkList,
959 const std::vector<OUString> &rExchangeList, // List of names to use
960 ::sd::DrawDocShell* pBookmarkDocSh,
961 Point const * pObjPos,
962 bool bCalcObjCount)
963{
964 bool bOK = true;
965 bool bOLEObjFound = false;
966 std::unique_ptr<::sd::View> pBMView;
967
968 SdDrawDocument* pBookmarkDoc = nullptr;
969
970 if (pBookmarkDocSh)
971 {
972 pBookmarkDoc = pBookmarkDocSh->GetDoc();
973 }
974 else if ( mxBookmarkDocShRef.is() )
975 {
976 pBookmarkDoc = mxBookmarkDocShRef->GetDoc();
977 }
978 else
979 {
980 return false;
981 }
982
983 if (rBookmarkList.empty())
984 {
985 pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr));
986 pBMView->EndListening(*pBookmarkDoc);
987 pBMView->MarkAll();
988 }
989 else
990 {
991 SdrPage* pPage;
992 SdrPageView* pPV;
993
994 for ( const auto& rBookmark : rBookmarkList )
995 {
996 // Get names of bookmarks from the list
997 SdrObject* pObj = pBookmarkDoc->GetObj(rBookmark);
998
999 if (pObj)
1000 {
1001 // Found an object
1002 if (pObj->GetObjInventor() == SdrInventor::Default &&
1003 pObj->GetObjIdentifier() == OBJ_OLE2)
1004 {
1005 bOLEObjFound = true;
1006 }
1007
1008 if (!pBMView)
1009 {
1010 // Create View for the first time
1011 pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr));
1012 pBMView->EndListening(*pBookmarkDoc);
1013 }
1014
1015 pPage = pObj->getSdrPageFromSdrObject();
1016
1017 if (pPage->IsMasterPage())
1018 {
1019 pPV = pBMView->ShowSdrPage(pBMView->GetModel()->GetMasterPage(pPage->GetPageNum()));
1020 }
1021 else
1022 {
1023 pPV = pBMView->GetSdrPageView();
1024 if( !pPV || (pPV->GetPage() != pPage))
1025 pPV = pBMView->ShowSdrPage(pPage);
1026 }
1027
1028 pBMView->MarkObj(pObj, pPV);
1029 }
1030 }
1031 }
1032
1033 if (pBMView)
1034 {
1035 // Insert selected objects
1036 std::unique_ptr<::sd::View> pView(new ::sd::View(*this, nullptr));
1037 pView->EndListening(*this);
1038
1039 // Look for the page into which the objects are supposed to be inserted
1040 SdrPage* pPage = GetSdPage(0, PageKind::Standard);
1041
1042 if (mpDocSh)
1043 {
1044 ::sd::ViewShell* pViewSh = mpDocSh->GetViewShell();
1045
1046 if (pViewSh)
1047 {
1048 // Which page is currently in view?
1049 SdrPageView* pPV = pViewSh->GetView()->GetSdrPageView();
1050
1051 if (pPV)
1052 {
1053 pPage = pPV->GetPage();
1054 }
1055 else if (pViewSh->GetActualPage())
1056 {
1057 pPage = pViewSh->GetActualPage();
1058 }
1059 }
1060 }
1061
1062 Point aObjPos;
1063
1064 if (pObjPos)
1065 {
1066 aObjPos = *pObjPos;
1067 }
1068 else
1069 {
1070 aObjPos = ::tools::Rectangle(Point(), pPage->GetSize()).Center();
1071 }
1072
1073 size_t nCountBefore = 0;
1074
1075 if (!rExchangeList.empty() || bCalcObjCount)
1076 {
1077 // Sort OrdNums and get the number of objects before inserting
1078 pPage->RecalcObjOrdNums();
1079 nCountBefore = pPage->GetObjCount();
1080 }
1081
1082 if (bOLEObjFound)
1083 pBMView->GetDoc().SetAllocDocSh(true);
1084
1085 SdDrawDocument* pTmpDoc = static_cast<SdDrawDocument*>( pBMView->CreateMarkedObjModel().release() );
1086 bOK = pView->Paste(*pTmpDoc, aObjPos, pPage, SdrInsertFlags::NONE);
1087
1088 if (bOLEObjFound)
1089 pBMView->GetDoc().SetAllocDocSh(false);
1090
1091 if (!bOLEObjFound)
1092 delete pTmpDoc; // Would otherwise be destroyed by DocShell
1093
1094 pView.reset();
1095
1096 // Get number of objects after inserting.
1097 const size_t nCount = pPage->GetObjCount();
1098 if (nCountBefore < nCount)
1099 {
1100 size_t nObj = nCountBefore;
1101 for (const auto& rExchange : rExchangeList)
1102 {
1103 // Get the name to use from the Exchange list
1104 if (pPage->GetObj(nObj))
1105 {
1106 pPage->GetObj(nObj)->SetName(rExchange);
1107 }
1108
1109 ++nObj;
1110 if (nObj >= nCount)
1111 break;
1112 }
1113 }
1114 }
1115
1116 return bOK;
1117}
1118
1119// Stops the bookmark insertion
1120void SdDrawDocument::CloseBookmarkDoc()
1121{
1122 if (mxBookmarkDocShRef.is())
1123 {
1124 mxBookmarkDocShRef->DoClose();
1125 }
1126
1127 mxBookmarkDocShRef.clear();
1128 maBookmarkFile.clear();
1129}
1130
1131// Is this document read-only?
1132bool SdDrawDocument::IsReadOnly() const
1133{
1134 return false;
1135}
1136
1137// In the subsequent AllocModel() a DocShell (xAllocedDocShRef) is created.
1138// Any pre-existing DocShell is deleted
1139void SdDrawDocument::SetAllocDocSh(bool bAlloc)
1140{
1141 mbAllocDocSh = bAlloc;
1142
1143 if(mxAllocedDocShRef.is())
1144 {
1145 mxAllocedDocShRef->DoClose();
1146 }
1147
1148 mxAllocedDocShRef.clear();
1149}
1150
1151// Return list of CustomShows (create it, too, if necessary)
1152SdCustomShowList* SdDrawDocument::GetCustomShowList(bool bCreate)
1153{
1154 if (!mpCustomShowList && bCreate)
1155 {
1156 mpCustomShowList.reset(new SdCustomShowList);
1157 }
1158
1159 return mpCustomShowList.get();
1160}
1161
1162// Remove unused master pages and layouts
1163void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, bool bOnlyDuplicatePages, bool bUndo)
1164{
1165 ::sd::View* pView = nullptr;
1166 SfxUndoManager* pUndoMgr = nullptr;
1167
1168 if( bUndo && !IsUndoEnabled() )
1169 bUndo = false;
1170
1171 if (mpDocSh)
1172 {
1173 pUndoMgr = mpDocSh->GetUndoManager();
1174
1175 if (mpDocSh->GetViewShell())
1176 pView = mpDocSh->GetViewShell()->GetView();
1177 }
1178
1179 // Check all master pages
1180 sal_uInt16 nSdMasterPageCount = GetMasterSdPageCount( PageKind::Standard );
1181 for (sal_Int32 nMPage = nSdMasterPageCount - 1; nMPage >= 0; nMPage--)
1182 {
1183 SdPage* pMaster = pMasterPage;
1184 SdPage* pNotesMaster = nullptr;
1185
1186 if (!pMaster)
1187 {
1188 pMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Standard );
1189 pNotesMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Notes );
1190 }
1191 else
1192 {
1193 for ( sal_uInt16 nMPg = 0; nMPg < GetMasterPageCount(); nMPg++ )
1194 {
1195 if ( pMaster == GetMasterPage( nMPg ) )
1196 {
1197 pNotesMaster = static_cast<SdPage*>( GetMasterPage( ++nMPg ) );
1198 break;
1199 }
1200 }
1201 }
1202
1203 DBG_ASSERT( pMaster->GetPageKind() == PageKind::Standard, "wrong page kind" )do { if (true && (!(pMaster->GetPageKind() == PageKind
::Standard))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1203" ": "), "%s", "wrong page kind"); } } while (false
)
;
1204
1205 if ( pMaster->GetPageKind() == PageKind::Standard &&
1206 GetMasterPageUserCount( pMaster ) == 0 &&
1207 pNotesMaster )
1208 {
1209 // Do not delete master pages that have their precious flag set
1210 bool bDeleteMaster = !pMaster->IsPrecious();
1211 OUString aLayoutName = pMaster->GetLayoutName();
1212
1213 if(bOnlyDuplicatePages )
1214 {
1215 // remove only duplicate pages
1216 bDeleteMaster = false;
1217 for (sal_uInt16 i = 0; i < GetMasterSdPageCount( PageKind::Standard ); i++)
1218 {
1219 SdPage* pMPg = GetMasterSdPage( i, PageKind::Standard );
1220 if( pMPg != pMaster &&
1221 pMPg->GetLayoutName() == aLayoutName )
1222 {
1223 // duplicate page found -> remove it
1224 bDeleteMaster = true;
1225 }
1226 }
1227 }
1228
1229 if( bDeleteMaster )
1230 {
1231 if (pView)
1232 {
1233 // if MasterPage is visible hide on pageview
1234 SdrPageView* pPgView = pView->GetSdrPageView();
1235 if (pPgView)
1236 {
1237 SdrPage* pShownPage = pPgView->GetPage();
1238 if( (pShownPage == pMaster) || (pShownPage == pNotesMaster) )
1239 {
1240 pView->HideSdrPage();
1241 pView->ShowSdrPage( GetSdPage( 0, PageKind::Standard ) );
1242 }
1243 }
1244 }
1245
1246 if( bUndo )
1247 {
1248 BegUndo();
1249 AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster ) );
1250 }
1251
1252 RemoveMasterPage( pNotesMaster->GetPageNum() );
1253
1254 if( !bUndo )
1255 delete pNotesMaster;
1256
1257 if( bUndo )
1258 AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster));
1259
1260 RemoveMasterPage( pMaster->GetPageNum() );
1261
1262 if( !bUndo )
1263 delete pMaster;
1264
1265 if( bUndo )
1266 EndUndo(); // do this here already, so Joe's actions happen _between_ our own
1267
1268 // Delete old, unused layout stylesheets
1269 bool bDeleteOldStyleSheets = true;
1270 for ( sal_uInt16 nMPg = 0;
1271 nMPg < GetMasterPageCount() && bDeleteOldStyleSheets;
1272 nMPg++ )
1273 {
1274 SdPage* pMPg = static_cast<SdPage*>( GetMasterPage(nMPg) );
1275 if (pMPg->GetLayoutName() == aLayoutName)
1276 {
1277 bDeleteOldStyleSheets = false;
1278 }
1279 }
1280
1281 if (bDeleteOldStyleSheets)
1282 {
1283 SdStyleSheetVector aRemove;
1284 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList( aLayoutName, aRemove );
1285
1286 if( bUndo )
1287 {
1288 StyleSheetCopyResultVector aUndoRemove;
1289 aUndoRemove.reserve(aRemove.size());
1290 for (const auto& a : aRemove)
1291 aUndoRemove.emplace_back(a.get(), true);
1292
1293 if (pUndoMgr)
1294 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoRemove, false));
1295 }
1296
1297 for( const auto& a : aRemove )
1298 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->Remove(a.get());
1299 }
1300 }
1301 }
1302
1303 if (pMasterPage)
1304 break; // Just this one master page!
1305 }
1306}
1307
1308/** Exchange master page
1309 *
1310 * Either the nSdPageNum gets a new, own master page or the master page is
1311 * exchanged completely (which then applies to all pages).
1312 *
1313 * nSdPageNum : page number that the new master page should get.
1314 * rLayoutName : LayoutName of the new master page
1315 * pSourceDoc : document (template) to get the master page from
1316 * bMaster : exchange the master page of nSdPageNum
1317 * bCheckMasters: remove unused master pages
1318 *
1319 * If pSourceDoc == NULL, an empty master page is applied.
1320 * If rLayoutName is empty, the first master page is used.
1321 */
1322// #i121863# factored out functionality
1323static bool isMasterPageLayoutNameUnique(const SdDrawDocument& rDoc, const OUString& rCandidate)
1324{
1325 if (rCandidate.isEmpty())
1326 {
1327 return false;
1328 }
1329
1330 const sal_uInt16 nPageCount(rDoc.GetMasterPageCount());
1331
1332 for(sal_uInt16 a(0); a < nPageCount; a++)
1333 {
1334 const SdrPage* pCandidate = rDoc.GetMasterPage(a);
1335 OUString aPageLayoutName(pCandidate->GetLayoutName());
1336 sal_Int32 nIndex = aPageLayoutName.indexOf(SD_LT_SEPARATOR"~LT~");
1337 if( nIndex != -1 )
1338 aPageLayoutName = aPageLayoutName.copy(0, nIndex);
1339
1340 if(aPageLayoutName == rCandidate)
1341 {
1342 return false;
1343 }
1344 }
1345
1346 return true;
1347}
1348
1349// #i121863# factored out functionality
1350static OUString createNewMasterPageLayoutName(const SdDrawDocument& rDoc)
1351{
1352 const OUString aBaseName(SdResId(STR_LAYOUT_DEFAULT_NAMEreinterpret_cast<char const *>("STR_LAYOUT_DEFAULT_NAME"
"\004" u8"Default")
));
1353 sal_uInt16 nCount(0);
1354 for (;;)
1355 {
1356 OUString aRetval = aBaseName;
1357 if(nCount)
1358 {
1359 aRetval += OUString::number(nCount);
1360 }
1361 if (isMasterPageLayoutNameUnique(rDoc, aRetval))
1362 return aRetval;
1363 nCount++;
1364 }
1365}
1366
1367void SdDrawDocument::SetMasterPage(sal_uInt16 nSdPageNum,
1368 const OUString& rLayoutName,
1369 SdDrawDocument* pSourceDoc,
1370 bool bMaster,
1371 bool bCheckMasters)
1372{
1373 SfxUndoManager* pUndoMgr = nullptr;
1374
1375 if( mpDocSh )
1376 {
1377 mpDocSh->SetWaitCursor( true );
1378 pUndoMgr = mpDocSh->GetUndoManager();
1379 }
1380
1381 const bool bUndo = pUndoMgr && IsUndoEnabled();
1382
1383 if (bUndo)
1384 {
1385 ViewShellId nViewShellId(-1);
1386 if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell())
1387 nViewShellId = pViewShell->GetViewShellBase().GetViewShellId();
1388 pUndoMgr->EnterListAction(SdResId(STR_UNDO_SET_PRESLAYOUTreinterpret_cast<char const *>("STR_UNDO_SET_PRESLAYOUT"
"\004" u8"Apply presentation layout")
), OUString(), 0, nViewShellId);
1389 }
1390
1391 SdPage* pSelectedPage = GetSdPage(nSdPageNum, PageKind::Standard);
1392 SdPage* pNotes = static_cast<SdPage*>( GetPage(pSelectedPage->GetPageNum()+1) );
1393 SdPage& rOldMaster = static_cast<SdPage&>(pSelectedPage->TRG_GetMasterPage());
1394 SdPage& rOldNotesMaster = static_cast<SdPage&>(pNotes->TRG_GetMasterPage());
1395 SdPage* pMaster = nullptr;
1396 SdPage* pNotesMaster = nullptr;
1397 OUString aOldPageLayoutName(pSelectedPage->GetLayoutName());
1398 OUString aOldLayoutName(aOldPageLayoutName);
1399 sal_Int32 nIndex = aOldLayoutName.indexOf( SD_LT_SEPARATOR"~LT~" );
1400 if( nIndex != -1 )
1401 aOldLayoutName = aOldLayoutName.copy(0, nIndex);
1402
1403 if (pSourceDoc)
1404 {
1405 std::vector<StyleReplaceData> aReplList; // List of replaced stylesheets
1406 bool bLayoutReloaded = false; // Was ex. layout reloaded?
1407
1408 // LayoutName, Page and Notes page
1409 if (rLayoutName.isEmpty())
1410 {
1411 // No LayoutName: take first MasterPage
1412 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1413 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1414 }
1415 else
1416 {
1417 OUString aSearchFor = rLayoutName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung";
1418
1419 for (sal_uInt16 nMP = 0; nMP < pSourceDoc->GetMasterPageCount(); ++nMP)
1420 {
1421 SdPage* pMP = static_cast<SdPage*>( pSourceDoc->GetMasterPage(nMP) );
1422
1423 if (pMP->GetLayoutName() == aSearchFor)
1424 {
1425 if (pMP->GetPageKind() == PageKind::Standard)
1426 pMaster = pMP;
1427 if (pMP->GetPageKind() == PageKind::Notes)
1428 pNotesMaster = pMP;
1429 }
1430 if (pMaster && pNotesMaster)
1431 break;
1432 }
1433 DBG_ASSERT(pMaster, "MasterPage (Standard page) not found")do { if (true && (!(pMaster))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1433" ": "), "%s", "MasterPage (Standard page) not found"
); } } while (false)
;
1434 DBG_ASSERT(pNotesMaster, "MasterPage (Notes page) not found")do { if (true && (!(pNotesMaster))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1434" ": "), "%s", "MasterPage (Notes page) not found")
; } } while (false)
;
1435
1436 // this should not happen, but looking at crash reports, it does
1437 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1438 {
1439 // so take the first MasterPage
1440 pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard);
1441 pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes);
1442 }
1443 }
1444
1445 // we should never reach this, but one never knows...
1446 if( (pMaster == nullptr) || (pNotesMaster == nullptr) )
1447 {
1448 if (bUndo)
1449 pUndoMgr->LeaveListAction();
1450
1451 if( mpDocSh )
1452 mpDocSh->SetWaitCursor( false );
1453
1454 OSL_FAIL( "SdDrawDocument::SetMasterPage() failed!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1454" ": "), "%s", "SdDrawDocument::SetMasterPage() failed!"
); } } while (false)
;
1455
1456 return;
1457 }
1458
1459 const OUString aOriginalNewLayoutName( pMaster->GetName() );
1460 OUString aTargetNewLayoutName(aOriginalNewLayoutName);
1461
1462 if (pSourceDoc != this)
1463 {
1464 // #i121863# clone masterpages, they are from another model (!)
1465 std::unique_ptr<SdPage> pNewNotesMaster(dynamic_cast< SdPage* >(pNotesMaster->CloneSdrPage(*this)));
1466 std::unique_ptr<SdPage> pNewMaster(dynamic_cast< SdPage* >(pMaster->CloneSdrPage(*this)));
1467
1468 if(!pNewNotesMaster || !pNewMaster)
1469 {
1470 OSL_FAIL("SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1470" ": "), "%s", "SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!"
); } } while (false)
;
1471 return;
1472 }
1473
1474 pNotesMaster = pNewNotesMaster.release();
1475 pMaster = pNewMaster.release();
1476
1477 // layout name needs to be unique
1478 aTargetNewLayoutName = pMaster->GetLayoutName();
1479 sal_Int32 nIndex2 = aTargetNewLayoutName.indexOf(SD_LT_SEPARATOR"~LT~");
1480 if( nIndex2 != -1 )
1481 aTargetNewLayoutName = aTargetNewLayoutName.copy(0, nIndex2);
1482
1483 if(!isMasterPageLayoutNameUnique(*this, aTargetNewLayoutName))
1484 {
1485 aTargetNewLayoutName = createNewMasterPageLayoutName(*this);
1486
1487 OUString aTemp = aTargetNewLayoutName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung";
1488
1489 pMaster->SetName(aTargetNewLayoutName);
1490 pMaster->SetLayoutName(aTemp);
1491
1492 pNotesMaster->SetName(aTargetNewLayoutName);
1493 pNotesMaster->SetLayoutName(aTemp);
1494 }
1495 }
1496
1497 if (pSourceDoc != this)
1498 {
1499 const sal_uInt16 nMasterPageCount = GetMasterPageCount();
1500 for ( sal_uInt16 nMPage = 0; nMPage < nMasterPageCount; nMPage++ )
1501 {
1502 SdPage* pCheckMaster = static_cast<SdPage*>(GetMasterPage(nMPage));
1503 if( pCheckMaster->GetName() == aTargetNewLayoutName )
1504 {
1505 bLayoutReloaded = true;
1506 break;
1507 }
1508 }
1509
1510 // Correct or create presentation templates --
1511 // only worry about presentation templates
1512 OUString aName;
1513 SdStyleSheetPool* pSourceStyleSheetPool = static_cast<SdStyleSheetPool*>( pSourceDoc->GetStyleSheetPool() );
1514
1515 StyleSheetCopyResultVector aCreatedStyles; // List of created stylesheets
1516 SfxStyleSheetBase* pHisSheet = pSourceStyleSheetPool->First(SfxStyleFamily::Page);
1517
1518 while (pHisSheet)
1519 {
1520 aName = pHisSheet->GetName();
1521
1522 // #i121863# search in source styles with original style name from source of
1523 // evtl. cloned master (not-cloned, renamed for uniqueness)
1524 if( aName.startsWith( aOriginalNewLayoutName ) )
1525 {
1526 // #i121863# build name of evtl. cloned master style to search for
1527 if(aOriginalNewLayoutName != aTargetNewLayoutName)
1528 {
1529 const sal_Int32 nPos(aName.indexOf(SD_LT_SEPARATOR"~LT~"));
1530 aName = aTargetNewLayoutName + aName.copy(nPos);
1531 }
1532
1533 SfxStyleSheet* pMySheet = static_cast<SfxStyleSheet*>( mxStyleSheetPool->Find(aName, SfxStyleFamily::Page) );
1534
1535 if (pMySheet)
1536 {
1537 // A stylesheet of the same name already exists -> overwrite contents
1538 bool bTest = pMySheet->SetName(pHisSheet->GetName());
1539 DBG_ASSERT(bTest, "Renaming StyleSheet failed.")do { if (true && (!(bTest))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx"
":" "1539" ": "), "%s", "Renaming StyleSheet failed."); } } while
(false)
;
1540 pMySheet->GetItemSet().ClearItem(); // Delete all
1541
1542 if (bUndo)
1543 {
1544 pUndoMgr->AddUndoAction(std::make_unique<StyleSheetUndoAction>(this,
1545 pMySheet, &pHisSheet->GetItemSet()));
1546 }
1547 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1548 pMySheet->Broadcast(SfxHint(SfxHintId::DataChanged));
1549 }
1550 else
1551 {
1552 // create new style
1553 OUString aHelpFile;
1554 pMySheet = static_cast<SfxStyleSheet*>( &mxStyleSheetPool->Make(aName, SfxStyleFamily::Page, pHisSheet->GetMask()) );
1555 pMySheet->SetHelpId( aHelpFile, pHisSheet->GetHelpId(aHelpFile) );
1556 pMySheet->GetItemSet().ClearItem(); // Delete all
1557 pMySheet->GetItemSet().Put(pHisSheet->GetItemSet());
1558
1559 aCreatedStyles.emplace_back(static_cast<SdStyleSheet*>(pMySheet), true);
1560 }
1561
1562 StyleReplaceData aReplData;
1563 aReplData.nNewFamily = pMySheet->GetFamily();
1564 aReplData.nFamily = pMySheet->GetFamily();
1565 aReplData.aNewName = pMySheet->GetName();
1566
1567 // #i121863# re-create original name of style used at page where to replace with
1568 // this new style
1569 OUString aTemp(pMySheet->GetName());
1570 const sal_Int32 nPos(aTemp.indexOf(SD_LT_SEPARATOR"~LT~"));
1571 aTemp = aOldLayoutName + aTemp.copy(nPos);
1572 aReplData.aName = aTemp;
1573 aReplList.push_back(aReplData);
1574 }
1575
1576 pHisSheet = pSourceStyleSheetPool->Next();
1577 }
1578
1579 // If new styles were created: re-create parent chaining of the item
1580 // sets in the styles.
1581 if(!aCreatedStyles.empty())
1582 {
1583 for ( const auto& rRData : aReplList )
1584 {
1585 SfxStyleSheetBase* pSOld = mxStyleSheetPool->Find(rRData.aName, SfxStyleFamily::Page);
1586 SfxStyleSheetBase* pSNew = mxStyleSheetPool->Find(rRData.aNewName, SfxStyleFamily::Page);
1587
1588 if (pSOld && pSNew)
1589 {
1590 const OUString& rParentOfOld = pSOld->GetParent();
1591 const OUString& rParentOfNew = pSNew->GetParent();
1592
1593 if (!rParentOfOld.isEmpty() && rParentOfNew.isEmpty())
1594 {
1595 std::vector<StyleReplaceData>::iterator pRDIter = std::find_if(aReplList.begin(), aReplList.end(),
1596 [&rParentOfOld](const StyleReplaceData& rRD) { return (rRD.aName == rParentOfOld) && (rRD.aName != rRD.aNewName); });
1597 if (pRDIter != aReplList.end())
1598 {
1599 OUString aParentOfNew(pRDIter->aNewName);
1600 pSNew->SetParent(aParentOfNew);
1601 }
1602 }
1603 }
1604 }
1605 }
1606
1607 if (bUndo && !aCreatedStyles.empty())
1608 {
1609 // Add UndoAction for creating and inserting the stylesheets to
1610 // the top of the UndoManager
1611 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>( this, aCreatedStyles, true));
1612 }
1613 }
1614
1615 // Create layout name based upon the name of the page layout of the
1616 // master page
1617 OUString aPageLayoutName(pMaster->GetLayoutName());
1618 OUString aLayoutName = aPageLayoutName;
1619 sal_Int32 nIndex2 = aLayoutName.indexOf( SD_LT_SEPARATOR"~LT~" );
1620 if( nIndex2 != -1 )
1621 aLayoutName = aLayoutName.copy( 0, nIndex2);
1622
1623 // #i121863# Do *not* remove from original document any longer, it is potentially used there
1624 // and would lead to crashes. Rely on the automatic process of removing unused masterpages
1625 // (see RemoveUnnecessaryMasterPages)
1626 //if (pSourceDoc != this)
1627 //{
1628 // // Remove from the source document
1629 // pSourceDoc->RemoveMasterPage(pNotesMaster->GetPageNum());
1630 // pSourceDoc->RemoveMasterPage(pMaster->GetPageNum());
1631 //}
1632
1633 // Register the new master pages with the document and then use
1634 // the new presentation layout for the default and notes pages
1635 if (pSourceDoc != this)
1636 {
1637 // Insert the master pages:
1638 // Insert master pages from new layouts at the end.
1639 // If a layout is being replaced, however, insert them before the
1640 // position of the old master page, so from now on the new master
1641 // page will be found when searching (e.g.
1642 // SdPage::SetPresentationLayout).
1643 sal_uInt16 nInsertPos = rOldMaster.GetPageNum();
1644 BegUndo();
1645
1646 if (!bLayoutReloaded)
1647 nInsertPos = 0xFFFF;
1648 InsertMasterPage(pMaster, nInsertPos);
1649 if( bUndo )
1650 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1651
1652 nInsertPos++;
1653 if (!bLayoutReloaded)
1654 nInsertPos = 0xFFFF;
1655 InsertMasterPage(pNotesMaster, nInsertPos);
1656 if( bUndo )
1657 {
1658 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1659
1660 EndUndo(); // do this here already, so Joe's actions happen _between_ our own.
1661 }
1662 }
1663
1664 // Fill list with pages
1665 std::vector<SdPage*> aPageList;
1666
1667// #98456, this has to be removed according to CL (KA 07/08/2002)
1668// #109884# but we need them again to restore the styles of the presentation objects while undo
1669 aPageList.push_back(pMaster);
1670 aPageList.push_back(pNotesMaster);
1671
1672 if (bMaster || bLayoutReloaded)
1673 {
1674 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1675 {
1676 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1677 OUString aTest = pPage->GetLayoutName();
1678 if (aTest == aOldPageLayoutName)
1679 {
1680 aPageList.push_back(pPage);
1681 }
1682 }
1683
1684 }
1685 else
1686 {
1687 aPageList.push_back(pSelectedPage);
1688 aPageList.push_back(pNotes);
1689 }
1690
1691 for (SdPage* pPage : aPageList)
1692 {
1693 AutoLayout eAutoLayout = pPage->GetAutoLayout();
1694
1695 if( bUndo )
1696 {
1697 pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction>
1698 (this,
1699 pPage->IsMasterPage() ? aLayoutName : aOldLayoutName,
1700 aLayoutName,
1701 eAutoLayout, eAutoLayout, false, pPage));
1702 }
1703 pPage->SetPresentationLayout(aLayoutName);
1704 pPage->SetAutoLayout(eAutoLayout);
1705 }
1706
1707 // Adapt new master pages
1708 if (pSourceDoc != this)
1709 {
1710 Size aSize(rOldMaster.GetSize());
1711 ::tools::Rectangle aBorderRect(rOldMaster.GetLeftBorder(),
1712 rOldMaster.GetUpperBorder(),
1713 rOldMaster.GetRightBorder(),
1714 rOldMaster.GetLowerBorder());
1715 pMaster->ScaleObjects(aSize, aBorderRect, true);
1716 pMaster->SetSize(aSize);
1717 pMaster->SetBorder(rOldMaster.GetLeftBorder(),
1718 rOldMaster.GetUpperBorder(),
1719 rOldMaster.GetRightBorder(),
1720 rOldMaster.GetLowerBorder());
1721 pMaster->SetOrientation( rOldMaster.GetOrientation() );
1722 pMaster->SetAutoLayout(pMaster->GetAutoLayout());
1723
1724 aSize = rOldNotesMaster.GetSize();
1725 ::tools::Rectangle aNotesBorderRect(rOldNotesMaster.GetLeftBorder(),
1726 rOldNotesMaster.GetUpperBorder(),
1727 rOldNotesMaster.GetRightBorder(),
1728 rOldNotesMaster.GetLowerBorder());
1729 pNotesMaster->ScaleObjects(aSize, aNotesBorderRect, true);
1730 pNotesMaster->SetSize(aSize);
1731 pNotesMaster->SetBorder(rOldNotesMaster.GetLeftBorder(),
1732 rOldNotesMaster.GetUpperBorder(),
1733 rOldNotesMaster.GetRightBorder(),
1734 rOldNotesMaster.GetLowerBorder());
1735 pNotesMaster->SetOrientation( rOldNotesMaster.GetOrientation() );
1736 pNotesMaster->SetAutoLayout(pNotesMaster->GetAutoLayout());
1737
1738 if( (pSourceDoc->GetDocumentType() == DocumentType::Impress) &&
1739 (GetDocumentType() == DocumentType::Draw) )
1740 {
1741 pMaster->RemoveEmptyPresentationObjects();
1742 pNotesMaster->RemoveEmptyPresentationObjects();
1743 }
1744 }
1745 }
1746 else
1747 {
1748 // Find a new name for the layout
1749 OUString aName(createNewMasterPageLayoutName(*this));
1750 OUString aPageLayoutName(aName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung");
1751
1752 // Generate new stylesheets
1753 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutStyleSheets(aName);
1754 SdStyleSheetVector aCreatedStyles;
1755 static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList(aName, aCreatedStyles);
1756
1757 if( bUndo )
1758 {
1759 StyleSheetCopyResultVector aUndoInsert;
1760 aUndoInsert.reserve(aCreatedStyles.size());
1761 for (const auto& a : aCreatedStyles)
1762 aUndoInsert.emplace_back(a.get(), true);
1763 pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoInsert, true));
1764 // Generate new master pages and register them with the document
1765 BegUndo();
1766 }
1767
1768 pMaster = AllocSdPage(true);
1769 pMaster->SetSize(pSelectedPage->GetSize());
1770 pMaster->SetBorder(pSelectedPage->GetLeftBorder(),
1771 pSelectedPage->GetUpperBorder(),
1772 pSelectedPage->GetRightBorder(),
1773 pSelectedPage->GetLowerBorder() );
1774 pMaster->SetName(aName);
1775 pMaster->SetLayoutName(aPageLayoutName);
1776 InsertMasterPage(pMaster);
1777
1778 if( bUndo )
1779 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster));
1780
1781 pMaster->SetAutoLayout(AUTOLAYOUT_NONE, true, true);
1782
1783 pNotesMaster = AllocSdPage(true);
1784 pNotesMaster->SetPageKind(PageKind::Notes);
1785 pNotesMaster->SetSize(pNotes->GetSize());
1786 pNotesMaster->SetBorder(pNotes->GetLeftBorder(),
1787 pNotes->GetUpperBorder(),
1788 pNotes->GetRightBorder(),
1789 pNotes->GetLowerBorder() );
1790 pNotesMaster->SetName(aName);
1791 pNotesMaster->SetLayoutName(aPageLayoutName);
1792 InsertMasterPage(pNotesMaster);
1793
1794 if( bUndo )
1795 AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster));
1796
1797 pNotesMaster->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
1798
1799 if( bUndo )
1800 EndUndo();
1801
1802 // Create a list of affected default and notes pages
1803 std::vector<SdPage*> aPageList;
1804 if (bMaster)
1805 {
1806 for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++)
1807 {
1808 SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) );
1809 if (pPage->GetLayoutName() == aOldPageLayoutName)
1810 {
1811 aPageList.push_back(pPage);
1812 }
1813 }
1814 }
1815 else
1816 {
1817 aPageList.push_back(pSelectedPage);
1818 aPageList.push_back(pNotes);
1819 }
1820
1821 // Set presentation layout and AutoLayout for the affected pages
1822 for ( auto& rpPage : aPageList )
1823 {
1824 AutoLayout eOldAutoLayout = rpPage->GetAutoLayout();
1825 AutoLayout eNewAutoLayout =
1826 rpPage->GetPageKind() == PageKind::Standard ? AUTOLAYOUT_NONE : AUTOLAYOUT_NOTES;
1827
1828 if( bUndo )
1829 {
1830 pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction>
1831 (this, aOldLayoutName, aName,
1832 eOldAutoLayout, eNewAutoLayout, true,
1833 rpPage));
1834 }
1835
1836 rpPage->SetPresentationLayout(aName);
1837 rpPage->SetAutoLayout(eNewAutoLayout);
1838 }
1839 }
1840
1841 // If the old master pages aren't used anymore, they and their styles have
1842 // to be removed.
1843 if (bCheckMasters)
1844 {
1845 // Check all
1846 RemoveUnnecessaryMasterPages();
1847 }
1848 else
1849 {
1850 // Check only the master page that was replaced
1851 RemoveUnnecessaryMasterPages(&rOldMaster);
1852 }
1853
1854 if( bUndo )
1855 pUndoMgr->LeaveListAction();
1856
1857 if( mpDocSh )
1858 mpDocSh->SetWaitCursor( false );
1859}
1860
1861void SdDrawDocument::Merge(SdrModel& rSourceModel,
1862 sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
1863 sal_uInt16 nDestPos,
1864 bool bMergeMasterPages, bool bAllMasterPages,
1865 bool bUndo, bool bTreadSourceAsConst)
1866{
1867 sal_uInt16 nMasterPageCount = GetMasterPageCount();
1868 SdrModel::Merge( rSourceModel, nFirstPageNum, nLastPageNum, nDestPos, bMergeMasterPages, bAllMasterPages, bUndo, bTreadSourceAsConst );
1869
1870 // add style family for each new master page
1871 for( sal_uInt16 nMaster = nMasterPageCount; nMaster < GetMasterPageCount(); nMaster++ )
1872 {
1873 SdPage* pPage = static_cast< SdPage* >( GetMasterPage( nMaster ) );
1874 if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) )
1875 {
1876 // new master page created, add its style family
1877 SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
1878 if( pStylePool )
1879 pStylePool->AddStyleFamily( pPage );
1880 }
1881 }
1882}
1883
1884/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/ref.hxx

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#ifndef INCLUDED_TOOLS_REF_HXX
20#define INCLUDED_TOOLS_REF_HXX
21
22#include <sal/config.h>
23#include <cassert>
24#include <tools/toolsdllapi.h>
25#include <utility>
26
27/**
28 This implements similar functionality to boost::intrusive_ptr
29*/
30
31namespace tools {
32
33/** T must be a class that extends SvRefBase */
34template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final {
35public:
36 SvRef(): pObj(nullptr) {}
37
38 SvRef(SvRef&& rObj) noexcept
39 {
40 pObj = rObj.pObj;
41 rObj.pObj = nullptr;
42 }
43
44 SvRef(SvRef const & rObj): pObj(rObj.pObj)
45 {
46 if (pObj != nullptr) pObj->AddNextRef();
47 }
48
49 SvRef(T * pObjP): pObj(pObjP)
50 {
51 if (pObj != nullptr) pObj->AddFirstRef();
52 }
53
54 ~SvRef()
55 {
56 if (pObj != nullptr) pObj->ReleaseRef();
57 }
58
59 void clear()
60 {
61 if (pObj != nullptr) {
62 T * pRefObj = pObj;
63 pObj = nullptr;
64 pRefObj->ReleaseRef();
65 }
66 }
67
68 SvRef & operator =(SvRef const & rObj)
69 {
70 if (rObj.pObj != nullptr) {
71 rObj.pObj->AddNextRef();
72 }
73 T * pRefObj = pObj;
74 pObj = rObj.pObj;
75 if (pRefObj != nullptr) {
76 pRefObj->ReleaseRef();
77 }
78 return *this;
79 }
80
81 SvRef & operator =(SvRef && rObj)
82 {
83 if (pObj != nullptr) {
84 pObj->ReleaseRef();
85 }
86 pObj = rObj.pObj;
87 rObj.pObj = nullptr;
88 return *this;
89 }
90
91 bool is() const { return pObj != nullptr; }
4
Assuming the condition is true
5
Returning the value 1, which participates in a condition later
92
93 explicit operator bool() const { return is(); }
94
95 T * get() const { return pObj; }
96
97 T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 97, __extension__ __PRETTY_FUNCTION__))
; return pObj; }
98
99 T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 99, __extension__ __PRETTY_FUNCTION__))
; return *pObj; }
100
101 bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; }
102 bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); }
103
104private:
105 T * pObj;
106};
107
108/**
109 * This implements similar functionality to std::make_shared.
110 */
111template<typename T, typename... Args>
112SvRef<T> make_ref(Args&& ... args)
113{
114 return SvRef<T>(new T(std::forward<Args>(args)...));
115}
116
117}
118
119/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */
120class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase
121{
122 // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
123 // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
124 unsigned int nRefCount : 31;
125 // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
126 unsigned int bNoDelete : 1;
127
128protected:
129 virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE;
130
131public:
132 SvRefBase() : nRefCount(0), bNoDelete(1) {}
133 SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {}
134
135 SvRefBase & operator=(const SvRefBase &) { return *this; }
136
137 void RestoreNoDelete()
138 { bNoDelete = 1; }
139
140 void AddNextRef()
141 {
142 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
142, __extension__ __PRETTY_FUNCTION__))
;
143 ++nRefCount;
144 }
145
146 void AddFirstRef()
147 {
148 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
148, __extension__ __PRETTY_FUNCTION__))
;
149 if( bNoDelete )
150 bNoDelete = 0;
151 ++nRefCount;
152 }
153
154 void ReleaseRef()
155 {
156 assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail
("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 156, __extension__ __PRETTY_FUNCTION__))
;
157 if( --nRefCount == 0 && !bNoDelete)
158 {
159 // I'm not sure about the original purpose of this line, but right now
160 // it serves the purpose that anything that attempts to do an AddRef()
161 // after an object is deleted will trip an assert.
162 nRefCount = 1 << 30;
163 delete this;
164 }
165 }
166
167 unsigned int GetRefCount() const
168 { return nRefCount; }
169};
170
171template<typename T>
172class SvCompatWeakBase;
173
174/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T.
175*/
176template<typename T>
177class SvCompatWeakHdl final : public SvRefBase
178{
179 friend class SvCompatWeakBase<T>;
180 T* _pObj;
181
182 SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
183
184public:
185 void ResetWeakBase( ) { _pObj = nullptr; }
186 T* GetObj() { return _pObj; }
187};
188
189/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame.
190 Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted.
191*/
192template<typename T>
193class SvCompatWeakBase
194{
195 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
196
197public:
198 /** Does not use initializer due to compiler warnings,
199 because the lifetime of the _xHdl object can exceed the lifetime of this class.
200 */
201 SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); }
202
203 ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); }
204
205 SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); }
206};
207
208/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak.
209*/
210template<typename T>
211class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef
212{
213 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
214public:
215 SvCompatWeakRef( ) {}
216 SvCompatWeakRef( T* pObj )
217 { if( pObj ) _xHdl = pObj->GetHdl(); }
218#if defined(__COVERITY__)
219 ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {}
220#endif
221 SvCompatWeakRef& operator = ( T * pObj )
222 { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; }
223 bool is() const
224 { return _xHdl.is() && _xHdl->GetObj(); }
225 explicit operator bool() const { return is(); }
226 T* operator -> () const
227 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
228 operator T* () const
229 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
230};
231
232#endif
233
234/* vim:set shiftwidth=4 softtabstop=4 expandtab: */