xref: /AOO41X/main/sfx2/source/doc/printhelper.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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 "printhelper.hxx"
28 
29 #include <com/sun/star/view/XPrintJob.hpp>
30 #include <com/sun/star/awt/Size.hpp>
31 #include <com/sun/star/lang/IllegalArgumentException.hpp>
32 #include <com/sun/star/view/PaperFormat.hpp>
33 #include <com/sun/star/view/PaperOrientation.hpp>
34 #include <com/sun/star/ucb/NameClash.hpp>
35 #include <com/sun/star/lang/XUnoTunnel.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/lang/EventObject.hpp>
38 #include <com/sun/star/view/DuplexMode.hpp>
39 
40 #include <svl/lstner.hxx>
41 #include <svl/stritem.hxx>
42 #include <svl/intitem.hxx>
43 #include <svl/eitem.hxx>
44 #include <unotools/tempfile.hxx>
45 #include <unotools/localfilehelper.hxx>
46 #include <osl/file.hxx>
47 #include <osl/thread.hxx>
48 #include <tools/urlobj.hxx>
49 #include <ucbhelper/content.hxx>
50 #include <cppuhelper/interfacecontainer.hxx>
51 #include <vos/mutex.hxx>
52 #include <cppuhelper/implbase1.hxx>
53 
54 #include <sfx2/viewfrm.hxx>
55 #include <sfx2/viewsh.hxx>
56 #include <sfx2/dispatch.hxx>
57 #include <sfx2/request.hxx>
58 #include <sfx2/printer.hxx>
59 #include <sfx2/app.hxx>
60 #include <sfx2/objsh.hxx>
61 #include <sfx2/event.hxx>
62 
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 
66 struct IMPL_PrintListener_DataContainer : public SfxListener
67 {
68     SfxObjectShellRef                               m_pObjectShell;
69     ::cppu::OMultiTypeInterfaceContainerHelper      m_aInterfaceContainer;
70     uno::Reference< com::sun::star::view::XPrintJob>     m_xPrintJob;
71     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aPrintOptions;
72 
73     IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
74             :   m_pObjectShell          ( 0 )
75             ,   m_aInterfaceContainer   ( aMutex )
76     {
77     }
78 
79 
80     void Notify(            SfxBroadcaster& aBC     ,
81                     const   SfxHint&        aHint   ) ;
82 };
83 
84 awt::Size impl_Size_Object2Struct( const Size& aSize )
85 {
86     awt::Size aReturnValue;
87     aReturnValue.Width  = aSize.Width()  ;
88     aReturnValue.Height = aSize.Height() ;
89     return aReturnValue ;
90 }
91 
92 Size impl_Size_Struct2Object( const awt::Size& aSize )
93 {
94     Size aReturnValue;
95     aReturnValue.Width()  = aSize.Width  ;
96     aReturnValue.Height() = aSize.Height ;
97     return aReturnValue ;
98 }
99 
100 class SfxPrintJob_Impl : public cppu::WeakImplHelper1
101 <
102     com::sun::star::view::XPrintJob
103 >
104 {
105         IMPL_PrintListener_DataContainer* m_pData;
106 
107 public:
108         SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData );
109         virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrintOptions(  ) throw (RuntimeException);
110         virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrinter(  ) throw (RuntimeException);
111         virtual Reference< ::com::sun::star::view::XPrintable > SAL_CALL getPrintable(  ) throw (RuntimeException);
112         virtual void SAL_CALL cancelJob() throw (RuntimeException);
113 };
114 
115 SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData )
116     : m_pData( pData )
117 {
118 }
119 
120 Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrintOptions() throw (RuntimeException)
121 {
122     return m_pData->m_aPrintOptions;
123 }
124 
125 Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrinter() throw (RuntimeException)
126 {
127     if( m_pData->m_pObjectShell.Is() )
128     {
129         Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell->GetModel(), UNO_QUERY );
130         if ( xPrintable.is() )
131             return xPrintable->getPrinter();
132     }
133     return Sequence< ::com::sun::star::beans::PropertyValue >();
134 }
135 
136 Reference< ::com::sun::star::view::XPrintable > SAL_CALL SfxPrintJob_Impl::getPrintable() throw (RuntimeException)
137 {
138     Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell.Is() ? m_pData->m_pObjectShell->GetModel() : NULL, UNO_QUERY );
139     return xPrintable;
140 }
141 
142 void SAL_CALL SfxPrintJob_Impl::cancelJob() throw (RuntimeException)
143 {
144     // FIXME: how to cancel PrintJob via API?!
145     if( m_pData->m_pObjectShell.Is() )
146         m_pData->m_pObjectShell->Broadcast( SfxPrintingHint( -2 ) );
147 }
148 
149 SfxPrintHelper::SfxPrintHelper()
150 {
151     m_pData = new IMPL_PrintListener_DataContainer(m_aMutex);
152 }
153 
154 void SAL_CALL SfxPrintHelper::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
155 {
156     if ( aArguments.getLength() )
157     {
158         com::sun::star::uno::Reference < com::sun::star::frame::XModel > xModel;
159         aArguments[0] >>= xModel;
160         uno::Reference < lang::XUnoTunnel > xObj( xModel, uno::UNO_QUERY );
161         uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
162         sal_Int64 nHandle = xObj->getSomething( aSeq );
163         if ( nHandle )
164         {
165             m_pData->m_pObjectShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
166             m_pData->StartListening(*m_pData->m_pObjectShell);
167         }
168     }
169 }
170 
171 SfxPrintHelper::~SfxPrintHelper()
172 {
173     delete m_pData;
174 }
175 
176 namespace
177 {
178     view::PaperFormat convertToPaperFormat(Paper eFormat)
179     {
180         view::PaperFormat eRet;
181         switch (eFormat)
182         {
183             case PAPER_A3:
184                 eRet = view::PaperFormat_A3;
185                 break;
186             case PAPER_A4:
187                 eRet = view::PaperFormat_A4;
188                 break;
189             case PAPER_A5:
190                 eRet = view::PaperFormat_A5;
191                 break;
192             case PAPER_B4_ISO:
193                 eRet = view::PaperFormat_B4;
194                 break;
195             case PAPER_B5_ISO:
196                 eRet = view::PaperFormat_B5;
197                 break;
198             case PAPER_LETTER:
199                 eRet = view::PaperFormat_LETTER;
200                 break;
201             case PAPER_LEGAL:
202                 eRet = view::PaperFormat_LEGAL;
203                 break;
204             case PAPER_TABLOID:
205                 eRet = view::PaperFormat_TABLOID;
206                 break;
207             case PAPER_USER:
208             default:
209                 eRet = view::PaperFormat_USER;
210                 break;
211         }
212         return eRet;
213     }
214 
215     Paper convertToPaper(view::PaperFormat eFormat)
216     {
217         Paper eRet(PAPER_USER);
218         switch (eFormat)
219         {
220             case view::PaperFormat_A3:
221                 eRet = PAPER_A3;
222                 break;
223             case view::PaperFormat_A4:
224                 eRet = PAPER_A4;
225                 break;
226             case view::PaperFormat_A5:
227                 eRet = PAPER_A5;
228                 break;
229             case view::PaperFormat_B4:
230                 eRet = PAPER_B4_ISO;
231                 break;
232             case view::PaperFormat_B5:
233                 eRet = PAPER_B5_ISO;
234                 break;
235             case view::PaperFormat_LETTER:
236                 eRet = PAPER_LETTER;
237                 break;
238             case view::PaperFormat_LEGAL:
239                 eRet = PAPER_LEGAL;
240                 break;
241             case view::PaperFormat_TABLOID:
242                 eRet = PAPER_TABLOID;
243                 break;
244             case view::PaperFormat_USER:
245                 eRet = PAPER_USER;
246                 break;
247             case view::PaperFormat_MAKE_FIXED_SIZE:
248                 break;
249             //deliberate no default to force warn on a new papersize
250         }
251         return eRet;
252     }
253 }
254 
255 //________________________________________________________________________________________________________
256 //  XPrintable
257 //________________________________________________________________________________________________________
258 
259 uno::Sequence< beans::PropertyValue > SAL_CALL SfxPrintHelper::getPrinter() throw(::com::sun::star::uno::RuntimeException)
260 {
261     // object already disposed?
262     ::vos::OGuard aGuard( Application::GetSolarMutex() );
263 
264     // search for any view of this document that is currently printing
265     const Printer *pPrinter = NULL;
266     SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ? SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
267     SfxViewFrame* pFirst = pViewFrm;
268     while ( pViewFrm && !pPrinter )
269     {
270         pPrinter = pViewFrm->GetViewShell()->GetActivePrinter();
271         pViewFrm = SfxViewFrame::GetNext( *pViewFrm, m_pData->m_pObjectShell, sal_False );
272     }
273 
274     // if no view is printing currently, use the permanent SfxPrinter instance
275     if ( !pPrinter && pFirst )
276         pPrinter = pFirst->GetViewShell()->GetPrinter(sal_True);
277 
278     if ( !pPrinter )
279         return uno::Sequence< beans::PropertyValue >();
280 
281     uno::Sequence< beans::PropertyValue > aPrinter(8);
282 
283     aPrinter.getArray()[7].Name = DEFINE_CONST_UNICODE( "CanSetPaperSize" );
284     aPrinter.getArray()[7].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPERSIZE ) );
285 
286     aPrinter.getArray()[6].Name = DEFINE_CONST_UNICODE( "CanSetPaperFormat" );
287     aPrinter.getArray()[6].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPER ) );
288 
289     aPrinter.getArray()[5].Name = DEFINE_CONST_UNICODE( "CanSetPaperOrientation" );
290     aPrinter.getArray()[5].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_ORIENTATION ) );
291 
292     aPrinter.getArray()[4].Name = DEFINE_CONST_UNICODE( "IsBusy" );
293     aPrinter.getArray()[4].Value <<= ( pPrinter->IsPrinting() );
294 
295     aPrinter.getArray()[3].Name = DEFINE_CONST_UNICODE( "PaperSize" );
296     awt::Size aSize = impl_Size_Object2Struct(pPrinter->GetPaperSize() );
297     aPrinter.getArray()[3].Value <<= aSize;
298 
299     aPrinter.getArray()[2].Name = DEFINE_CONST_UNICODE( "PaperFormat" );
300     view::PaperFormat eFormat = convertToPaperFormat(pPrinter->GetPaper());
301     aPrinter.getArray()[2].Value <<= eFormat;
302 
303     aPrinter.getArray()[1].Name = DEFINE_CONST_UNICODE( "PaperOrientation" );
304     view::PaperOrientation eOrient = (view::PaperOrientation)pPrinter->GetOrientation();
305     aPrinter.getArray()[1].Value <<= eOrient;
306 
307     aPrinter.getArray()[0].Name = DEFINE_CONST_UNICODE( "Name" );
308     String sStringTemp = pPrinter->GetName() ;
309     aPrinter.getArray()[0].Value <<= ::rtl::OUString( sStringTemp );
310 
311     return aPrinter;
312 }
313 
314 //________________________________________________________________________________________________________
315 //  XPrintable
316 //________________________________________________________________________________________________________
317 
318 void SfxPrintHelper::impl_setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter,SfxPrinter*& pPrinter,sal_uInt16& nChangeFlags,SfxViewShell*& pViewSh)
319 
320 {
321     // alten Printer beschaffen
322     SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
323                                 SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
324     if ( !pViewFrm )
325         return;
326 
327     pViewSh = pViewFrm->GetViewShell();
328     pPrinter = pViewSh->GetPrinter(sal_True);
329     if ( !pPrinter )
330         return;
331 
332     // new Printer-Name available?
333     nChangeFlags = 0;
334     sal_Int32 lDummy = 0;
335     for ( int n = 0; n < rPrinter.getLength(); ++n )
336     {
337         // get Property-Value from printer description
338         const beans::PropertyValue &rProp = rPrinter.getConstArray()[n];
339 
340         // Name-Property?
341         if ( rProp.Name.compareToAscii( "Name" ) == 0 )
342         {
343             ::rtl::OUString sTemp;
344             if ( ( rProp.Value >>= sTemp ) == sal_False )
345                 throw ::com::sun::star::lang::IllegalArgumentException();
346 
347             String aPrinterName( sTemp ) ;
348             if ( aPrinterName != pPrinter->GetName() )
349             {
350                 pPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aPrinterName );
351                 nChangeFlags = SFX_PRINTER_PRINTER;
352             }
353             break;
354         }
355     }
356 
357     Size aSetPaperSize( 0, 0);
358     view::PaperFormat nPaperFormat = view::PaperFormat_USER;
359 
360     // other properties
361     for ( int i = 0; i < rPrinter.getLength(); ++i )
362     {
363         // get Property-Value from printer description
364         const beans::PropertyValue &rProp = rPrinter.getConstArray()[i];
365 
366         // PaperOrientation-Property?
367         if ( rProp.Name.compareToAscii( "PaperOrientation" ) == 0 )
368         {
369             view::PaperOrientation eOrient;
370             if ( ( rProp.Value >>= eOrient ) == sal_False )
371             {
372                 if ( ( rProp.Value >>= lDummy ) == sal_False )
373                     throw ::com::sun::star::lang::IllegalArgumentException();
374                 eOrient = ( view::PaperOrientation) lDummy;
375             }
376 
377             if ( (Orientation) eOrient != pPrinter->GetOrientation() )
378             {
379                 pPrinter->SetOrientation( (Orientation) eOrient );
380                 nChangeFlags |= SFX_PRINTER_CHG_ORIENTATION;
381             }
382         }
383 
384         // PaperFormat-Property?
385         else if ( rProp.Name.compareToAscii( "PaperFormat" ) == 0 )
386         {
387             if ( ( rProp.Value >>= nPaperFormat ) == sal_False )
388             {
389                 if ( ( rProp.Value >>= lDummy ) == sal_False )
390                     throw ::com::sun::star::lang::IllegalArgumentException();
391                 nPaperFormat = ( view::PaperFormat ) lDummy;
392             }
393 
394             if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
395             {
396                 pPrinter->SetPaper( convertToPaper(nPaperFormat) );
397                 nChangeFlags |= SFX_PRINTER_CHG_SIZE;
398             }
399         }
400 
401         // PaperSize-Property?
402         else if ( rProp.Name.compareToAscii( "PaperSize" ) == 0 )
403         {
404             awt::Size aTempSize ;
405             if ( ( rProp.Value >>= aTempSize ) == sal_False )
406             {
407                 throw ::com::sun::star::lang::IllegalArgumentException();
408             }
409             else
410             {
411                 aSetPaperSize = impl_Size_Struct2Object(aTempSize);
412             }
413         }
414 
415         // PrinterTray-Property
416         else if ( rProp.Name.compareToAscii( "PrinterPaperTray" ) == 0 )
417         {
418             rtl::OUString aTmp;
419             if ( ( rProp.Value >>= aTmp ) == sal_False )
420                 throw ::com::sun::star::lang::IllegalArgumentException();
421             sal_uInt16 nCount = pPrinter->GetPaperBinCount();
422             for (sal_uInt16 nBin=0; nBin<nCount; nBin++)
423             {
424                 ::rtl::OUString aName( pPrinter->GetPaperBinName(nBin) );
425                 if ( aName == aTmp )
426                 {
427                     pPrinter->SetPaperBin(nBin);
428                     break;
429                 }
430             }
431         }
432     }
433 
434     //os 12.11.98: die PaperSize darf nur gesetzt werden, wenn tatsaechlich
435     //PAPER_USER gilt, sonst koennte vom Treiber ein falsches Format gewaehlt werden
436     if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
437     {
438         //JP 23.09.98 - Bug 56929 - MapMode von 100mm in die am
439         //          Device gesetzten umrechnen. Zusaetzlich nur dann
440         //          setzen, wenn sie wirklich veraendert wurden.
441         aSetPaperSize = pPrinter->LogicToPixel( aSetPaperSize, MAP_100TH_MM );
442         if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
443         {
444             pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
445             nChangeFlags |= SFX_PRINTER_CHG_SIZE;
446         }
447     }
448 
449     // #96772#: wait until printing is done
450     SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
451     while ( pDocPrinter->IsPrinting() )
452         Application::Yield();
453 }
454 
455 void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
456         throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
457 {
458     // object already disposed?
459     ::vos::OGuard aGuard( Application::GetSolarMutex() );
460 
461     SfxViewShell* pViewSh = NULL;
462     SfxPrinter* pPrinter = NULL;
463     sal_uInt16 nChangeFlags = 0;
464     impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
465     // set new printer
466     if ( pViewSh && pPrinter )
467         pViewSh->SetPrinter( pPrinter, nChangeFlags, false );
468 }
469 
470 //________________________________________________________________________________________________________
471 //  ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
472 //________________________________________________________________________________________________________
473 
474 /* This implements a thread which will be started to wait for asynchronous
475    print jobs to temp. localy files. If they finish we move the temp. files
476    to her right locations by using the ucb.
477  */
478 class ImplUCBPrintWatcher : public ::osl::Thread
479 {
480     private:
481         /// of course we must know the printer which execute the job
482         SfxPrinter* m_pPrinter;
483         /// this describes the target location for the printed temp file
484         String m_sTargetURL;
485         /// it holds the temp file alive, till the print job will finish and remove it from disk automaticly if the object die
486         ::utl::TempFile* m_pTempFile;
487 
488     public:
489         /* initialize this watcher but don't start it */
490         ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFile* pTempFile, const String& sTargetURL )
491                 : m_pPrinter  ( pPrinter   )
492                 , m_sTargetURL( sTargetURL )
493                 , m_pTempFile ( pTempFile  )
494         {}
495 
496         /* waits for finishing of the print job and moves the temp file afterwards
497            Note: Starting of the job is done outside this thread!
498            But we have to free some of the given ressources on heap!
499          */
500         void SAL_CALL run()
501         {
502             /* SAFE { */
503             {
504                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
505                 while( m_pPrinter->IsPrinting() )
506                     Application::Yield();
507                 m_pPrinter = NULL; // don't delete it! It's borrowed only :-)
508             }
509             /* } SAFE */
510 
511             // lock for further using of our member isn't neccessary - because
512             // we truns alone by defenition. Nobody join for us nor use us ...
513             ImplUCBPrintWatcher::moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
514 
515             // finishing of this run() method will call onTerminate() automaticly
516             // kill this thread there!
517         }
518 
519         /* nobody wait for this thread. We must kill ourself ...
520          */
521         void SAL_CALL onTerminated()
522         {
523             delete this;
524         }
525 
526         /* static helper to move the temp. file to the target location by using the ucb
527            It's static to be useable from outside too. So it's not realy neccessary to start
528            the thread, if finishing of the job was detected outside this thread.
529            But it must be called without using a corresponding thread for the given parameter!
530          */
531         static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const String& sTargetURL )
532         {
533             // move the file
534             try
535             {
536                 INetURLObject aSplitter(sTargetURL);
537                 String        sFileName = aSplitter.getName(
538                                             INetURLObject::LAST_SEGMENT,
539                                             true,
540                                             INetURLObject::DECODE_WITH_CHARSET);
541                 if (aSplitter.removeSegment() && sFileName.Len()>0)
542                 {
543                     ::ucbhelper::Content aSource(
544                             ::rtl::OUString((*ppTempFile)->GetURL()),
545                             ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >());
546 
547                     ::ucbhelper::Content aTarget(
548                             ::rtl::OUString(aSplitter.GetMainURL(INetURLObject::NO_DECODE)),
549                             ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >());
550 
551                     aTarget.transferContent(
552                             aSource,
553                             ::ucbhelper::InsertOperation_COPY,
554                             ::rtl::OUString(sFileName),
555                             ::com::sun::star::ucb::NameClash::OVERWRITE);
556                 }
557             }
558             catch( ::com::sun::star::ucb::ContentCreationException& ) { DBG_ERROR("content create exception"); }
559             catch( ::com::sun::star::ucb::CommandAbortedException&  ) { DBG_ERROR("command abort exception"); }
560             catch( ::com::sun::star::uno::RuntimeException&         ) { DBG_ERROR("runtime exception"); }
561             catch( ::com::sun::star::uno::Exception&                ) { DBG_ERROR("unknown exception"); }
562 
563             // kill the temp file!
564             delete *ppTempFile;
565             *ppTempFile = NULL;
566         }
567 };
568 
569 //------------------------------------------------
570 
571 //________________________________________________________________________________________________________
572 //  XPrintable
573 //________________________________________________________________________________________________________
574 void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
575         throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
576 {
577     if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
578         return;
579 
580     // object already disposed?
581     // object already disposed?
582     ::vos::OGuard aGuard( Application::GetSolarMutex() );
583 
584     // get view for sfx printing capabilities
585     SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
586                                 SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
587     if ( !pViewFrm )
588         return;
589     SfxViewShell* pView = pViewFrm->GetViewShell();
590     if ( !pView )
591         return;
592 
593 //  SfxAllItemSet aArgs( pView->GetPool() );
594     sal_Bool bMonitor = sal_False;
595     // We need this information at the end of this method, if we start the vcl printer
596     // by executing the slot. Because if it is a ucb relevant URL we must wait for
597     // finishing the print job and move the temporary local file by using the ucb
598     // to the right location. But in case of no file name is given or it is already
599     // a local one we can supress this special handling. Because then vcl makes all
600     // right for us.
601     String sUcbUrl;
602     ::utl::TempFile* pUCBPrintTempFile = NULL;
603 
604     uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
605     sal_Int32 nProps = 0;
606     sal_Bool  bWaitUntilEnd = sal_False;
607     sal_Int16 nDuplexMode = ::com::sun::star::view::DuplexMode::UNKNOWN;
608     for ( int n = 0; n < rOptions.getLength(); ++n )
609     {
610         // get Property-Value from options
611         const beans::PropertyValue &rProp = rOptions.getConstArray()[n];
612 
613         // FileName-Property?
614         if ( rProp.Name.compareToAscii( "FileName" ) == 0 )
615         {
616             // unpack th URL and check for a valid and well known protocol
617             ::rtl::OUString sTemp;
618             if (
619                 ( rProp.Value.getValueType()!=::getCppuType((const ::rtl::OUString*)0))  ||
620                 (!(rProp.Value>>=sTemp))
621                )
622             {
623                 throw ::com::sun::star::lang::IllegalArgumentException();
624             }
625 
626             String        sPath        ;
627             String        sURL  (sTemp);
628             INetURLObject aCheck(sURL );
629             if (aCheck.GetProtocol()==INET_PROT_NOT_VALID)
630             {
631                 // OK - it's not a valid URL. But may it's a simple
632                 // system path directly. It will be supported for historical
633                 // reasons. Otherwhise we break to much external code ...
634                 // We try to convert it to a file URL. If its possible
635                 // we put the system path to the item set and let vcl work with it.
636                 // No ucb or thread will be neccessary then. In case it couldnt be
637                 // converted its not an URL nor a system path. Then we can't accept
638                 // this parameter and have to throw an exception.
639                 ::rtl::OUString sSystemPath(sTemp);
640                 ::rtl::OUString sFileURL;
641                 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
642                     throw ::com::sun::star::lang::IllegalArgumentException();
643                 aCheckedArgs[nProps].Name = rProp.Name;
644                 aCheckedArgs[nProps++].Value <<= sFileURL;
645                 // and append the local filename
646                 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
647                 aCheckedArgs[nProps].Name = rtl::OUString::createFromAscii("LocalFileName");
648                 aCheckedArgs[nProps++].Value <<= ::rtl::OUString( sTemp );
649             }
650             else
651             // It's a valid URL. but now we must know, if it is a local one or not.
652             // It's a question of using ucb or not!
653             if (::utl::LocalFileHelper::ConvertURLToSystemPath(sURL,sPath))
654             {
655                 // it's a local file, we can use vcl without special handling
656                 // And we have to use the system notation of the incoming URL.
657                 // But it into the descriptor and let the slot be executed at
658                 // the end of this method.
659                 aCheckedArgs[nProps].Name = rProp.Name;
660                 aCheckedArgs[nProps++].Value <<= sTemp;
661                 // and append the local filename
662                 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
663                 aCheckedArgs[nProps].Name = rtl::OUString::createFromAscii("LocalFileName");
664                 aCheckedArgs[nProps++].Value <<= ::rtl::OUString( sPath );
665             }
666             else
667             {
668                 // it's an ucb target. So we must use a temp. file for vcl
669                 // and move it after printing by using the ucb.
670                 // Create a temp file on the heap (because it must delete the
671                 // real file on disk automaticly if it die - bt we have to share it with
672                 // some other sources ... e.g. the ImplUCBPrintWatcher).
673                 // And we put the name of this temp file to the descriptor instead
674                 // of the URL. The URL we save for later using seperatly.
675                 // Execution of the print job will be done later by executing
676                 // a slot ...
677                 pUCBPrintTempFile = new ::utl::TempFile();
678                 pUCBPrintTempFile->EnableKillingFile();
679 
680                 //FIXME: does it work?
681                 aCheckedArgs[nProps].Name = rtl::OUString::createFromAscii("LocalFileName");
682                 aCheckedArgs[nProps++].Value <<= ::rtl::OUString( pUCBPrintTempFile->GetFileName() );
683                 sUcbUrl = sURL;
684             }
685         }
686 
687         // CopyCount-Property
688         else if ( rProp.Name.compareToAscii( "CopyCount" ) == 0 )
689         {
690             sal_Int32 nCopies = 0;
691             if ( ( rProp.Value >>= nCopies ) == sal_False )
692                 throw ::com::sun::star::lang::IllegalArgumentException();
693 
694             aCheckedArgs[nProps].Name = rProp.Name;
695             aCheckedArgs[nProps++].Value <<= nCopies;
696         }
697 
698         // Collate-Property
699         // Sort-Property (deprecated)
700         else if ( rProp.Name.compareToAscii( "Collate" ) == 0 ||
701                 ( rProp.Name.compareToAscii( "Sort" ) == 0 ) )
702         {
703             sal_Bool bTemp = sal_Bool();
704             if ( rProp.Value >>= bTemp )
705             {
706                 aCheckedArgs[nProps].Name = rtl::OUString::createFromAscii("Collate");
707                 aCheckedArgs[nProps++].Value <<= bTemp;
708             }
709             else
710                 throw ::com::sun::star::lang::IllegalArgumentException();
711         }
712 
713         // Pages-Property
714         else if ( rProp.Name.compareToAscii( "Pages" ) == 0 )
715         {
716             ::rtl::OUString sTemp;
717             if( rProp.Value >>= sTemp )
718             {
719                 aCheckedArgs[nProps].Name = rProp.Name;
720                 aCheckedArgs[nProps++].Value <<= sTemp;
721             }
722             else
723                 throw ::com::sun::star::lang::IllegalArgumentException();
724         }
725 
726         // MonitorVisible
727         else if ( rProp.Name.compareToAscii( "MonitorVisible" ) == 0 )
728         {
729             if( !(rProp.Value >>= bMonitor) )
730                 throw ::com::sun::star::lang::IllegalArgumentException();
731             aCheckedArgs[nProps].Name = rProp.Name;
732             aCheckedArgs[nProps++].Value <<= bMonitor;
733         }
734 
735         // Wait
736         else if ( rProp.Name.compareToAscii( "Wait" ) == 0 )
737         {
738             if ( !(rProp.Value >>= bWaitUntilEnd) )
739                 throw ::com::sun::star::lang::IllegalArgumentException();
740             aCheckedArgs[nProps].Name = rProp.Name;
741             aCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
742         }
743 
744         else if ( rProp.Name.compareToAscii( "DuplexMode" ) == 0 )
745         {
746             if ( !(rProp.Value >>= nDuplexMode ) )
747                 throw ::com::sun::star::lang::IllegalArgumentException();
748             aCheckedArgs[nProps].Name = rProp.Name;
749             aCheckedArgs[nProps++].Value <<= nDuplexMode;
750         }
751     }
752 
753     if ( nProps != aCheckedArgs.getLength() )
754         aCheckedArgs.realloc(nProps);
755 
756     // Execute the print request every time.
757     // It doesn'tmatter if it is a real printer used or we print to a local file
758     // nor if we print to a temp file and move it afterwards by using the ucb.
759     // That will be handled later. see pUCBPrintFile below!
760     pView->ExecPrint( aCheckedArgs, sal_True, sal_False );
761 
762     // Ok - may be execution before has finished (or started!) printing.
763     // And may it was a printing to a file.
764     // Now we have to check if we can move the file (if neccessary) via ucb to his right location.
765     // Cases:
766     //  a) printing finished                        => move the file directly and forget the watcher thread
767     //  b) printing is asynchron and runs currently => start watcher thread and exit this method
768     //                                                 This thread make all neccessary things by itself.
769     if (pUCBPrintTempFile!=NULL)
770     {
771         // a)
772         SfxPrinter* pPrinter = pView->GetPrinter();
773         if ( ! pPrinter->IsPrinting() )
774             ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
775         // b)
776         else
777         {
778             // Note: we create(d) some ressource on the heap. (thread and tep file)
779             // They will be delected by the thread automaticly if he finish his run() method.
780             ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
781             pWatcher->create();
782         }
783     }
784 }
785 
786 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
787 {
788     if ( &rBC == m_pObjectShell )
789     {
790         SfxPrintingHint* pPrintHint = PTR_CAST( SfxPrintingHint, &rHint );
791         if ( pPrintHint )
792         {
793             if ( pPrintHint->GetWhich() == com::sun::star::view::PrintableState_JOB_STARTED )
794             {
795                 if ( !m_xPrintJob.is() )
796                     m_xPrintJob = new SfxPrintJob_Impl( this );
797                 m_aPrintOptions = pPrintHint->GetOptions();
798             }
799             else if ( pPrintHint->GetWhich() != -2 )    // -2 : CancelPrintJob
800             {
801                 view::PrintJobEvent aEvent;
802                 aEvent.Source = m_xPrintJob;
803                 aEvent.State = (com::sun::star::view::PrintableState) pPrintHint->GetWhich();
804                 ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer( ::getCppuType( ( const uno::Reference< view::XPrintJobListener >*) NULL ) );
805                 if ( pContainer!=NULL )
806                 {
807                     ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
808                     while (pIterator.hasMoreElements())
809                         ((view::XPrintJobListener*)pIterator.next())->printJobEvent( aEvent );
810                 }
811             }
812         }
813     }
814 }
815 
816 void SAL_CALL SfxPrintHelper::addPrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
817 {
818     ::vos::OGuard aGuard( Application::GetSolarMutex() );
819     m_pData->m_aInterfaceContainer.addInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );
820 }
821 
822 void SAL_CALL SfxPrintHelper::removePrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
823 {
824     ::vos::OGuard aGuard( Application::GetSolarMutex() );
825     m_pData->m_aInterfaceContainer.removeInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );
826 }
827 
828 
829