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