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