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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <memory>
24 #include <utility>
25 
26 #include <DrawDocShell.hxx>
27 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
28 #include <editeng/outlobj.hxx>
29 #include <tools/urlobj.hxx>
30 #include <vcl/waitobj.hxx>
31 #include <svx/svxids.hrc>
32 #include <editeng/editeng.hxx>
33 #include <editeng/editstat.hxx>
34 #include <editeng/flstitem.hxx>
35 #include <svl/flagitem.hxx>
36 #include <sot/storage.hxx>
37 #include <sfx2/dinfdlg.hxx>
38 #include <sfx2/docfile.hxx>
39 #include <sfx2/docfilt.hxx>
40 #include <sfx2/dispatch.hxx>
41 #include <svx/svdotext.hxx>
42 #include <sfx2/printer.hxx>
43 #include <svtools/ctrltool.hxx>
44 #include <comphelper/classids.hxx>
45 #include <sot/formats.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <com/sun/star/drawing/XDrawPage.hpp>
48 #include <com/sun/star/drawing/XDrawView.hpp>
49 
50 #include <app.hrc>
51 #include <strings.hrc>
52 #include <strmname.h>
53 #include <FrameView.hxx>
54 #include <optsitem.hxx>
55 #include <Outliner.hxx>
56 #include <sdattr.hrc>
57 #include <drawdoc.hxx>
58 #include <ViewShell.hxx>
59 #include <sdmod.hxx>
60 #include <View.hxx>
61 #include <EffectMigration.hxx>
62 #include <CustomAnimationEffect.hxx>
63 #include <sdpage.hxx>
64 #include <sdresid.hxx>
65 #include <DrawViewShell.hxx>
66 #include <ViewShellBase.hxx>
67 #include <Window.hxx>
68 #include <OutlineView.hxx>
69 #include <OutlineViewShell.hxx>
70 #include <sdxmlwrp.hxx>
71 #include <sdpptwrp.hxx>
72 #include <sdcgmfilter.hxx>
73 #include <sdgrffilter.hxx>
74 #include <sdhtmlfilter.hxx>
75 #include <sdpdffilter.hxx>
76 #include <framework/FrameworkHelper.hxx>
77 
78 #include <sfx2/zoomitem.hxx>
79 
80 using namespace ::com::sun::star;
81 using namespace ::com::sun::star::uno;
82 using ::sd::framework::FrameworkHelper;
83 
84 namespace sd {
85 
86 /**
87  * Creates (if necessary) and returns a SfxPrinter
88  */
GetPrinter(bool bCreate)89 SfxPrinter* DrawDocShell::GetPrinter(bool bCreate)
90 {
91     if (bCreate && !mpPrinter)
92     {
93         // create ItemSet with special pool area
94         auto pSet = std::make_unique<SfxItemSet>( GetPool(),
95                             svl::Items<SID_PRINTER_NOTFOUND_WARN,  SID_PRINTER_NOTFOUND_WARN,
96                             SID_PRINTER_CHANGESTODOC,   SID_PRINTER_CHANGESTODOC,
97                             ATTR_OPTIONS_PRINT,         ATTR_OPTIONS_PRINT>{} );
98         // set PrintOptionsSet
99         SdOptionsPrintItem aPrintItem( SD_MOD()->GetSdOptions(mpDoc->GetDocumentType()) );
100         SfxFlagItem aFlagItem( SID_PRINTER_CHANGESTODOC );
101         SfxPrinterChangeFlags nFlags =
102                 (aPrintItem.GetOptionsPrint().IsWarningSize() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) |
103                 (aPrintItem.GetOptionsPrint().IsWarningOrientation() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE);
104         aFlagItem.SetValue( static_cast<int>(nFlags) );
105 
106         pSet->Put( aPrintItem );
107         pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aPrintItem.GetOptionsPrint().IsWarningPrinter() ) );
108         pSet->Put( aFlagItem );
109 
110         mpPrinter = VclPtr<SfxPrinter>::Create(std::move(pSet));
111         mbOwnPrinter = true;
112 
113         // set output quality
114         sal_uInt16 nQuality = aPrintItem.GetOptionsPrint().GetOutputQuality();
115 
116         DrawModeFlags nMode = DrawModeFlags::Default;
117         // 1 == Grayscale, 2 == Black & White (with grayscale images)
118         if( nQuality == 1 )
119             nMode = DrawModeFlags::GrayLine | DrawModeFlags::GrayFill | DrawModeFlags::GrayText | DrawModeFlags::GrayBitmap | DrawModeFlags::GrayGradient;
120         else if( nQuality == 2 )
121             nMode = DrawModeFlags::BlackLine | DrawModeFlags::WhiteFill | DrawModeFlags::BlackText | DrawModeFlags::GrayBitmap | DrawModeFlags::WhiteGradient;
122 
123         mpPrinter->SetDrawMode( nMode );
124 
125         MapMode aMM (mpPrinter->GetMapMode());
126         aMM.SetMapUnit(MapUnit::Map100thMM);
127         mpPrinter->SetMapMode(aMM);
128         UpdateRefDevice();
129     }
130     return mpPrinter;
131 }
132 
133 /**
134  * Set new SfxPrinter (transfer of ownership)
135  */
SetPrinter(SfxPrinter * pNewPrinter)136 void DrawDocShell::SetPrinter(SfxPrinter *pNewPrinter)
137 {
138     if ( mpViewShell )
139     {
140         ::sd::View* pView = mpViewShell->GetView();
141         if ( pView->IsTextEdit() )
142             pView->SdrEndTextEdit();
143     }
144 
145     if ( mpPrinter && mbOwnPrinter && (mpPrinter.get() != pNewPrinter) )
146         mpPrinter.disposeAndClear();
147 
148     mpPrinter = pNewPrinter;
149     mbOwnPrinter = true;
150     if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED )
151         UpdateFontList();
152     UpdateRefDevice();
153 }
154 
UpdateFontList()155 void DrawDocShell::UpdateFontList()
156 {
157     mpFontList.reset();
158     OutputDevice* pRefDevice = nullptr;
159     if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED )
160         pRefDevice = GetPrinter(true);
161     else
162         pRefDevice = SD_MOD()->GetVirtualRefDevice();
163     mpFontList.reset( new FontList(pRefDevice, nullptr) );
164     SvxFontListItem aFontListItem( mpFontList.get(), SID_ATTR_CHAR_FONTLIST );
165     PutItem( aFontListItem );
166 }
167 
GetDocumentPrinter()168 Printer* DrawDocShell::GetDocumentPrinter()
169 {
170     return GetPrinter(false);
171 }
172 
OnDocumentPrinterChanged(Printer * pNewPrinter)173 void DrawDocShell::OnDocumentPrinterChanged(Printer* pNewPrinter)
174 {
175     // if we already have a printer, see if it's the same
176     if( mpPrinter )
177     {
178         // easy case
179         if( mpPrinter == pNewPrinter )
180             return;
181 
182         // compare if it's the same printer with the same job setup
183         if( (mpPrinter->GetName() == pNewPrinter->GetName()) &&
184             (mpPrinter->GetJobSetup() == pNewPrinter->GetJobSetup()))
185             return;
186     }
187 
188     SfxPrinter* const pSfxPrinter = dynamic_cast<SfxPrinter*>(pNewPrinter);
189     if (pSfxPrinter)
190     {
191         SetPrinter(pSfxPrinter);
192 
193         // container owns printer
194         mbOwnPrinter = false;
195     }
196 }
197 
UpdateRefDevice()198 void DrawDocShell::UpdateRefDevice()
199 {
200     if( !mpDoc )
201         return;
202 
203     // Determine the device for which the output will be formatted.
204     VclPtr< OutputDevice > pRefDevice;
205     switch (mpDoc->GetPrinterIndependentLayout())
206     {
207         case css::document::PrinterIndependentLayout::DISABLED:
208             pRefDevice = mpPrinter.get();
209             break;
210 
211         case css::document::PrinterIndependentLayout::ENABLED:
212             pRefDevice = SD_MOD()->GetVirtualRefDevice();
213             break;
214 
215         default:
216             // We are confronted with an invalid or un-implemented
217             // layout mode.  Use the printer as formatting device
218             // as a fall-back.
219             SAL_WARN( "sd", "DrawDocShell::UpdateRefDevice(): Unexpected printer layout mode");
220 
221             pRefDevice = mpPrinter.get();
222             break;
223     }
224     mpDoc->SetRefDevice( pRefDevice.get() );
225 
226     SdOutliner* pOutl = mpDoc->GetOutliner( false );
227 
228     if( pOutl )
229         pOutl->SetRefDevice( pRefDevice );
230 
231     SdOutliner* pInternalOutl = mpDoc->GetInternalOutliner( false );
232 
233     if( pInternalOutl )
234         pInternalOutl->SetRefDevice( pRefDevice );
235 }
236 
237 /**
238  * Creates new document, opens streams
239  */
InitNew(const css::uno::Reference<css::embed::XStorage> & xStorage)240 bool DrawDocShell::InitNew( const css::uno::Reference< css::embed::XStorage >& xStorage )
241 {
242     bool bRet = SfxObjectShell::InitNew( xStorage );
243 
244     ::tools::Rectangle aVisArea( Point(0, 0), Size(14100, 10000) );
245     SetVisArea(aVisArea);
246 
247     if (bRet)
248     {
249         if( !mbSdDataObj )
250             mpDoc->NewOrLoadCompleted(NEW_DOC);  // otherwise calling
251                                                 // NewOrLoadCompleted(NEW_LOADED) in
252                                                 // SdDrawDocument::AllocModel()
253     }
254     return bRet;
255 }
256 
257 /**
258  * loads pools and document
259  */
Load(SfxMedium & rMedium)260 bool DrawDocShell::Load( SfxMedium& rMedium )
261 {
262     // If this is an ODF file being loaded, then by default, use legacy processing
263     // for tdf#99729 (if required, it will be overridden in *::ReadUserDataSequence())
264     if (IsOwnStorageFormat(rMedium))
265     {
266         mpDoc->SetAnchoredTextOverflowLegacy(true);
267     }
268 
269     bool       bRet = false;
270     bool       bStartPresentation = false;
271     ErrCode nError = ERRCODE_NONE;
272 
273     SfxItemSet* pSet = rMedium.GetItemSet();
274 
275     if( pSet )
276     {
277         if( (  SfxItemState::SET == pSet->GetItemState(SID_PREVIEW ) ) && pSet->Get( SID_PREVIEW ).GetValue() )
278         {
279             mpDoc->SetStarDrawPreviewMode( true );
280         }
281 
282         if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
283             pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
284         {
285             bStartPresentation = true;
286             mpDoc->SetStartWithPresentation( true );
287         }
288     }
289 
290     bRet = SfxObjectShell::Load( rMedium );
291     if (bRet)
292     {
293         comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
294         rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false);
295         bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError );
296     }
297 
298     if( bRet )
299     {
300         // for legacy markup in OOoXML filter, convert the animations now
301         EffectMigration::DocumentLoaded(*GetDoc());
302         UpdateTablePointers();
303 
304         // If we're an embedded OLE object, use tight bounds
305         // for our visArea. No point in showing the user lots of empty
306         // space. Had to remove the check for empty VisArea below,
307         // since XML load always sets a VisArea before.
308         //TODO/LATER: looks a little bit strange!
309         if( ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) && SfxObjectShell::GetVisArea( ASPECT_CONTENT ).IsEmpty() )
310         {
311             SdPage* pPage = mpDoc->GetSdPage( 0, PageKind::Standard );
312 
313             if( pPage )
314                 SetVisArea( pPage->GetAllObjBoundRect() );
315         }
316 
317         FinishedLoading();
318 
319         const INetURLObject aUrl;
320         SfxObjectShell::SetAutoLoad( aUrl, 0, false );
321     }
322     else
323     {
324         if( nError == ERRCODE_IO_BROKENPACKAGE )
325             SetError(ERRCODE_IO_BROKENPACKAGE);
326 
327         // TODO/LATER: correct error handling?!
328         //pStore->SetError(SVSTREAM_WRONGVERSION);
329         else
330             SetError(ERRCODE_ABORT);
331     }
332 
333     // tell SFX to change viewshell when in preview mode
334     if( IsPreview() || bStartPresentation )
335     {
336         SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
337         if( pMediumSet )
338             pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) );
339     }
340 
341     return bRet;
342 }
343 
344 /**
345  * loads content for organizer
346  */
LoadFrom(SfxMedium & rMedium)347 bool DrawDocShell::LoadFrom( SfxMedium& rMedium )
348 {
349     std::unique_ptr<WaitObject> pWait;
350     if( mpViewShell )
351         pWait.reset(new WaitObject( static_cast<vcl::Window*>(mpViewShell->GetActiveWindow()) ));
352 
353     mpDoc->NewOrLoadCompleted( NEW_DOC );
354     mpDoc->CreateFirstPages();
355     mpDoc->StopWorkStartupDelay();
356 
357     // TODO/LATER: nobody is interested in the error code?!
358     ErrCode nError = ERRCODE_NONE;
359     bool bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Organizer, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError );
360 
361     // tell SFX to change viewshell when in preview mode
362     if( IsPreview() )
363     {
364         SfxItemSet *pSet = GetMedium()->GetItemSet();
365 
366         if( pSet )
367             pSet->Put( SfxUInt16Item( SID_VIEW_ID, 5 ) );
368     }
369 
370     return bRet;
371 }
372 
373 /**
374  * load from 3rd party format
375  */
ImportFrom(SfxMedium & rMedium,uno::Reference<text::XTextRange> const & xInsertPosition)376 bool DrawDocShell::ImportFrom(SfxMedium &rMedium,
377         uno::Reference<text::XTextRange> const& xInsertPosition)
378 {
379     const OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
380     if (aFilterName == "Impress MS PowerPoint 2007 XML" ||
381         aFilterName == "Impress MS PowerPoint 2007 XML AutoPlay" ||
382         aFilterName == "Impress MS PowerPoint 2007 XML VBA")
383     {
384         // As this is a MSFT format, we should use the "MS Compat"
385         // mode for spacing before and after paragraphs.
386 
387         // This is copied from what is done for .ppt import in
388         // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx
389         // in. We need to tell both the edit engine of the draw outliner,
390         // and the document, to do "summation of paragraphs".
391         SdrOutliner& rOutl = mpDoc->GetDrawOutliner();
392         EEControlBits nControlWord = rOutl.GetEditEngine().GetControlWord();
393         nControlWord |=  EEControlBits::ULSPACESUMMATION;
394         const_cast<EditEngine&>(rOutl.GetEditEngine()).SetControlWord( nControlWord );
395 
396         mpDoc->SetSummationOfParagraphs();
397     }
398 
399     const bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition);
400 
401     SfxItemSet* pSet = rMedium.GetItemSet();
402     if( pSet )
403     {
404         if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
405             pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
406         {
407             mpDoc->SetStartWithPresentation( true );
408 
409             // tell SFX to change viewshell when in preview mode
410             if( IsPreview() )
411             {
412                 SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
413                 if( pMediumSet )
414                     pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, 1 ) );
415             }
416         }
417     }
418 
419     return bRet;
420 }
421 
422 /**
423  * load from a foreign format
424  */
ConvertFrom(SfxMedium & rMedium)425 bool DrawDocShell::ConvertFrom( SfxMedium& rMedium )
426 {
427     const OUString  aFilterName( rMedium.GetFilter()->GetFilterName() );
428     bool            bRet = false;
429     bool            bStartPresentation = false;
430 
431     SetWaitCursor( true );
432 
433     SfxItemSet* pSet = rMedium.GetItemSet();
434     if( pSet )
435     {
436         if( (  SfxItemState::SET == pSet->GetItemState(SID_PREVIEW ) ) && pSet->Get( SID_PREVIEW ).GetValue() )
437         {
438             mpDoc->SetStarDrawPreviewMode( true );
439         }
440 
441         if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
442             pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
443         {
444             bStartPresentation = true;
445             mpDoc->SetStartWithPresentation( true );
446         }
447     }
448 
449     if( aFilterName == pFilterPowerPoint97
450         || aFilterName == pFilterPowerPoint97Template
451         || aFilterName == pFilterPowerPoint97AutoPlay)
452     {
453         mpDoc->StopWorkStartupDelay();
454         bRet = SdPPTFilter( rMedium, *this ).Import();
455     }
456     else if (aFilterName.indexOf("impress8") >= 0 ||
457              aFilterName.indexOf("draw8") >= 0)
458     {
459         // TODO/LATER: nobody is interested in the error code?!
460         mpDoc->CreateFirstPages();
461         mpDoc->StopWorkStartupDelay();
462         ErrCode nError = ERRCODE_NONE;
463         bRet = SdXMLFilter( rMedium, *this ).Import( nError );
464 
465     }
466     else if (aFilterName.indexOf("StarOffice XML (Draw)") >= 0 ||
467              aFilterName.indexOf("StarOffice XML (Impress)") >= 0)
468     {
469         // TODO/LATER: nobody is interested in the error code?!
470         mpDoc->CreateFirstPages();
471         mpDoc->StopWorkStartupDelay();
472         ErrCode nError = ERRCODE_NONE;
473         bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SOFFICE_FILEFORMAT_60 ).Import( nError );
474     }
475     else if (aFilterName == "CGM - Computer Graphics Metafile")
476     {
477         mpDoc->CreateFirstPages();
478         mpDoc->StopWorkStartupDelay();
479         bRet = SdCGMFilter( rMedium, *this ).Import();
480     }
481     else if (aFilterName == "draw_pdf_import")
482     {
483         mpDoc->CreateFirstPages();
484         mpDoc->StopWorkStartupDelay();
485         bRet = SdPdfFilter(rMedium, *this).Import();
486     }
487     else
488     {
489         mpDoc->CreateFirstPages();
490         mpDoc->StopWorkStartupDelay();
491         bRet = SdGRFFilter( rMedium, *this ).Import();
492     }
493 
494     FinishedLoading();
495 
496     // tell SFX to change viewshell when in preview mode
497     if( IsPreview() )
498     {
499         SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
500 
501         if( pMediumSet )
502             pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, 5 ) );
503     }
504     SetWaitCursor( false );
505 
506     // tell SFX to change viewshell when in preview mode
507     if( IsPreview() || bStartPresentation )
508     {
509         SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
510         if( pMediumSet )
511             pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) );
512     }
513 
514     return bRet;
515 }
516 
517 /**
518  * Writes pools and document to the open streams
519  */
Save()520 bool DrawDocShell::Save()
521 {
522     mpDoc->StopWorkStartupDelay();
523 
524     //TODO/LATER: why this?!
525     if( GetCreateMode() == SfxObjectCreateMode::STANDARD )
526         SfxObjectShell::SetVisArea( ::tools::Rectangle() );
527 
528     bool bRet = SfxObjectShell::Save();
529 
530     if( bRet )
531         bRet = SdXMLFilter( *GetMedium(), *this, SDXMLMODE_Normal, SotStorage::GetVersion( GetMedium()->GetStorage() ) ).Export();
532 
533     return bRet;
534 }
535 
536 /**
537  * Writes pools and document to the provided storage
538  */
SaveAs(SfxMedium & rMedium)539 bool DrawDocShell::SaveAs( SfxMedium& rMedium )
540 {
541     mpDoc->setDocAccTitle(OUString());
542     if (SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst(this))
543     {
544         if (vcl::Window* pSysWin = pFrame1->GetWindow().GetSystemWindow())
545         {
546             pSysWin->SetAccessibleName(OUString());
547         }
548     }
549     mpDoc->StopWorkStartupDelay();
550 
551     //With custom animation, if Outliner is modified, update text before saving
552     if( mpViewShell )
553     {
554         SdPage* pPage = mpViewShell->getCurrentPage();
555         if( pPage && pPage->getMainSequence()->getCount() )
556         {
557             SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject();
558             SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner();
559             if( pObj && pOutl && pOutl->IsModified() )
560             {
561                 std::unique_ptr<OutlinerParaObject> pNewText = pOutl->CreateParaObject( 0, pOutl->GetParagraphCount() );
562                 pObj->SetOutlinerParaObject( std::move(pNewText) );
563                 pOutl->ClearModifyFlag();
564             }
565         }
566     }
567 
568     //TODO/LATER: why this?!
569     if( GetCreateMode() == SfxObjectCreateMode::STANDARD )
570         SfxObjectShell::SetVisArea( ::tools::Rectangle() );
571 
572     bool bRet = SfxObjectShell::SaveAs( rMedium );
573 
574     if( bRet )
575         bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Export();
576 
577     if( GetError() == ERRCODE_NONE )
578         SetError(ERRCODE_NONE);
579 
580     return bRet;
581 }
582 
583 /**
584  * save to foreign format
585  */
ConvertTo(SfxMedium & rMedium)586 bool DrawDocShell::ConvertTo( SfxMedium& rMedium )
587 {
588     bool bRet = false;
589 
590     if( mpDoc->GetPageCount() )
591     {
592         std::shared_ptr<const SfxFilter> pMediumFilter = rMedium.GetFilter();
593         const OUString aTypeName( pMediumFilter->GetTypeName() );
594         std::unique_ptr<SdFilter> xFilter;
595 
596         if( aTypeName.indexOf( "graphic_HTML" ) >= 0 )
597         {
598             xFilter = std::make_unique<SdHTMLFilter>(rMedium, *this);
599         }
600         else if( aTypeName.indexOf( "MS_PowerPoint_97" ) >= 0 )
601         {
602             xFilter = std::make_unique<SdPPTFilter>(rMedium, *this);
603             static_cast<SdPPTFilter*>(xFilter.get())->PreSaveBasic();
604         }
605         else if ( aTypeName.indexOf( "CGM_Computer_Graphics_Metafile" ) >= 0 )
606         {
607             xFilter = std::make_unique<SdCGMFilter>(rMedium, *this);
608         }
609         else if( aTypeName.indexOf( "draw8" ) >= 0 ||
610                  aTypeName.indexOf( "impress8" ) >= 0 )
611         {
612             xFilter = std::make_unique<SdXMLFilter>(rMedium, *this);
613         }
614         else if( aTypeName.indexOf( "StarOffice_XML_Impress" ) >= 0 ||
615                  aTypeName.indexOf( "StarOffice_XML_Draw" ) >= 0 )
616         {
617             xFilter = std::make_unique<SdXMLFilter>(rMedium, *this, SDXMLMODE_Normal, SOFFICE_FILEFORMAT_60);
618         }
619         else
620         {
621             xFilter = std::make_unique<SdGRFFilter>(rMedium, *this);
622         }
623 
624         if (xFilter)
625         {
626             if ( mpViewShell )
627             {
628                 ::sd::View* pView = mpViewShell->GetView();
629                 if ( pView->IsTextEdit() )
630                     pView->SdrEndTextEdit();
631             }
632 
633             bRet = xFilter->Export();
634         }
635     }
636 
637     return bRet;
638 }
639 
640 /**
641  * Reopen own streams to ensure that nobody else can prevent use from opening
642  * them.
643  */
SaveCompleted(const css::uno::Reference<css::embed::XStorage> & xStorage)644 bool DrawDocShell::SaveCompleted( const css::uno::Reference< css::embed::XStorage >& xStorage )
645 {
646     bool bRet = false;
647 
648     if( SfxObjectShell::SaveCompleted(xStorage) )
649     {
650         mpDoc->NbcSetChanged( false );
651 
652         if( mpViewShell )
653         {
654             if( dynamic_cast< OutlineViewShell *>( mpViewShell ) !=  nullptr )
655                 static_cast<OutlineView*>(mpViewShell->GetView())
656                     ->GetOutliner().ClearModifyFlag();
657 
658             SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner();
659             if( pOutl )
660             {
661                 SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject();
662                 if( pObj )
663                     pObj->NbcSetOutlinerParaObject( pOutl->CreateParaObject() );
664 
665                 pOutl->ClearModifyFlag();
666             }
667         }
668 
669         bRet = true;
670 
671         SfxViewFrame* pFrame = ( mpViewShell && mpViewShell->GetViewFrame() ) ?
672                                mpViewShell->GetViewFrame() :
673                                SfxViewFrame::Current();
674 
675         if( pFrame )
676             pFrame->GetBindings().Invalidate( SID_NAVIGATOR_STATE, true );
677     }
678     return bRet;
679 }
680 
GetStyleSheetPool()681 SfxStyleSheetBasePool* DrawDocShell::GetStyleSheetPool()
682 {
683     return mpDoc->GetStyleSheetPool();
684 }
685 
GotoBookmark(const OUString & rBookmark)686 void DrawDocShell::GotoBookmark(const OUString& rBookmark)
687 {
688     auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell );
689     if (!pDrawViewShell)
690         return;
691 
692     ViewShellBase& rBase (mpViewShell->GetViewShellBase());
693 
694     bool bIsMasterPage = false;
695     sal_uInt16 nPageNumber = SDRPAGE_NOTFOUND;
696     SdrObject* pObj = nullptr;
697 
698     const OUString sInteraction( "action?" );
699     if ( rBookmark.match( sInteraction ) )
700     {
701         const OUString sJump( "jump=" );
702         if ( rBookmark.match( sJump, sInteraction.getLength() ) )
703         {
704             OUString aDestination( rBookmark.copy( sInteraction.getLength() + sJump.getLength() ) );
705             if ( aDestination.match( "firstslide" ) )
706             {
707                 nPageNumber = 1;
708             }
709             else if ( aDestination.match( "lastslide" ) )
710             {
711                 nPageNumber = mpDoc->GetPageCount() - 2;
712             }
713             else if ( aDestination.match( "previousslide" ) )
714             {
715                 SdPage* pPage = pDrawViewShell->GetActualPage();
716                 nPageNumber = pPage->GetPageNum();
717                 nPageNumber = nPageNumber > 2 ? nPageNumber - 2 : SDRPAGE_NOTFOUND;
718             }
719             else if ( aDestination.match( "nextslide" ) )
720             {
721                 SdPage* pPage = pDrawViewShell->GetActualPage();
722                 nPageNumber = pPage->GetPageNum() + 2;
723                 if ( nPageNumber >= mpDoc->GetPageCount() )
724                     nPageNumber = SDRPAGE_NOTFOUND;
725             }
726         }
727     }
728     else
729     {
730         // Is the bookmark a page?
731         nPageNumber = mpDoc->GetPageByName( rBookmark, bIsMasterPage );
732 
733         if (nPageNumber == SDRPAGE_NOTFOUND)
734         {
735             // Is the bookmark an object?
736             pObj = mpDoc->GetObj(rBookmark);
737 
738             if (pObj)
739             {
740                 nPageNumber = pObj->getSdrPageFromSdrObject()->GetPageNum();
741             }
742         }
743     }
744     if (nPageNumber != SDRPAGE_NOTFOUND)
745     {
746         // Jump to the bookmarked page.  This is done in three steps.
747 
748         SdPage* pPage;
749         if (bIsMasterPage)
750             pPage = static_cast<SdPage*>( mpDoc->GetMasterPage(nPageNumber) );
751         else
752             pPage = static_cast<SdPage*>( mpDoc->GetPage(nPageNumber) );
753 
754         // 1.) Change the view shell to the edit view, the notes view,
755         // or the handout view.
756         PageKind eNewPageKind = pPage->GetPageKind();
757 
758         if( (eNewPageKind != PageKind::Standard) && (mpDoc->GetDocumentType() == DocumentType::Draw) )
759             return;
760 
761         if (eNewPageKind != pDrawViewShell->GetPageKind())
762         {
763             // change work area
764             GetFrameView()->SetPageKind(eNewPageKind);
765             OUString sViewURL;
766             switch (eNewPageKind)
767             {
768                 case PageKind::Standard:
769                     sViewURL = FrameworkHelper::msImpressViewURL;
770                     break;
771                 case PageKind::Notes:
772                     sViewURL = FrameworkHelper::msNotesViewURL;
773                     break;
774                 case PageKind::Handout:
775                     sViewURL = FrameworkHelper::msHandoutViewURL;
776                     break;
777                 default:
778                     break;
779             }
780             if (!sViewURL.isEmpty())
781             {
782                 std::shared_ptr<FrameworkHelper> pHelper (
783                     FrameworkHelper::Instance(rBase));
784                 pHelper->RequestView(
785                     sViewURL,
786                     FrameworkHelper::msCenterPaneURL);
787                 pHelper->WaitForUpdate();
788 
789                 // Get the new DrawViewShell.
790                 mpViewShell = pHelper->GetViewShell(FrameworkHelper::msCenterPaneURL).get();
791                 pDrawViewShell = dynamic_cast<sd::DrawViewShell*>(mpViewShell);
792             }
793             else
794             {
795                 pDrawViewShell = nullptr;
796             }
797         }
798 
799         if (pDrawViewShell != nullptr)
800         {
801             setEditMode(pDrawViewShell, bIsMasterPage);
802 
803             // Make the bookmarked page the current page.  This is done
804             // by using the API because this takes care of all the
805             // little things to be done.  Especially writing the view
806             // data to the frame view.
807             sal_uInt16 nSdPgNum = (nPageNumber - 1) / 2;
808             Reference<drawing::XDrawView> xController (rBase.GetController(), UNO_QUERY);
809             if (xController.is())
810             {
811                 Reference<drawing::XDrawPage> xDrawPage (pPage->getUnoPage(), UNO_QUERY);
812                 xController->setCurrentPage (xDrawPage);
813             }
814             else
815             {
816                 // As a fall back switch to the page via the core.
817                 DBG_ASSERT (xController.is(),
818                     "DrawDocShell::GotoBookmark: can't switch page via API");
819                 pDrawViewShell->SwitchPage(nSdPgNum);
820             }
821 
822             if (pDrawViewShell->GetDispatcher())
823             {
824                 // show page
825                 SvxZoomItem aZoom;
826                 aZoom.SetType( SvxZoomType::WHOLEPAGE );
827                 pDrawViewShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM, SfxCallMode::ASYNCHRON, { &aZoom });
828             }
829 
830             if (pObj != nullptr)
831             {
832                 // select object
833                 pDrawViewShell->GetView()->UnmarkAll();
834                 pDrawViewShell->GetView()->MarkObj(
835                     pObj,
836                     pDrawViewShell->GetView()->GetSdrPageView());
837             }
838         }
839     }
840 
841     SfxBindings& rBindings = ((pDrawViewShell && pDrawViewShell->GetViewFrame()!=nullptr)
842         ? pDrawViewShell->GetViewFrame()
843         : SfxViewFrame::Current() )->GetBindings();
844 
845     rBindings.Invalidate(SID_NAVIGATOR_STATE, true);
846     rBindings.Invalidate(SID_NAVIGATOR_PAGENAME);
847 }
848 
849 /**
850  * If it should become a document template.
851  */
SaveAsOwnFormat(SfxMedium & rMedium)852 bool DrawDocShell::SaveAsOwnFormat( SfxMedium& rMedium )
853 {
854 
855     std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter();
856 
857     if (pFilter->IsOwnTemplateFormat())
858     {
859         /* now the StarDraw specialty:
860            we assign known layout names to the layout template of the first
861            page, we set the layout names of the affected masterpages and pages.
862            We inform all text objects of the affected standard, note and
863            masterpages about the name change.
864         */
865 
866         OUString aLayoutName;
867 
868         SfxStringItem const * pLayoutItem;
869         if( rMedium.GetItemSet()->GetItemState(SID_TEMPLATE_NAME, false, reinterpret_cast<const SfxPoolItem**>(& pLayoutItem) ) == SfxItemState::SET )
870         {
871             aLayoutName = pLayoutItem->GetValue();
872         }
873         else
874         {
875             INetURLObject aURL( rMedium.GetName() );
876             aURL.removeExtension();
877             aLayoutName = aURL.getName();
878         }
879 
880         if (aLayoutName.isEmpty())
881         {
882             sal_uInt32 nCount = mpDoc->GetMasterSdPageCount(PageKind::Standard);
883             for (sal_uInt32 i = 0; i < nCount; ++i)
884             {
885                 OUString aOldPageLayoutName = mpDoc->GetMasterSdPage(i, PageKind::Standard)->GetLayoutName();
886                 OUString aNewLayoutName = aLayoutName;
887                 // Don't add suffix for the first master page
888                 if( i > 0 )
889                     aNewLayoutName += OUString::number(i);
890 
891                 mpDoc->RenameLayoutTemplate(aOldPageLayoutName, aNewLayoutName);
892             }
893         }
894     }
895 
896     return SfxObjectShell::SaveAsOwnFormat(rMedium);
897 }
898 
FillClass(SvGlobalName * pClassName,SotClipboardFormatId * pFormat,OUString * pFullTypeName,sal_Int32 nFileFormat,bool bTemplate) const899 void DrawDocShell::FillClass(SvGlobalName* pClassName,
900                                         SotClipboardFormatId* pFormat,
901                                         OUString* pFullTypeName,
902                                         sal_Int32 nFileFormat,
903                                         bool bTemplate /* = false */) const
904 {
905     if (nFileFormat == SOFFICE_FILEFORMAT_60)
906     {
907         if ( meDocType == DocumentType::Draw )
908         {
909             *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60);
910             *pFormat = SotClipboardFormatId::STARDRAW_60;
911             *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_60);
912         }
913         else
914         {
915             *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60);
916             *pFormat = SotClipboardFormatId::STARIMPRESS_60;
917             *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_60);
918         }
919     }
920     else if (nFileFormat == SOFFICE_FILEFORMAT_8)
921     {
922         if ( meDocType == DocumentType::Draw )
923         {
924             *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60);
925             *pFormat = bTemplate ? SotClipboardFormatId::STARDRAW_8_TEMPLATE : SotClipboardFormatId::STARDRAW_8;
926             *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API
927         }
928         else
929         {
930             *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60);
931             *pFormat = bTemplate ? SotClipboardFormatId::STARIMPRESS_8_TEMPLATE : SotClipboardFormatId::STARIMPRESS_8;
932             *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API
933         }
934     }
935 }
936 
GetDocumentRefDev()937 OutputDevice* DrawDocShell::GetDocumentRefDev()
938 {
939     OutputDevice* pReferenceDevice = SfxObjectShell::GetDocumentRefDev ();
940     // Only when our parent does not have a reference device then we return
941     // our own.
942     if (pReferenceDevice == nullptr && mpDoc != nullptr)
943         pReferenceDevice = mpDoc->GetRefDevice ();
944     return pReferenceDevice;
945 }
946 
947 /** executes the SID_OPENDOC slot to let the framework open a document
948     with the given URL and this document as a referer */
OpenBookmark(const OUString & rBookmarkURL)949 void DrawDocShell::OpenBookmark( const OUString& rBookmarkURL )
950 {
951     SfxStringItem   aStrItem( SID_FILE_NAME, rBookmarkURL );
952     SfxStringItem   aReferer( SID_REFERER, GetMedium()->GetName() );
953     const SfxPoolItem* ppArgs[] = { &aStrItem, &aReferer, nullptr };
954     ( mpViewShell ? mpViewShell->GetViewFrame() : SfxViewFrame::Current() )->GetBindings().Execute( SID_OPENHYPERLINK, ppArgs );
955 }
956 
CreateDocumentInfoDialog(weld::Window * pParent,const SfxItemSet & rSet)957 std::unique_ptr<SfxDocumentInfoDialog> DrawDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet)
958 {
959     std::unique_ptr<SfxDocumentInfoDialog> xDlg = std::make_unique<SfxDocumentInfoDialog>(pParent, rSet);
960     DrawDocShell* pDocSh = dynamic_cast<DrawDocShell*>(SfxObjectShell::Current());
961     if( pDocSh == this )
962     {
963         xDlg->AddFontTabPage();
964     }
965     return xDlg;
966 }
967 
setEditMode(DrawViewShell * pDrawViewShell,bool isMasterPage)968 void DrawDocShell::setEditMode(DrawViewShell* pDrawViewShell, bool isMasterPage)
969 {
970     // Set the edit mode to either the normal edit mode or the
971     // master page mode.
972     EditMode eNewEditMode = EditMode::Page;
973     if (isMasterPage)
974     {
975         eNewEditMode = EditMode::MasterPage;
976     }
977 
978     if (eNewEditMode != pDrawViewShell->GetEditMode())
979     {
980         // Set EditMode
981         pDrawViewShell->ChangeEditMode(eNewEditMode, false);
982     }
983 }
984 } // end of namespace sd
985 
986 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
987