xref: /trunk/main/sd/source/core/drawdoc2.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 
32 #include <com/sun/star/embed/XVisualObject.hpp>
33 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
34 #include <vcl/wrkwin.hxx>
35 #include <sfx2/printer.hxx>
36 #include <sfx2/app.hxx>
37 #ifndef SD_OUTLINE_HXX
38 #include "Outliner.hxx"
39 #endif
40 #include <editeng/paperinf.hxx>
41 #include <svx/svdopage.hxx>
42 #include <svx/svdoole2.hxx>
43 #include <svx/svdotext.hxx>
44 #include <svx/svdograf.hxx>
45 #include <svx/svdundo.hxx>
46 #include <vcl/svapp.hxx>
47 #include <editeng/eeitem.hxx>
48 #include <editeng/langitem.hxx>
49 #include <svl/itempool.hxx>
50 #include <svx/svdpool.hxx>
51 #include <editeng/flditem.hxx>
52 
53 #include <sfx2/linkmgr.hxx>
54 #include <editeng/editdata.hxx>
55 #include <svx/dialogs.hrc>
56 #include <svx/dialmgr.hxx>                  // SVX_RESSTR
57 
58 #include "eetext.hxx"
59 #include <svx/svditer.hxx>
60 #include <svtools/imapobj.hxx>
61 
62 
63 #include "sdresid.hxx"
64 #include "drawdoc.hxx"
65 #include "sdpage.hxx"
66 #include "pglink.hxx"
67 #include "glob.hrc"
68 #include "glob.hxx"
69 #include "stlpool.hxx"
70 #include "sdiocmpt.hxx"
71 #include "anminfo.hxx"
72 #include "imapinfo.hxx"
73 #include "cusshow.hxx"
74 #include "undo/undomanager.hxx"
75 
76 #include "../ui/inc/DrawDocShell.hxx"
77 #include "../ui/inc/FrameView.hxx"
78 #include "../ui/inc/cfgids.hxx"
79 #include "../ui/inc/strings.hrc"
80 
81 #include "PageListWatcher.hxx"
82 #include <vcl/virdev.hxx>
83 
84 using namespace ::sd;
85 
86 const long PRINT_OFFSET = 30;       // siehe \svx\source\dialog\page.cxx (PB)
87 
88 using namespace com::sun::star;
89 
90 /*************************************************************************
91 |*
92 |* Sucht ein Objekt per Name
93 |*
94 \************************************************************************/
95 
96 SdrObject* SdDrawDocument::GetObj(const String& rObjName) const
97 {
98     SdrObject* pObj = NULL;
99     SdrObject* pObjFound = NULL;
100     SdPage* pPage = NULL;
101 
102     /**************************************************************************
103     * Zuerst alle Pages durchsuchen
104     **************************************************************************/
105     sal_uInt16 nPage = 0;
106     const sal_uInt16 nMaxPages = GetPageCount();
107 
108     while (nPage < nMaxPages && !pObjFound)
109     {
110         pPage = (SdPage*) GetPage(nPage);
111         SdrObjListIter aIter(*pPage, IM_DEEPWITHGROUPS);
112 
113         while (aIter.IsMore() && !pObjFound)
114         {
115             pObj = aIter.Next();
116 
117             if( ( rObjName == pObj->GetName() ) ||
118                 ( SdrInventor == pObj->GetObjInventor() &&
119                   OBJ_OLE2 == pObj->GetObjIdentifier() &&
120                   rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
121             {
122                 pObjFound = pObj;
123             }
124         }
125 
126         nPage++;
127     }
128 
129     /**************************************************************************
130     * Wenn nicht gefunden, dann alle MasterPages durchsuchen
131     **************************************************************************/
132     nPage = 0;
133     const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
134 
135     while (nPage < nMaxMasterPages && !pObjFound)
136     {
137         pPage = (SdPage*) GetMasterPage(nPage);
138         SdrObjListIter aIter(*pPage, IM_DEEPWITHGROUPS);
139 
140         while (aIter.IsMore() && !pObjFound)
141         {
142             pObj = aIter.Next();
143 
144             if( ( rObjName == pObj->GetName() ) ||
145                 ( SdrInventor == pObj->GetObjInventor() &&
146                   OBJ_OLE2 == pObj->GetObjIdentifier() &&
147                   rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
148             {
149                 pObjFound = pObj;
150             }
151         }
152 
153         nPage++;
154     }
155 
156     return (pObjFound);
157 }
158 
159 
160 /*************************************************************************
161 |*
162 |* Sucht die SdPage per Name
163 |*
164 \************************************************************************/
165 
166 sal_uInt16 SdDrawDocument::GetPageByName(const String& rPgName, sal_Bool& rbIsMasterPage) const
167 {
168     SdPage* pPage = NULL;
169     sal_uInt16 nPage = 0;
170     const sal_uInt16 nMaxPages = GetPageCount();
171     sal_uInt16 nPageNum = SDRPAGE_NOTFOUND;
172 
173     rbIsMasterPage = sal_False;
174 
175     // Search all regular pages and all notes pages (handout pages are
176     // ignored.)
177     while (nPage < nMaxPages && nPageNum == SDRPAGE_NOTFOUND)
178     {
179         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
180             GetPage(nPage)));
181 
182         if (pPage != NULL
183             && pPage->GetPageKind() != PK_HANDOUT
184             && pPage->GetName() == rPgName)
185         {
186             nPageNum = nPage;
187         }
188 
189         nPage++;
190     }
191 
192     // Search all master pages when not found among non-master pages.
193     const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
194     nPage = 0;
195 
196     while (nPage < nMaxMasterPages && nPageNum == SDRPAGE_NOTFOUND)
197     {
198         pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
199             GetMasterPage(nPage)));
200 
201         if (pPage && pPage->GetName() == rPgName)
202         {
203             nPageNum = nPage;
204             rbIsMasterPage = sal_True;
205         }
206 
207         nPage++;
208     }
209 
210     return nPageNum;
211 }
212 
213 
214 /*************************************************************************
215 |*
216 |*
217 |*
218 \************************************************************************/
219 
220 SdPage* SdDrawDocument::GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const
221 {
222     // #109538#
223     return mpDrawPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
224 }
225 
226 /*************************************************************************
227 |*
228 |*
229 |*
230 \************************************************************************/
231 
232 sal_uInt16 SdDrawDocument::GetSdPageCount(PageKind ePgKind) const
233 {
234     // #109538#
235     return (sal_uInt16)mpDrawPageListWatcher->GetSdPageCount(ePgKind);
236 }
237 
238 /*************************************************************************
239 |*
240 |*
241 |*
242 \************************************************************************/
243 
244 SdPage* SdDrawDocument::GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind)
245 {
246     // #109538#
247     return mpMasterPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
248 }
249 
250 /*************************************************************************
251 |*
252 |*
253 |*
254 \************************************************************************/
255 
256 sal_uInt16 SdDrawDocument::GetMasterSdPageCount(PageKind ePgKind) const
257 {
258     // #109538#
259     return (sal_uInt16)mpMasterPageListWatcher->GetSdPageCount(ePgKind);
260 }
261 
262 /*************************************************************************
263 |*
264 |*  die in den Seitenobjekten der Notizseiten eingetragenen
265 |*  Seitennummern anpassen
266 |*
267 \************************************************************************/
268 
269 void SdDrawDocument::UpdatePageObjectsInNotes(sal_uInt16 nStartPos)
270 {
271     sal_uInt16  nPageCount  = GetPageCount();
272     SdPage* pPage       = NULL;
273 
274     for (sal_uInt16 nPage = nStartPos; nPage < nPageCount; nPage++)
275     {
276         pPage = (SdPage*)GetPage(nPage);
277 
278         // wenn es eine Notizseite ist, Seitenobjekt suchen
279         // und Nummer korrigieren
280         if (pPage && pPage->GetPageKind() == PK_NOTES)
281         {
282             sal_uLong nObjCount = pPage->GetObjCount();
283             SdrObject* pObj = NULL;
284             for (sal_uLong nObj = 0; nObj < nObjCount; nObj++)
285             {
286                 pObj = pPage->GetObj(nObj);
287                 if (pObj->GetObjIdentifier() == OBJ_PAGE &&
288                     pObj->GetObjInventor() == SdrInventor)
289                 {
290                     // das Seitenobjekt stellt die vorhergende Seite (also
291                     // die Zeichenseite) dar
292                     DBG_ASSERTWARNING(nStartPos, "Notizseitenpos. darf nicht 0 sein");
293 
294                     DBG_ASSERTWARNING(nPage > 1, "Seitenobjekt darf nicht Handzettel darstellen");
295 
296                     if (nStartPos > 0 && nPage > 1)
297                         ((SdrPageObj*)pObj)->SetReferencedPage(GetPage(nPage - 1));
298                 }
299             }
300         }
301     }
302 }
303 
304 void SdDrawDocument::UpdatePageRelativeURLs(const String& rOldName, const String& rNewName)
305 {
306     if (rNewName.Len() == 0)
307         return;
308 
309     SfxItemPool& pPool(GetPool());
310     sal_uInt32 nCount = pPool.GetItemCount2(EE_FEATURE_FIELD);
311     for (sal_uInt32 nOff = 0; nOff < nCount; nOff++)
312     {
313         const SfxPoolItem *pItem = pPool.GetItem2(EE_FEATURE_FIELD, nOff);
314         const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem * > (pItem);
315 
316         if(pFldItem)
317         {
318             SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
319 
320             if(pURLField)
321             {
322                 XubString aURL = pURLField->GetURL();
323 
324                 if (aURL.Len() && (aURL.GetChar(0) == 35) && (aURL.Search(rOldName, 1) == 1))
325                 {
326                     if (aURL.Len() == rOldName.Len() + 1) // standard page name
327                     {
328                         aURL.Erase (1, aURL.Len() - 1);
329                         aURL += rNewName;
330                         pURLField->SetURL(aURL);
331                     }
332                     else
333                     {
334                         const XubString sNotes = SdResId(STR_NOTES);
335                         if (aURL.Len() == rOldName.Len() + 2 + sNotes.Len() && aURL.Search(sNotes, rOldName.Len() + 2) == rOldName.Len() + 2)
336                         {
337                             aURL.Erase (1, aURL.Len() - 1);
338                             aURL += rNewName;
339                             aURL += ' ';
340                             aURL += sNotes;
341                             pURLField->SetURL(aURL);
342                         }
343                     }
344                 }
345             }
346         }
347     }
348 }
349 
350 void SdDrawDocument::UpdatePageRelativeURLs(SdPage* pPage, sal_uInt16 nPos, sal_Int32 nIncrement)
351 {
352     bool bNotes = (pPage->GetPageKind() == PK_NOTES);
353 
354     SfxItemPool& pPool(GetPool());
355     sal_uInt32 nCount = pPool.GetItemCount2(EE_FEATURE_FIELD);
356     for (sal_uInt32 nOff = 0; nOff < nCount; nOff++)
357     {
358         const SfxPoolItem *pItem = pPool.GetItem2(EE_FEATURE_FIELD, nOff);
359         const SvxFieldItem* pFldItem;
360 
361         if ((pFldItem = dynamic_cast< const SvxFieldItem * > (pItem)) != 0)
362         {
363             SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
364 
365             if(pURLField)
366             {
367                 XubString aURL = pURLField->GetURL();
368 
369                 if (aURL.Len() && (aURL.GetChar(0) == 35))
370                 {
371                     XubString aHashSlide('#');
372                     aHashSlide += SdResId(STR_PAGE);
373 
374                     if (aURL.CompareTo(aHashSlide, aHashSlide.Len()) == COMPARE_EQUAL)
375                     {
376                         XubString aURLCopy = aURL;
377                         const XubString sNotes = SdResId(STR_NOTES);
378 
379                         aURLCopy.Erase(0, aHashSlide.Len());
380 
381                         bool bNotesLink = (aURLCopy.Len() >= sNotes.Len() + 3 && aURLCopy.Search(sNotes, aURLCopy.Len() - sNotes.Len()) == aURLCopy.Len() - sNotes.Len());
382 
383                         if (bNotesLink ^ bNotes)
384                             continue; // no compatible link and page
385 
386                         if (bNotes)
387                             aURLCopy.Erase(aURLCopy.Len() - sNotes.Len(), sNotes.Len());
388 
389                         sal_Int32 number = aURLCopy.ToInt32();
390                         sal_uInt16 realPageNumber = (nPos + 1)/ 2;
391 
392                         if ( number >= realPageNumber )
393                         {
394                             // update link page number
395                             number += nIncrement;
396                             aURL.Erase (aHashSlide.Len() + 1, aURL.Len() - aHashSlide.Len() - 1);
397                             aURL += XubString::CreateFromInt32(number);
398                             if (bNotes)
399                             {
400                                 aURL += ' ';
401                                 aURL += sNotes;
402                             }
403                             pURLField->SetURL(aURL);
404                         }
405                     }
406                 }
407             }
408         }
409     }
410 }
411 
412 /*************************************************************************
413 |*
414 |*  Seite verschieben
415 |*
416 \************************************************************************/
417 
418 void SdDrawDocument::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
419 {
420     // Seite verschieben
421     FmFormModel::MovePage(nPgNum, nNewPos);
422 
423     sal_uInt16 nMin = Min(nPgNum, nNewPos);
424 
425     UpdatePageObjectsInNotes(nMin);
426 }
427 
428 /*************************************************************************
429 |*
430 |*  Seite einfuegen
431 |*
432 \************************************************************************/
433 
434 void SdDrawDocument::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
435 {
436     bool bLast = (nPos == GetPageCount());
437 
438     FmFormModel::InsertPage(pPage, nPos);
439 
440     ((SdPage*)pPage)->ConnectLink();
441 
442     UpdatePageObjectsInNotes(nPos);
443 
444     if (!bLast)
445         UpdatePageRelativeURLs(static_cast<SdPage*>( pPage ), nPos, 1);
446 
447 }
448 
449 /*************************************************************************
450 |*
451 |*  Seite loeschen
452 |*
453 \************************************************************************/
454 
455 void SdDrawDocument::DeletePage(sal_uInt16 nPgNum)
456 {
457     FmFormModel::DeletePage(nPgNum);
458 
459     UpdatePageObjectsInNotes(nPgNum);
460 }
461 
462 /*************************************************************************
463 |*
464 |*  Seite entfernen
465 |*
466 \************************************************************************/
467 
468 SdrPage* SdDrawDocument::RemovePage(sal_uInt16 nPgNum)
469 {
470     SdrPage* pPage = FmFormModel::RemovePage(nPgNum);
471 
472     bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2);
473 
474     ((SdPage*)pPage)->DisconnectLink();
475     ReplacePageInCustomShows( dynamic_cast< SdPage* >( pPage ), 0 );
476     UpdatePageObjectsInNotes(nPgNum);
477 
478     if (!bLast)
479         UpdatePageRelativeURLs((SdPage*)pPage, nPgNum, -1);
480 
481     return pPage;
482 }
483 
484 // Warning: This is not called for new master pages created from SdrModel::Merge,
485 // you also have to modify code in SdDrawDocument::Merge!
486 void SdDrawDocument::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos )
487 {
488     FmFormModel::InsertMasterPage( pPage, nPos );
489     if( pPage && pPage->IsMasterPage() && (static_cast<SdPage*>(pPage)->GetPageKind() == PK_STANDARD) )
490     {
491         // new master page created, add its style family
492         SdStyleSheetPool* pStylePool = (SdStyleSheetPool*) GetStyleSheetPool();
493         if( pStylePool )
494             pStylePool->AddStyleFamily( static_cast<SdPage*>(pPage) );
495     }
496 }
497 
498 SdrPage* SdDrawDocument::RemoveMasterPage(sal_uInt16 nPgNum)
499 {
500     SdPage* pPage = static_cast<SdPage*>(GetMasterPage(nPgNum ));
501     if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PK_STANDARD) )
502     {
503         // master page removed, remove its style family
504         SdStyleSheetPool* pStylePool = (SdStyleSheetPool*) GetStyleSheetPool();
505         if( pStylePool )
506             pStylePool->RemoveStyleFamily( pPage );
507     }
508 
509     return FmFormModel::RemoveMasterPage(nPgNum);
510 }
511 
512 /*************************************************************************
513 |*
514 |* Seiten selektieren
515 |*
516 \************************************************************************/
517 
518 void SdDrawDocument::SetSelected(SdPage* pPage, sal_Bool bSelect)
519 {
520     PageKind ePageKind = pPage->GetPageKind();
521 
522     if (ePageKind == PK_STANDARD)
523     {
524         pPage->SetSelected(bSelect);
525 
526         const sal_uInt16 nDestPageNum(pPage->GetPageNum() + 1);
527         SdPage* pNotesPage = 0L;
528 
529         if(nDestPageNum < GetPageCount())
530         {
531             pNotesPage = (SdPage*)GetPage(nDestPageNum);
532         }
533 
534         if (pNotesPage && pNotesPage->GetPageKind() == PK_NOTES)
535         {
536             pNotesPage->SetSelected(bSelect);
537         }
538     }
539     else if (ePageKind == PK_NOTES)
540     {
541         pPage->SetSelected(bSelect);
542         SdPage* pStandardPage = (SdPage*) GetPage( pPage->GetPageNum() - 1 );
543 
544         if (pStandardPage && pStandardPage->GetPageKind() == PK_STANDARD)
545             pStandardPage->SetSelected(bSelect);
546     }
547 }
548 
549 /*************************************************************************
550 |*
551 |* Sofern noch keine Seiten vorhanden sind, werden nun Seiten erzeugt
552 |*
553 \************************************************************************/
554 
555 void SdDrawDocument::CreateFirstPages( SdDrawDocument* pRefDocument /* = 0 */ )
556 {
557     /**************************************************************************
558     * Wenn noch keine Seite im Model vorhanden ist (Datei-Neu), wird
559     * eine neue Seite eingefuegt
560     **************************************************************************/
561     sal_uInt16 nPageCount = GetPageCount();
562 
563     if (nPageCount <= 1)
564     {
565         // #i57181# Paper size depends on Language, like in Writer
566         Size aDefSize = SvxPaperInfo::GetDefaultPaperSize( MAP_100TH_MM );
567 
568         /**********************************************************************
569         * Handzettel-Seite einfuegen
570         **********************************************************************/
571         sal_Bool bMasterPage;
572         SdPage* pHandoutPage = dynamic_cast< SdPage* >( AllocPage(bMasterPage=sal_False) );
573 
574         SdPage* pRefPage = NULL;
575 
576         if( pRefDocument )
577             pRefPage = pRefDocument->GetSdPage( 0, PK_HANDOUT );
578 
579         if( pRefPage )
580         {
581             pHandoutPage->SetSize(pRefPage->GetSize());
582             pHandoutPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
583         }
584         else
585         {
586             pHandoutPage->SetSize(aDefSize);
587             pHandoutPage->SetBorder(0, 0, 0, 0);
588         }
589 
590         pHandoutPage->SetPageKind(PK_HANDOUT);
591         pHandoutPage->SetName( String (SdResId(STR_HANDOUT) ) );
592         InsertPage(pHandoutPage, 0);
593 
594         /**********************************************************************
595         * MasterPage einfuegen und an der Handzettel-Seite vermerken
596         **********************************************************************/
597         SdPage* pHandoutMPage = (SdPage*) AllocPage(bMasterPage=sal_True);
598         pHandoutMPage->SetSize( pHandoutPage->GetSize() );
599         pHandoutMPage->SetPageKind(PK_HANDOUT);
600         pHandoutMPage->SetBorder( pHandoutPage->GetLftBorder(),
601                                   pHandoutPage->GetUppBorder(),
602                                   pHandoutPage->GetRgtBorder(),
603                                   pHandoutPage->GetLwrBorder() );
604         InsertMasterPage(pHandoutMPage, 0);
605         pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
606 
607         /**********************************************************************
608         * Seite einfuegen
609         * Sofern nPageCount==1 ist, wurde das Model fuers Clipboad erzeugt.
610         * Eine Standard-Seite ist daher schon vorhanden.
611         **********************************************************************/
612         SdPage* pPage;
613         sal_Bool bClipboard = sal_False;
614 
615         if( pRefDocument )
616             pRefPage = pRefDocument->GetSdPage( 0, PK_STANDARD );
617 
618         if (nPageCount == 0)
619         {
620             pPage = dynamic_cast< SdPage* >( AllocPage(bMasterPage=sal_False) );
621 
622             if( pRefPage )
623             {
624                 pPage->SetSize( pRefPage->GetSize() );
625                 pPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
626             }
627             else if (meDocType == DOCUMENT_TYPE_DRAW)
628             {
629                 // Draw: stets Default-Groesse mit Raendern
630                 pPage->SetSize(aDefSize);
631 
632                 SfxPrinter* pPrinter = mpDocSh->GetPrinter(sal_False);
633                 if (pPrinter && pPrinter->IsValid())
634                 {
635                     Size aOutSize(pPrinter->GetOutputSize());
636                     Point aPageOffset(pPrinter->GetPageOffset());
637                     aPageOffset -= pPrinter->PixelToLogic( Point() );
638                     long nOffset = !aPageOffset.X() && !aPageOffset.X() ? 0 : PRINT_OFFSET;
639 
640                     sal_uLong nTop    = aPageOffset.Y();
641                     sal_uLong nLeft   = aPageOffset.X();
642                     sal_uLong nBottom = Max((long)(aDefSize.Height() - aOutSize.Height() - nTop + nOffset), 0L);
643                     sal_uLong nRight  = Max((long)(aDefSize.Width() - aOutSize.Width() - nLeft + nOffset), 0L);
644 
645                     pPage->SetBorder(nLeft, nTop, nRight, nBottom);
646                 }
647                 else
648                 {
649                     // The printer is not available.  Use a border of 10mm
650                     // on each side instead.
651                     // This has to be kept synchronized with the border
652                     // width set in the
653                     // SvxPageDescPage::PaperSizeSelect_Impl callback.
654                     pPage->SetBorder(1000, 1000, 1000, 1000);
655                 }
656             }
657             else
658             {
659                 // Impress: stets Bildschirmformat, quer
660                 Size aSz( SvxPaperInfo::GetPaperSize(PAPER_SCREEN, MAP_100TH_MM) );
661                 pPage->SetSize( Size( aSz.Height(), aSz.Width() ) );
662                 pPage->SetBorder(0, 0, 0, 0);
663             }
664 
665             InsertPage(pPage, 1);
666         }
667         else
668         {
669             bClipboard = sal_True;
670             pPage = (SdPage*) GetPage(1);
671         }
672 
673         /**********************************************************************
674         * MasterPage einfuegen und an der Seite vermerken
675         **********************************************************************/
676         SdPage* pMPage = (SdPage*) AllocPage(bMasterPage=sal_True);
677         pMPage->SetSize( pPage->GetSize() );
678         pMPage->SetBorder( pPage->GetLftBorder(),
679                            pPage->GetUppBorder(),
680                            pPage->GetRgtBorder(),
681                            pPage->GetLwrBorder() );
682         InsertMasterPage(pMPage, 1);
683         pPage->TRG_SetMasterPage( *pMPage );
684         if( bClipboard )
685             pMPage->SetLayoutName( pPage->GetLayoutName() );
686 
687         /**********************************************************************
688         * Notizen-Seite einfuegen
689         **********************************************************************/
690         SdPage* pNotesPage = (SdPage*) AllocPage(bMasterPage=sal_False);
691 
692         if( pRefDocument )
693             pRefPage = pRefDocument->GetSdPage( 0, PK_NOTES );
694 
695         if( pRefPage )
696         {
697             pNotesPage->SetSize( pRefPage->GetSize() );
698             pNotesPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
699         }
700         else
701         {
702             // Stets Hochformat
703             if (aDefSize.Height() >= aDefSize.Width())
704             {
705                 pNotesPage->SetSize(aDefSize);
706             }
707             else
708             {
709                 pNotesPage->SetSize( Size(aDefSize.Height(), aDefSize.Width()) );
710             }
711 
712             pNotesPage->SetBorder(0, 0, 0, 0);
713         }
714         pNotesPage->SetPageKind(PK_NOTES);
715         InsertPage(pNotesPage, 2);
716         if( bClipboard )
717             pNotesPage->SetLayoutName( pPage->GetLayoutName() );
718 
719         /**********************************************************************
720         * MasterPage einfuegen und an der Notizen-Seite vermerken
721         **********************************************************************/
722         SdPage* pNotesMPage = (SdPage*) AllocPage(bMasterPage=sal_True);
723         pNotesMPage->SetSize( pNotesPage->GetSize() );
724         pNotesMPage->SetPageKind(PK_NOTES);
725         pNotesMPage->SetBorder( pNotesPage->GetLftBorder(),
726                                 pNotesPage->GetUppBorder(),
727                                 pNotesPage->GetRgtBorder(),
728                                 pNotesPage->GetLwrBorder() );
729         InsertMasterPage(pNotesMPage, 2);
730         pNotesPage->TRG_SetMasterPage( *pNotesMPage );
731         if( bClipboard )
732             pNotesMPage->SetLayoutName( pPage->GetLayoutName() );
733 
734 
735         if( !pRefPage && (meDocType != DOCUMENT_TYPE_DRAW) )
736             pPage->SetAutoLayout( AUTOLAYOUT_TITLE, sal_True, sal_True );
737 
738         mpWorkStartupTimer = new Timer();
739         mpWorkStartupTimer->SetTimeoutHdl( LINK(this, SdDrawDocument, WorkStartupHdl) );
740         mpWorkStartupTimer->SetTimeout(2000);
741         mpWorkStartupTimer->Start();
742 
743         SetChanged(sal_False);
744     }
745 }
746 
747 /*************************************************************************
748 |*
749 |* Erzeugt fehlende Notiz und Handzettelseiten (nach PowerPoint-Import)
750 |* Es wird davon ausgegangen, dass mindestens eine Standard-Seite und
751 |* eine Standard-MasterPage vorhanden sind.
752 |*
753 \************************************************************************/
754 
755 sal_Bool SdDrawDocument::CreateMissingNotesAndHandoutPages()
756 {
757     sal_Bool bOK = sal_False;
758     sal_uInt16 nPageCount = GetPageCount();
759 
760     if (nPageCount != 0)
761     {
762         /**********************************************************************
763         * PageKind setzen
764         **********************************************************************/
765         SdPage* pHandoutMPage = (SdPage*) GetMasterPage(0);
766         pHandoutMPage->SetPageKind(PK_HANDOUT);
767 
768         SdPage* pHandoutPage = (SdPage*) GetPage(0);
769         pHandoutPage->SetPageKind(PK_HANDOUT);
770         pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
771 
772         for (sal_uInt16 i = 1; i < nPageCount; i = i + 2)
773         {
774             SdPage* pPage = (SdPage*) GetPage(i);
775 
776             if(!pPage->TRG_HasMasterPage())
777             {
778                 // Keine MasterPage gesetzt -> erste Standard-MasterPage nehmen
779                 // (Wenn bei PPT keine Standard-Seite vorhanden war)
780                 pPage->TRG_SetMasterPage(*GetMasterPage(1));
781             }
782 
783             SdPage* pNotesPage = (SdPage*) GetPage(i+1);
784             pNotesPage->SetPageKind(PK_NOTES);
785 
786             // Notiz-MasterPages setzen
787             sal_uInt16 nMasterPageAfterPagesMasterPage = (pPage->TRG_GetMasterPage()).GetPageNum() + 1;
788             pNotesPage->TRG_SetMasterPage(*GetMasterPage(nMasterPageAfterPagesMasterPage));
789         }
790 
791         bOK = sal_True;
792         StopWorkStartupDelay();
793         SetChanged(sal_False);
794     }
795 
796     return(bOK);
797 }
798 
799 /*************************************************************************
800 |*
801 |* - selektierte Seiten hinter genannte Seite schieben
802 |*   (nTargetPage = (sal_uInt16)-1  --> vor erste Seite schieben)
803 |* - ergibt sal_True, wenn Seiten verschoben wurden
804 |*
805 \************************************************************************/
806 
807 sal_Bool SdDrawDocument::MovePages(sal_uInt16 nTargetPage)
808 {
809     SdPage* pTargetPage        = NULL;
810     SdPage* pPage              = NULL;
811     sal_uInt16  nPage;
812     sal_uInt16  nNoOfPages         = GetSdPageCount(PK_STANDARD);
813     sal_Bool    bSomethingHappened = sal_False;
814 
815     const bool bUndo = IsUndoEnabled();
816 
817     if( bUndo )
818         BegUndo(String(SdResId(STR_UNDO_MOVEPAGES)));
819 
820     // Liste mit selektierten Seiten
821     List    aPageList;
822     for (nPage = 0; nPage < nNoOfPages; nPage++)
823     {
824         pPage = GetSdPage(nPage, PK_STANDARD);
825         if (pPage->IsSelected())
826         {
827             aPageList.Insert(pPage, LIST_APPEND);
828         }
829     }
830 
831     // falls noetig, nach vorne hangeln, bis nicht selektierte Seite gefunden
832     nPage = nTargetPage;
833     if (nPage != (sal_uInt16)-1)
834     {
835         pPage = GetSdPage(nPage, PK_STANDARD);
836         while (nPage > 0 && pPage->IsSelected())
837         {
838             nPage--;
839             pPage = GetSdPage(nPage, PK_STANDARD);
840         }
841 
842         if (pPage->IsSelected())
843         {
844             nPage = (sal_uInt16)-1;
845         }
846     }
847 
848     // vor der ersten Seite einfuegen
849     if (nPage == (sal_uInt16)-1)
850     {
851         while (aPageList.Count() > 0)
852         {
853             aPageList.Last();
854 
855             nPage = ( (SdPage*) aPageList.GetCurObject() )->GetPageNum();
856             if (nPage != 0)
857             {
858                 SdrPage* pPg = GetPage(nPage);
859                 if( bUndo )
860                     AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, 1));
861                 MovePage(nPage, 1);
862                 pPg = GetPage(nPage+1);
863                 if( bUndo )
864                     AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, 2));
865                 MovePage(nPage+1, 2);
866                 bSomethingHappened = sal_True;
867             }
868             aPageList.Remove();
869         }
870     }
871     // hinter <nPage> einfuegen
872     else
873     {
874         pTargetPage = GetSdPage(nPage, PK_STANDARD);
875         nTargetPage = nPage;
876         nTargetPage = 2 * nTargetPage + 1;    // PK_STANDARD --> absolut
877         while (aPageList.Count() > 0)
878         {
879             pPage = (SdPage*)aPageList.GetObject(0);
880             nPage = pPage->GetPageNum();
881             if (nPage > nTargetPage)
882             {
883                 nTargetPage += 2;        // hinter (!) der Seite einfuegen
884 
885                 if (nPage != nTargetPage)
886                 {
887                     SdrPage* pPg = GetPage(nPage);
888                     if( bUndo )
889                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
890                     MovePage(nPage, nTargetPage);
891                     pPg = GetPage(nPage+1);
892                     if( bUndo )
893                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
894                     MovePage(nPage+1, nTargetPage+1);
895                     bSomethingHappened = sal_True;
896                 }
897             }
898             else
899             {
900                 if (nPage != nTargetPage)
901                 {
902                     SdrPage* pPg = GetPage(nPage+1);
903                     if( bUndo )
904                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
905                     MovePage(nPage+1, nTargetPage+1);
906                     pPg = GetPage(nPage);
907                     if( bUndo )
908                         AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
909                     MovePage(nPage, nTargetPage);
910                     bSomethingHappened = sal_True;
911                 }
912             }
913             aPageList.Remove((sal_uLong)0);
914             nTargetPage = pPage->GetPageNum();
915         }
916     }
917 
918     if( bUndo )
919         EndUndo();
920 
921     return bSomethingHappened;
922 }
923 
924 
925 /*************************************************************************
926 |*
927 |* Anzahl der Links im sfx2::LinkManager zurueckgeben
928 |*
929 \************************************************************************/
930 
931 sal_uLong SdDrawDocument::GetLinkCount()
932 {
933     return ( pLinkManager->GetLinks().Count() );
934 }
935 
936 /*************************************************************************
937 |*
938 |* Language setzen
939 |*
940 \************************************************************************/
941 
942 void SdDrawDocument::SetLanguage( const LanguageType eLang, const sal_uInt16 nId )
943 {
944     sal_Bool bChanged = sal_False;
945 
946     if( nId == EE_CHAR_LANGUAGE && meLanguage != eLang )
947     {
948         meLanguage = eLang;
949         bChanged = sal_True;
950     }
951     else if( nId == EE_CHAR_LANGUAGE_CJK && meLanguageCJK != eLang )
952     {
953         meLanguageCJK = eLang;
954         bChanged = sal_True;
955     }
956     else if( nId == EE_CHAR_LANGUAGE_CTL && meLanguageCTL != eLang )
957     {
958         meLanguageCTL = eLang;
959         bChanged = sal_True;
960     }
961 
962     if( bChanged )
963     {
964         GetDrawOutliner().SetDefaultLanguage( Application::GetSettings().GetLanguage() );
965         pHitTestOutliner->SetDefaultLanguage( Application::GetSettings().GetLanguage() );
966         pItemPool->SetPoolDefaultItem( SvxLanguageItem( eLang, nId ) );
967         SetChanged( bChanged );
968     }
969 }
970 
971 
972 /*************************************************************************
973 |*
974 |* Return language
975 |*
976 \************************************************************************/
977 
978 LanguageType SdDrawDocument::GetLanguage( const sal_uInt16 nId ) const
979 {
980     LanguageType eLangType = meLanguage;
981 
982     if( nId == EE_CHAR_LANGUAGE_CJK )
983         eLangType = meLanguageCJK;
984     else if( nId == EE_CHAR_LANGUAGE_CTL )
985         eLangType = meLanguageCTL;
986 
987     return eLangType;
988 }
989 
990 
991 /*************************************************************************
992 |*
993 |* WorkStartup einleiten
994 |*
995 \************************************************************************/
996 
997 IMPL_LINK( SdDrawDocument, WorkStartupHdl, Timer *, EMPTYARG )
998 {
999     if( mpDocSh )
1000         mpDocSh->SetWaitCursor( sal_True );
1001 
1002     sal_Bool bChanged = IsChanged();        // merken
1003 
1004     // Autolayouts initialisieren
1005     SdPage* pHandoutMPage = GetMasterSdPage(0, PK_HANDOUT);
1006 
1007     if (pHandoutMPage->GetAutoLayout() == AUTOLAYOUT_NONE)
1008     {
1009         // AutoLayout wurde noch nicht umgesetzt -> Initialisieren
1010         pHandoutMPage->SetAutoLayout(AUTOLAYOUT_HANDOUT6, sal_True, sal_True);
1011     }
1012 
1013     SdPage* pPage = GetSdPage(0, PK_STANDARD);
1014 
1015     if (pPage->GetAutoLayout() == AUTOLAYOUT_NONE)
1016     {
1017         // AutoLayout wurde noch nicht umgesetzt -> Initialisieren
1018         pPage->SetAutoLayout(AUTOLAYOUT_NONE, sal_True, sal_True);
1019     }
1020 
1021     SdPage* pNotesPage = GetSdPage(0, PK_NOTES);
1022 
1023     if (pNotesPage->GetAutoLayout() == AUTOLAYOUT_NONE)
1024     {
1025         // AutoLayout wurde noch nicht umgesetzt -> Initialisieren
1026         pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, sal_True, sal_True);
1027     }
1028 
1029     SetChanged(bChanged || sal_False);
1030 
1031     if( mpDocSh )
1032         mpDocSh->SetWaitCursor( sal_False );
1033     return 0;
1034 }
1035 
1036 
1037 /*************************************************************************
1038 |*
1039 |* Wenn der WorkStartupTimer erzeugt worden ist (das erfolgt ausschliesslich
1040 |* in SdDrawViewShell::Consruct() ), so wird der Timer ggf. gestoppt und
1041 |* das WorkStartup eingeleitet
1042 |*
1043 \************************************************************************/
1044 
1045 void SdDrawDocument::StopWorkStartupDelay()
1046 {
1047     if (mpWorkStartupTimer)
1048     {
1049         if ( mpWorkStartupTimer->IsActive() )
1050         {
1051             // Timer war noch nicht abgelaufen -> WorkStartup wird eingeleitet
1052             mpWorkStartupTimer->Stop();
1053             WorkStartupHdl(NULL);
1054         }
1055 
1056         delete mpWorkStartupTimer;
1057         mpWorkStartupTimer = NULL;
1058     }
1059 }
1060 
1061 /*************************************************************************
1062 |*
1063 |* Wenn der WorkStartupTimer erzeugt worden ist (das erfolgt ausschliesslich
1064 |* in SdDrawViewShell::Consruct() ), so wird der Timer ggf. gestoppt und
1065 |* das WorkStartup eingeleitet
1066 |*
1067 \************************************************************************/
1068 
1069 SdAnimationInfo* SdDrawDocument::GetAnimationInfo(SdrObject* pObject) const
1070 {
1071     DBG_ASSERT(pObject, "sd::SdDrawDocument::GetAnimationInfo(), invalid argument!");
1072     if( pObject )
1073         return GetShapeUserData( *pObject, false );
1074     else
1075         return 0;
1076 }
1077 
1078 SdAnimationInfo* SdDrawDocument::GetShapeUserData(SdrObject& rObject, bool bCreate /* = false */ )
1079 {
1080     sal_uInt16 nUD          = 0;
1081     sal_uInt16 nUDCount     = rObject.GetUserDataCount();
1082     SdrObjUserData* pUD = 0;
1083     SdAnimationInfo* pRet = 0;
1084 
1085     // gibt es in den User-Daten eine Animationsinformation?
1086     for (nUD = 0; nUD < nUDCount; nUD++)
1087     {
1088         pUD = rObject.GetUserData(nUD);
1089         if((pUD->GetInventor() == SdUDInventor) && (pUD->GetId() == SD_ANIMATIONINFO_ID))
1090         {
1091             pRet = dynamic_cast<SdAnimationInfo*>(pUD);
1092             break;
1093         }
1094     }
1095 
1096     if( (pRet == 0) && bCreate )
1097     {
1098         pRet = new SdAnimationInfo( rObject );
1099         rObject.InsertUserData( pRet);
1100     }
1101 
1102     return pRet;
1103 }
1104 
1105 
1106 /*************************************************************************
1107 |*
1108 |*
1109 |*
1110 \************************************************************************/
1111 
1112 SdIMapInfo* SdDrawDocument::GetIMapInfo( SdrObject* pObject ) const
1113 {
1114     DBG_ASSERT(pObject, "ohne Objekt keine IMapInfo");
1115 
1116     SdrObjUserData* pUserData = NULL;
1117     SdIMapInfo*     pIMapInfo = NULL;
1118     sal_uInt16          nCount = pObject->GetUserDataCount();
1119 
1120     // gibt es in den User-Daten eine IMap-Information?
1121     for ( sal_uInt16 i = 0; i < nCount; i++ )
1122     {
1123         pUserData = pObject->GetUserData( i );
1124 
1125         if ( ( pUserData->GetInventor() == SdUDInventor ) && ( pUserData->GetId() == SD_IMAPINFO_ID ) )
1126             pIMapInfo = (SdIMapInfo*) pUserData;
1127     }
1128 
1129     return pIMapInfo;
1130 }
1131 
1132 
1133 /*************************************************************************
1134 |*
1135 |*
1136 |*
1137 \************************************************************************/
1138 
1139 IMapObject* SdDrawDocument::GetHitIMapObject( SdrObject* pObj,
1140                                               const Point& rWinPoint,
1141                                               const ::Window& /* rCmpWnd */ )
1142 {
1143     SdIMapInfo* pIMapInfo = GetIMapInfo( pObj );
1144     IMapObject* pIMapObj = NULL;
1145 
1146     if ( pIMapInfo )
1147     {
1148         const MapMode       aMap100( MAP_100TH_MM );
1149         Size                aGraphSize;
1150         Point               aRelPoint( rWinPoint );
1151         ImageMap&           rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
1152         const Rectangle&    rRect = pObj->GetLogicRect();
1153         sal_Bool                bObjSupported = sal_False;
1154 
1155         // HitTest ausfuehren
1156         if ( pObj->ISA( SdrGrafObj )  ) // einfaches Grafik-Objekt
1157         {
1158             const SdrGrafObj*   pGrafObj = (const SdrGrafObj*) pObj;
1159             const GeoStat&      rGeo = pGrafObj->GetGeoStat();
1160             SdrGrafObjGeoData*  pGeoData = (SdrGrafObjGeoData*) pGrafObj->GetGeoData();
1161 
1162             // Drehung rueckgaengig
1163             if ( rGeo.nDrehWink )
1164                 RotatePoint( aRelPoint, rRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
1165 
1166             // Spiegelung rueckgaengig
1167             if ( pGeoData->bMirrored )
1168                 aRelPoint.X() = rRect.Right() + rRect.Left() - aRelPoint.X();
1169 
1170             // ggf. Unshear:
1171             if ( rGeo.nShearWink )
1172                 ShearPoint( aRelPoint, rRect.TopLeft(), -rGeo.nTan );
1173 
1174             if ( pGrafObj->GetGrafPrefMapMode().GetMapUnit() == MAP_PIXEL )
1175                 aGraphSize = Application::GetDefaultDevice()->PixelToLogic( pGrafObj->GetGrafPrefSize(), aMap100 );
1176             else
1177                 aGraphSize = OutputDevice::LogicToLogic( pGrafObj->GetGrafPrefSize(),
1178                                                          pGrafObj->GetGrafPrefMapMode(), aMap100 );
1179 
1180             delete pGeoData;
1181             bObjSupported = sal_True;
1182         }
1183         else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt
1184         {
1185             aGraphSize = ( (SdrOle2Obj*) pObj )->GetOrigObjSize();
1186             bObjSupported = sal_True;
1187         }
1188 
1189         // hat alles geklappt, dann HitTest ausfuehren
1190         if ( bObjSupported )
1191         {
1192             // relativen Mauspunkt berechnen
1193             aRelPoint -= rRect.TopLeft();
1194             pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, rRect.GetSize(), aRelPoint );
1195 
1196             // Deaktivierte Objekte wollen wir nicht
1197             if ( pIMapObj && !pIMapObj->IsActive() )
1198                 pIMapObj = NULL;
1199         }
1200     }
1201 
1202     return pIMapObj;
1203 }
1204 
1205 /** this method enforces that the masterpages are in the currect order,
1206     that is at position 1 is a PK_STANDARD masterpage followed by a
1207     PK_NOTES masterpage and so on. #
1208 */
1209 void SdDrawDocument::CheckMasterPages()
1210 {
1211 //  RemoveMasterPage(2); // code to test the creation of notes pages
1212 
1213     sal_uInt16 nMaxPages = GetMasterPageCount();
1214 
1215     // we need at least a handout master and one master page
1216     if( nMaxPages < 2 )
1217     {
1218         return;
1219     }
1220 
1221     SdPage* pPage = NULL;
1222     SdPage* pNotesPage = NULL;
1223 
1224     sal_uInt16 nPage;
1225 
1226     // first see if the page order is correct
1227     for( nPage = 1; nPage < nMaxPages; nPage++ )
1228     {
1229         pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
1230         // if an odd page is not a standard page or an even page is not a notes page
1231         if( ((1 == (nPage & 1)) && (pPage->GetPageKind() != PK_STANDARD) ) ||
1232             ((0 == (nPage & 1)) && (pPage->GetPageKind() != PK_NOTES) ) )
1233             break; // then we have a fatal error
1234     }
1235 
1236     if( nPage < nMaxPages )
1237     {
1238         // there is a fatal error in the master page order,
1239         // we need to repair the document
1240         sal_Bool bChanged = sal_False;
1241 
1242         nPage = 1;
1243         while( nPage < nMaxPages )
1244         {
1245             pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
1246             if( pPage->GetPageKind() != PK_STANDARD )
1247             {
1248                 bChanged = sal_True;
1249                 sal_uInt16 nFound = nPage + 1;
1250                 while( nFound < nMaxPages )
1251                 {
1252                     pPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1253                     if( PK_STANDARD == pPage->GetPageKind() )
1254                     {
1255                         MoveMasterPage( nFound, nPage );
1256                         pPage->SetInserted(sal_True);
1257                         break;
1258 
1259                     }
1260 
1261                     nFound++;
1262                 }
1263 
1264                 // if we don't have any more standard pages, were done
1265                 if( nMaxPages == nFound )
1266                     break;
1267             }
1268 
1269             nPage++;
1270 
1271             if( nPage < nMaxPages )
1272                 pNotesPage = static_cast<SdPage*>(GetMasterPage( nPage ));
1273             else
1274                 pNotesPage = NULL;
1275 
1276             if( (NULL == pNotesPage) || (pNotesPage->GetPageKind() != PK_NOTES) || ( pPage->GetLayoutName() != pNotesPage->GetLayoutName() ) )
1277             {
1278                 bChanged = sal_True;
1279 
1280                 sal_uInt16 nFound = nPage + 1;
1281                 while( nFound < nMaxPages )
1282                 {
1283                     pNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1284                     if( (PK_NOTES == pNotesPage->GetPageKind()) && ( pPage->GetLayoutName() == pNotesPage->GetLayoutName() ) )
1285                     {
1286                         MoveMasterPage( nFound, nPage );
1287                         pNotesPage->SetInserted(sal_True);
1288                         break;
1289                     }
1290 
1291                     nFound++;
1292                 }
1293 
1294                 // looks like we lost a notes page
1295                 if( nMaxPages == nFound )
1296                 {
1297                     // so create one
1298 
1299                     // first find a reference notes page for size
1300                     SdPage* pRefNotesPage = NULL;
1301                     nFound = 0;
1302                     while( nFound < nMaxPages )
1303                     {
1304                         pRefNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
1305                         if( PK_NOTES == pRefNotesPage->GetPageKind() )
1306                             break;
1307                         nFound++;
1308                     }
1309                     if( nFound == nMaxPages )
1310                         pRefNotesPage = NULL;
1311 
1312                     SdPage* pNewNotesPage = static_cast<SdPage*>(AllocPage(sal_True));
1313                     pNewNotesPage->SetPageKind(PK_NOTES);
1314                     if( pRefNotesPage )
1315                     {
1316                         pNewNotesPage->SetSize( pRefNotesPage->GetSize() );
1317                         pNewNotesPage->SetBorder( pRefNotesPage->GetLftBorder(),
1318                                                 pRefNotesPage->GetUppBorder(),
1319                                                 pRefNotesPage->GetRgtBorder(),
1320                                                 pRefNotesPage->GetLwrBorder() );
1321                     }
1322                     InsertMasterPage(pNewNotesPage,  nPage );
1323                     pNewNotesPage->SetLayoutName( pPage->GetLayoutName() );
1324                     pNewNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, sal_True, sal_True );
1325                     nMaxPages++;
1326                 }
1327             }
1328 
1329             nPage++;
1330         }
1331 
1332         // now remove all remaining and unused non PK_STANDARD slides
1333         while( nPage < nMaxPages )
1334         {
1335             bChanged = sal_True;
1336 
1337             RemoveMasterPage( nPage );
1338             nMaxPages--;
1339         }
1340 
1341         if( bChanged )
1342         {
1343             DBG_ERROR( "master pages where in a wrong order" );
1344             RecalcPageNums( sal_True);
1345         }
1346     }
1347 }
1348 
1349 sal_uInt16 SdDrawDocument::CreatePage (
1350     SdPage* pActualPage,
1351     PageKind ePageKind,
1352     const String& sStandardPageName,
1353     const String& sNotesPageName,
1354     AutoLayout eStandardLayout,
1355     AutoLayout eNotesLayout,
1356     sal_Bool bIsPageBack,
1357     sal_Bool bIsPageObj,
1358     const sal_Int32 nInsertPosition)
1359 {
1360     SdPage* pPreviousStandardPage;
1361     SdPage* pPreviousNotesPage;
1362     SdPage* pStandardPage;
1363     SdPage* pNotesPage;
1364 
1365     // From the given page determine the standard page and notes page of which
1366     // to take the layout and the position where to insert the new pages.
1367     if (ePageKind == PK_NOTES)
1368     {
1369         pPreviousNotesPage = pActualPage;
1370         sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1371         pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3);
1372         eStandardLayout = pPreviousStandardPage->GetAutoLayout();
1373     }
1374     else
1375     {
1376         pPreviousStandardPage = pActualPage;
1377         sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1378         pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1);
1379         eNotesLayout = pPreviousNotesPage->GetAutoLayout();
1380     }
1381 
1382     // Create new standard page and set it up.
1383     pStandardPage = (SdPage*) AllocPage(sal_False);
1384 
1385     // #108658#
1386     // Set the size here since else the presobj autolayout
1387     // will be wrong.
1388     pStandardPage->SetSize( pPreviousStandardPage->GetSize() );
1389     pStandardPage->SetBorder( pPreviousStandardPage->GetLftBorder(),
1390                               pPreviousStandardPage->GetUppBorder(),
1391                               pPreviousStandardPage->GetRgtBorder(),
1392                               pPreviousStandardPage->GetLwrBorder() );
1393 
1394     // Use master page of current page.
1395     pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage());
1396 
1397     // User layout of current standard page.
1398     pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() );
1399     pStandardPage->SetAutoLayout(eStandardLayout, sal_True);
1400     pStandardPage->setHeaderFooterSettings( pPreviousStandardPage->getHeaderFooterSettings() );
1401 
1402     // transition settings of current page
1403     pStandardPage->setTransitionType( pPreviousStandardPage->getTransitionType() );
1404     pStandardPage->setTransitionSubtype( pPreviousStandardPage->getTransitionSubtype() );
1405     pStandardPage->setTransitionDirection( pPreviousStandardPage->getTransitionDirection() );
1406     pStandardPage->setTransitionFadeColor( pPreviousStandardPage->getTransitionFadeColor() );
1407     pStandardPage->setTransitionDuration( pPreviousStandardPage->getTransitionDuration() );
1408 
1409     // apply previous animation timing
1410     pStandardPage->SetPresChange( pPreviousStandardPage->GetPresChange() );
1411     pStandardPage->SetTime( pPreviousStandardPage->GetTime() );
1412 
1413     // Create new notes page and set it up.
1414     pNotesPage = (SdPage*) AllocPage(sal_False);
1415     pNotesPage->SetPageKind(PK_NOTES);
1416 
1417     // Use master page of current page.
1418     pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage());
1419 
1420     // Use layout of current notes page.
1421     pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() );
1422     pNotesPage->SetAutoLayout(eNotesLayout, sal_True);
1423     pNotesPage->setHeaderFooterSettings( pPreviousNotesPage->getHeaderFooterSettings() );
1424 
1425     return InsertPageSet (
1426         pActualPage,
1427         ePageKind,
1428         sStandardPageName,
1429         sNotesPageName,
1430         eStandardLayout,
1431         eNotesLayout,
1432         bIsPageBack,
1433         bIsPageObj,
1434         pStandardPage,
1435         pNotesPage,
1436         nInsertPosition);
1437 }
1438 
1439 
1440 
1441 
1442 sal_uInt16 SdDrawDocument::DuplicatePage (sal_uInt16 nPageNum)
1443 {
1444     PageKind ePageKind = PK_STANDARD;
1445 
1446     // Get current page.
1447     SdPage* pActualPage = GetSdPage(nPageNum, ePageKind);
1448 
1449     // Get background flags.
1450     SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
1451     sal_uInt8 aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False);
1452     sal_uInt8 aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False);
1453     SetOfByte aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers();
1454 
1455     // Get layout from current page.
1456     AutoLayout eAutoLayout = pActualPage->GetAutoLayout();
1457 
1458     return DuplicatePage (
1459         pActualPage, ePageKind,
1460         // No names for the new slides.
1461         String(), String(),
1462         eAutoLayout, eAutoLayout,
1463         aVisibleLayers.IsSet(aBckgrnd),
1464         aVisibleLayers.IsSet(aBckgrndObj));
1465 }
1466 
1467 
1468 
1469 
1470 sal_uInt16 SdDrawDocument::DuplicatePage (
1471     SdPage* pActualPage,
1472     PageKind ePageKind,
1473     const String& sStandardPageName,
1474     const String& sNotesPageName,
1475     AutoLayout eStandardLayout,
1476     AutoLayout eNotesLayout,
1477     sal_Bool bIsPageBack,
1478     sal_Bool bIsPageObj,
1479     const sal_Int32 nInsertPosition)
1480 {
1481     SdPage* pPreviousStandardPage;
1482     SdPage* pPreviousNotesPage;
1483     SdPage* pStandardPage;
1484     SdPage* pNotesPage;
1485 
1486     // From the given page determine the standard page and the notes page
1487     // of which to make copies.
1488     if (ePageKind == PK_NOTES)
1489     {
1490         pPreviousNotesPage = pActualPage;
1491         sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1492         pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3);
1493     }
1494     else
1495     {
1496         pPreviousStandardPage = pActualPage;
1497         sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1498         pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1);
1499     }
1500 
1501     // Create duplicates of a standard page and the associated notes page.
1502     pStandardPage = (SdPage*) pPreviousStandardPage->Clone();
1503     pNotesPage = (SdPage*) pPreviousNotesPage->Clone();
1504 
1505     return InsertPageSet (
1506         pActualPage,
1507         ePageKind,
1508         sStandardPageName,
1509         sNotesPageName,
1510         eStandardLayout,
1511         eNotesLayout,
1512         bIsPageBack,
1513         bIsPageObj,
1514         pStandardPage,
1515         pNotesPage,
1516         nInsertPosition);
1517 }
1518 
1519 
1520 
1521 
1522 sal_uInt16 SdDrawDocument::InsertPageSet (
1523     SdPage* pActualPage,
1524     PageKind ePageKind,
1525     const String& sStandardPageName,
1526     const String& sNotesPageName,
1527     AutoLayout eStandardLayout,
1528     AutoLayout eNotesLayout,
1529     sal_Bool bIsPageBack,
1530     sal_Bool bIsPageObj,
1531     SdPage* pStandardPage,
1532     SdPage* pNotesPage,
1533     sal_Int32 nInsertPosition)
1534 {
1535     SdPage* pPreviousStandardPage;
1536     SdPage* pPreviousNotesPage;
1537     sal_uInt16 nStandardPageNum;
1538     sal_uInt16 nNotesPageNum;
1539     String aStandardPageName = sStandardPageName;
1540     String aNotesPageName = sNotesPageName;
1541 
1542     // Gather some information about the standard page and the notes page
1543     // that are to be inserted.  This makes sure that there is allways one
1544     // standard page followed by one notes page.
1545     if (ePageKind == PK_NOTES)
1546     {
1547         pPreviousNotesPage = pActualPage;
1548         nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
1549         pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3);
1550         nStandardPageNum = nNotesPageNum - 1;
1551         eStandardLayout = pPreviousStandardPage->GetAutoLayout();
1552     }
1553     else
1554     {
1555         pPreviousStandardPage = pActualPage;
1556         nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
1557         pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1);
1558         nNotesPageNum = nStandardPageNum + 1;
1559         aNotesPageName = aStandardPageName;
1560         eNotesLayout = pPreviousNotesPage->GetAutoLayout();
1561     }
1562 
1563     OSL_ASSERT(nNotesPageNum==nStandardPageNum+1);
1564     if (nInsertPosition < 0)
1565         nInsertPosition = nStandardPageNum;
1566 
1567     // Set up and insert the standard page.
1568     SetupNewPage (
1569         pPreviousStandardPage,
1570         pStandardPage,
1571         aStandardPageName,
1572         nInsertPosition,
1573         bIsPageBack,
1574         bIsPageObj);
1575 
1576     // Set up and insert the notes page.
1577     pNotesPage->SetPageKind(PK_NOTES);
1578     SetupNewPage (
1579         pPreviousNotesPage,
1580         pNotesPage,
1581         aNotesPageName,
1582         nInsertPosition+1,
1583         bIsPageBack,
1584         bIsPageObj);
1585 
1586     // Return an index that allows the caller to access the newly inserted
1587     // pages by using GetSdPage().
1588     return pStandardPage->GetPageNum() / 2;
1589 }
1590 
1591 
1592 
1593 
1594 void SdDrawDocument::SetupNewPage (
1595     SdPage* pPreviousPage,
1596     SdPage* pPage,
1597     const String& sPageName,
1598     sal_uInt16 nInsertionPoint,
1599     sal_Bool bIsPageBack,
1600     sal_Bool bIsPageObj)
1601 {
1602     if (pPreviousPage != NULL)
1603     {
1604         pPage->SetSize( pPreviousPage->GetSize() );
1605         pPage->SetBorder( pPreviousPage->GetLftBorder(),
1606             pPreviousPage->GetUppBorder(),
1607             pPreviousPage->GetRgtBorder(),
1608             pPreviousPage->GetLwrBorder() );
1609     }
1610     pPage->SetName(sPageName);
1611 
1612     InsertPage(pPage, nInsertionPoint);
1613 
1614     if (pPreviousPage != NULL)
1615     {
1616         SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
1617         sal_uInt8 aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), sal_False);
1618         sal_uInt8 aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), sal_False);
1619         SetOfByte aVisibleLayers = pPreviousPage->TRG_GetMasterPageVisibleLayers();
1620         aVisibleLayers.Set(aBckgrnd, bIsPageBack);
1621         aVisibleLayers.Set(aBckgrndObj, bIsPageObj);
1622         pPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
1623     }
1624 }
1625 
1626 sd::UndoManager* SdDrawDocument::GetUndoManager() const
1627 {
1628     return mpDocSh ? dynamic_cast< sd::UndoManager* >(mpDocSh->GetUndoManager()) : 0;
1629 }
1630 
1631 // eof
1632