1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/settings.hxx>
21 
22 #include <sal/log.hxx>
23 #include <tools/debug.hxx>
24 #include <sfx2/printer.hxx>
25 #include <editeng/paperinf.hxx>
26 #include <svx/svdopage.hxx>
27 #include <svx/svdoole2.hxx>
28 #include <svx/svdundo.hxx>
29 #include <vcl/svapp.hxx>
30 #include <editeng/eeitem.hxx>
31 #include <editeng/langitem.hxx>
32 #include <svl/itempool.hxx>
33 #include <editeng/flditem.hxx>
34 
35 #include <sfx2/linkmgr.hxx>
36 #include <svx/svdoutl.hxx>
37 #include <svx/svdlayer.hxx>
38 
39 #include <svx/svditer.hxx>
40 #include <comphelper/lok.hxx>
41 #include <xmloff/autolayout.hxx>
42 
43 #include <sdresid.hxx>
44 #include <drawdoc.hxx>
45 #include <sdpage.hxx>
46 #include <strings.hrc>
47 #include <glob.hxx>
48 #include <stlpool.hxx>
49 #include <anminfo.hxx>
50 #include <undo/undomanager.hxx>
51 #include <sfx2/lokhelper.hxx>
52 #include <unomodel.hxx>
53 
54 #include <DrawDocShell.hxx>
55 
56 #include "PageListWatcher.hxx"
57 #include <unokywds.hxx>
58 
59 using namespace ::sd;
60 
61 const ::tools::Long PRINT_OFFSET = 30;       // see /svx/source/dialog/page.cxx
62 
63 using namespace com::sun::star;
64 
65 // Looks up an object by name
GetObj(std::u16string_view rObjName) const66 SdrObject* SdDrawDocument::GetObj(std::u16string_view rObjName) const
67 {
68     SdrObject* pObj = nullptr;
69     SdrObject* pObjFound = nullptr;
70     const SdPage* pPage = nullptr;
71 
72     // First search in all pages
73     sal_uInt16 nPage = 0;
74     const sal_uInt16 nMaxPages = GetPageCount();
75 
76     while (nPage < nMaxPages && !pObjFound)
77     {
78         pPage = static_cast<const SdPage*>( GetPage(nPage) );
79         SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
80 
81         while (aIter.IsMore() && !pObjFound)
82         {
83             pObj = aIter.Next();
84 
85             if( ( pObj->GetName() == rObjName ) ||
86                 ( SdrInventor::Default == pObj->GetObjInventor() &&
87                   OBJ_OLE2 == pObj->GetObjIdentifier() &&
88                   rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
89             {
90                 pObjFound = pObj;
91             }
92         }
93 
94         nPage++;
95     }
96 
97     // If it couldn't be found, look through all master pages
98     nPage = 0;
99     const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
100 
101     while (nPage < nMaxMasterPages && !pObjFound)
102     {
103         pPage = static_cast<const SdPage*>( GetMasterPage(nPage) );
104         SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
105 
106         while (aIter.IsMore() && !pObjFound)
107         {
108             pObj = aIter.Next();
109 
110             if( ( pObj->GetName() == rObjName ) ||
111                 ( SdrInventor::Default == pObj->GetObjInventor() &&
112                   OBJ_OLE2 == pObj->GetObjIdentifier() &&
113                   rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
114             {
115                 pObjFound = pObj;
116             }
117         }
118 
119         nPage++;
120     }
121 
122     return pObjFound;
123 }
124 
125 // Find SdPage by name
GetPageByName(std::u16string_view rPgName,bool & rbIsMasterPage) const126 sal_uInt16 SdDrawDocument::GetPageByName(std::u16string_view rPgName, bool& rbIsMasterPage) const
127 {
128     SdPage* pPage = nullptr;
129     sal_uInt16 nPage = 0;
130     const sal_uInt16 nMaxPages = GetPageCount();
131     sal_uInt16 nPageNum = SDRPAGE_NOTFOUND;
132 
133     rbIsMasterPage = false;
134 
135     // Search all regular pages and all notes pages (handout pages are
136     // ignored)
137     while (nPage < nMaxPages && nPageNum == SDRPAGE_NOTFOUND)
138     {
139         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
140             GetPage(nPage)));
141 
142         if (pPage != nullptr
143             && pPage->GetPageKind() != PageKind::Handout
144             && pPage->GetName() == rPgName)
145         {
146             nPageNum = nPage;
147         }
148 
149         nPage++;
150     }
151 
152     // Search all master pages when not found among non-master pages
153     const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
154     nPage = 0;
155 
156     while (nPage < nMaxMasterPages && nPageNum == SDRPAGE_NOTFOUND)
157     {
158         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
159             GetMasterPage(nPage)));
160 
161         if (pPage && pPage->GetName() == rPgName)
162         {
163             nPageNum = nPage;
164             rbIsMasterPage = true;
165         }
166 
167         nPage++;
168     }
169 
170     return nPageNum;
171 }
172 
IsPageNameUnique(std::u16string_view rPgName) const173 bool SdDrawDocument::IsPageNameUnique( std::u16string_view rPgName ) const
174 {
175     sal_uInt16 nCount = 0;
176     SdPage* pPage = nullptr;
177 
178     // Search all regular pages and all notes pages (handout pages are ignored)
179     sal_uInt16 nPage = 0;
180     sal_uInt16 nMaxPages = GetPageCount();
181     while (nPage < nMaxPages)
182     {
183         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(GetPage(nPage)));
184 
185         if (pPage && pPage->GetName() == rPgName && pPage->GetPageKind() != PageKind::Handout)
186             nCount++;
187 
188         nPage++;
189     }
190 
191     // Search all master pages
192     nPage = 0;
193     nMaxPages = GetMasterPageCount();
194     while (nPage < nMaxPages)
195     {
196         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(GetMasterPage(nPage)));
197 
198         if (pPage && pPage->GetName() == rPgName)
199             nCount++;
200 
201         nPage++;
202     }
203 
204     return nCount == 1;
205 }
206 
GetSdPage(sal_uInt16 nPgNum,PageKind ePgKind) const207 SdPage* SdDrawDocument::GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const
208 {
209     return mpDrawPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
210 }
211 
GetSdPageCount(PageKind ePgKind) const212 sal_uInt16 SdDrawDocument::GetSdPageCount(PageKind ePgKind) const
213 {
214     return static_cast<sal_uInt16>(mpDrawPageListWatcher->GetSdPageCount(ePgKind));
215 }
216 
GetMasterSdPage(sal_uInt16 nPgNum,PageKind ePgKind)217 SdPage* SdDrawDocument::GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind)
218 {
219     return mpMasterPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
220 }
221 
GetMasterSdPageCount(PageKind ePgKind) const222 sal_uInt16 SdDrawDocument::GetMasterSdPageCount(PageKind ePgKind) const
223 {
224     return static_cast<sal_uInt16>(mpMasterPageListWatcher->GetSdPageCount(ePgKind));
225 }
226 
GetActiveSdPageCount() const227 sal_uInt16 SdDrawDocument::GetActiveSdPageCount() const
228 {
229     return static_cast<sal_uInt16>(mpDrawPageListWatcher->GetVisibleSdPageCount());
230 }
231 
232 // Adapt the page numbers that are registered in the page objects of the notes
233 // pages
UpdatePageObjectsInNotes(sal_uInt16 nStartPos)234 void SdDrawDocument::UpdatePageObjectsInNotes(sal_uInt16 nStartPos)
235 {
236     sal_uInt16  nPageCount  = GetPageCount();
237     SdPage* pPage       = nullptr;
238 
239     for (sal_uInt16 nPage = nStartPos; nPage < nPageCount; nPage++)
240     {
241         pPage = static_cast<SdPage*>( GetPage(nPage) );
242 
243         // If this is a notes page, find its page object and correct the page
244         // number
245         if (pPage && pPage->GetPageKind() == PageKind::Notes)
246         {
247             const size_t nObjCount = pPage->GetObjCount();
248             for (size_t nObj = 0; nObj < nObjCount; ++nObj)
249             {
250                 SdrObject* pObj = pPage->GetObj(nObj);
251                 if (pObj->GetObjIdentifier() == OBJ_PAGE &&
252                     pObj->GetObjInventor() == SdrInventor::Default)
253                 {
254                     // The page object is the preceding page (drawing page)
255                     SAL_WARN_IF(!nStartPos, "sd", "Position of notes page must not be 0.");
256 
257                     SAL_WARN_IF(nPage <= 1, "sd", "Page object must not be a handout.");
258 
259                     if (nStartPos > 0 && nPage > 1)
260                         static_cast<SdrPageObj*>(pObj)->SetReferencedPage(GetPage(nPage - 1));
261                 }
262             }
263         }
264     }
265 }
266 
UpdatePageRelativeURLs(const OUString & rOldName,std::u16string_view rNewName)267 void SdDrawDocument::UpdatePageRelativeURLs(const OUString& rOldName, std::u16string_view rNewName)
268 {
269     if (rNewName.empty())
270         return;
271 
272     SfxItemPool& rPool(GetPool());
273     for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(EE_FEATURE_FIELD))
274     {
275         const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem * > (pItem);
276 
277         if(pFldItem)
278         {
279             SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
280 
281             if(pURLField)
282             {
283                 OUString aURL = pURLField->GetURL();
284 
285                 if (!aURL.isEmpty() && (aURL[0] == 35) && (aURL.indexOf(rOldName, 1) == 1))
286                 {
287                     if (aURL.getLength() == rOldName.getLength() + 1) // standard page name
288                     {
289                         aURL = aURL.replaceAt(1, aURL.getLength() - 1, "") +
290                             rNewName;
291                         pURLField->SetURL(aURL);
292                     }
293                     else
294                     {
295                         const OUString sNotes(SdResId(STR_NOTES));
296                         if (aURL.getLength() == rOldName.getLength() + 2 + sNotes.getLength()
297                             && aURL.indexOf(sNotes, rOldName.getLength() + 2) == rOldName.getLength() + 2)
298                         {
299                             aURL = aURL.replaceAt(1, aURL.getLength() - 1, "") +
300                                 rNewName + " " + sNotes;
301                             pURLField->SetURL(aURL);
302                         }
303                     }
304                 }
305             }
306         }
307     }
308 }
309 
UpdatePageRelativeURLs(SdPage const * pPage,sal_uInt16 nPos,sal_Int32 nIncrement)310 void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * pPage, sal_uInt16 nPos, sal_Int32 nIncrement)
311 {
312     bool bNotes = (pPage->GetPageKind() == PageKind::Notes);
313 
314     SfxItemPool& rPool(GetPool());
315     for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(EE_FEATURE_FIELD))
316     {
317         const SvxFieldItem* pFldItem;
318 
319         if ((pFldItem = dynamic_cast< const SvxFieldItem * > (pItem)) != nullptr)
320         {
321             SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
322 
323             if(pURLField)
324             {
325                 OUString aURL = pURLField->GetURL();
326 
327                 if (!aURL.isEmpty() && (aURL[0] == 35))
328                 {
329                     OUString aHashSlide = "#" + SdResId(STR_PAGE);
330 
331                     if (aURL.startsWith(aHashSlide))
332                     {
333                         OUString aURLCopy = aURL;
334                         const OUString sNotes(SdResId(STR_NOTES));
335 
336                         aURLCopy = aURLCopy.replaceAt(0, aHashSlide.getLength(), "");
337 
338                         bool bNotesLink = ( aURLCopy.getLength() >= sNotes.getLength() + 3
339                             && aURLCopy.endsWith(sNotes) );
340 
341                         if (bNotesLink != bNotes)
342                             continue; // no compatible link and page
343 
344                         if (bNotes)
345                             aURLCopy = aURLCopy.replaceAt(aURLCopy.getLength() - sNotes.getLength(), sNotes.getLength(), "");
346 
347                         sal_Int32 number = aURLCopy.toInt32();
348                         sal_uInt16 realPageNumber = (nPos + 1)/ 2;
349 
350                         if ( number >= realPageNumber )
351                         {
352                             // update link page number
353                             number += nIncrement;
354                             aURL = aURL.replaceAt(aHashSlide.getLength() + 1, aURL.getLength() - aHashSlide.getLength() - 1, "") +
355                                 OUString::number(number);
356                             if (bNotes)
357                             {
358                                 aURL += " " + sNotes;
359                             }
360                             pURLField->SetURL(aURL);
361                         }
362                     }
363                 }
364             }
365         }
366     }
367 }
368 
369 // Move page
MovePage(sal_uInt16 nPgNum,sal_uInt16 nNewPos)370 void SdDrawDocument::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
371 {
372     FmFormModel::MovePage(nPgNum, nNewPos);
373 
374     sal_uInt16 nMin = std::min(nPgNum, nNewPos);
375 
376     UpdatePageObjectsInNotes(nMin);
377 }
378 
379 // Insert page
InsertPage(SdrPage * pPage,sal_uInt16 nPos)380 void SdDrawDocument::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
381 {
382     bool bLast = (nPos == GetPageCount());
383 
384     FmFormModel::InsertPage(pPage, nPos);
385 
386     static_cast<SdPage*>(pPage)->ConnectLink();
387 
388     UpdatePageObjectsInNotes(nPos);
389 
390     if (!bLast)
391         UpdatePageRelativeURLs(static_cast<SdPage*>( pPage ), nPos, 1);
392 
393     if (comphelper::LibreOfficeKit::isActive() && static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard)
394     {
395         SdXImpressDocument* pDoc = comphelper::getUnoTunnelImplementation<SdXImpressDocument>(this->getUnoModel());
396         SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc);
397     }
398 }
399 
400 // Delete page
DeletePage(sal_uInt16 nPgNum)401 void SdDrawDocument::DeletePage(sal_uInt16 nPgNum)
402 {
403     FmFormModel::DeletePage(nPgNum);
404 
405     UpdatePageObjectsInNotes(nPgNum);
406 }
407 
408 // Remove page
RemovePage(sal_uInt16 nPgNum)409 rtl::Reference<SdrPage> SdDrawDocument::RemovePage(sal_uInt16 nPgNum)
410 {
411     rtl::Reference<SdrPage> pPage = FmFormModel::RemovePage(nPgNum);
412 
413     bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2);
414 
415     auto pSdPage = static_cast<SdPage*>(pPage.get());
416     pSdPage->DisconnectLink();
417     ReplacePageInCustomShows( pSdPage, nullptr );
418     UpdatePageObjectsInNotes(nPgNum);
419 
420     if (!bLast)
421         UpdatePageRelativeURLs(pSdPage, nPgNum, -1);
422 
423     if (comphelper::LibreOfficeKit::isActive() && pSdPage->GetPageKind() == PageKind::Standard)
424     {
425         SdXImpressDocument* pDoc = comphelper::getUnoTunnelImplementation<SdXImpressDocument>(this->getUnoModel());
426         SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc);
427     }
428 
429     return pPage;
430 }
431 
432 // Warning: This is not called for new master pages created from SdrModel::Merge,
433 // you also have to modify code in SdDrawDocument::Merge!
InsertMasterPage(SdrPage * pPage,sal_uInt16 nPos)434 void SdDrawDocument::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos )
435 {
436     FmFormModel::InsertMasterPage( pPage, nPos );
437     if( pPage->IsMasterPage() && (static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard) )
438     {
439         // new master page created, add its style family
440         SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
441         if( pStylePool )
442             pStylePool->AddStyleFamily( static_cast<SdPage*>(pPage) );
443     }
444 }
445 
RemoveMasterPage(sal_uInt16 nPgNum)446 rtl::Reference<SdrPage> SdDrawDocument::RemoveMasterPage(sal_uInt16 nPgNum)
447 {
448     SdPage* pPage = static_cast<SdPage*>(GetMasterPage(nPgNum ));
449     if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) )
450     {
451         // master page removed, remove its style family
452         SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
453         if( pStylePool )
454             pStylePool->RemoveStyleFamily( pPage );
455     }
456 
457     return FmFormModel::RemoveMasterPage(nPgNum);
458 }
459 
460 //Select pages
SetSelected(SdPage * pPage,bool bSelect)461 void SdDrawDocument::SetSelected(SdPage* pPage, bool bSelect)
462 {
463     PageKind ePageKind = pPage->GetPageKind();
464 
465     if (ePageKind == PageKind::Standard)
466     {
467         pPage->SetSelected(bSelect);
468 
469         const sal_uInt16 nDestPageNum(pPage->GetPageNum() + 1);
470         SdPage* pNotesPage = nullptr;
471 
472         if(nDestPageNum < GetPageCount())
473         {
474             pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum));
475         }
476 
477         if (pNotesPage && pNotesPage->GetPageKind() == PageKind::Notes)
478         {
479             pNotesPage->SetSelected(bSelect);
480         }
481     }
482     else if (ePageKind == PageKind::Notes)
483     {
484         pPage->SetSelected(bSelect);
485         SdPage* pStandardPage = static_cast<SdPage*>( GetPage( pPage->GetPageNum() - 1 ) );
486 
487         if (pStandardPage && pStandardPage->GetPageKind() == PageKind::Standard)
488             pStandardPage->SetSelected(bSelect);
489     }
490 }
491 
492 // If no pages exist yet, create them now
CreateFirstPages(SdDrawDocument const * pRefDocument)493 void SdDrawDocument::CreateFirstPages( SdDrawDocument const * pRefDocument /* = 0 */ )
494 {
495     // If no page exists yet in the model, (File -> New), insert a page
496     sal_uInt16 nPageCount = GetPageCount();
497 
498     if (nPageCount > 1)
499         return;
500 
501     // #i57181# Paper size depends on Language, like in Writer
502     Size aDefSize = SvxPaperInfo::GetDefaultPaperSize( MapUnit::Map100thMM );
503 
504     // Insert handout page
505     rtl::Reference<SdPage> pHandoutPage = AllocSdPage(false);
506 
507     SdPage* pRefPage = nullptr;
508 
509     if( pRefDocument )
510         pRefPage = pRefDocument->GetSdPage( 0, PageKind::Handout );
511 
512     if( pRefPage )
513     {
514         pHandoutPage->SetSize(pRefPage->GetSize());
515         pHandoutPage->SetBorder( pRefPage->GetLeftBorder(), pRefPage->GetUpperBorder(), pRefPage->GetRightBorder(), pRefPage->GetLowerBorder() );
516     }
517     else
518     {
519         pHandoutPage->SetSize(aDefSize);
520         pHandoutPage->SetBorder(0, 0, 0, 0);
521     }
522 
523     pHandoutPage->SetPageKind(PageKind::Handout);
524     pHandoutPage->SetName( SdResId(STR_HANDOUT) );
525     InsertPage(pHandoutPage.get(), 0);
526 
527     // Insert master page and register this with the handout page
528     rtl::Reference<SdPage> pHandoutMPage = AllocSdPage(true);
529     pHandoutMPage->SetSize( pHandoutPage->GetSize() );
530     pHandoutMPage->SetPageKind(PageKind::Handout);
531     pHandoutMPage->SetBorder( pHandoutPage->GetLeftBorder(),
532                               pHandoutPage->GetUpperBorder(),
533                               pHandoutPage->GetRightBorder(),
534                               pHandoutPage->GetLowerBorder() );
535     InsertMasterPage(pHandoutMPage.get(), 0);
536     pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
537 
538     // Insert page
539     // If nPageCount==1 is, the model for the clipboard was created, thus a
540     // default page must already exist
541     rtl::Reference<SdPage> pPage;
542     bool bClipboard = false;
543 
544     if( pRefDocument )
545         pRefPage = pRefDocument->GetSdPage( 0, PageKind::Standard );
546 
547     if (nPageCount == 0)
548     {
549         pPage = AllocSdPage(false);
550 
551         if( pRefPage )
552         {
553             pPage->SetSize( pRefPage->GetSize() );
554             pPage->SetBorder( pRefPage->GetLeftBorder(), pRefPage->GetUpperBorder(), pRefPage->GetRightBorder(), pRefPage->GetLowerBorder() );
555         }
556         else if (meDocType == DocumentType::Draw)
557         {
558             // Draw: always use default size with margins
559             pPage->SetSize(aDefSize);
560 
561             SfxPrinter* pPrinter = mpDocSh->GetPrinter(false);
562             if (pPrinter && pPrinter->IsValid())
563             {
564                 Size aOutSize(pPrinter->GetOutputSize());
565                 Point aPageOffset(pPrinter->GetPageOffset());
566                 aPageOffset -= pPrinter->PixelToLogic( Point() );
567                 ::tools::Long nOffset = !aPageOffset.X() && !aPageOffset.Y() ? 0 : PRINT_OFFSET;
568 
569                 sal_uLong nTop    = aPageOffset.Y();
570                 sal_uLong nLeft   = aPageOffset.X();
571                 sal_uLong nBottom = std::max(::tools::Long(aDefSize.Height() - aOutSize.Height() - nTop + nOffset), ::tools::Long(0));
572                 sal_uLong nRight  = std::max(::tools::Long(aDefSize.Width() - aOutSize.Width() - nLeft + nOffset), ::tools::Long(0));
573 
574                 pPage->SetBorder(nLeft, nTop, nRight, nBottom);
575             }
576             else
577             {
578                 // The printer is not available.  Use a border of 10mm
579                 // on each side instead.
580                 // This has to be kept synchronized with the border
581                 // width set in the
582                 // SvxPageDescPage::PaperSizeSelect_Impl callback.
583                 pPage->SetBorder(1000, 1000, 1000, 1000);
584             }
585         }
586         else
587         {
588             // Impress: always use screen format, landscape.
589             Size aSz( SvxPaperInfo::GetPaperSize(PAPER_SCREEN_16_9, MapUnit::Map100thMM) );
590             pPage->SetSize( Size( aSz.Height(), aSz.Width() ) );
591             pPage->SetBorder(0, 0, 0, 0);
592         }
593 
594         InsertPage(pPage.get(), 1);
595     }
596     else
597     {
598         bClipboard = true;
599         pPage = static_cast<SdPage*>( GetPage(1) );
600     }
601 
602     // Insert master page, then register this with the page
603     rtl::Reference<SdPage> pMPage = AllocSdPage(true);
604     pMPage->SetSize( pPage->GetSize() );
605     pMPage->SetBorder( pPage->GetLeftBorder(),
606                        pPage->GetUpperBorder(),
607                        pPage->GetRightBorder(),
608                        pPage->GetLowerBorder() );
609     InsertMasterPage(pMPage.get(), 1);
610     pPage->TRG_SetMasterPage( *pMPage );
611     if( bClipboard )
612         pMPage->SetLayoutName( pPage->GetLayoutName() );
613 
614     // Insert notes page
615     rtl::Reference<SdPage> pNotesPage = AllocSdPage(false);
616 
617     if( pRefDocument )
618         pRefPage = pRefDocument->GetSdPage( 0, PageKind::Notes );
619 
620     if( pRefPage )
621     {
622         pNotesPage->SetSize( pRefPage->GetSize() );
623         pNotesPage->SetBorder( pRefPage->GetLeftBorder(), pRefPage->GetUpperBorder(), pRefPage->GetRightBorder(), pRefPage->GetLowerBorder() );
624     }
625     else
626     {
627         // Always use portrait format
628         if (aDefSize.Height() >= aDefSize.Width())
629         {
630             pNotesPage->SetSize(aDefSize);
631         }
632         else
633         {
634             pNotesPage->SetSize( Size(aDefSize.Height(), aDefSize.Width()) );
635         }
636 
637         pNotesPage->SetBorder(0, 0, 0, 0);
638     }
639     pNotesPage->SetPageKind(PageKind::Notes);
640     InsertPage(pNotesPage.get(), 2);
641     if( bClipboard )
642         pNotesPage->SetLayoutName( pPage->GetLayoutName() );
643 
644     // Insert master page, then register this with the notes page
645     rtl::Reference<SdPage> pNotesMPage = AllocSdPage(true);
646     pNotesMPage->SetSize( pNotesPage->GetSize() );
647     pNotesMPage->SetPageKind(PageKind::Notes);
648     pNotesMPage->SetBorder( pNotesPage->GetLeftBorder(),
649                             pNotesPage->GetUpperBorder(),
650                             pNotesPage->GetRightBorder(),
651                             pNotesPage->GetLowerBorder() );
652     InsertMasterPage(pNotesMPage.get(), 2);
653     pNotesPage->TRG_SetMasterPage( *pNotesMPage );
654     if( bClipboard )
655         pNotesMPage->SetLayoutName( pPage->GetLayoutName() );
656 
657     if( !pRefPage && (meDocType != DocumentType::Draw) )
658         pPage->SetAutoLayout( AUTOLAYOUT_TITLE, true, true );
659 
660     mpWorkStartupTimer.reset( new Timer("DrawWorkStartupTimer") );
661     mpWorkStartupTimer->SetInvokeHandler( LINK(this, SdDrawDocument, WorkStartupHdl) );
662     mpWorkStartupTimer->SetTimeout(2000);
663     mpWorkStartupTimer->Start();
664 
665     SetChanged(false);
666 }
667 
668 // Creates missing notes and handout pages (after PowerPoint import).
669 // We assume that at least one default page and one default master page exist.
670 
CreateMissingNotesAndHandoutPages()671 bool SdDrawDocument::CreateMissingNotesAndHandoutPages()
672 {
673     bool bOK = false;
674     sal_uInt16 nPageCount = GetPageCount();
675 
676     if (nPageCount != 0)
677     {
678         // Set PageKind
679         SdPage* pHandoutMPage = static_cast<SdPage*>( GetMasterPage(0) );
680         pHandoutMPage->SetPageKind(PageKind::Handout);
681 
682         SdPage* pHandoutPage = static_cast<SdPage*>( GetPage(0) );
683         pHandoutPage->SetPageKind(PageKind::Handout);
684         pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
685 
686         for (sal_uInt16 i = 1; i < nPageCount; i = i + 2)
687         {
688             SdPage* pPage = static_cast<SdPage*>( GetPage(i) );
689 
690             if(!pPage->TRG_HasMasterPage())
691             {
692                 // No master page set -> use first default master page
693                 // (If there was no default page in the PPT)
694                 pPage->TRG_SetMasterPage(*GetMasterPage(1));
695             }
696 
697             SdPage* pNotesPage = static_cast<SdPage*>( GetPage(i+1) );
698             pNotesPage->SetPageKind(PageKind::Notes);
699 
700             // Set notes master page
701             sal_uInt16 nMasterPageAfterPagesMasterPage = pPage->TRG_GetMasterPage().GetPageNum() + 1;
702             pNotesPage->TRG_SetMasterPage(*GetMasterPage(nMasterPageAfterPagesMasterPage));
703         }
704 
705         bOK = true;
706         StopWorkStartupDelay();
707         SetChanged(false);
708     }
709 
710     return bOK;
711 }
712 
UnselectAllPages()713 void SdDrawDocument::UnselectAllPages()
714 {
715     sal_uInt16 nNoOfPages = GetSdPageCount(PageKind::Standard);
716     for (sal_uInt16 nPage = 0; nPage < nNoOfPages; ++nPage)
717     {
718         SdPage* pPage = GetSdPage(nPage, PageKind::Standard);
719         pPage->SetSelected(false);
720     }
721 }
722 
723 // + Move selected pages after said page
724 //   (nTargetPage = (sal_uInt16)-1  --> move before first page)
725 // + Returns sal_True when the page has been moved
MovePages(sal_uInt16 nTargetPage)726 bool SdDrawDocument::MovePages(sal_uInt16 nTargetPage)
727 {
728     SdPage* pPage              = nullptr;
729     sal_uInt16  nPage;
730     sal_uInt16  nNoOfPages         = GetSdPageCount(PageKind::Standard);
731     bool    bSomethingHappened = false;
732 
733     const bool bUndo = IsUndoEnabled();
734 
735     if( bUndo )
736         BegUndo(SdResId(STR_UNDO_MOVEPAGES));
737 
738     // List of selected pages
739     std::vector<SdPage*> aPageList;
740     for (nPage = 0; nPage < nNoOfPages; nPage++)
741     {
742         pPage = GetSdPage(nPage, PageKind::Standard);
743 
744         if (pPage->IsSelected()) {
745             aPageList.push_back(pPage);
746         }
747     }
748 
749     // If necessary, look backwards, until we find a page that wasn't selected
750     nPage = nTargetPage;
751 
752     if (nPage != sal_uInt16(-1))
753     {
754         pPage = GetSdPage(nPage, PageKind::Standard);
755         while (nPage > 0 && pPage->IsSelected())
756         {
757             nPage--;
758             pPage = GetSdPage(nPage, PageKind::Standard);
759         }
760 
761         if (pPage->IsSelected())
762         {
763             nPage = sal_uInt16(-1);
764         }
765     }
766 
767     // Insert before the first page
768     if (nPage == sal_uInt16(-1))
769     {
770         std::vector<SdPage*>::reverse_iterator iter;
771         for (iter = aPageList.rbegin(); iter != aPageList.rend(); ++iter)
772         {
773             nPage = (*iter)->GetPageNum();
774             if (nPage != 0)
775             {
776                 SdrPage* pPg = GetPage(nPage);
777                 if( bUndo )
778                     AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, 1));
779                 MovePage(nPage, 1);
780                 pPg = GetPage(nPage+1);
781                 if( bUndo )
782                     AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, 2));
783                 MovePage(nPage+1, 2);
784                 bSomethingHappened = true;
785             }
786         }
787     }
788     // Insert after <nPage>
789     else
790     {
791         nTargetPage = 2 * nPage + 1;    // PageKind::Standard --> absolute
792 
793         for (const auto& rpPage : aPageList)
794         {
795             nPage = rpPage->GetPageNum();
796             if (nPage > nTargetPage)
797             {
798                 nTargetPage += 2;        // Insert _after_ the page
799 
800                 if (nPage != nTargetPage)
801                 {
802                     SdrPage* pPg = GetPage(nPage);
803                     if( bUndo )
804                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
805                     MovePage(nPage, nTargetPage);
806                     pPg = GetPage(nPage+1);
807                     if( bUndo )
808                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
809                     MovePage(nPage+1, nTargetPage+1);
810                     bSomethingHappened = true;
811                 }
812             }
813             else
814             {
815                 if (nPage != nTargetPage)
816                 {
817                     SdrPage* pPg = GetPage(nPage+1);
818                     if( bUndo )
819                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
820                     MovePage(nPage+1, nTargetPage+1);
821                     pPg = GetPage(nPage);
822                     if( bUndo )
823                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
824                     MovePage(nPage, nTargetPage);
825                     bSomethingHappened = true;
826                 }
827             }
828             nTargetPage = rpPage->GetPageNum();
829         }
830     }
831 
832     if( bUndo )
833         EndUndo();
834 
835     return bSomethingHappened;
836 }
837 
838 // Return number of links in sfx2::LinkManager
GetLinkCount() const839 sal_uLong SdDrawDocument::GetLinkCount() const
840 {
841     return m_pLinkManager->GetLinks().size();
842 }
843 
844 // Set Language
SetLanguage(const LanguageType eLang,const sal_uInt16 nId)845 void SdDrawDocument::SetLanguage( const LanguageType eLang, const sal_uInt16 nId )
846 {
847     bool bChanged = false;
848 
849     if( nId == EE_CHAR_LANGUAGE && meLanguage != eLang )
850     {
851         meLanguage = eLang;
852         bChanged = true;
853     }
854     else if( nId == EE_CHAR_LANGUAGE_CJK && meLanguageCJK != eLang )
855     {
856         meLanguageCJK = eLang;
857         bChanged = true;
858     }
859     else if( nId == EE_CHAR_LANGUAGE_CTL && meLanguageCTL != eLang )
860     {
861         meLanguageCTL = eLang;
862         bChanged = true;
863     }
864 
865     if( bChanged )
866     {
867         GetDrawOutliner().SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
868         m_pHitTestOutliner->SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
869         m_pItemPool->SetPoolDefaultItem( SvxLanguageItem( eLang, nId ) );
870         SetChanged( bChanged );
871     }
872 }
873 
874 // Return language
GetLanguage(const sal_uInt16 nId) const875 LanguageType SdDrawDocument::GetLanguage( const sal_uInt16 nId ) const
876 {
877     LanguageType eLangType = meLanguage;
878 
879     if( nId == EE_CHAR_LANGUAGE_CJK )
880         eLangType = meLanguageCJK;
881     else if( nId == EE_CHAR_LANGUAGE_CTL )
882         eLangType = meLanguageCTL;
883 
884     return eLangType;
885 }
886 
887 // Initiate WorkStartup
IMPL_LINK_NOARG(SdDrawDocument,WorkStartupHdl,Timer *,void)888 IMPL_LINK_NOARG(SdDrawDocument, WorkStartupHdl, Timer *, void)
889 {
890     if (IsTransportContainer())
891         return;
892 
893     if( mpDocSh )
894         mpDocSh->SetWaitCursor( true );
895 
896     bool bChanged = IsChanged();        // remember this
897 
898     // Initialize Autolayouts
899     SdPage* pHandoutMPage = GetMasterSdPage(0, PageKind::Handout);
900 
901     if (pHandoutMPage->GetAutoLayout() == AUTOLAYOUT_NONE)
902     {
903         // No AutoLayout yet -> initialize
904         pHandoutMPage->SetAutoLayout(AUTOLAYOUT_HANDOUT6, true, true);
905     }
906 
907     SdPage* pPage = GetSdPage(0, PageKind::Standard);
908 
909     if (pPage->GetAutoLayout() == AUTOLAYOUT_NONE)
910     {
911         // No AutoLayout yet -> initialize
912         pPage->SetAutoLayout(AUTOLAYOUT_NONE, true, true);
913     }
914 
915     SdPage* pNotesPage = GetSdPage(0, PageKind::Notes);
916 
917     if (pNotesPage->GetAutoLayout() == AUTOLAYOUT_NONE)
918     {
919         // No AutoLayout yet -> initialize
920         pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
921     }
922 
923     SetChanged(bChanged);
924 
925     if( mpDocSh )
926         mpDocSh->SetWaitCursor( false );
927 }
928 
929 // When the WorkStartupTimer has been created (this only happens in
930 // SdDrawViewShell::Construct() ), the timer may be stopped and the WorkStartup
931 // may be initiated.
StopWorkStartupDelay()932 void SdDrawDocument::StopWorkStartupDelay()
933 {
934     if (mpWorkStartupTimer)
935     {
936         if ( mpWorkStartupTimer->IsActive() )
937         {
938             // Timer not yet expired -> initiate WorkStartup
939             mpWorkStartupTimer->Stop();
940             WorkStartupHdl(nullptr);
941         }
942 
943         mpWorkStartupTimer.reset();
944     }
945 }
946 
947 // When the WorkStartupTimer has been created (this only happens in
948 // SdDrawViewShell::Construct() ), the timer may be stopped and the WorkStartup
949 // may be initiated.
GetAnimationInfo(SdrObject * pObject)950 SdAnimationInfo* SdDrawDocument::GetAnimationInfo(SdrObject* pObject)
951 {
952     DBG_ASSERT(pObject, "sd::SdDrawDocument::GetAnimationInfo(), invalid argument!");
953     if( pObject )
954         return GetShapeUserData( *pObject );
955     else
956         return nullptr;
957 }
958 
GetShapeUserData(SdrObject & rObject,bool bCreate)959 SdAnimationInfo* SdDrawDocument::GetShapeUserData(SdrObject& rObject, bool bCreate /* = false */ )
960 {
961     sal_uInt16 nUD          = 0;
962     sal_uInt16 nUDCount     = rObject.GetUserDataCount();
963     SdAnimationInfo* pRet = nullptr;
964 
965     // Can we find animation information within the user data?
966     for (nUD = 0; nUD < nUDCount; nUD++)
967     {
968         SdrObjUserData* pUD = rObject.GetUserData(nUD);
969         if((pUD->GetInventor() == SdrInventor::StarDrawUserData) && (pUD->GetId() == SD_ANIMATIONINFO_ID))
970         {
971             pRet = dynamic_cast<SdAnimationInfo*>(pUD);
972             break;
973         }
974     }
975 
976     if( (pRet == nullptr) && bCreate )
977     {
978         pRet = new SdAnimationInfo( rObject );
979         rObject.AppendUserData( std::unique_ptr<SdrObjUserData>(pRet) );
980     }
981 
982     return pRet;
983 }
984 
985 /** this method enforces that the masterpages are in the correct order,
986     that is at position 1 is a PageKind::Standard masterpage followed by a
987     PageKind::Notes masterpage and so on. #
988 */
CheckMasterPages()989 void SdDrawDocument::CheckMasterPages()
990 {
991     sal_uInt16 nMaxPages = GetMasterPageCount();
992 
993     // we need at least a handout master and one master page
994     if( nMaxPages < 2 )
995     {
996         return;
997     }
998 
999     SdPage* pPage = nullptr;
1000 
1001     sal_uInt16 nPage;
1002 
1003     // first see if the page order is correct
1004     for( nPage = 1; nPage < nMaxPages; nPage++ )
1005     {
1006         pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
1007         // if an odd page is not a standard page or an even page is not a notes page
1008         if( ((1 == (nPage & 1)) && (pPage->GetPageKind() != PageKind::Standard) ) ||
1009             ((0 == (nPage & 1)) && (pPage->GetPageKind() != PageKind::Notes) ) )
1010             break; // then we have a fatal error
1011     }
1012 
1013     if( nPage >= nMaxPages )
1014         return;
1015 
1016     SdPage* pNotesPage = nullptr;
1017 
1018     // there is a fatal error in the master page order,
1019     // we need to repair the document
1020     bool bChanged = false;
1021 
1022     nPage = 1;
1023     while( nPage < nMaxPages )
1024     {
1025         pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
1026         if( pPage->GetPageKind() != PageKind::Standard )
1027         {
1028             bChanged = true;
1029             sal_uInt16 nFound = nPage + 1;
1030             while( nFound < nMaxPages )
1031             {
1032                 pPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1033                 if( PageKind::Standard == pPage->GetPageKind() )
1034                 {
1035                     MoveMasterPage( nFound, nPage );
1036                     pPage->SetInserted();
1037                     break;
1038 
1039                 }
1040 
1041                 nFound++;
1042             }
1043 
1044             // if we don't have any more standard pages, were done
1045             if( nMaxPages == nFound )
1046                 break;
1047         }
1048 
1049         nPage++;
1050 
1051         if( nPage < nMaxPages )
1052             pNotesPage = static_cast<SdPage*>(GetMasterPage( nPage ));
1053         else
1054             pNotesPage = nullptr;
1055 
1056         if( (nullptr == pNotesPage) || (pNotesPage->GetPageKind() != PageKind::Notes) || ( pPage->GetLayoutName() != pNotesPage->GetLayoutName() ) )
1057         {
1058             bChanged = true;
1059 
1060             sal_uInt16 nFound = nPage + 1;
1061             while( nFound < nMaxPages )
1062             {
1063                 pNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1064                 if( (PageKind::Notes == pNotesPage->GetPageKind()) && ( pPage->GetLayoutName() == pNotesPage->GetLayoutName() ) )
1065                 {
1066                     MoveMasterPage( nFound, nPage );
1067                     pNotesPage->SetInserted();
1068                     break;
1069                 }
1070 
1071                 nFound++;
1072             }
1073 
1074             // looks like we lost a notes page
1075             if( nMaxPages == nFound )
1076             {
1077                 // so create one
1078 
1079                 // first find a reference notes page for size
1080                 SdPage* pRefNotesPage = nullptr;
1081                 nFound = 0;
1082                 while( nFound < nMaxPages )
1083                 {
1084                     pRefNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1085                     if( PageKind::Notes == pRefNotesPage->GetPageKind() )
1086                         break;
1087                     nFound++;
1088                 }
1089                 if( nFound == nMaxPages )
1090                     pRefNotesPage = nullptr;
1091 
1092                 rtl::Reference<SdPage> pNewNotesPage = AllocSdPage(true);
1093                 pNewNotesPage->SetPageKind(PageKind::Notes);
1094                 if( pRefNotesPage )
1095                 {
1096                     pNewNotesPage->SetSize( pRefNotesPage->GetSize() );
1097                     pNewNotesPage->SetBorder( pRefNotesPage->GetLeftBorder(),
1098                                             pRefNotesPage->GetUpperBorder(),
1099                                             pRefNotesPage->GetRightBorder(),
1100                                             pRefNotesPage->GetLowerBorder() );
1101                 }
1102                 InsertMasterPage(pNewNotesPage.get(),  nPage );
1103                 pNewNotesPage->SetLayoutName( pPage->GetLayoutName() );
1104                 pNewNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true );
1105                 nMaxPages++;
1106             }
1107         }
1108 
1109         nPage++;
1110     }
1111 
1112     // now remove all remaining and unused non PageKind::Standard slides
1113     while( nPage < nMaxPages )
1114     {
1115         bChanged = true;
1116 
1117         RemoveMasterPage( nPage );
1118         nMaxPages--;
1119     }
1120 
1121     if( bChanged )
1122     {
1123         OSL_FAIL( "master pages where in a wrong order" );
1124         RecalcPageNums( true);
1125     }
1126 }
1127 
CreatePage(SdPage * pActualPage,PageKind ePageKind,const OUString & sStandardPageName,const OUString & sNotesPageName,AutoLayout eStandardLayout,AutoLayout eNotesLayout,bool bIsPageBack,bool bIsPageObj,const sal_Int32 nInsertPosition)1128 sal_uInt16 SdDrawDocument::CreatePage (
1129     SdPage* pActualPage,
1130     PageKind ePageKind,
1131     const OUString& sStandardPageName,
1132     const OUString& sNotesPageName,
1133     AutoLayout eStandardLayout,
1134     AutoLayout eNotesLayout,
1135     bool bIsPageBack,
1136     bool bIsPageObj,
1137     const sal_Int32 nInsertPosition)
1138 {
1139     SdPage* pPreviousStandardPage;
1140     SdPage* pPreviousNotesPage;
1141     rtl::Reference<SdPage> pStandardPage;
1142     rtl::Reference<SdPage> pNotesPage;
1143 
1144     // From the given page determine the standard page and notes page of which
1145     // to take the layout and the position where to insert the new pages.
1146     if (ePageKind == PageKind::Notes)
1147     {
1148         pPreviousNotesPage = pActualPage;
1149         sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1150         pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
1151         eStandardLayout = pPreviousStandardPage->GetAutoLayout();
1152     }
1153     else
1154     {
1155         pPreviousStandardPage = pActualPage;
1156         sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1157         pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
1158         eNotesLayout = pPreviousNotesPage->GetAutoLayout();
1159     }
1160 
1161     // Create new standard page and set it up
1162     pStandardPage = AllocSdPage(false);
1163 
1164     // Set the size here since else the presobj autolayout
1165     // will be wrong.
1166     pStandardPage->SetSize( pPreviousStandardPage->GetSize() );
1167     pStandardPage->SetBorder( pPreviousStandardPage->GetLeftBorder(),
1168                               pPreviousStandardPage->GetUpperBorder(),
1169                               pPreviousStandardPage->GetRightBorder(),
1170                               pPreviousStandardPage->GetLowerBorder() );
1171 
1172     // Use master page of current page.
1173     pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage());
1174 
1175     // User layout of current standard page
1176     pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() );
1177     pStandardPage->SetAutoLayout(eStandardLayout, true);
1178     pStandardPage->setHeaderFooterSettings( pPreviousStandardPage->getHeaderFooterSettings() );
1179 
1180     // transition settings of current page
1181     pStandardPage->setTransitionType( pPreviousStandardPage->getTransitionType() );
1182     pStandardPage->setTransitionSubtype( pPreviousStandardPage->getTransitionSubtype() );
1183     pStandardPage->setTransitionDirection( pPreviousStandardPage->getTransitionDirection() );
1184     pStandardPage->setTransitionFadeColor( pPreviousStandardPage->getTransitionFadeColor() );
1185     pStandardPage->setTransitionDuration( pPreviousStandardPage->getTransitionDuration() );
1186 
1187     // apply previous animation timing
1188     pStandardPage->SetPresChange( pPreviousStandardPage->GetPresChange() );
1189     pStandardPage->SetTime( pPreviousStandardPage->GetTime() );
1190 
1191     // Create new notes page and set it up
1192     pNotesPage = AllocSdPage(false);
1193     pNotesPage->SetPageKind(PageKind::Notes);
1194 
1195     // Use master page of current page
1196     pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage());
1197 
1198     // Use layout of current notes page
1199     pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() );
1200     pNotesPage->SetAutoLayout(eNotesLayout, true);
1201     pNotesPage->setHeaderFooterSettings( pPreviousNotesPage->getHeaderFooterSettings() );
1202 
1203     return InsertPageSet (
1204         pActualPage,
1205         ePageKind,
1206         sStandardPageName,
1207         sNotesPageName,
1208         bIsPageBack,
1209         bIsPageObj,
1210         pStandardPage.get(),
1211         pNotesPage.get(),
1212         nInsertPosition);
1213 }
1214 
DuplicatePage(sal_uInt16 nPageNum)1215 sal_uInt16 SdDrawDocument::DuplicatePage (sal_uInt16 nPageNum)
1216 {
1217     PageKind ePageKind = PageKind::Standard;
1218 
1219     // Get current page
1220     SdPage* pActualPage = GetSdPage(nPageNum, ePageKind);
1221 
1222     // Get background flags
1223     SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
1224     SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
1225     SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
1226     SdrLayerIDSet aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers();
1227 
1228     return DuplicatePage (
1229         pActualPage, ePageKind,
1230         // No names for the new slides
1231         OUString(), OUString(),
1232         aVisibleLayers.IsSet(aBckgrnd),
1233         aVisibleLayers.IsSet(aBckgrndObj), -1);
1234 }
1235 
DuplicatePage(SdPage * pActualPage,PageKind ePageKind,const OUString & sStandardPageName,const OUString & sNotesPageName,bool bIsPageBack,bool bIsPageObj,const sal_Int32 nInsertPosition)1236 sal_uInt16 SdDrawDocument::DuplicatePage (
1237     SdPage* pActualPage,
1238     PageKind ePageKind,
1239     const OUString& sStandardPageName,
1240     const OUString& sNotesPageName,
1241     bool bIsPageBack,
1242     bool bIsPageObj,
1243     const sal_Int32 nInsertPosition)
1244 {
1245     SdPage* pPreviousStandardPage;
1246     SdPage* pPreviousNotesPage;
1247     rtl::Reference<SdPage> pStandardPage;
1248     rtl::Reference<SdPage> pNotesPage;
1249 
1250     // From the given page determine the standard page and the notes page
1251     // of which to make copies.
1252     if (ePageKind == PageKind::Notes)
1253     {
1254         pPreviousNotesPage = pActualPage;
1255         sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1256         pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
1257     }
1258     else
1259     {
1260         pPreviousStandardPage = pActualPage;
1261         sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1262         pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
1263     }
1264 
1265     // Create duplicates of a standard page and the associated notes page
1266     pStandardPage = static_cast<SdPage*>( pPreviousStandardPage->CloneSdrPage(*this).get() );
1267     pNotesPage = static_cast<SdPage*>( pPreviousNotesPage->CloneSdrPage(*this).get() );
1268 
1269     return InsertPageSet (
1270         pActualPage,
1271         ePageKind,
1272         sStandardPageName,
1273         sNotesPageName,
1274         bIsPageBack,
1275         bIsPageObj,
1276         pStandardPage.get(),
1277         pNotesPage.get(),
1278         nInsertPosition);
1279 }
1280 
InsertPageSet(SdPage * pActualPage,PageKind ePageKind,const OUString & sStandardPageName,const OUString & sNotesPageName,bool bIsPageBack,bool bIsPageObj,SdPage * pStandardPage,SdPage * pNotesPage,sal_Int32 nInsertPosition)1281 sal_uInt16 SdDrawDocument::InsertPageSet (
1282     SdPage* pActualPage,
1283     PageKind ePageKind,
1284     const OUString& sStandardPageName,
1285     const OUString& sNotesPageName,
1286     bool bIsPageBack,
1287     bool bIsPageObj,
1288     SdPage* pStandardPage,
1289     SdPage* pNotesPage,
1290     sal_Int32 nInsertPosition)
1291 {
1292     SdPage* pPreviousStandardPage;
1293     SdPage* pPreviousNotesPage;
1294     sal_uInt16 nStandardPageNum;
1295     sal_uInt16 nNotesPageNum;
1296     OUString aNotesPageName(sNotesPageName);
1297 
1298     // Gather some information about the standard page and the notes page
1299     // that are to be inserted. This makes sure that there is always one
1300     // standard page followed by one notes page.
1301     if (ePageKind == PageKind::Notes)
1302     {
1303         pPreviousNotesPage = pActualPage;
1304         nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1305         pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
1306         nStandardPageNum = nNotesPageNum - 1;
1307     }
1308     else
1309     {
1310         pPreviousStandardPage = pActualPage;
1311         nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1312         pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
1313         nNotesPageNum = nStandardPageNum + 1;
1314         aNotesPageName = sStandardPageName;
1315     }
1316 
1317     OSL_ASSERT(nNotesPageNum==nStandardPageNum+1);
1318     if (nInsertPosition < 0)
1319         nInsertPosition = nStandardPageNum;
1320 
1321     // Set up and insert the standard page
1322     SetupNewPage (
1323         pPreviousStandardPage,
1324         pStandardPage,
1325         sStandardPageName,
1326         nInsertPosition,
1327         bIsPageBack,
1328         bIsPageObj);
1329 
1330     // Set up and insert the notes page
1331     pNotesPage->SetPageKind(PageKind::Notes);
1332     SetupNewPage (
1333         pPreviousNotesPage,
1334         pNotesPage,
1335         aNotesPageName,
1336         nInsertPosition+1,
1337         bIsPageBack,
1338         bIsPageObj);
1339 
1340     // Return an index that allows the caller to access the newly inserted
1341     // pages by using GetSdPage()
1342     return pStandardPage->GetPageNum() / 2;
1343 }
1344 
SetupNewPage(SdPage const * pPreviousPage,SdPage * pPage,const OUString & sPageName,sal_uInt16 nInsertionPoint,bool bIsPageBack,bool bIsPageObj)1345 void SdDrawDocument::SetupNewPage (
1346     SdPage const * pPreviousPage,
1347     SdPage* pPage,
1348     const OUString& sPageName,
1349     sal_uInt16 nInsertionPoint,
1350     bool bIsPageBack,
1351     bool bIsPageObj)
1352 {
1353     if (pPreviousPage != nullptr)
1354     {
1355         pPage->SetSize( pPreviousPage->GetSize() );
1356         pPage->SetBorder( pPreviousPage->GetLeftBorder(),
1357             pPreviousPage->GetUpperBorder(),
1358             pPreviousPage->GetRightBorder(),
1359             pPreviousPage->GetLowerBorder() );
1360     }
1361     pPage->SetName(sPageName);
1362 
1363     InsertPage(pPage, nInsertionPoint);
1364 
1365     if (pPreviousPage != nullptr)
1366     {
1367         SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
1368         SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
1369         SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
1370         SdrLayerIDSet aVisibleLayers = pPreviousPage->TRG_GetMasterPageVisibleLayers();
1371         aVisibleLayers.Set(aBckgrnd, bIsPageBack);
1372         aVisibleLayers.Set(aBckgrndObj, bIsPageObj);
1373         pPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
1374     }
1375 }
1376 
GetUndoManager() const1377 sd::UndoManager* SdDrawDocument::GetUndoManager() const
1378 {
1379     return mpDocSh ? dynamic_cast< sd::UndoManager* >(mpDocSh->GetUndoManager()) : nullptr;
1380 }
1381 
1382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1383