xref: /trunk/main/sfx2/source/view/viewprn.cxx (revision 309711504682cafc503a6b3667ea5af9b42b4ce7)
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_sfx2.hxx"
30 
31 #include <com/sun/star/document/XDocumentProperties.hpp>
32 #include <com/sun/star/view/PrintableState.hpp>
33 #include "com/sun/star/view/XRenderable.hpp"
34 
35 #include <svl/itempool.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <svtools/prnsetup.hxx>
38 #include <svl/flagitem.hxx>
39 #include <svl/stritem.hxx>
40 #include <svl/intitem.hxx>
41 #include <svl/eitem.hxx>
42 #include <sfx2/app.hxx>
43 #include <unotools/useroptions.hxx>
44 #include <unotools/printwarningoptions.hxx>
45 #include <tools/datetime.hxx>
46 #include <sfx2/bindings.hxx>
47 #include <sfx2/objface.hxx>
48 #include <sfx2/viewsh.hxx>
49 #include "viewimp.hxx"
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/prnmon.hxx>
52 #include "sfx2/sfxresid.hxx"
53 #include <sfx2/request.hxx>
54 #include <sfx2/objsh.hxx>
55 #include "sfxtypes.hxx"
56 #include <sfx2/event.hxx>
57 #include <sfx2/docfile.hxx>
58 #include <sfx2/docfilt.hxx>
59 
60 #include "toolkit/awt/vclxdevice.hxx"
61 
62 #include "view.hrc"
63 #include "helpid.hrc"
64 
65 using namespace com::sun::star;
66 using namespace com::sun::star::uno;
67 
68 TYPEINIT1(SfxPrintingHint, SfxHint);
69 
70 // -----------------------------------------------------------------------
71 class SfxPrinterController : public vcl::PrinterController, public SfxListener
72 {
73     Any                                     maCompleteSelection;
74     Any                                     maSelection;
75     Reference< view::XRenderable >          mxRenderable;
76     mutable Printer*                        mpLastPrinter;
77     mutable Reference<awt::XDevice>         mxDevice;
78     SfxViewShell*                           mpViewShell;
79     SfxObjectShell*                         mpObjectShell;
80     sal_Bool        m_bOrigStatus;
81     sal_Bool        m_bNeedsChange;
82     sal_Bool        m_bApi;
83     sal_Bool        m_bTempPrinter;
84     util::DateTime  m_aLastPrinted;
85     ::rtl::OUString m_aLastPrintedBy;
86 
87     Sequence< beans::PropertyValue > getMergedOptions() const;
88     const Any& getSelectionObject() const;
89 public:
90     SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
91                           const Any& i_rComplete,
92                           const Any& i_rSelection,
93                           const Any& i_rViewProp,
94                           const Reference< view::XRenderable >& i_xRender,
95                           sal_Bool i_bApi, sal_Bool i_bDirect,
96                           SfxViewShell* pView,
97                           const uno::Sequence< beans::PropertyValue >& rProps
98                         );
99 
100     virtual ~SfxPrinterController();
101     virtual void Notify( SfxBroadcaster&, const SfxHint& );
102 
103     virtual int  getPageCount() const;
104     virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const;
105     virtual void printPage( int i_nPage ) const;
106     virtual void jobStarted();
107     virtual void jobFinished( com::sun::star::view::PrintableState );
108 };
109 
110 SfxPrinterController::SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
111                                             const Any& i_rComplete,
112                                             const Any& i_rSelection,
113                                             const Any& i_rViewProp,
114                                             const Reference< view::XRenderable >& i_xRender,
115                                             sal_Bool i_bApi, sal_Bool i_bDirect,
116                                             SfxViewShell* pView,
117                                             const uno::Sequence< beans::PropertyValue >& rProps
118                                           )
119     : PrinterController( i_rPrinter)
120     , maCompleteSelection( i_rComplete )
121     , maSelection( i_rSelection )
122     , mxRenderable( i_xRender )
123     , mpLastPrinter( NULL )
124     , mpViewShell( pView )
125     , mpObjectShell(0)
126     , m_bOrigStatus( sal_False )
127     , m_bNeedsChange( sal_False )
128     , m_bApi(i_bApi)
129     , m_bTempPrinter( i_rPrinter.get() != NULL )
130 {
131     if ( mpViewShell )
132     {
133         StartListening( *mpViewShell );
134         mpObjectShell = mpViewShell->GetObjectShell();
135         StartListening( *mpObjectShell );
136     }
137 
138     // initialize extra ui options
139     if( mxRenderable.is() )
140     {
141         for (sal_Int32 nProp=0; nProp<rProps.getLength(); nProp++)
142             setValue( rProps[nProp].Name, rProps[nProp].Value );
143 
144         Sequence< beans::PropertyValue > aRenderOptions( 3 );
145         aRenderOptions[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExtraPrintUIOptions" ) );
146         aRenderOptions[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "View" ) );
147         aRenderOptions[1].Value = i_rViewProp;
148         aRenderOptions[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) );
149         aRenderOptions[2].Value <<= sal_True;
150         try
151         {
152             Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
153             int nProps = aRenderParms.getLength();
154             for( int i = 0; i < nProps; i++ )
155             {
156                 if( aRenderParms[i].Name.equalsAscii( "ExtraPrintUIOptions" ) )
157                 {
158                     Sequence< beans::PropertyValue > aUIProps;
159                     aRenderParms[i].Value >>= aUIProps;
160                     setUIOptions( aUIProps );
161                 }
162                 else if( aRenderParms[i].Name.compareToAscii( "NUp", 3 ) == 0 )
163                 {
164                     setValue( aRenderParms[i].Name, aRenderParms[i].Value );
165                 }
166             }
167         }
168         catch( lang::IllegalArgumentException& )
169         {
170             // the first renderer should always be available for the UI options,
171             // but catch the exception to be safe
172         }
173     }
174 
175     // set some job parameters
176     setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsApi" ) ), makeAny( i_bApi ) );
177     setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDirect" ) ), makeAny( i_bDirect ) );
178     setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) ), makeAny( sal_True ) );
179     setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "View" ) ), i_rViewProp );
180 }
181 
182 void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
183 {
184     if ( rHint.IsA(TYPE(SfxSimpleHint)) )
185     {
186         if ( ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
187         {
188             EndListening(*mpViewShell);
189             EndListening(*mpObjectShell);
190             mpViewShell = 0;
191             mpObjectShell = 0;
192         }
193     }
194 }
195 
196 SfxPrinterController::~SfxPrinterController()
197 {
198 }
199 
200 const Any& SfxPrinterController::getSelectionObject() const
201 {
202     const beans::PropertyValue* pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintSelectionOnly" ) ) );
203     if( pVal )
204     {
205         sal_Bool bSel = sal_False;
206         pVal->Value >>= bSel;
207         return bSel ? maSelection : maCompleteSelection;
208     }
209 
210     sal_Int32 nChoice = 0;
211     pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ) );
212     if( pVal )
213         pVal->Value >>= nChoice;
214     return (nChoice > 1) ? maSelection : maCompleteSelection;
215 }
216 
217 Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const
218 {
219     boost::shared_ptr<Printer> pPrinter( getPrinter() );
220     if( pPrinter.get() != mpLastPrinter )
221     {
222         mpLastPrinter = pPrinter.get();
223         VCLXDevice* pXDevice = new VCLXDevice();
224         pXDevice->SetOutputDevice( mpLastPrinter );
225         mxDevice = Reference< awt::XDevice >( pXDevice );
226     }
227 
228     Sequence< beans::PropertyValue > aRenderOptions( 1 );
229     aRenderOptions[ 0 ].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) );
230     aRenderOptions[ 0 ].Value <<= mxDevice;
231 
232     aRenderOptions = getJobProperties( aRenderOptions );
233     return aRenderOptions;
234 }
235 
236 int SfxPrinterController::getPageCount() const
237 {
238     int nPages = 0;
239     boost::shared_ptr<Printer> pPrinter( getPrinter() );
240     if( mxRenderable.is() && pPrinter )
241     {
242         Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
243         nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions );
244     }
245     return nPages;
246 }
247 
248 Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const
249 {
250     boost::shared_ptr<Printer> pPrinter( getPrinter() );
251     Sequence< beans::PropertyValue > aResult;
252 
253     if( mxRenderable.is() && pPrinter )
254     {
255         Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
256         try
257         {
258             aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions );
259         }
260         catch( lang::IllegalArgumentException& )
261         {
262         }
263     }
264     return aResult;
265 }
266 
267 void SfxPrinterController::printPage( int i_nPage ) const
268 {
269     boost::shared_ptr<Printer> pPrinter( getPrinter() );
270     if( mxRenderable.is() && pPrinter )
271     {
272         Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
273         try
274         {
275             mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions );
276         }
277         catch( lang::IllegalArgumentException& )
278         {
279             // don't care enough about nonexistant page here
280             // to provoke a crash
281         }
282     }
283 }
284 
285 void SfxPrinterController::jobStarted()
286 {
287     if ( mpObjectShell )
288     {
289         m_bOrigStatus = mpObjectShell->IsEnableSetModified();
290 
291         // check configuration: shall update of printing information in DocInfo set the document to "modified"?
292         if ( m_bOrigStatus && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
293         {
294             mpObjectShell->EnableSetModified( sal_False );
295             m_bNeedsChange = sal_True;
296         }
297 
298         // refresh document info
299         uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
300         m_aLastPrintedBy = xDocProps->getPrintedBy();
301         m_aLastPrinted = xDocProps->getPrintDate();
302 
303         xDocProps->setPrintedBy( mpObjectShell->IsUseUserData()
304             ? ::rtl::OUString( SvtUserOptions().GetFullName() )
305             : ::rtl::OUString() );
306         ::DateTime now;
307 
308         xDocProps->setPrintDate( util::DateTime(
309             now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(),
310             now.GetDay(), now.GetMonth(), now.GetYear() ) );
311 
312         // FIXME: how to get all print options incl. AdditionalOptions easily?
313         uno::Sequence < beans::PropertyValue > aOpts;
314         mpObjectShell->Broadcast( SfxPrintingHint( view::PrintableState_JOB_STARTED, aOpts ) );
315     }
316 }
317 
318 void SfxPrinterController::jobFinished( com::sun::star::view::PrintableState nState )
319 {
320     if ( mpObjectShell )
321     {
322         bool bCopyJobSetup = false;
323         mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
324         switch ( nState )
325         {
326             case view::PrintableState_JOB_FAILED :
327             {
328                 // "real" problem (not simply printing cancelled by user)
329                 String aMsg( SfxResId( STR_NOSTARTPRINTER ) );
330                 if ( !m_bApi )
331                     ErrorBox( mpViewShell->GetWindow(), WB_OK | WB_DEF_OK,  aMsg ).Execute();
332                 // intentionally no break
333             }
334             case view::PrintableState_JOB_ABORTED :
335             {
336                 // printing not succesful, reset DocInfo
337                 uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
338                 xDocProps->setPrintedBy(m_aLastPrintedBy);
339                 xDocProps->setPrintDate(m_aLastPrinted);
340                 break;
341             }
342 
343             case view::PrintableState_JOB_SPOOLED :
344             case view::PrintableState_JOB_COMPLETED :
345             {
346                 SfxBindings& rBind = mpViewShell->GetViewFrame()->GetBindings();
347                 rBind.Invalidate( SID_PRINTDOC );
348                 rBind.Invalidate( SID_PRINTDOCDIRECT );
349                 rBind.Invalidate( SID_SETUPPRINTER );
350                 bCopyJobSetup = ! m_bTempPrinter;
351                 break;
352             }
353 
354             default:
355                 break;
356         }
357 
358         if( bCopyJobSetup && mpViewShell )
359         {
360             // #i114306#
361             // Note: this possibly creates a printer that gets immediately replaced
362             // by a new one. The reason for this is that otherwise we would not get
363             // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no
364             // other way here to get the item set.
365             SfxPrinter* pDocPrt = mpViewShell->GetPrinter(sal_True);
366             if( pDocPrt )
367             {
368                 if( pDocPrt->GetName() == getPrinter()->GetName() )
369                     pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
370                 else
371                 {
372                     SfxPrinter* pNewPrt = new SfxPrinter( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
373                     pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
374                     mpViewShell->SetPrinter( pNewPrt, SFX_PRINTER_PRINTER | SFX_PRINTER_JOBSETUP );
375                 }
376             }
377         }
378 
379         if ( m_bNeedsChange )
380             mpObjectShell->EnableSetModified( m_bOrigStatus );
381 
382         if ( mpViewShell )
383         {
384             mpViewShell->pImp->m_pPrinterController.reset();
385         }
386     }
387 }
388 
389 //====================================================================
390 
391 class SfxDialogExecutor_Impl
392 
393 /*  [Beschreibung]
394 
395     Eine Instanz dieser Klasse wird f"ur die Laufzeit des Printer-Dialogs
396     erzeugt, um im dessen Click-Handler f"ur die Zus"atze den per
397     virtueller Methode von der abgeleiteten SfxViewShell erzeugten
398     Print-Options-Dialog zu erzeugen und die dort eingestellten Optionen
399     als SfxItemSet zu zwischenzuspeichern.
400 */
401 
402 {
403 private:
404     SfxViewShell*           _pViewSh;
405     PrinterSetupDialog*     _pSetupParent;
406     SfxItemSet*             _pOptions;
407     sal_Bool                _bModified;
408     sal_Bool                _bHelpDisabled;
409 
410     DECL_LINK( Execute, void * );
411 
412 public:
413             SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent );
414             ~SfxDialogExecutor_Impl() { delete _pOptions; }
415 
416     Link                GetLink() const { return LINK( this, SfxDialogExecutor_Impl, Execute); }
417     const SfxItemSet*   GetOptions() const { return _pOptions; }
418     void                DisableHelp() { _bHelpDisabled = sal_True; }
419 };
420 
421 //--------------------------------------------------------------------
422 
423 SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ) :
424 
425     _pViewSh        ( pViewSh ),
426     _pSetupParent   ( pParent ),
427     _pOptions       ( NULL ),
428     _bModified      ( sal_False ),
429     _bHelpDisabled  ( sal_False )
430 
431 {
432 }
433 
434 //--------------------------------------------------------------------
435 
436 IMPL_LINK( SfxDialogExecutor_Impl, Execute, void *, EMPTYARG )
437 {
438     // Options lokal merken
439     if ( !_pOptions )
440     {
441         DBG_ASSERT( _pSetupParent, "no dialog parent" );
442         if( _pSetupParent )
443             _pOptions = ( (SfxPrinter*)_pSetupParent->GetPrinter() )->GetOptions().Clone();
444     }
445 
446     // Dialog ausf"uhren
447     SfxPrintOptionsDialog* pDlg = new SfxPrintOptionsDialog( static_cast<Window*>(_pSetupParent),
448                                                              _pViewSh, _pOptions );
449     if ( _bHelpDisabled )
450         pDlg->DisableHelp();
451     if ( pDlg->Execute() == RET_OK )
452     {
453         delete _pOptions;
454         _pOptions = pDlg->GetOptions().Clone();
455 
456     }
457     delete pDlg;
458 
459     return 0;
460 }
461 
462 //-------------------------------------------------------------------------
463 
464 sal_Bool UseStandardPrinter_Impl( Window* /*pParent*/, SfxPrinter* pDocPrinter )
465 {
466     // Optionen abfragen, ob gewarnt werden soll (Doc uebersteuert App)
467     sal_Bool bWarn = sal_False;
468     const SfxItemSet *pDocOptions = &pDocPrinter->GetOptions();
469     if ( pDocOptions )
470     {
471         sal_uInt16 nWhich = pDocOptions->GetPool()->GetWhich(SID_PRINTER_NOTFOUND_WARN);
472         const SfxBoolItem* pBoolItem = NULL;
473         pDocPrinter->GetOptions().GetItemState( nWhich, sal_False, (const SfxPoolItem**) &pBoolItem );
474         if ( pBoolItem )
475             bWarn = pBoolItem->GetValue();
476     }
477 /*
478     // ggf. den User fragen
479     if ( bWarn )
480     {
481         // Geht nicht mehr ohne OrigJobSetup!
482         String aTmp( SfxResId( STR_PRINTER_NOTAVAIL ) );
483         QueryBox aBox( pParent, WB_OK_CANCEL | WB_DEF_OK, aTmp );
484         return RET_OK == aBox.Execute();
485     }
486 */
487     // nicht gewarnt => einfach so den StandardDrucker nehmen
488     return sal_True;
489 }
490 //-------------------------------------------------------------------------
491 
492 SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter )
493 
494 /*  Interne Methode zum Setzen der Unterschiede von 'pNewPrinter' zum
495     aktuellen Printer. pNewPrinter wird entweder "ubernommen oder gel"oscht.
496 */
497 
498 {
499     // aktuellen Printer holen
500     SfxPrinter *pDocPrinter = GetPrinter();
501 
502     // Printer-Options auswerten
503     bool bOriToDoc = false;
504     bool bSizeToDoc = false;
505     if ( &pDocPrinter->GetOptions() )
506     {
507         sal_uInt16 nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC);
508         const SfxFlagItem *pFlagItem = 0;
509         pDocPrinter->GetOptions().GetItemState( nWhich, sal_False, (const SfxPoolItem**) &pFlagItem );
510         bOriToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION) : sal_False;
511         bSizeToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE) : sal_False;
512     }
513 
514     // vorheriges Format und Size feststellen
515     Orientation eOldOri = pDocPrinter->GetOrientation();
516     Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
517 
518     // neues Format und Size feststellen
519     Orientation eNewOri = pNewPrinter->GetOrientation();
520     Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
521 
522     // "Anderungen am Seitenformat feststellen
523     sal_Bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
524     sal_Bool bPgSzChg = ( aOldPgSz.Height() !=
525             ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
526             aOldPgSz.Width() !=
527             ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
528             bSizeToDoc;
529 
530     // Message und Flags f"ur Seitenformat-"Anderung zusammenstellen
531     String aMsg;
532     sal_uInt16 nNewOpt=0;
533     if( bOriChg && bPgSzChg )
534     {
535         aMsg = String(SfxResId(STR_PRINT_NEWORISIZE));
536         nNewOpt = SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE;
537     }
538     else if (bOriChg )
539     {
540         aMsg = String(SfxResId(STR_PRINT_NEWORI));
541         nNewOpt = SFX_PRINTER_CHG_ORIENTATION;
542     }
543     else if (bPgSzChg)
544     {
545         aMsg = String(SfxResId(STR_PRINT_NEWSIZE));
546         nNewOpt = SFX_PRINTER_CHG_SIZE;
547     }
548 
549     // in dieser Variable sammeln, was sich so ge"aendert hat
550     sal_uInt16 nChangedFlags = 0;
551 
552     // ggf. Nachfrage, ob Seitenformat vom Drucker "ubernommen werden soll
553     if ( ( bOriChg  || bPgSzChg ) &&
554         RET_YES == QueryBox(0, WB_YES_NO | WB_DEF_OK, aMsg).Execute() )
555     // Flags mit "Anderungen f"ur <SetPrinter(SfxPrinter*)> mitpflegen
556     nChangedFlags |= nNewOpt;
557 
558     // fuer den MAC sein "temporary of class String" im naechsten if()
559     String aTempPrtName = pNewPrinter->GetName();
560     String aDocPrtName = pDocPrinter->GetName();
561 
562     // Wurde der Drucker gewechselt oder von Default auf Specific
563     // oder umgekehrt geaendert?
564     if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
565     {
566         // neuen Printer "ubernehmen
567         // pNewPrinter->SetOrigJobSetup( pNewPrinter->GetJobSetup() );
568         nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP;
569         pDocPrinter = pNewPrinter;
570     }
571     else
572     {
573         // Extra-Optionen vergleichen
574         if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
575         {
576             // Options haben sich geaendert
577             pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
578             nChangedFlags |= SFX_PRINTER_OPTIONS;
579         }
580 
581         // JobSetups vergleichen
582         JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
583         JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
584         if ( aNewJobSetup != aOldJobSetup )
585         {
586             // JobSetup hat sich geaendert (=> App mu\s neu formatieren)
587             // pDocPrinter->SetOrigJobSetup( aNewJobSetup );
588             nChangedFlags |= SFX_PRINTER_JOBSETUP;
589         }
590 
591         // alten, ver"anderten Printer behalten
592         pDocPrinter->SetPrinterProps( pNewPrinter );
593         delete pNewPrinter;
594     }
595 
596     if ( 0 != nChangedFlags )
597         // SetPrinter will delete the old printer if it changes
598         SetPrinter( pDocPrinter, nChangedFlags );
599     return pDocPrinter;
600 }
601 
602 //-------------------------------------------------------------------------
603 // Unter WIN32 tritt leider das Problem auf, dass nichts gedruckt
604 // wird, wenn SID_PRINTDOCDIRECT auflaueft; bisher bekannte,
605 // einzige Abhilfe ist in diesem Fall das Abschalten der Optimierungen
606 // (KA 17.12.95)
607 #ifdef _MSC_VER
608 #pragma optimize ( "", off )
609 #endif
610 
611 void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, sal_Bool bIsAPI, sal_Bool bIsDirect )
612 {
613     // get the current selection; our controller should know it
614     Reference< frame::XController > xController( GetController() );
615     Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
616 
617     Any aSelection;
618     if( xSupplier.is() )
619         aSelection = xSupplier->getSelection();
620     else
621         aSelection <<= GetObjectShell()->GetModel();
622     Any aComplete( makeAny( GetObjectShell()->GetModel() ) );
623     Any aViewProp( makeAny( xController ) );
624     boost::shared_ptr<Printer> aPrt;
625 
626     const beans::PropertyValue* pVal = rProps.getConstArray();
627     for( sal_Int32 i = 0; i < rProps.getLength(); i++ )
628     {
629         if( pVal[i].Name.equalsAscii( "PrinterName" ) )
630         {
631             rtl::OUString aPrinterName;
632             pVal[i].Value >>= aPrinterName;
633             aPrt.reset( new Printer( aPrinterName ) );
634             break;
635         }
636     }
637 
638     boost::shared_ptr<vcl::PrinterController> pController( new SfxPrinterController(
639                                                                                aPrt,
640                                                                                aComplete,
641                                                                                aSelection,
642                                                                                aViewProp,
643                                                                                GetRenderable(),
644                                                                                bIsAPI,
645                                                                                bIsDirect,
646                                                                                this,
647                                                                                rProps
648                                                                                ) );
649     pImp->m_pPrinterController = pController;
650 
651     SfxObjectShell *pObjShell = GetObjectShell();
652     pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobName" ) ),
653                         makeAny( rtl::OUString( pObjShell->GetTitle(0) ) ) );
654 
655     // FIXME: job setup
656     SfxPrinter* pDocPrt = GetPrinter(sal_False);
657     JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup();
658     if( bIsDirect )
659         aJobSetup.SetValue( String( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ),
660                             String( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) );
661 
662     Printer::PrintJob( pController, aJobSetup );
663 }
664 
665 Printer* SfxViewShell::GetActivePrinter() const
666 {
667     return (pImp->m_pPrinterController)
668         ?  pImp->m_pPrinterController->getPrinter().get() : 0;
669 }
670 
671 void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
672 {
673     // sal_uInt16                  nCopies=1;
674     sal_uInt16                  nDialogRet = RET_CANCEL;
675     // sal_Bool                    bCollate=sal_False;
676     SfxPrinter*             pPrinter = 0;
677     SfxDialogExecutor_Impl* pExecutor = 0;
678     bool                    bSilent = false;
679     sal_Bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
680     if ( bIsAPI )
681     {
682         SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, sal_False);
683         bSilent = pSilentItem && pSilentItem->GetValue();
684     }
685 
686     //FIXME: how to transport "bPrintOnHelp"?
687 
688     // no help button in dialogs if called from the help window
689     // (pressing help button would exchange the current page inside the help document that is going to be printed!)
690     String aHelpFilterName( DEFINE_CONST_UNICODE("writer_web_HTML_help") );
691     SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium();
692     const SfxFilter* pFilter = pMedium ? pMedium->GetFilter() : NULL;
693     sal_Bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == aHelpFilterName );
694 
695     const sal_uInt16 nId = rReq.GetSlot();
696     switch( nId )
697     {
698         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
699         case SID_PRINTDOC:
700         case SID_PRINTDOCDIRECT:
701         {
702             SfxObjectShell* pDoc = GetObjectShell();
703 
704             // derived class may decide to abort this
705             if( !pDoc->QuerySlotExecutable( nId ) )
706             {
707                 rReq.SetReturnValue( SfxBoolItem( 0, sal_False ) );
708                 return;
709             }
710 
711             bool bDetectHidden = ( !bSilent && pDoc );
712             if ( bDetectHidden && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES )
713                 break;
714 
715             SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False);
716             sal_Bool bSelection = pSelectItem && pSelectItem->GetValue();
717             if( pSelectItem && rReq.GetArgs()->Count() == 1 )
718                 bIsAPI = sal_False;
719 
720             uno::Sequence < beans::PropertyValue > aProps;
721             if ( bIsAPI )
722             {
723                 // supported properties:
724                 // String PrinterName
725                 // String FileName
726                 // Int16 From
727                 // Int16 To
728                 // In16 Copies
729                 // String RangeText
730                 // bool Selection
731                 // bool Asynchron
732                 // bool Collate
733                 // bool Silent
734                 TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
735                 for ( sal_Int32 nProp=0; nProp<aProps.getLength(); nProp++ )
736                 {
737                     if ( aProps[nProp].Name.equalsAscii("Copies") )
738                         aProps[nProp]. Name = rtl::OUString::createFromAscii("CopyCount");
739                     else if ( aProps[nProp].Name.equalsAscii("RangeText") )
740                         aProps[nProp]. Name = rtl::OUString::createFromAscii("Pages");
741                     if ( aProps[nProp].Name.equalsAscii("Asynchron") )
742                     {
743                         aProps[nProp]. Name = rtl::OUString::createFromAscii("Wait");
744                         sal_Bool bAsynchron = sal_False;
745                         aProps[nProp].Value >>= bAsynchron;
746                         aProps[nProp].Value <<= (sal_Bool) (!bAsynchron);
747                     }
748                     if ( aProps[nProp].Name.equalsAscii("Silent") )
749                     {
750                         aProps[nProp]. Name = rtl::OUString::createFromAscii("MonitorVisible");
751                         sal_Bool bPrintSilent = sal_False;
752                         aProps[nProp].Value >>= bPrintSilent;
753                         aProps[nProp].Value <<= (sal_Bool) (!bPrintSilent);
754                     }
755                 }
756             }
757             // HACK: writer sets the SID_SELECTION item when printing directly and expects
758             // to get only the selection document in that case (see getSelectionObject)
759             // however it also reacts to the PrintContent property. We need this distinction here, too,
760             // else one of the combinations print / print direct and selection / all will not work.
761             // it would be better if writer handled this internally
762             if( nId == SID_PRINTDOCDIRECT )
763             {
764                 sal_Int32 nLen = aProps.getLength();
765                 aProps.realloc( nLen + 1 );
766                 aProps[nLen].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintSelectionOnly" ) );
767                 aProps[nLen].Value = makeAny( bSelection );
768             }
769 
770             ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
771 
772             // FIXME: Recording
773             rReq.Done();
774             break;
775         }
776 
777         case SID_SETUPPRINTER :
778         case SID_PRINTER_NAME : // only for recorded macros
779         {
780             // get printer and printer settings from the document
781             SfxPrinter *pDocPrinter = GetPrinter(sal_True);
782 
783             // look for printer in parameters
784             SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, sal_False );
785             if ( pPrinterItem )
786             {
787                 // use PrinterName parameter to create a printer
788                 pPrinter = new SfxPrinter( pDocPrinter->GetOptions().Clone(), ((const SfxStringItem*) pPrinterItem)->GetValue() );
789 
790                 // if printer is unknown, it can't be used - now printer from document will be used
791                 if ( !pPrinter->IsOriginal() )
792                     DELETEZ(pPrinter);
793             }
794 
795             if ( SID_PRINTER_NAME == nId )
796             {
797                 // just set a recorded printer name
798                 if ( pPrinter )
799                     SetPrinter( pPrinter, SFX_PRINTER_PRINTER  );
800                 break;
801             }
802 
803             // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
804             if ( !pPrinter )
805                 // use default printer from document
806                 pPrinter = pDocPrinter;
807 
808             if( !pPrinter || !pPrinter->IsValid() )
809             {
810                 // no valid printer either in ItemSet or at the document
811                 if ( bSilent )
812                 {
813                     rReq.SetReturnValue(SfxBoolItem(0,sal_False));
814                     break;
815                 }
816                 else
817                     ErrorBox( NULL, WB_OK | WB_DEF_OK, String( SfxResId( STR_NODEFPRINTER ) ) ).Execute();
818             }
819 
820             if ( !pPrinter->IsOriginal() && rReq.GetArgs() && !UseStandardPrinter_Impl( NULL, pPrinter ) )
821             {
822                 // printer is not available, but standard printer should not be used
823                 rReq.SetReturnValue(SfxBoolItem(0,sal_False));
824                 break;
825             }
826 
827             // FIXME: printer isn't used for printing anymore!
828             if( pPrinter->IsPrinting() )
829             {
830                 // if printer is busy, abort printing
831                 if ( !bSilent )
832                     InfoBox( NULL, String( SfxResId( STR_ERROR_PRINTER_BUSY ) ) ).Execute();
833                 rReq.SetReturnValue(SfxBoolItem(0,sal_False));
834                 break;
835             }
836 
837             // if no arguments are given, retrieve them from a dialog
838             if ( !bIsAPI )
839             {
840                 // PrinterDialog needs a temporary printer
841                 SfxPrinter* pDlgPrinter = pPrinter->Clone();
842                 nDialogRet = 0;
843 
844                 // execute PrinterSetupDialog
845                 PrinterSetupDialog* pPrintSetupDlg = new PrinterSetupDialog( GetWindow() );
846 
847                 if (pImp->m_bHasPrintOptions)
848                 {
849                     // additional controls for dialog
850                     pExecutor = new SfxDialogExecutor_Impl( this, pPrintSetupDlg );
851                     if ( bPrintOnHelp )
852                         pExecutor->DisableHelp();
853                     pPrintSetupDlg->SetOptionsHdl( pExecutor->GetLink() );
854                 }
855 
856                 pPrintSetupDlg->SetPrinter( pDlgPrinter );
857                 nDialogRet = pPrintSetupDlg->Execute();
858 
859                 if ( pExecutor && pExecutor->GetOptions() )
860                 {
861                     if ( nDialogRet == RET_OK )
862                         // remark: have to be recorded if possible!
863                         pDlgPrinter->SetOptions( *pExecutor->GetOptions() );
864                     else
865                     {
866                         pPrinter->SetOptions( *pExecutor->GetOptions() );
867                         SetPrinter( pPrinter, SFX_PRINTER_OPTIONS );
868                     }
869                 }
870 
871                 DELETEZ( pPrintSetupDlg );
872 
873                 // no recording of PrinterSetup except printer name (is printer dependent)
874                 rReq.Ignore();
875 
876                 if ( nDialogRet == RET_OK )
877                 {
878                     if ( pPrinter->GetName() != pDlgPrinter->GetName() )
879                     {
880                         // user has changed the printer -> macro recording
881                         SfxRequest aReq( GetViewFrame(), SID_PRINTER_NAME );
882                         aReq.AppendItem( SfxStringItem( SID_PRINTER_NAME, pDlgPrinter->GetName() ) );
883                         aReq.Done();
884                     }
885 
886                     // take the changes made in the dialog
887                     pPrinter = SetPrinter_Impl( pDlgPrinter );
888 
889                     // forget new printer, it was taken over (as pPrinter) or deleted
890                     pDlgPrinter = NULL;
891 
892                 }
893                 else
894                 {
895                     // PrinterDialog is used to transfer information on printing,
896                     // so it will only be deleted here if dialog was cancelled
897                     DELETEZ( pDlgPrinter );
898                     rReq.Ignore();
899                     if ( SID_PRINTDOC == nId )
900                         rReq.SetReturnValue(SfxBoolItem(0,sal_False));
901                 }
902             }
903         }
904 
905         break;
906     }
907 }
908 
909 // Optimierungen wieder einschalten
910 #ifdef _MSC_VER
911 #pragma optimize ( "", on )
912 #endif
913 
914 //--------------------------------------------------------------------
915 
916 sal_Bool SfxViewShell::IsPrinterLocked() const
917 {
918     return pImp->m_nPrinterLocks > 0;
919 }
920 
921 //--------------------------------------------------------------------
922 
923 void SfxViewShell::LockPrinter( sal_Bool bLock)
924 {
925     sal_Bool bChanged = sal_False;
926     if ( bLock )
927     {
928         bChanged = 1 == ++pImp->m_nPrinterLocks;
929     }
930     else
931     {
932         bChanged = 0 == --pImp->m_nPrinterLocks;
933     }
934 
935     if ( bChanged )
936     {
937         Invalidate( SID_PRINTDOC );
938         Invalidate( SID_PRINTDOCDIRECT );
939         Invalidate( SID_SETUPPRINTER );
940     }
941 }
942 
943 //--------------------------------------------------------------------
944 
945 SfxPrinter* SfxViewShell::GetPrinter( sal_Bool /*bCreate*/ )
946 {
947     return 0;
948 }
949 
950 //--------------------------------------------------------------------
951 
952 sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, sal_uInt16 /*nDiffFlags*/, bool )
953 {
954     return 0;
955 }
956 
957 //--------------------------------------------------------------------
958 
959 SfxTabPage* SfxViewShell::CreatePrintOptionsPage
960 (
961     Window*             /*pParent*/,
962     const SfxItemSet&   /*rOptions*/
963 )
964 {
965     return 0;
966 }
967 
968 JobSetup SfxViewShell::GetJobSetup() const
969 {
970     return JobSetup();
971 }
972 
973