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