xref: /AOO41X/main/vcl/source/gdi/print3.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include "vcl/print.hxx"
31*cdf0e10cSrcweir #include "vcl/svapp.hxx"
32*cdf0e10cSrcweir #include "vcl/metaact.hxx"
33*cdf0e10cSrcweir #include "vcl/msgbox.hxx"
34*cdf0e10cSrcweir #include "vcl/configsettings.hxx"
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include "printdlg.hxx"
37*cdf0e10cSrcweir #include "svdata.hxx"
38*cdf0e10cSrcweir #include "salinst.hxx"
39*cdf0e10cSrcweir #include "salprn.hxx"
40*cdf0e10cSrcweir #include "svids.hrc"
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include "tools/urlobj.hxx"
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir #include "com/sun/star/ui/dialogs/XFilePicker.hpp"
45*cdf0e10cSrcweir #include "com/sun/star/ui/dialogs/XFilterManager.hpp"
46*cdf0e10cSrcweir #include "com/sun/star/ui/dialogs/TemplateDescription.hpp"
47*cdf0e10cSrcweir #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
48*cdf0e10cSrcweir #include "com/sun/star/view/DuplexMode.hpp"
49*cdf0e10cSrcweir #include "com/sun/star/lang/XMultiServiceFactory.hpp"
50*cdf0e10cSrcweir #include "com/sun/star/awt/Size.hpp"
51*cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir #include <hash_map>
54*cdf0e10cSrcweir #include <hash_set>
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir using namespace com::sun::star;
57*cdf0e10cSrcweir using namespace com::sun::star::uno;
58*cdf0e10cSrcweir using namespace com::sun::star::beans;
59*cdf0e10cSrcweir using namespace vcl;
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir class ImplPageCache
62*cdf0e10cSrcweir {
63*cdf0e10cSrcweir     struct CacheEntry
64*cdf0e10cSrcweir     {
65*cdf0e10cSrcweir         GDIMetaFile                 aPage;
66*cdf0e10cSrcweir         PrinterController::PageSize aSize;
67*cdf0e10cSrcweir     };
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir     std::vector< CacheEntry >  maPages;
70*cdf0e10cSrcweir     std::vector< sal_Int32 >    maPageNumbers;
71*cdf0e10cSrcweir     std::vector< sal_Int32 >    maCacheRanking;
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir     static const sal_Int32 nCacheSize = 6;
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir     void updateRanking( sal_Int32 nLastHit )
76*cdf0e10cSrcweir     {
77*cdf0e10cSrcweir         if( maCacheRanking[0] != nLastHit )
78*cdf0e10cSrcweir         {
79*cdf0e10cSrcweir             bool bMove = false;
80*cdf0e10cSrcweir             for( sal_Int32 i = nCacheSize-1; i > 0; i-- )
81*cdf0e10cSrcweir             {
82*cdf0e10cSrcweir                 if( maCacheRanking[i] == nLastHit )
83*cdf0e10cSrcweir                     bMove = true;
84*cdf0e10cSrcweir                 maCacheRanking[i] = maCacheRanking[i-1];
85*cdf0e10cSrcweir             }
86*cdf0e10cSrcweir             maCacheRanking[0] = nLastHit;
87*cdf0e10cSrcweir         }
88*cdf0e10cSrcweir     }
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir public:
91*cdf0e10cSrcweir     ImplPageCache()
92*cdf0e10cSrcweir     : maPages( nCacheSize )
93*cdf0e10cSrcweir     , maPageNumbers( nCacheSize, -1 )
94*cdf0e10cSrcweir     , maCacheRanking( nCacheSize )
95*cdf0e10cSrcweir     {
96*cdf0e10cSrcweir         for( sal_Int32 i = 0; i < nCacheSize; i++ )
97*cdf0e10cSrcweir             maCacheRanking[i] = nCacheSize - i - 1;
98*cdf0e10cSrcweir     }
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir     // caution: does not ensure uniqueness
101*cdf0e10cSrcweir     void insert( sal_Int32 i_nPageNo, const GDIMetaFile& i_rPage, const PrinterController::PageSize& i_rSize )
102*cdf0e10cSrcweir     {
103*cdf0e10cSrcweir         sal_Int32 nReplacePage = maCacheRanking.back();
104*cdf0e10cSrcweir         maPages[ nReplacePage ].aPage = i_rPage;
105*cdf0e10cSrcweir         maPages[ nReplacePage ].aSize = i_rSize;
106*cdf0e10cSrcweir         maPageNumbers[ nReplacePage ] = i_nPageNo;
107*cdf0e10cSrcweir         // cache insertion means in our case, the page was just queried
108*cdf0e10cSrcweir         // so update the ranking
109*cdf0e10cSrcweir         updateRanking( nReplacePage );
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir     // caution: bad algorithm; should there ever be reason to increase the cache size beyond 6
113*cdf0e10cSrcweir     // this needs to be urgently rewritten. However do NOT increase the cache size lightly,
114*cdf0e10cSrcweir     // whole pages can be rather memory intensive
115*cdf0e10cSrcweir     bool get( sal_Int32 i_nPageNo, GDIMetaFile& o_rPageFile, PrinterController::PageSize& o_rSize )
116*cdf0e10cSrcweir     {
117*cdf0e10cSrcweir         for( sal_Int32 i = 0; i < nCacheSize; ++i )
118*cdf0e10cSrcweir         {
119*cdf0e10cSrcweir             if( maPageNumbers[i] == i_nPageNo )
120*cdf0e10cSrcweir             {
121*cdf0e10cSrcweir                 updateRanking( i );
122*cdf0e10cSrcweir                 o_rPageFile = maPages[i].aPage;
123*cdf0e10cSrcweir                 o_rSize = maPages[i].aSize;
124*cdf0e10cSrcweir                 return true;
125*cdf0e10cSrcweir             }
126*cdf0e10cSrcweir         }
127*cdf0e10cSrcweir         return false;
128*cdf0e10cSrcweir     }
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir     void invalidate()
131*cdf0e10cSrcweir     {
132*cdf0e10cSrcweir         for( sal_Int32 i = 0; i < nCacheSize; ++i )
133*cdf0e10cSrcweir         {
134*cdf0e10cSrcweir             maPageNumbers[i] = -1;
135*cdf0e10cSrcweir             maPages[i].aPage.Clear();
136*cdf0e10cSrcweir             maCacheRanking[i] = nCacheSize - i - 1;
137*cdf0e10cSrcweir         }
138*cdf0e10cSrcweir     }
139*cdf0e10cSrcweir };
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir class vcl::ImplPrinterControllerData
142*cdf0e10cSrcweir {
143*cdf0e10cSrcweir public:
144*cdf0e10cSrcweir     struct ControlDependency
145*cdf0e10cSrcweir     {
146*cdf0e10cSrcweir         rtl::OUString       maDependsOnName;
147*cdf0e10cSrcweir         sal_Int32           mnDependsOnEntry;
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir         ControlDependency() : mnDependsOnEntry( -1 ) {}
150*cdf0e10cSrcweir     };
151*cdf0e10cSrcweir 
152*cdf0e10cSrcweir     typedef std::hash_map< rtl::OUString, size_t, rtl::OUStringHash > PropertyToIndexMap;
153*cdf0e10cSrcweir     typedef std::hash_map< rtl::OUString, ControlDependency, rtl::OUStringHash > ControlDependencyMap;
154*cdf0e10cSrcweir     typedef std::hash_map< rtl::OUString, Sequence< sal_Bool >, rtl::OUStringHash > ChoiceDisableMap;
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir     boost::shared_ptr<Printer>                                  mpPrinter;
157*cdf0e10cSrcweir     Sequence< PropertyValue >                                   maUIOptions;
158*cdf0e10cSrcweir     std::vector< PropertyValue >                                maUIProperties;
159*cdf0e10cSrcweir     std::vector< bool >                                         maUIPropertyEnabled;
160*cdf0e10cSrcweir     PropertyToIndexMap                                          maPropertyToIndex;
161*cdf0e10cSrcweir     Link                                                        maOptionChangeHdl;
162*cdf0e10cSrcweir     ControlDependencyMap                                        maControlDependencies;
163*cdf0e10cSrcweir     ChoiceDisableMap                                            maChoiceDisableMap;
164*cdf0e10cSrcweir     sal_Bool                                                    mbFirstPage;
165*cdf0e10cSrcweir     sal_Bool                                                    mbLastPage;
166*cdf0e10cSrcweir     sal_Bool                                                    mbReversePageOrder;
167*cdf0e10cSrcweir     view::PrintableState                                        meJobState;
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir     vcl::PrinterController::MultiPageSetup                      maMultiPage;
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir     vcl::PrintProgressDialog*                                   mpProgress;
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir     ImplPageCache                                               maPageCache;
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir     // set by user through printer config dialog
176*cdf0e10cSrcweir     // if set, pages are centered and trimmed onto the fixed page
177*cdf0e10cSrcweir     Size                                                        maFixedPageSize;
178*cdf0e10cSrcweir     sal_Int32                                                   mnDefaultPaperBin;
179*cdf0e10cSrcweir     sal_Int32                                                   mnFixedPaperBin;
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir     ImplPrinterControllerData() :
182*cdf0e10cSrcweir         mbFirstPage( sal_True ),
183*cdf0e10cSrcweir         mbLastPage( sal_False ),
184*cdf0e10cSrcweir         mbReversePageOrder( sal_False ),
185*cdf0e10cSrcweir         meJobState( view::PrintableState_JOB_STARTED ),
186*cdf0e10cSrcweir         mpProgress( NULL ),
187*cdf0e10cSrcweir         mnDefaultPaperBin( -1 ),
188*cdf0e10cSrcweir         mnFixedPaperBin( -1 )
189*cdf0e10cSrcweir     {}
190*cdf0e10cSrcweir     ~ImplPrinterControllerData() { delete mpProgress; }
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir     Size getRealPaperSize( const Size& i_rPageSize, bool bNoNUP ) const
193*cdf0e10cSrcweir     {
194*cdf0e10cSrcweir         if( maFixedPageSize.Width() > 0 && maFixedPageSize.Height() > 0 )
195*cdf0e10cSrcweir             return maFixedPageSize;
196*cdf0e10cSrcweir         if( maMultiPage.nRows * maMultiPage.nColumns > 1 && ! bNoNUP )
197*cdf0e10cSrcweir             return maMultiPage.aPaperSize;
198*cdf0e10cSrcweir         return i_rPageSize;
199*cdf0e10cSrcweir     }
200*cdf0e10cSrcweir     bool isFixedPageSize() const
201*cdf0e10cSrcweir     { return maFixedPageSize.Width() != 0 && maFixedPageSize.Height() != 0; }
202*cdf0e10cSrcweir     PrinterController::PageSize modifyJobSetup( const Sequence< PropertyValue >& i_rProps, bool bNoNUP );
203*cdf0e10cSrcweir };
204*cdf0e10cSrcweir 
205*cdf0e10cSrcweir PrinterController::PrinterController()
206*cdf0e10cSrcweir     : mpImplData( new ImplPrinterControllerData )
207*cdf0e10cSrcweir {
208*cdf0e10cSrcweir }
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir PrinterController::PrinterController( const boost::shared_ptr<Printer>& i_pPrinter )
211*cdf0e10cSrcweir     : mpImplData( new ImplPrinterControllerData )
212*cdf0e10cSrcweir {
213*cdf0e10cSrcweir     mpImplData->mpPrinter = i_pPrinter;
214*cdf0e10cSrcweir }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir static rtl::OUString queryFile( Printer* pPrinter )
217*cdf0e10cSrcweir {
218*cdf0e10cSrcweir     rtl::OUString aResult;
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir     uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
221*cdf0e10cSrcweir     if( xFactory.is() )
222*cdf0e10cSrcweir     {
223*cdf0e10cSrcweir         uno::Sequence< uno::Any > aTempl( 1 );
224*cdf0e10cSrcweir         aTempl.getArray()[0] <<= ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION;
225*cdf0e10cSrcweir         uno::Reference< ui::dialogs::XFilePicker > xFilePicker(
226*cdf0e10cSrcweir             xFactory->createInstanceWithArguments(
227*cdf0e10cSrcweir                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ),
228*cdf0e10cSrcweir                 aTempl ), uno::UNO_QUERY );
229*cdf0e10cSrcweir         DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" );
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir         uno::Reference< ui::dialogs::XFilterManager > xFilterMgr( xFilePicker, uno::UNO_QUERY );
232*cdf0e10cSrcweir         if( xFilePicker.is() && xFilterMgr.is() )
233*cdf0e10cSrcweir         {
234*cdf0e10cSrcweir             try
235*cdf0e10cSrcweir             {
236*cdf0e10cSrcweir #ifdef UNX
237*cdf0e10cSrcweir                 // add PostScript and PDF
238*cdf0e10cSrcweir                 bool bPS = true, bPDF = true;
239*cdf0e10cSrcweir                 if( pPrinter )
240*cdf0e10cSrcweir                 {
241*cdf0e10cSrcweir                     if( pPrinter->GetCapabilities( PRINTER_CAPABILITIES_PDF ) )
242*cdf0e10cSrcweir                         bPS = false;
243*cdf0e10cSrcweir                     else
244*cdf0e10cSrcweir                         bPDF = false;
245*cdf0e10cSrcweir                 }
246*cdf0e10cSrcweir                 if( bPS )
247*cdf0e10cSrcweir                     xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PostScript" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.ps" ) ) );
248*cdf0e10cSrcweir                 if( bPDF )
249*cdf0e10cSrcweir                     xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Portable Document Format" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.pdf" ) ) );
250*cdf0e10cSrcweir #elif defined WNT
251*cdf0e10cSrcweir 		(void)pPrinter;
252*cdf0e10cSrcweir                 xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.PRN" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.prn" ) ) );
253*cdf0e10cSrcweir #endif
254*cdf0e10cSrcweir                 // add arbitrary files
255*cdf0e10cSrcweir                 xFilterMgr->appendFilter( String( VclResId( SV_STDTEXT_ALLFILETYPES ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.*" ) ) );
256*cdf0e10cSrcweir             }
257*cdf0e10cSrcweir             catch( lang::IllegalArgumentException rExc )
258*cdf0e10cSrcweir             {
259*cdf0e10cSrcweir                 DBG_ERRORFILE( "caught IllegalArgumentException when registering filter\n" );
260*cdf0e10cSrcweir             }
261*cdf0e10cSrcweir 
262*cdf0e10cSrcweir             if( xFilePicker->execute() == ui::dialogs::ExecutableDialogResults::OK )
263*cdf0e10cSrcweir             {
264*cdf0e10cSrcweir                 uno::Sequence< ::rtl::OUString > aPathSeq( xFilePicker->getFiles() );
265*cdf0e10cSrcweir 				INetURLObject aObj( aPathSeq[0] );
266*cdf0e10cSrcweir 				aResult = aObj.PathToFileName();
267*cdf0e10cSrcweir             }
268*cdf0e10cSrcweir         }
269*cdf0e10cSrcweir     }
270*cdf0e10cSrcweir     return aResult;
271*cdf0e10cSrcweir }
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir struct PrintJobAsync
274*cdf0e10cSrcweir {
275*cdf0e10cSrcweir     boost::shared_ptr<PrinterController>  mpController;
276*cdf0e10cSrcweir     JobSetup                            maInitSetup;
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir     PrintJobAsync( const boost::shared_ptr<PrinterController>& i_pController,
279*cdf0e10cSrcweir                    const JobSetup& i_rInitSetup
280*cdf0e10cSrcweir                    )
281*cdf0e10cSrcweir     : mpController( i_pController ), maInitSetup( i_rInitSetup )
282*cdf0e10cSrcweir     {}
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir     DECL_LINK( ExecJob, void* );
285*cdf0e10cSrcweir };
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir IMPL_LINK( PrintJobAsync, ExecJob, void*, EMPTYARG )
288*cdf0e10cSrcweir {
289*cdf0e10cSrcweir     Printer::ImplPrintJob( mpController, maInitSetup );
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir     // clean up, do not access members after this
292*cdf0e10cSrcweir     delete this;
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir     return 0;
295*cdf0e10cSrcweir }
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir void Printer::PrintJob( const boost::shared_ptr<PrinterController>& i_pController,
298*cdf0e10cSrcweir                         const JobSetup& i_rInitSetup
299*cdf0e10cSrcweir                         )
300*cdf0e10cSrcweir {
301*cdf0e10cSrcweir     sal_Bool bSynchronous = sal_False;
302*cdf0e10cSrcweir     beans::PropertyValue* pVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wait" ) ) );
303*cdf0e10cSrcweir     if( pVal )
304*cdf0e10cSrcweir         pVal->Value >>= bSynchronous;
305*cdf0e10cSrcweir 
306*cdf0e10cSrcweir     if( bSynchronous )
307*cdf0e10cSrcweir         ImplPrintJob( i_pController, i_rInitSetup );
308*cdf0e10cSrcweir     else
309*cdf0e10cSrcweir     {
310*cdf0e10cSrcweir         PrintJobAsync* pAsync = new PrintJobAsync( i_pController, i_rInitSetup );
311*cdf0e10cSrcweir         Application::PostUserEvent( LINK( pAsync, PrintJobAsync, ExecJob ) );
312*cdf0e10cSrcweir     }
313*cdf0e10cSrcweir }
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir void Printer::ImplPrintJob( const boost::shared_ptr<PrinterController>& i_pController,
316*cdf0e10cSrcweir                             const JobSetup& i_rInitSetup
317*cdf0e10cSrcweir                             )
318*cdf0e10cSrcweir {
319*cdf0e10cSrcweir     boost::shared_ptr<PrinterController> pController( i_pController );
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir     // check if there is a default printer; if not, show an error box (if appropriate)
322*cdf0e10cSrcweir     if( GetDefaultPrinterName().Len() == 0  )
323*cdf0e10cSrcweir     {
324*cdf0e10cSrcweir         if(  pController->isShowDialogs()
325*cdf0e10cSrcweir              // && ! pController->isDirectPrint()
326*cdf0e10cSrcweir            )
327*cdf0e10cSrcweir         {
328*cdf0e10cSrcweir             ErrorBox aBox( NULL, VclResId( SV_PRINT_NOPRINTERWARNING ) );
329*cdf0e10cSrcweir             aBox.Execute();
330*cdf0e10cSrcweir         }
331*cdf0e10cSrcweir         pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDirect" ) ),
332*cdf0e10cSrcweir                                makeAny( sal_False ) );
333*cdf0e10cSrcweir     }
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir     // setup printer
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir     // #i114306# changed behavior back from persistence
338*cdf0e10cSrcweir     // if no specific printer is already set, create the default printer
339*cdf0e10cSrcweir     if( ! pController->getPrinter() )
340*cdf0e10cSrcweir     {
341*cdf0e10cSrcweir         rtl::OUString aPrinterName( i_rInitSetup.GetPrinterName() );
342*cdf0e10cSrcweir         boost::shared_ptr<Printer> pPrinter( new Printer( aPrinterName ) );
343*cdf0e10cSrcweir         pPrinter->SetJobSetup( i_rInitSetup );
344*cdf0e10cSrcweir         pController->setPrinter( pPrinter );
345*cdf0e10cSrcweir     }
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir     // reset last page property
348*cdf0e10cSrcweir     i_pController->setLastPage( sal_False );
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir     // update "PageRange" property inferring from other properties:
351*cdf0e10cSrcweir     // case 1: "Pages" set from UNO API ->
352*cdf0e10cSrcweir     //         setup "Print Selection" and insert "PageRange" attribute
353*cdf0e10cSrcweir     // case 2: "All pages" is selected
354*cdf0e10cSrcweir     //         update "Page range" attribute to have a sensible default,
355*cdf0e10cSrcweir     //         but leave "All" as selected
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir     // "Pages" attribute from API is now equivalent to "PageRange"
358*cdf0e10cSrcweir     // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
359*cdf0e10cSrcweir     // Argh ! That sure needs cleaning up
360*cdf0e10cSrcweir     beans::PropertyValue* pContentVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) ) );
361*cdf0e10cSrcweir     if( ! pContentVal )
362*cdf0e10cSrcweir         pContentVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ) );
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir     // case 1: UNO API has set "Pages"
365*cdf0e10cSrcweir     beans::PropertyValue* pPagesVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pages" ) ) );
366*cdf0e10cSrcweir     if( pPagesVal )
367*cdf0e10cSrcweir     {
368*cdf0e10cSrcweir         rtl::OUString aPagesVal;
369*cdf0e10cSrcweir         pPagesVal->Value >>= aPagesVal;
370*cdf0e10cSrcweir         if( aPagesVal.getLength() )
371*cdf0e10cSrcweir         {
372*cdf0e10cSrcweir             // "Pages" attribute from API is now equivalent to "PageRange"
373*cdf0e10cSrcweir             // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
374*cdf0e10cSrcweir             // Argh ! That sure needs cleaning up
375*cdf0e10cSrcweir             if( pContentVal )
376*cdf0e10cSrcweir             {
377*cdf0e10cSrcweir                 pContentVal->Value = makeAny( sal_Int32( 1 ) );
378*cdf0e10cSrcweir                 i_pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), pPagesVal->Value );
379*cdf0e10cSrcweir             }
380*cdf0e10cSrcweir         }
381*cdf0e10cSrcweir     }
382*cdf0e10cSrcweir     // case 2: is "All" selected ?
383*cdf0e10cSrcweir     else if( pContentVal )
384*cdf0e10cSrcweir     {
385*cdf0e10cSrcweir         sal_Int32 nContent = -1;
386*cdf0e10cSrcweir         if( pContentVal->Value >>= nContent )
387*cdf0e10cSrcweir         {
388*cdf0e10cSrcweir             if( nContent == 0 )
389*cdf0e10cSrcweir             {
390*cdf0e10cSrcweir                 // do not overwrite PageRange if it is already set
391*cdf0e10cSrcweir                 beans::PropertyValue* pRangeVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ) );
392*cdf0e10cSrcweir                 rtl::OUString aRange;
393*cdf0e10cSrcweir                 if( pRangeVal )
394*cdf0e10cSrcweir                     pRangeVal->Value >>= aRange;
395*cdf0e10cSrcweir                 if( aRange.getLength() == 0 )
396*cdf0e10cSrcweir                 {
397*cdf0e10cSrcweir                     sal_Int32 nPages = i_pController->getPageCount();
398*cdf0e10cSrcweir                     if( nPages > 0 )
399*cdf0e10cSrcweir                     {
400*cdf0e10cSrcweir                         rtl::OUStringBuffer aBuf( 32 );
401*cdf0e10cSrcweir                         aBuf.appendAscii( "1" );
402*cdf0e10cSrcweir                         if( nPages > 1 )
403*cdf0e10cSrcweir                         {
404*cdf0e10cSrcweir                             aBuf.appendAscii( "-" );
405*cdf0e10cSrcweir                             aBuf.append( nPages );
406*cdf0e10cSrcweir                         }
407*cdf0e10cSrcweir                         i_pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), makeAny( aBuf.makeStringAndClear() ) );
408*cdf0e10cSrcweir                     }
409*cdf0e10cSrcweir                 }
410*cdf0e10cSrcweir             }
411*cdf0e10cSrcweir         }
412*cdf0e10cSrcweir     }
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir     beans::PropertyValue* pReverseVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintReverse" ) ) );
415*cdf0e10cSrcweir     if( pReverseVal )
416*cdf0e10cSrcweir     {
417*cdf0e10cSrcweir         sal_Bool bReverse = sal_False;
418*cdf0e10cSrcweir         pReverseVal->Value >>= bReverse;
419*cdf0e10cSrcweir         pController->setReversePrint( bReverse );
420*cdf0e10cSrcweir     }
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir     // in direct print case check whether there is anything to print.
423*cdf0e10cSrcweir     // if not, show an errorbox (if appropriate)
424*cdf0e10cSrcweir     if( pController->isShowDialogs() && pController->isDirectPrint() )
425*cdf0e10cSrcweir     {
426*cdf0e10cSrcweir         if( pController->getFilteredPageCount() == 0 )
427*cdf0e10cSrcweir         {
428*cdf0e10cSrcweir             ErrorBox aBox( NULL, VclResId( SV_PRINT_NOCONTENT ) );
429*cdf0e10cSrcweir             aBox.Execute();
430*cdf0e10cSrcweir             return;
431*cdf0e10cSrcweir         }
432*cdf0e10cSrcweir     }
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir     // check if the printer brings up its own dialog
435*cdf0e10cSrcweir     // in that case leave the work to that dialog
436*cdf0e10cSrcweir     if( ! pController->getPrinter()->GetCapabilities( PRINTER_CAPABILITIES_EXTERNALDIALOG ) &&
437*cdf0e10cSrcweir         ! pController->isDirectPrint() &&
438*cdf0e10cSrcweir         pController->isShowDialogs()
439*cdf0e10cSrcweir         )
440*cdf0e10cSrcweir     {
441*cdf0e10cSrcweir         try
442*cdf0e10cSrcweir         {
443*cdf0e10cSrcweir             PrintDialog aDlg( NULL, i_pController );
444*cdf0e10cSrcweir             if( ! aDlg.Execute() )
445*cdf0e10cSrcweir             {
446*cdf0e10cSrcweir                 GDIMetaFile aPageFile;
447*cdf0e10cSrcweir                 i_pController->abortJob();
448*cdf0e10cSrcweir                 return;
449*cdf0e10cSrcweir             }
450*cdf0e10cSrcweir             if( aDlg.isPrintToFile() )
451*cdf0e10cSrcweir             {
452*cdf0e10cSrcweir                 rtl::OUString aFile = queryFile( pController->getPrinter().get() );
453*cdf0e10cSrcweir                 if( ! aFile.getLength() )
454*cdf0e10cSrcweir                 {
455*cdf0e10cSrcweir                     i_pController->abortJob();
456*cdf0e10cSrcweir                     return;
457*cdf0e10cSrcweir                 }
458*cdf0e10cSrcweir                 pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LocalFileName" ) ),
459*cdf0e10cSrcweir                                        makeAny( aFile ) );
460*cdf0e10cSrcweir             }
461*cdf0e10cSrcweir             else if( aDlg.isSingleJobs() )
462*cdf0e10cSrcweir             {
463*cdf0e10cSrcweir                 pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ),
464*cdf0e10cSrcweir                                        makeAny( sal_True ) );
465*cdf0e10cSrcweir             }
466*cdf0e10cSrcweir         }
467*cdf0e10cSrcweir         catch( std::bad_alloc& )
468*cdf0e10cSrcweir         {
469*cdf0e10cSrcweir         }
470*cdf0e10cSrcweir     }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir     pController->pushPropertiesToPrinter();
473*cdf0e10cSrcweir 
474*cdf0e10cSrcweir     rtl::OUString aJobName;
475*cdf0e10cSrcweir     beans::PropertyValue* pJobNameVal = pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobName" ) ) );
476*cdf0e10cSrcweir     if( pJobNameVal )
477*cdf0e10cSrcweir         pJobNameVal->Value >>= aJobName;
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir     pController->getPrinter()->StartJob( String( aJobName ), pController );
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir     pController->jobFinished( pController->getJobState() );
482*cdf0e10cSrcweir }
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir bool Printer::StartJob( const rtl::OUString& i_rJobName, boost::shared_ptr<vcl::PrinterController>& i_pController )
485*cdf0e10cSrcweir {
486*cdf0e10cSrcweir 	mnError = PRINTER_OK;
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir 	if ( IsDisplayPrinter() )
489*cdf0e10cSrcweir 		return sal_False;
490*cdf0e10cSrcweir 
491*cdf0e10cSrcweir 	if ( IsJobActive() || IsPrinting() )
492*cdf0e10cSrcweir 		return sal_False;
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir 	sal_uLong   nCopies = mnCopyCount;
495*cdf0e10cSrcweir 	bool    bCollateCopy = mbCollateCopy;
496*cdf0e10cSrcweir 	bool    bUserCopy = sal_False;
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir     if ( nCopies > 1 )
499*cdf0e10cSrcweir     {
500*cdf0e10cSrcweir         sal_uLong nDevCopy;
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir         if ( bCollateCopy )
503*cdf0e10cSrcweir             nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES );
504*cdf0e10cSrcweir         else
505*cdf0e10cSrcweir             nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COPIES );
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir         // need to do copies by hand ?
508*cdf0e10cSrcweir         if ( nCopies > nDevCopy )
509*cdf0e10cSrcweir         {
510*cdf0e10cSrcweir             bUserCopy = sal_True;
511*cdf0e10cSrcweir             nCopies = 1;
512*cdf0e10cSrcweir             bCollateCopy = sal_False;
513*cdf0e10cSrcweir         }
514*cdf0e10cSrcweir     }
515*cdf0e10cSrcweir     else
516*cdf0e10cSrcweir         bCollateCopy = sal_False;
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir     ImplSVData* pSVData = ImplGetSVData();
520*cdf0e10cSrcweir     mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir     if ( !mpPrinter )
523*cdf0e10cSrcweir         return sal_False;
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir     sal_Bool bSinglePrintJobs = sal_False;
526*cdf0e10cSrcweir     beans::PropertyValue* pSingleValue = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ) );
527*cdf0e10cSrcweir     if( pSingleValue )
528*cdf0e10cSrcweir     {
529*cdf0e10cSrcweir         pSingleValue->Value >>= bSinglePrintJobs;
530*cdf0e10cSrcweir     }
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir     beans::PropertyValue* pFileValue = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LocalFileName" ) ) );
533*cdf0e10cSrcweir     if( pFileValue )
534*cdf0e10cSrcweir     {
535*cdf0e10cSrcweir         rtl::OUString aFile;
536*cdf0e10cSrcweir         pFileValue->Value >>= aFile;
537*cdf0e10cSrcweir         if( aFile.getLength() )
538*cdf0e10cSrcweir         {
539*cdf0e10cSrcweir             mbPrintFile = sal_True;
540*cdf0e10cSrcweir             maPrintFile = aFile;
541*cdf0e10cSrcweir             bSinglePrintJobs = sal_False;
542*cdf0e10cSrcweir         }
543*cdf0e10cSrcweir     }
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir     XubString* pPrintFile = NULL;
546*cdf0e10cSrcweir     if ( mbPrintFile )
547*cdf0e10cSrcweir         pPrintFile = &maPrintFile;
548*cdf0e10cSrcweir     mpPrinterOptions->ReadFromConfig( mbPrintFile );
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir     maJobName		        = i_rJobName;
551*cdf0e10cSrcweir     mnCurPage		        = 1;
552*cdf0e10cSrcweir     mnCurPrintPage	        = 1;
553*cdf0e10cSrcweir     mbPrinting		        = sal_True;
554*cdf0e10cSrcweir     if( GetCapabilities( PRINTER_CAPABILITIES_USEPULLMODEL ) )
555*cdf0e10cSrcweir     {
556*cdf0e10cSrcweir         mbJobActive             = sal_True;
557*cdf0e10cSrcweir         // sallayer does all necessary page printing
558*cdf0e10cSrcweir         // and also handles showing a dialog
559*cdf0e10cSrcweir         // that also means it must call jobStarted when the dialog is finished
560*cdf0e10cSrcweir         // it also must set the JobState of the Controller
561*cdf0e10cSrcweir         if( mpPrinter->StartJob( pPrintFile,
562*cdf0e10cSrcweir                                  i_rJobName,
563*cdf0e10cSrcweir                                  Application::GetDisplayName(),
564*cdf0e10cSrcweir                                  maJobSetup.ImplGetConstData(),
565*cdf0e10cSrcweir                                  *i_pController ) )
566*cdf0e10cSrcweir         {
567*cdf0e10cSrcweir             EndJob();
568*cdf0e10cSrcweir         }
569*cdf0e10cSrcweir         else
570*cdf0e10cSrcweir         {
571*cdf0e10cSrcweir             mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() );
572*cdf0e10cSrcweir             if ( !mnError )
573*cdf0e10cSrcweir                 mnError = PRINTER_GENERALERROR;
574*cdf0e10cSrcweir             pSVData->mpDefInst->DestroyPrinter( mpPrinter );
575*cdf0e10cSrcweir             mnCurPage		    = 0;
576*cdf0e10cSrcweir             mnCurPrintPage	    = 0;
577*cdf0e10cSrcweir             mbPrinting		    = sal_False;
578*cdf0e10cSrcweir             mpPrinter = NULL;
579*cdf0e10cSrcweir 
580*cdf0e10cSrcweir             return false;
581*cdf0e10cSrcweir         }
582*cdf0e10cSrcweir     }
583*cdf0e10cSrcweir     else
584*cdf0e10cSrcweir     {
585*cdf0e10cSrcweir         // possibly a dialog has been shown
586*cdf0e10cSrcweir         // now the real job starts
587*cdf0e10cSrcweir         i_pController->setJobState( view::PrintableState_JOB_STARTED );
588*cdf0e10cSrcweir         i_pController->jobStarted();
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir         int nJobs = 1;
591*cdf0e10cSrcweir         int nOuterRepeatCount = 1;
592*cdf0e10cSrcweir         int nInnerRepeatCount = 1;
593*cdf0e10cSrcweir         if( bUserCopy )
594*cdf0e10cSrcweir         {
595*cdf0e10cSrcweir             if( mbCollateCopy )
596*cdf0e10cSrcweir                 nOuterRepeatCount = mnCopyCount;
597*cdf0e10cSrcweir             else
598*cdf0e10cSrcweir                 nInnerRepeatCount = mnCopyCount;
599*cdf0e10cSrcweir         }
600*cdf0e10cSrcweir         if( bSinglePrintJobs )
601*cdf0e10cSrcweir         {
602*cdf0e10cSrcweir             nJobs = mnCopyCount;
603*cdf0e10cSrcweir             nCopies = 1;
604*cdf0e10cSrcweir             nOuterRepeatCount = nInnerRepeatCount = 1;
605*cdf0e10cSrcweir         }
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir         for( int nJobIteration = 0; nJobIteration < nJobs; nJobIteration++ )
608*cdf0e10cSrcweir         {
609*cdf0e10cSrcweir             bool bError = false, bAborted = false;
610*cdf0e10cSrcweir             if( mpPrinter->StartJob( pPrintFile,
611*cdf0e10cSrcweir                                      i_rJobName,
612*cdf0e10cSrcweir                                      Application::GetDisplayName(),
613*cdf0e10cSrcweir                                      nCopies,
614*cdf0e10cSrcweir                                      bCollateCopy,
615*cdf0e10cSrcweir                                      i_pController->isDirectPrint(),
616*cdf0e10cSrcweir                                      maJobSetup.ImplGetConstData() ) )
617*cdf0e10cSrcweir             {
618*cdf0e10cSrcweir                 mbJobActive             = sal_True;
619*cdf0e10cSrcweir                 i_pController->createProgressDialog();
620*cdf0e10cSrcweir                 int nPages = i_pController->getFilteredPageCount();
621*cdf0e10cSrcweir                 for( int nOuterIteration = 0; nOuterIteration < nOuterRepeatCount && ! bAborted; nOuterIteration++ )
622*cdf0e10cSrcweir                 {
623*cdf0e10cSrcweir                     for( int nPage = 0; nPage < nPages && ! bAborted; nPage++ )
624*cdf0e10cSrcweir                     {
625*cdf0e10cSrcweir                         for( int nInnerIteration = 0; nInnerIteration < nInnerRepeatCount && ! bAborted; nInnerIteration++ )
626*cdf0e10cSrcweir                         {
627*cdf0e10cSrcweir                             if( nPage == nPages-1 &&
628*cdf0e10cSrcweir                                 nOuterIteration == nOuterRepeatCount-1 &&
629*cdf0e10cSrcweir                                 nInnerIteration == nInnerRepeatCount-1 &&
630*cdf0e10cSrcweir                                 nJobIteration == nJobs-1 )
631*cdf0e10cSrcweir                             {
632*cdf0e10cSrcweir                                 i_pController->setLastPage( sal_True );
633*cdf0e10cSrcweir                             }
634*cdf0e10cSrcweir                             i_pController->printFilteredPage( nPage );
635*cdf0e10cSrcweir                             if( i_pController->isProgressCanceled() )
636*cdf0e10cSrcweir                             {
637*cdf0e10cSrcweir                                 i_pController->abortJob();
638*cdf0e10cSrcweir                                 bAborted = true;
639*cdf0e10cSrcweir                             }
640*cdf0e10cSrcweir                         }
641*cdf0e10cSrcweir                     }
642*cdf0e10cSrcweir                     // FIXME: duplex ?
643*cdf0e10cSrcweir                 }
644*cdf0e10cSrcweir                 EndJob();
645*cdf0e10cSrcweir 
646*cdf0e10cSrcweir                 if( nJobIteration < nJobs-1 )
647*cdf0e10cSrcweir                 {
648*cdf0e10cSrcweir                     mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
649*cdf0e10cSrcweir 
650*cdf0e10cSrcweir                     if ( mpPrinter )
651*cdf0e10cSrcweir                     {
652*cdf0e10cSrcweir                         maJobName		        = i_rJobName;
653*cdf0e10cSrcweir                         mnCurPage		        = 1;
654*cdf0e10cSrcweir                         mnCurPrintPage	        = 1;
655*cdf0e10cSrcweir                         mbPrinting		        = sal_True;
656*cdf0e10cSrcweir                     }
657*cdf0e10cSrcweir                     else
658*cdf0e10cSrcweir                         bError = true;
659*cdf0e10cSrcweir                 }
660*cdf0e10cSrcweir             }
661*cdf0e10cSrcweir             else
662*cdf0e10cSrcweir                 bError = true;
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir             if( bError )
665*cdf0e10cSrcweir             {
666*cdf0e10cSrcweir                 mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() );
667*cdf0e10cSrcweir                 if ( !mnError )
668*cdf0e10cSrcweir                     mnError = PRINTER_GENERALERROR;
669*cdf0e10cSrcweir                 i_pController->setJobState( mnError == PRINTER_ABORT
670*cdf0e10cSrcweir                                             ? view::PrintableState_JOB_ABORTED
671*cdf0e10cSrcweir                                             : view::PrintableState_JOB_FAILED );
672*cdf0e10cSrcweir                 if( mpPrinter )
673*cdf0e10cSrcweir                     pSVData->mpDefInst->DestroyPrinter( mpPrinter );
674*cdf0e10cSrcweir                 mnCurPage		    = 0;
675*cdf0e10cSrcweir                 mnCurPrintPage	    = 0;
676*cdf0e10cSrcweir                 mbPrinting		    = sal_False;
677*cdf0e10cSrcweir                 mpPrinter = NULL;
678*cdf0e10cSrcweir 
679*cdf0e10cSrcweir                 return false;
680*cdf0e10cSrcweir             }
681*cdf0e10cSrcweir         }
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir         if( i_pController->getJobState() == view::PrintableState_JOB_STARTED )
684*cdf0e10cSrcweir             i_pController->setJobState( view::PrintableState_JOB_SPOOLED );
685*cdf0e10cSrcweir     }
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir     // make last used printer persistent for UI jobs
688*cdf0e10cSrcweir     if( i_pController->isShowDialogs() && ! i_pController->isDirectPrint() )
689*cdf0e10cSrcweir     {
690*cdf0e10cSrcweir         SettingsConfigItem* pItem = SettingsConfigItem::get();
691*cdf0e10cSrcweir         pItem->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
692*cdf0e10cSrcweir                          rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinterUsed" ) ),
693*cdf0e10cSrcweir                          GetName()
694*cdf0e10cSrcweir                          );
695*cdf0e10cSrcweir     }
696*cdf0e10cSrcweir 
697*cdf0e10cSrcweir 	return true;
698*cdf0e10cSrcweir }
699*cdf0e10cSrcweir 
700*cdf0e10cSrcweir PrinterController::~PrinterController()
701*cdf0e10cSrcweir {
702*cdf0e10cSrcweir     delete mpImplData;
703*cdf0e10cSrcweir }
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir view::PrintableState PrinterController::getJobState() const
706*cdf0e10cSrcweir {
707*cdf0e10cSrcweir     return mpImplData->meJobState;
708*cdf0e10cSrcweir }
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir void PrinterController::setJobState( view::PrintableState i_eState )
711*cdf0e10cSrcweir {
712*cdf0e10cSrcweir     mpImplData->meJobState = i_eState;
713*cdf0e10cSrcweir }
714*cdf0e10cSrcweir 
715*cdf0e10cSrcweir const boost::shared_ptr<Printer>& PrinterController::getPrinter() const
716*cdf0e10cSrcweir {
717*cdf0e10cSrcweir     return mpImplData->mpPrinter;
718*cdf0e10cSrcweir }
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir void PrinterController::setPrinter( const boost::shared_ptr<Printer>& i_rPrinter )
721*cdf0e10cSrcweir {
722*cdf0e10cSrcweir     mpImplData->mpPrinter = i_rPrinter;
723*cdf0e10cSrcweir     setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) ),
724*cdf0e10cSrcweir               makeAny( rtl::OUString( i_rPrinter->GetName() ) ) );
725*cdf0e10cSrcweir     mpImplData->mnDefaultPaperBin = mpImplData->mpPrinter->GetPaperBin();
726*cdf0e10cSrcweir     mpImplData->mnFixedPaperBin = -1;
727*cdf0e10cSrcweir }
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir void PrinterController:: resetPrinterOptions( bool i_bFileOutput )
730*cdf0e10cSrcweir {
731*cdf0e10cSrcweir     PrinterOptions aOpt;
732*cdf0e10cSrcweir     aOpt.ReadFromConfig( i_bFileOutput );
733*cdf0e10cSrcweir     mpImplData->mpPrinter->SetPrinterOptions( aOpt );
734*cdf0e10cSrcweir }
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir bool PrinterController::setupPrinter( Window* i_pParent )
737*cdf0e10cSrcweir {
738*cdf0e10cSrcweir     bool bRet = false;
739*cdf0e10cSrcweir     if( mpImplData->mpPrinter.get() )
740*cdf0e10cSrcweir     {
741*cdf0e10cSrcweir         // get old data
742*cdf0e10cSrcweir         Size aPaperSize( mpImplData->mpPrinter->PixelToLogic(
743*cdf0e10cSrcweir             mpImplData->mpPrinter->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
744*cdf0e10cSrcweir         sal_uInt16 nPaperBin = mpImplData->mpPrinter->GetPaperBin();
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir         // call driver setup
747*cdf0e10cSrcweir         bRet = mpImplData->mpPrinter->Setup( i_pParent );
748*cdf0e10cSrcweir         if( bRet )
749*cdf0e10cSrcweir         {
750*cdf0e10cSrcweir             // was papersize or bin  overridden ? if so we need to take action
751*cdf0e10cSrcweir             Size aNewPaperSize( mpImplData->mpPrinter->PixelToLogic(
752*cdf0e10cSrcweir                 mpImplData->mpPrinter->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
753*cdf0e10cSrcweir             sal_uInt16 nNewPaperBin = mpImplData->mpPrinter->GetPaperBin();
754*cdf0e10cSrcweir             if( aNewPaperSize != aPaperSize || nNewPaperBin != nPaperBin )
755*cdf0e10cSrcweir             {
756*cdf0e10cSrcweir                 mpImplData->maFixedPageSize = aNewPaperSize;
757*cdf0e10cSrcweir                 mpImplData->maPageCache.invalidate();
758*cdf0e10cSrcweir                 awt::Size aOverrideSize;
759*cdf0e10cSrcweir                 aOverrideSize.Width = aNewPaperSize.Width();
760*cdf0e10cSrcweir                 aOverrideSize.Height = aNewPaperSize.Height();
761*cdf0e10cSrcweir                 setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OverridePageSize" ) ),
762*cdf0e10cSrcweir                           makeAny( aOverrideSize ) );
763*cdf0e10cSrcweir                 mpImplData->mnFixedPaperBin = nNewPaperBin;
764*cdf0e10cSrcweir             }
765*cdf0e10cSrcweir         }
766*cdf0e10cSrcweir     }
767*cdf0e10cSrcweir     return bRet;
768*cdf0e10cSrcweir }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir PrinterController::PageSize vcl::ImplPrinterControllerData::modifyJobSetup( const Sequence< PropertyValue >& i_rProps, bool bNoNUP )
771*cdf0e10cSrcweir {
772*cdf0e10cSrcweir     PrinterController::PageSize aPageSize;
773*cdf0e10cSrcweir     aPageSize.aSize = mpPrinter->GetPaperSize();
774*cdf0e10cSrcweir     awt::Size aSetSize, aIsSize;
775*cdf0e10cSrcweir     sal_Int32 nPaperBin = mnDefaultPaperBin;
776*cdf0e10cSrcweir     for( sal_Int32 nProperty = 0, nPropertyCount = i_rProps.getLength(); nProperty < nPropertyCount; ++nProperty )
777*cdf0e10cSrcweir     {
778*cdf0e10cSrcweir         if( i_rProps[ nProperty ].Name.equalsAscii( "PreferredPageSize" ) )
779*cdf0e10cSrcweir         {
780*cdf0e10cSrcweir             i_rProps[ nProperty ].Value >>= aSetSize;
781*cdf0e10cSrcweir         }
782*cdf0e10cSrcweir         else if( i_rProps[ nProperty ].Name.equalsAscii( "PageSize" ) )
783*cdf0e10cSrcweir         {
784*cdf0e10cSrcweir             i_rProps[ nProperty ].Value >>= aIsSize;
785*cdf0e10cSrcweir         }
786*cdf0e10cSrcweir         else if( i_rProps[ nProperty ].Name.equalsAscii( "PageIncludesNonprintableArea" ) )
787*cdf0e10cSrcweir         {
788*cdf0e10cSrcweir             sal_Bool bVal = sal_False;
789*cdf0e10cSrcweir             i_rProps[ nProperty ].Value >>= bVal;
790*cdf0e10cSrcweir             aPageSize.bFullPaper = static_cast<bool>(bVal);
791*cdf0e10cSrcweir         }
792*cdf0e10cSrcweir         else if( i_rProps[ nProperty ].Name.equalsAscii( "PrinterPaperTray" ) )
793*cdf0e10cSrcweir         {
794*cdf0e10cSrcweir             sal_Int32 nBin = -1;
795*cdf0e10cSrcweir             i_rProps[ nProperty ].Value >>= nBin;
796*cdf0e10cSrcweir             if( nBin >= 0 && nBin < mpPrinter->GetPaperBinCount() )
797*cdf0e10cSrcweir                 nPaperBin = nBin;
798*cdf0e10cSrcweir         }
799*cdf0e10cSrcweir     }
800*cdf0e10cSrcweir 
801*cdf0e10cSrcweir     Size aCurSize( mpPrinter->GetPaperSize() );
802*cdf0e10cSrcweir     if( aSetSize.Width && aSetSize.Height )
803*cdf0e10cSrcweir     {
804*cdf0e10cSrcweir         Size aSetPaperSize( aSetSize.Width, aSetSize.Height );
805*cdf0e10cSrcweir         Size aRealPaperSize( getRealPaperSize( aSetPaperSize, bNoNUP ) );
806*cdf0e10cSrcweir         if( aRealPaperSize != aCurSize )
807*cdf0e10cSrcweir             aIsSize = aSetSize;
808*cdf0e10cSrcweir     }
809*cdf0e10cSrcweir 
810*cdf0e10cSrcweir     if( aIsSize.Width && aIsSize.Height )
811*cdf0e10cSrcweir     {
812*cdf0e10cSrcweir         aPageSize.aSize.Width() = aIsSize.Width;
813*cdf0e10cSrcweir         aPageSize.aSize.Height() = aIsSize.Height;
814*cdf0e10cSrcweir 
815*cdf0e10cSrcweir         Size aRealPaperSize( getRealPaperSize( aPageSize.aSize, bNoNUP ) );
816*cdf0e10cSrcweir         if( aRealPaperSize != aCurSize )
817*cdf0e10cSrcweir             mpPrinter->SetPaperSizeUser( aRealPaperSize, ! isFixedPageSize() );
818*cdf0e10cSrcweir     }
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir     if( nPaperBin != -1 && nPaperBin != mpPrinter->GetPaperBin() )
821*cdf0e10cSrcweir         mpPrinter->SetPaperBin( nPaperBin );
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir     return aPageSize;
824*cdf0e10cSrcweir }
825*cdf0e10cSrcweir 
826*cdf0e10cSrcweir int PrinterController::getPageCountProtected() const
827*cdf0e10cSrcweir {
828*cdf0e10cSrcweir     const MapMode aMapMode( MAP_100TH_MM );
829*cdf0e10cSrcweir 
830*cdf0e10cSrcweir     mpImplData->mpPrinter->Push();
831*cdf0e10cSrcweir     mpImplData->mpPrinter->SetMapMode( aMapMode );
832*cdf0e10cSrcweir     int nPages = getPageCount();
833*cdf0e10cSrcweir     mpImplData->mpPrinter->Pop();
834*cdf0e10cSrcweir     return nPages;
835*cdf0e10cSrcweir }
836*cdf0e10cSrcweir 
837*cdf0e10cSrcweir Sequence< beans::PropertyValue > PrinterController::getPageParametersProtected( int i_nPage ) const
838*cdf0e10cSrcweir {
839*cdf0e10cSrcweir     const MapMode aMapMode( MAP_100TH_MM );
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir     mpImplData->mpPrinter->Push();
842*cdf0e10cSrcweir     mpImplData->mpPrinter->SetMapMode( aMapMode );
843*cdf0e10cSrcweir     Sequence< beans::PropertyValue > aResult( getPageParameters( i_nPage ) );
844*cdf0e10cSrcweir     mpImplData->mpPrinter->Pop();
845*cdf0e10cSrcweir     return aResult;
846*cdf0e10cSrcweir }
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir PrinterController::PageSize PrinterController::getPageFile( int i_nUnfilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache )
849*cdf0e10cSrcweir {
850*cdf0e10cSrcweir     // update progress if necessary
851*cdf0e10cSrcweir     if( mpImplData->mpProgress )
852*cdf0e10cSrcweir     {
853*cdf0e10cSrcweir         // do nothing if printing is canceled
854*cdf0e10cSrcweir         if( mpImplData->mpProgress->isCanceled() )
855*cdf0e10cSrcweir             return PrinterController::PageSize();
856*cdf0e10cSrcweir         mpImplData->mpProgress->tick();
857*cdf0e10cSrcweir         Application::Reschedule( true );
858*cdf0e10cSrcweir     }
859*cdf0e10cSrcweir 
860*cdf0e10cSrcweir     if( i_bMayUseCache )
861*cdf0e10cSrcweir     {
862*cdf0e10cSrcweir         PrinterController::PageSize aPageSize;
863*cdf0e10cSrcweir         if( mpImplData->maPageCache.get( i_nUnfilteredPage, o_rMtf, aPageSize ) )
864*cdf0e10cSrcweir         {
865*cdf0e10cSrcweir             return aPageSize;
866*cdf0e10cSrcweir         }
867*cdf0e10cSrcweir     }
868*cdf0e10cSrcweir     else
869*cdf0e10cSrcweir         mpImplData->maPageCache.invalidate();
870*cdf0e10cSrcweir 
871*cdf0e10cSrcweir     o_rMtf.Clear();
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir     // get page parameters
874*cdf0e10cSrcweir     Sequence< PropertyValue > aPageParm( getPageParametersProtected( i_nUnfilteredPage ) );
875*cdf0e10cSrcweir     const MapMode aMapMode( MAP_100TH_MM );
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir     mpImplData->mpPrinter->Push();
878*cdf0e10cSrcweir     mpImplData->mpPrinter->SetMapMode( aMapMode );
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir     // modify job setup if necessary
881*cdf0e10cSrcweir     PrinterController::PageSize aPageSize = mpImplData->modifyJobSetup( aPageParm, true );
882*cdf0e10cSrcweir 
883*cdf0e10cSrcweir     o_rMtf.SetPrefSize( aPageSize.aSize );
884*cdf0e10cSrcweir     o_rMtf.SetPrefMapMode( aMapMode );
885*cdf0e10cSrcweir 
886*cdf0e10cSrcweir     mpImplData->mpPrinter->EnableOutput( sal_False );
887*cdf0e10cSrcweir 
888*cdf0e10cSrcweir     o_rMtf.Record( mpImplData->mpPrinter.get() );
889*cdf0e10cSrcweir 
890*cdf0e10cSrcweir     printPage( i_nUnfilteredPage );
891*cdf0e10cSrcweir 
892*cdf0e10cSrcweir     o_rMtf.Stop();
893*cdf0e10cSrcweir     o_rMtf.WindStart();
894*cdf0e10cSrcweir     mpImplData->mpPrinter->Pop();
895*cdf0e10cSrcweir 
896*cdf0e10cSrcweir     if( i_bMayUseCache )
897*cdf0e10cSrcweir         mpImplData->maPageCache.insert( i_nUnfilteredPage, o_rMtf, aPageSize );
898*cdf0e10cSrcweir 
899*cdf0e10cSrcweir     // reset "FirstPage" property to false now we've gotten at least our first one
900*cdf0e10cSrcweir     mpImplData->mbFirstPage = sal_False;
901*cdf0e10cSrcweir 
902*cdf0e10cSrcweir     return aPageSize;
903*cdf0e10cSrcweir }
904*cdf0e10cSrcweir 
905*cdf0e10cSrcweir static void appendSubPage( GDIMetaFile& o_rMtf, const Rectangle& i_rClipRect, GDIMetaFile& io_rSubPage, bool i_bDrawBorder )
906*cdf0e10cSrcweir {
907*cdf0e10cSrcweir     // intersect all clipregion actions with our clip rect
908*cdf0e10cSrcweir     io_rSubPage.WindStart();
909*cdf0e10cSrcweir     io_rSubPage.Clip( i_rClipRect );
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir     // save gstate
912*cdf0e10cSrcweir     o_rMtf.AddAction( new MetaPushAction( PUSH_ALL ) );
913*cdf0e10cSrcweir 
914*cdf0e10cSrcweir     // clip to page rect
915*cdf0e10cSrcweir     o_rMtf.AddAction( new MetaClipRegionAction( Region( i_rClipRect ), sal_True ) );
916*cdf0e10cSrcweir 
917*cdf0e10cSrcweir     // append the subpage
918*cdf0e10cSrcweir     io_rSubPage.WindStart();
919*cdf0e10cSrcweir     io_rSubPage.Play( o_rMtf );
920*cdf0e10cSrcweir 
921*cdf0e10cSrcweir     // restore gstate
922*cdf0e10cSrcweir     o_rMtf.AddAction( new MetaPopAction() );
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir     // draw a border
925*cdf0e10cSrcweir     if( i_bDrawBorder )
926*cdf0e10cSrcweir     {
927*cdf0e10cSrcweir         // save gstate
928*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_CLIPREGION | PUSH_MAPMODE ) );
929*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaMapModeAction( MapMode( MAP_100TH_MM ) ) );
930*cdf0e10cSrcweir 
931*cdf0e10cSrcweir         Rectangle aBorderRect( i_rClipRect );
932*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaLineColorAction( Color( COL_BLACK ), sal_True ) );
933*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaFillColorAction( Color( COL_TRANSPARENT ), sal_False ) );
934*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaRectAction( aBorderRect ) );
935*cdf0e10cSrcweir 
936*cdf0e10cSrcweir         // restore gstate
937*cdf0e10cSrcweir         o_rMtf.AddAction( new MetaPopAction() );
938*cdf0e10cSrcweir     }
939*cdf0e10cSrcweir }
940*cdf0e10cSrcweir 
941*cdf0e10cSrcweir PrinterController::PageSize PrinterController::getFilteredPageFile( int i_nFilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache )
942*cdf0e10cSrcweir {
943*cdf0e10cSrcweir     const MultiPageSetup& rMPS( mpImplData->maMultiPage );
944*cdf0e10cSrcweir     int nSubPages = rMPS.nRows * rMPS.nColumns;
945*cdf0e10cSrcweir     if( nSubPages < 1 )
946*cdf0e10cSrcweir         nSubPages = 1;
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir     // reverse sheet order
949*cdf0e10cSrcweir     if( mpImplData->mbReversePageOrder )
950*cdf0e10cSrcweir     {
951*cdf0e10cSrcweir         int nDocPages = getFilteredPageCount();
952*cdf0e10cSrcweir         i_nFilteredPage = nDocPages - 1 - i_nFilteredPage;
953*cdf0e10cSrcweir     }
954*cdf0e10cSrcweir 
955*cdf0e10cSrcweir     // there is no filtering to be done (and possibly the page size of the
956*cdf0e10cSrcweir     // original page is to be set), when N-Up is "neutral" that is there is
957*cdf0e10cSrcweir     // only one subpage and the margins are 0
958*cdf0e10cSrcweir     if( nSubPages == 1 &&
959*cdf0e10cSrcweir         rMPS.nLeftMargin == 0 && rMPS.nRightMargin == 0 &&
960*cdf0e10cSrcweir         rMPS.nTopMargin == 0 && rMPS.nBottomMargin == 0 )
961*cdf0e10cSrcweir     {
962*cdf0e10cSrcweir         PrinterController::PageSize aPageSize = getPageFile( i_nFilteredPage, o_rMtf, i_bMayUseCache );
963*cdf0e10cSrcweir         Size aPaperSize = mpImplData->getRealPaperSize( aPageSize.aSize, true );
964*cdf0e10cSrcweir         mpImplData->mpPrinter->SetMapMode( MapMode( MAP_100TH_MM ) );
965*cdf0e10cSrcweir         mpImplData->mpPrinter->SetPaperSizeUser( aPaperSize, ! mpImplData->isFixedPageSize() );
966*cdf0e10cSrcweir         if( aPaperSize != aPageSize.aSize )
967*cdf0e10cSrcweir         {
968*cdf0e10cSrcweir             // user overridden page size, center Metafile
969*cdf0e10cSrcweir             o_rMtf.WindStart();
970*cdf0e10cSrcweir             long nDX = (aPaperSize.Width() - aPageSize.aSize.Width()) / 2;
971*cdf0e10cSrcweir             long nDY = (aPaperSize.Height() - aPageSize.aSize.Height()) / 2;
972*cdf0e10cSrcweir             o_rMtf.Move( nDX, nDY, mpImplData->mpPrinter->ImplGetDPIX(), mpImplData->mpPrinter->ImplGetDPIY() );
973*cdf0e10cSrcweir             o_rMtf.WindStart();
974*cdf0e10cSrcweir             o_rMtf.SetPrefSize( aPaperSize );
975*cdf0e10cSrcweir             aPageSize.aSize = aPaperSize;
976*cdf0e10cSrcweir         }
977*cdf0e10cSrcweir         return aPageSize;
978*cdf0e10cSrcweir     }
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir     // set last page property really only on the very last page to be rendered
981*cdf0e10cSrcweir     // that is on the last subpage of a NUp run
982*cdf0e10cSrcweir     sal_Bool bIsLastPage = mpImplData->mbLastPage;
983*cdf0e10cSrcweir     mpImplData->mbLastPage = sal_False;
984*cdf0e10cSrcweir 
985*cdf0e10cSrcweir     Size aPaperSize( mpImplData->getRealPaperSize( mpImplData->maMultiPage.aPaperSize, false ) );
986*cdf0e10cSrcweir 
987*cdf0e10cSrcweir     // multi page area: page size minus margins + one time spacing right and down
988*cdf0e10cSrcweir     // the added spacing is so each subpage can be calculated including its spacing
989*cdf0e10cSrcweir     Size aMPArea( aPaperSize );
990*cdf0e10cSrcweir     aMPArea.Width()  -= rMPS.nLeftMargin + rMPS.nRightMargin;
991*cdf0e10cSrcweir     aMPArea.Width()  += rMPS.nHorizontalSpacing;
992*cdf0e10cSrcweir     aMPArea.Height() -= rMPS.nTopMargin + rMPS.nBottomMargin;
993*cdf0e10cSrcweir     aMPArea.Height() += rMPS.nVerticalSpacing;
994*cdf0e10cSrcweir 
995*cdf0e10cSrcweir     // determine offsets
996*cdf0e10cSrcweir     long nAdvX = aMPArea.Width() / rMPS.nColumns;
997*cdf0e10cSrcweir     long nAdvY = aMPArea.Height() / rMPS.nRows;
998*cdf0e10cSrcweir 
999*cdf0e10cSrcweir     // determine size of a "cell" subpage, leave a little space around pages
1000*cdf0e10cSrcweir     Size aSubPageSize( nAdvX - rMPS.nHorizontalSpacing, nAdvY - rMPS.nVerticalSpacing );
1001*cdf0e10cSrcweir 
1002*cdf0e10cSrcweir     o_rMtf.Clear();
1003*cdf0e10cSrcweir     o_rMtf.SetPrefSize( aPaperSize );
1004*cdf0e10cSrcweir     o_rMtf.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
1005*cdf0e10cSrcweir     o_rMtf.AddAction( new MetaMapModeAction( MapMode( MAP_100TH_MM ) ) );
1006*cdf0e10cSrcweir 
1007*cdf0e10cSrcweir     int nDocPages = getPageCountProtected();
1008*cdf0e10cSrcweir     for( int nSubPage = 0; nSubPage < nSubPages; nSubPage++ )
1009*cdf0e10cSrcweir     {
1010*cdf0e10cSrcweir         // map current sub page to real page
1011*cdf0e10cSrcweir         int nPage = (i_nFilteredPage * nSubPages + nSubPage) / rMPS.nRepeat;
1012*cdf0e10cSrcweir         if( nSubPage == nSubPages-1 ||
1013*cdf0e10cSrcweir             nPage == nDocPages-1 )
1014*cdf0e10cSrcweir         {
1015*cdf0e10cSrcweir             mpImplData->mbLastPage = bIsLastPage;
1016*cdf0e10cSrcweir         }
1017*cdf0e10cSrcweir         if( nPage >= 0 && nPage < nDocPages )
1018*cdf0e10cSrcweir         {
1019*cdf0e10cSrcweir             GDIMetaFile aPageFile;
1020*cdf0e10cSrcweir             PrinterController::PageSize aPageSize = getPageFile( nPage, aPageFile, i_bMayUseCache );
1021*cdf0e10cSrcweir             if( aPageSize.aSize.Width() && aPageSize.aSize.Height() )
1022*cdf0e10cSrcweir             {
1023*cdf0e10cSrcweir                 long nCellX = 0, nCellY = 0;
1024*cdf0e10cSrcweir                 switch( rMPS.nOrder )
1025*cdf0e10cSrcweir                 {
1026*cdf0e10cSrcweir                 case PrinterController::LRTB:
1027*cdf0e10cSrcweir                     nCellX = (nSubPage % rMPS.nColumns);
1028*cdf0e10cSrcweir                     nCellY = (nSubPage / rMPS.nColumns);
1029*cdf0e10cSrcweir                     break;
1030*cdf0e10cSrcweir                 case PrinterController::TBLR:
1031*cdf0e10cSrcweir                     nCellX = (nSubPage / rMPS.nRows);
1032*cdf0e10cSrcweir                     nCellY = (nSubPage % rMPS.nRows);
1033*cdf0e10cSrcweir                     break;
1034*cdf0e10cSrcweir                 case PrinterController::RLTB:
1035*cdf0e10cSrcweir                     nCellX = rMPS.nColumns - 1 - (nSubPage % rMPS.nColumns);
1036*cdf0e10cSrcweir                     nCellY = (nSubPage / rMPS.nColumns);
1037*cdf0e10cSrcweir                     break;
1038*cdf0e10cSrcweir                 case PrinterController::TBRL:
1039*cdf0e10cSrcweir                     nCellX = rMPS.nColumns - 1 - (nSubPage / rMPS.nRows);
1040*cdf0e10cSrcweir                     nCellY = (nSubPage % rMPS.nRows);
1041*cdf0e10cSrcweir                     break;
1042*cdf0e10cSrcweir                 }
1043*cdf0e10cSrcweir                 // scale the metafile down to a sub page size
1044*cdf0e10cSrcweir                 double fScaleX = double(aSubPageSize.Width())/double(aPageSize.aSize.Width());
1045*cdf0e10cSrcweir                 double fScaleY = double(aSubPageSize.Height())/double(aPageSize.aSize.Height());
1046*cdf0e10cSrcweir                 double fScale  = std::min( fScaleX, fScaleY );
1047*cdf0e10cSrcweir                 aPageFile.Scale( fScale, fScale );
1048*cdf0e10cSrcweir                 aPageFile.WindStart();
1049*cdf0e10cSrcweir 
1050*cdf0e10cSrcweir                 // move the subpage so it is centered in its "cell"
1051*cdf0e10cSrcweir                 long nOffX = (aSubPageSize.Width() - long(double(aPageSize.aSize.Width()) * fScale)) / 2;
1052*cdf0e10cSrcweir                 long nOffY = (aSubPageSize.Height() - long(double(aPageSize.aSize.Height()) * fScale)) / 2;
1053*cdf0e10cSrcweir                 long nX = rMPS.nLeftMargin + nOffX + nAdvX * nCellX;
1054*cdf0e10cSrcweir                 long nY = rMPS.nTopMargin + nOffY + nAdvY * nCellY;
1055*cdf0e10cSrcweir                 aPageFile.Move( nX, nY, mpImplData->mpPrinter->ImplGetDPIX(), mpImplData->mpPrinter->ImplGetDPIY() );
1056*cdf0e10cSrcweir                 aPageFile.WindStart();
1057*cdf0e10cSrcweir                 // calculate border rectangle
1058*cdf0e10cSrcweir                 Rectangle aSubPageRect( Point( nX, nY ),
1059*cdf0e10cSrcweir                                         Size( long(double(aPageSize.aSize.Width())*fScale),
1060*cdf0e10cSrcweir                                               long(double(aPageSize.aSize.Height())*fScale) ) );
1061*cdf0e10cSrcweir 
1062*cdf0e10cSrcweir                 // append subpage to page
1063*cdf0e10cSrcweir                 appendSubPage( o_rMtf, aSubPageRect, aPageFile, rMPS.bDrawBorder );
1064*cdf0e10cSrcweir             }
1065*cdf0e10cSrcweir         }
1066*cdf0e10cSrcweir     }
1067*cdf0e10cSrcweir     o_rMtf.WindStart();
1068*cdf0e10cSrcweir 
1069*cdf0e10cSrcweir     // subsequent getPageFile calls have changed the paper, reset it to current value
1070*cdf0e10cSrcweir     mpImplData->mpPrinter->SetMapMode( MapMode( MAP_100TH_MM ) );
1071*cdf0e10cSrcweir     mpImplData->mpPrinter->SetPaperSizeUser( aPaperSize, ! mpImplData->isFixedPageSize() );
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir     return PrinterController::PageSize( aPaperSize, true );
1074*cdf0e10cSrcweir }
1075*cdf0e10cSrcweir 
1076*cdf0e10cSrcweir int PrinterController::getFilteredPageCount()
1077*cdf0e10cSrcweir {
1078*cdf0e10cSrcweir     int nDiv = mpImplData->maMultiPage.nRows * mpImplData->maMultiPage.nColumns;
1079*cdf0e10cSrcweir     if( nDiv < 1 )
1080*cdf0e10cSrcweir         nDiv = 1;
1081*cdf0e10cSrcweir     return (getPageCountProtected() * mpImplData->maMultiPage.nRepeat + (nDiv-1)) / nDiv;
1082*cdf0e10cSrcweir }
1083*cdf0e10cSrcweir 
1084*cdf0e10cSrcweir sal_uLong PrinterController::removeTransparencies( GDIMetaFile& i_rIn, GDIMetaFile& o_rOut )
1085*cdf0e10cSrcweir {
1086*cdf0e10cSrcweir     sal_uLong nRestoreDrawMode = mpImplData->mpPrinter->GetDrawMode();
1087*cdf0e10cSrcweir     sal_Int32 nMaxBmpDPIX = mpImplData->mpPrinter->ImplGetDPIX();
1088*cdf0e10cSrcweir     sal_Int32 nMaxBmpDPIY = mpImplData->mpPrinter->ImplGetDPIY();
1089*cdf0e10cSrcweir 
1090*cdf0e10cSrcweir     const PrinterOptions&   rPrinterOptions = mpImplData->mpPrinter->GetPrinterOptions();
1091*cdf0e10cSrcweir 
1092*cdf0e10cSrcweir     static const sal_Int32 OPTIMAL_BMP_RESOLUTION = 300;
1093*cdf0e10cSrcweir     static const sal_Int32 NORMAL_BMP_RESOLUTION  = 200;
1094*cdf0e10cSrcweir 
1095*cdf0e10cSrcweir 
1096*cdf0e10cSrcweir     if( rPrinterOptions.IsReduceBitmaps() )
1097*cdf0e10cSrcweir     {
1098*cdf0e10cSrcweir         // calculate maximum resolution for bitmap graphics
1099*cdf0e10cSrcweir         if( PRINTER_BITMAP_OPTIMAL == rPrinterOptions.GetReducedBitmapMode() )
1100*cdf0e10cSrcweir         {
1101*cdf0e10cSrcweir             nMaxBmpDPIX = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIX );
1102*cdf0e10cSrcweir             nMaxBmpDPIY = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIY );
1103*cdf0e10cSrcweir         }
1104*cdf0e10cSrcweir         else if( PRINTER_BITMAP_NORMAL == rPrinterOptions.GetReducedBitmapMode() )
1105*cdf0e10cSrcweir         {
1106*cdf0e10cSrcweir             nMaxBmpDPIX = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIX );
1107*cdf0e10cSrcweir             nMaxBmpDPIY = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIY );
1108*cdf0e10cSrcweir         }
1109*cdf0e10cSrcweir         else
1110*cdf0e10cSrcweir         {
1111*cdf0e10cSrcweir             nMaxBmpDPIX = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIX );
1112*cdf0e10cSrcweir             nMaxBmpDPIY = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIY );
1113*cdf0e10cSrcweir         }
1114*cdf0e10cSrcweir     }
1115*cdf0e10cSrcweir 
1116*cdf0e10cSrcweir     // convert to greysacles
1117*cdf0e10cSrcweir     if( rPrinterOptions.IsConvertToGreyscales() )
1118*cdf0e10cSrcweir     {
1119*cdf0e10cSrcweir         mpImplData->mpPrinter->SetDrawMode( mpImplData->mpPrinter->GetDrawMode() |
1120*cdf0e10cSrcweir                                             ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT |
1121*cdf0e10cSrcweir                                               DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) );
1122*cdf0e10cSrcweir     }
1123*cdf0e10cSrcweir 
1124*cdf0e10cSrcweir     // disable transparency output
1125*cdf0e10cSrcweir     if( rPrinterOptions.IsReduceTransparency() && ( PRINTER_TRANSPARENCY_NONE == rPrinterOptions.GetReducedTransparencyMode() ) )
1126*cdf0e10cSrcweir     {
1127*cdf0e10cSrcweir         mpImplData->mpPrinter->SetDrawMode( mpImplData->mpPrinter->GetDrawMode() | DRAWMODE_NOTRANSPARENCY );
1128*cdf0e10cSrcweir     }
1129*cdf0e10cSrcweir 
1130*cdf0e10cSrcweir     Color aBg( COL_TRANSPARENT ); // default: let RemoveTransparenciesFromMetaFile do its own background logic
1131*cdf0e10cSrcweir     if( mpImplData->maMultiPage.nRows * mpImplData->maMultiPage.nColumns > 1 )
1132*cdf0e10cSrcweir     {
1133*cdf0e10cSrcweir         // in N-Up printing we have no "page" background operation
1134*cdf0e10cSrcweir         // we also have no way to determine the paper color
1135*cdf0e10cSrcweir         // so let's go for white, which will kill 99.9% of the real cases
1136*cdf0e10cSrcweir         aBg = Color( COL_WHITE );
1137*cdf0e10cSrcweir     }
1138*cdf0e10cSrcweir     mpImplData->mpPrinter->RemoveTransparenciesFromMetaFile( i_rIn, o_rOut, nMaxBmpDPIX, nMaxBmpDPIY,
1139*cdf0e10cSrcweir                                                              rPrinterOptions.IsReduceTransparency(),
1140*cdf0e10cSrcweir                                                              rPrinterOptions.GetReducedTransparencyMode() == PRINTER_TRANSPARENCY_AUTO,
1141*cdf0e10cSrcweir                                                              rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency(),
1142*cdf0e10cSrcweir                                                              aBg
1143*cdf0e10cSrcweir                                                              );
1144*cdf0e10cSrcweir     return nRestoreDrawMode;
1145*cdf0e10cSrcweir }
1146*cdf0e10cSrcweir 
1147*cdf0e10cSrcweir void PrinterController::printFilteredPage( int i_nPage )
1148*cdf0e10cSrcweir {
1149*cdf0e10cSrcweir     if( mpImplData->meJobState != view::PrintableState_JOB_STARTED )
1150*cdf0e10cSrcweir         return;
1151*cdf0e10cSrcweir 
1152*cdf0e10cSrcweir     GDIMetaFile aPageFile;
1153*cdf0e10cSrcweir     PrinterController::PageSize aPageSize = getFilteredPageFile( i_nPage, aPageFile );
1154*cdf0e10cSrcweir 
1155*cdf0e10cSrcweir     if( mpImplData->mpProgress )
1156*cdf0e10cSrcweir     {
1157*cdf0e10cSrcweir         // do nothing if printing is canceled
1158*cdf0e10cSrcweir         if( mpImplData->mpProgress->isCanceled() )
1159*cdf0e10cSrcweir         {
1160*cdf0e10cSrcweir             setJobState( view::PrintableState_JOB_ABORTED );
1161*cdf0e10cSrcweir             return;
1162*cdf0e10cSrcweir         }
1163*cdf0e10cSrcweir     }
1164*cdf0e10cSrcweir 
1165*cdf0e10cSrcweir     // in N-Up printing set the correct page size
1166*cdf0e10cSrcweir     mpImplData->mpPrinter->SetMapMode( MAP_100TH_MM );
1167*cdf0e10cSrcweir 	// aPageSize was filtered through mpImplData->getRealPaperSize already by getFilteredPageFile()
1168*cdf0e10cSrcweir     mpImplData->mpPrinter->SetPaperSizeUser( aPageSize.aSize, ! mpImplData->isFixedPageSize() );
1169*cdf0e10cSrcweir     if( mpImplData->mnFixedPaperBin != -1 &&
1170*cdf0e10cSrcweir         mpImplData->mpPrinter->GetPaperBin() != mpImplData->mnFixedPaperBin )
1171*cdf0e10cSrcweir     {
1172*cdf0e10cSrcweir         mpImplData->mpPrinter->SetPaperBin( mpImplData->mnFixedPaperBin );
1173*cdf0e10cSrcweir     }
1174*cdf0e10cSrcweir 
1175*cdf0e10cSrcweir     // if full paper is meant to be used, move the output to accomodate for pageoffset
1176*cdf0e10cSrcweir     if( aPageSize.bFullPaper )
1177*cdf0e10cSrcweir     {
1178*cdf0e10cSrcweir         Point aPageOffset( mpImplData->mpPrinter->GetPageOffset() );
1179*cdf0e10cSrcweir         aPageFile.WindStart();
1180*cdf0e10cSrcweir         aPageFile.Move( -aPageOffset.X(), -aPageOffset.Y(), mpImplData->mpPrinter->ImplGetDPIX(), mpImplData->mpPrinter->ImplGetDPIY() );
1181*cdf0e10cSrcweir     }
1182*cdf0e10cSrcweir 
1183*cdf0e10cSrcweir     GDIMetaFile aCleanedFile;
1184*cdf0e10cSrcweir     sal_uLong nRestoreDrawMode = removeTransparencies( aPageFile, aCleanedFile );
1185*cdf0e10cSrcweir 
1186*cdf0e10cSrcweir     mpImplData->mpPrinter->EnableOutput( sal_True );
1187*cdf0e10cSrcweir 
1188*cdf0e10cSrcweir     // actually print the page
1189*cdf0e10cSrcweir     mpImplData->mpPrinter->ImplStartPage();
1190*cdf0e10cSrcweir 
1191*cdf0e10cSrcweir     mpImplData->mpPrinter->Push();
1192*cdf0e10cSrcweir     aCleanedFile.WindStart();
1193*cdf0e10cSrcweir     aCleanedFile.Play( mpImplData->mpPrinter.get() );
1194*cdf0e10cSrcweir     mpImplData->mpPrinter->Pop();
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir     mpImplData->mpPrinter->ImplEndPage();
1197*cdf0e10cSrcweir 
1198*cdf0e10cSrcweir     mpImplData->mpPrinter->SetDrawMode( nRestoreDrawMode );
1199*cdf0e10cSrcweir }
1200*cdf0e10cSrcweir 
1201*cdf0e10cSrcweir void PrinterController::jobStarted()
1202*cdf0e10cSrcweir {
1203*cdf0e10cSrcweir }
1204*cdf0e10cSrcweir 
1205*cdf0e10cSrcweir void PrinterController::jobFinished( view::PrintableState )
1206*cdf0e10cSrcweir {
1207*cdf0e10cSrcweir }
1208*cdf0e10cSrcweir 
1209*cdf0e10cSrcweir void PrinterController::abortJob()
1210*cdf0e10cSrcweir {
1211*cdf0e10cSrcweir     setJobState( view::PrintableState_JOB_ABORTED );
1212*cdf0e10cSrcweir     // applications (well, sw) depend on a page request with "IsLastPage" = true
1213*cdf0e10cSrcweir     // to free resources, else they (well, sw) will crash eventually
1214*cdf0e10cSrcweir     setLastPage( sal_True );
1215*cdf0e10cSrcweir     delete mpImplData->mpProgress;
1216*cdf0e10cSrcweir     mpImplData->mpProgress = NULL;
1217*cdf0e10cSrcweir     GDIMetaFile aMtf;
1218*cdf0e10cSrcweir     getPageFile( 0, aMtf, false );
1219*cdf0e10cSrcweir }
1220*cdf0e10cSrcweir 
1221*cdf0e10cSrcweir void PrinterController::setLastPage( sal_Bool i_bLastPage )
1222*cdf0e10cSrcweir {
1223*cdf0e10cSrcweir     mpImplData->mbLastPage = i_bLastPage;
1224*cdf0e10cSrcweir }
1225*cdf0e10cSrcweir 
1226*cdf0e10cSrcweir void PrinterController::setReversePrint( sal_Bool i_bReverse )
1227*cdf0e10cSrcweir {
1228*cdf0e10cSrcweir     mpImplData->mbReversePageOrder = i_bReverse;
1229*cdf0e10cSrcweir }
1230*cdf0e10cSrcweir 
1231*cdf0e10cSrcweir bool PrinterController::getReversePrint() const
1232*cdf0e10cSrcweir {
1233*cdf0e10cSrcweir     return mpImplData->mbReversePageOrder;
1234*cdf0e10cSrcweir }
1235*cdf0e10cSrcweir 
1236*cdf0e10cSrcweir Sequence< PropertyValue > PrinterController::getJobProperties( const Sequence< PropertyValue >& i_rMergeList ) const
1237*cdf0e10cSrcweir {
1238*cdf0e10cSrcweir     std::hash_set< rtl::OUString, rtl::OUStringHash > aMergeSet;
1239*cdf0e10cSrcweir     size_t nResultLen = size_t(i_rMergeList.getLength()) + mpImplData->maUIProperties.size() + 3;
1240*cdf0e10cSrcweir     for( int i = 0; i < i_rMergeList.getLength(); i++ )
1241*cdf0e10cSrcweir         aMergeSet.insert( i_rMergeList[i].Name );
1242*cdf0e10cSrcweir 
1243*cdf0e10cSrcweir     Sequence< PropertyValue > aResult( nResultLen );
1244*cdf0e10cSrcweir     for( int i = 0; i < i_rMergeList.getLength(); i++ )
1245*cdf0e10cSrcweir         aResult[i] = i_rMergeList[i];
1246*cdf0e10cSrcweir     int nCur = i_rMergeList.getLength();
1247*cdf0e10cSrcweir     for( size_t i = 0; i < mpImplData->maUIProperties.size(); i++ )
1248*cdf0e10cSrcweir     {
1249*cdf0e10cSrcweir         if( aMergeSet.find( mpImplData->maUIProperties[i].Name ) == aMergeSet.end() )
1250*cdf0e10cSrcweir             aResult[nCur++] = mpImplData->maUIProperties[i];
1251*cdf0e10cSrcweir     }
1252*cdf0e10cSrcweir     // append IsFirstPage
1253*cdf0e10cSrcweir     if( aMergeSet.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFirstPage" ) ) ) == aMergeSet.end() )
1254*cdf0e10cSrcweir     {
1255*cdf0e10cSrcweir         PropertyValue aVal;
1256*cdf0e10cSrcweir         aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFirstPage" ) );
1257*cdf0e10cSrcweir         aVal.Value <<= mpImplData->mbFirstPage;
1258*cdf0e10cSrcweir         aResult[nCur++] = aVal;
1259*cdf0e10cSrcweir     }
1260*cdf0e10cSrcweir     // append IsLastPage
1261*cdf0e10cSrcweir     if( aMergeSet.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsLastPage" ) ) ) == aMergeSet.end() )
1262*cdf0e10cSrcweir     {
1263*cdf0e10cSrcweir         PropertyValue aVal;
1264*cdf0e10cSrcweir         aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsLastPage" ) );
1265*cdf0e10cSrcweir         aVal.Value <<= mpImplData->mbLastPage;
1266*cdf0e10cSrcweir         aResult[nCur++] = aVal;
1267*cdf0e10cSrcweir     }
1268*cdf0e10cSrcweir     // append IsPrinter
1269*cdf0e10cSrcweir     if( aMergeSet.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) ) ) == aMergeSet.end() )
1270*cdf0e10cSrcweir     {
1271*cdf0e10cSrcweir         PropertyValue aVal;
1272*cdf0e10cSrcweir         aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) );
1273*cdf0e10cSrcweir         aVal.Value <<= sal_True;
1274*cdf0e10cSrcweir         aResult[nCur++] = aVal;
1275*cdf0e10cSrcweir     }
1276*cdf0e10cSrcweir     aResult.realloc( nCur );
1277*cdf0e10cSrcweir     return aResult;
1278*cdf0e10cSrcweir }
1279*cdf0e10cSrcweir 
1280*cdf0e10cSrcweir const Sequence< beans::PropertyValue >& PrinterController::getUIOptions() const
1281*cdf0e10cSrcweir {
1282*cdf0e10cSrcweir     return mpImplData->maUIOptions;
1283*cdf0e10cSrcweir }
1284*cdf0e10cSrcweir 
1285*cdf0e10cSrcweir beans::PropertyValue* PrinterController::getValue( const rtl::OUString& i_rProperty )
1286*cdf0e10cSrcweir {
1287*cdf0e10cSrcweir     std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it =
1288*cdf0e10cSrcweir         mpImplData->maPropertyToIndex.find( i_rProperty );
1289*cdf0e10cSrcweir     return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : NULL;
1290*cdf0e10cSrcweir }
1291*cdf0e10cSrcweir 
1292*cdf0e10cSrcweir const beans::PropertyValue* PrinterController::getValue( const rtl::OUString& i_rProperty ) const
1293*cdf0e10cSrcweir {
1294*cdf0e10cSrcweir     std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it =
1295*cdf0e10cSrcweir         mpImplData->maPropertyToIndex.find( i_rProperty );
1296*cdf0e10cSrcweir     return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : NULL;
1297*cdf0e10cSrcweir }
1298*cdf0e10cSrcweir 
1299*cdf0e10cSrcweir Sequence< beans::PropertyValue > PrinterController::getValues( const Sequence< rtl::OUString >& i_rNames ) const
1300*cdf0e10cSrcweir {
1301*cdf0e10cSrcweir     Sequence< beans::PropertyValue > aRet( i_rNames.getLength() );
1302*cdf0e10cSrcweir     sal_Int32 nFound = 0;
1303*cdf0e10cSrcweir     for( sal_Int32 i = 0; i < i_rNames.getLength(); i++ )
1304*cdf0e10cSrcweir     {
1305*cdf0e10cSrcweir         const beans::PropertyValue* pVal = getValue( i_rNames[i] );
1306*cdf0e10cSrcweir         if( pVal )
1307*cdf0e10cSrcweir             aRet[ nFound++ ] = *pVal;
1308*cdf0e10cSrcweir     }
1309*cdf0e10cSrcweir     aRet.realloc( nFound );
1310*cdf0e10cSrcweir     return aRet;
1311*cdf0e10cSrcweir }
1312*cdf0e10cSrcweir 
1313*cdf0e10cSrcweir void PrinterController::setValue( const rtl::OUString& i_rName, const Any& i_rValue )
1314*cdf0e10cSrcweir {
1315*cdf0e10cSrcweir     beans::PropertyValue aVal;
1316*cdf0e10cSrcweir     aVal.Name = i_rName;
1317*cdf0e10cSrcweir     aVal.Value = i_rValue;
1318*cdf0e10cSrcweir 
1319*cdf0e10cSrcweir     setValue( aVal );
1320*cdf0e10cSrcweir }
1321*cdf0e10cSrcweir 
1322*cdf0e10cSrcweir void PrinterController::setValue( const beans::PropertyValue& i_rValue )
1323*cdf0e10cSrcweir {
1324*cdf0e10cSrcweir     std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it =
1325*cdf0e10cSrcweir         mpImplData->maPropertyToIndex.find( i_rValue.Name );
1326*cdf0e10cSrcweir     if( it != mpImplData->maPropertyToIndex.end() )
1327*cdf0e10cSrcweir         mpImplData->maUIProperties[ it->second ] = i_rValue;
1328*cdf0e10cSrcweir     else
1329*cdf0e10cSrcweir     {
1330*cdf0e10cSrcweir         // insert correct index into property map
1331*cdf0e10cSrcweir         mpImplData->maPropertyToIndex[ i_rValue.Name ] = mpImplData->maUIProperties.size();
1332*cdf0e10cSrcweir         mpImplData->maUIProperties.push_back( i_rValue );
1333*cdf0e10cSrcweir         mpImplData->maUIPropertyEnabled.push_back( true );
1334*cdf0e10cSrcweir     }
1335*cdf0e10cSrcweir }
1336*cdf0e10cSrcweir 
1337*cdf0e10cSrcweir void PrinterController::setUIOptions( const Sequence< beans::PropertyValue >& i_rOptions )
1338*cdf0e10cSrcweir {
1339*cdf0e10cSrcweir     DBG_ASSERT( mpImplData->maUIOptions.getLength() == 0, "setUIOptions called twice !" );
1340*cdf0e10cSrcweir 
1341*cdf0e10cSrcweir     mpImplData->maUIOptions = i_rOptions;
1342*cdf0e10cSrcweir 
1343*cdf0e10cSrcweir     for( int i = 0; i < i_rOptions.getLength(); i++ )
1344*cdf0e10cSrcweir     {
1345*cdf0e10cSrcweir         Sequence< beans::PropertyValue > aOptProp;
1346*cdf0e10cSrcweir         i_rOptions[i].Value >>= aOptProp;
1347*cdf0e10cSrcweir         bool bIsEnabled = true;
1348*cdf0e10cSrcweir         bool bHaveProperty = false;
1349*cdf0e10cSrcweir         rtl::OUString aPropName;
1350*cdf0e10cSrcweir         vcl::ImplPrinterControllerData::ControlDependency aDep;
1351*cdf0e10cSrcweir         Sequence< sal_Bool > aChoicesDisabled;
1352*cdf0e10cSrcweir         for( int n = 0; n < aOptProp.getLength(); n++ )
1353*cdf0e10cSrcweir         {
1354*cdf0e10cSrcweir             const beans::PropertyValue& rEntry( aOptProp[ n ] );
1355*cdf0e10cSrcweir             if( rEntry.Name.equalsAscii( "Property" ) )
1356*cdf0e10cSrcweir             {
1357*cdf0e10cSrcweir                 PropertyValue aVal;
1358*cdf0e10cSrcweir                 rEntry.Value >>= aVal;
1359*cdf0e10cSrcweir                 DBG_ASSERT( mpImplData->maPropertyToIndex.find( aVal.Name )
1360*cdf0e10cSrcweir                             == mpImplData->maPropertyToIndex.end(), "duplicate property entry" );
1361*cdf0e10cSrcweir                 setValue( aVal );
1362*cdf0e10cSrcweir                 aPropName = aVal.Name;
1363*cdf0e10cSrcweir                 bHaveProperty = true;
1364*cdf0e10cSrcweir             }
1365*cdf0e10cSrcweir             else if( rEntry.Name.equalsAscii( "Enabled" ) )
1366*cdf0e10cSrcweir             {
1367*cdf0e10cSrcweir                 sal_Bool bValue = sal_True;
1368*cdf0e10cSrcweir                 rEntry.Value >>= bValue;
1369*cdf0e10cSrcweir                 bIsEnabled = bValue;
1370*cdf0e10cSrcweir             }
1371*cdf0e10cSrcweir             else if( rEntry.Name.equalsAscii( "DependsOnName" ) )
1372*cdf0e10cSrcweir             {
1373*cdf0e10cSrcweir                 rEntry.Value >>= aDep.maDependsOnName;
1374*cdf0e10cSrcweir             }
1375*cdf0e10cSrcweir             else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) )
1376*cdf0e10cSrcweir             {
1377*cdf0e10cSrcweir                 rEntry.Value >>= aDep.mnDependsOnEntry;
1378*cdf0e10cSrcweir             }
1379*cdf0e10cSrcweir             else if( rEntry.Name.equalsAscii( "ChoicesDisabled" ) )
1380*cdf0e10cSrcweir             {
1381*cdf0e10cSrcweir                 rEntry.Value >>= aChoicesDisabled;
1382*cdf0e10cSrcweir             }
1383*cdf0e10cSrcweir         }
1384*cdf0e10cSrcweir         if( bHaveProperty )
1385*cdf0e10cSrcweir         {
1386*cdf0e10cSrcweir             vcl::ImplPrinterControllerData::PropertyToIndexMap::const_iterator it =
1387*cdf0e10cSrcweir                 mpImplData->maPropertyToIndex.find( aPropName );
1388*cdf0e10cSrcweir             // sanity check
1389*cdf0e10cSrcweir             if( it != mpImplData->maPropertyToIndex.end() )
1390*cdf0e10cSrcweir             {
1391*cdf0e10cSrcweir                 mpImplData->maUIPropertyEnabled[ it->second ] = bIsEnabled;
1392*cdf0e10cSrcweir             }
1393*cdf0e10cSrcweir             if( aDep.maDependsOnName.getLength() > 0 )
1394*cdf0e10cSrcweir                 mpImplData->maControlDependencies[ aPropName ] = aDep;
1395*cdf0e10cSrcweir             if( aChoicesDisabled.getLength() > 0 )
1396*cdf0e10cSrcweir                 mpImplData->maChoiceDisableMap[ aPropName ] = aChoicesDisabled;
1397*cdf0e10cSrcweir         }
1398*cdf0e10cSrcweir     }
1399*cdf0e10cSrcweir }
1400*cdf0e10cSrcweir 
1401*cdf0e10cSrcweir void PrinterController::enableUIOption( const rtl::OUString& i_rProperty, bool i_bEnable )
1402*cdf0e10cSrcweir {
1403*cdf0e10cSrcweir     std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it =
1404*cdf0e10cSrcweir         mpImplData->maPropertyToIndex.find( i_rProperty );
1405*cdf0e10cSrcweir     if( it != mpImplData->maPropertyToIndex.end() )
1406*cdf0e10cSrcweir     {
1407*cdf0e10cSrcweir         // call handler only for actual changes
1408*cdf0e10cSrcweir         if( ( mpImplData->maUIPropertyEnabled[ it->second ] && ! i_bEnable ) ||
1409*cdf0e10cSrcweir             ( ! mpImplData->maUIPropertyEnabled[ it->second ] && i_bEnable ) )
1410*cdf0e10cSrcweir         {
1411*cdf0e10cSrcweir             mpImplData->maUIPropertyEnabled[ it->second ] = i_bEnable;
1412*cdf0e10cSrcweir             rtl::OUString aPropName( i_rProperty );
1413*cdf0e10cSrcweir             mpImplData->maOptionChangeHdl.Call( &aPropName );
1414*cdf0e10cSrcweir         }
1415*cdf0e10cSrcweir     }
1416*cdf0e10cSrcweir }
1417*cdf0e10cSrcweir 
1418*cdf0e10cSrcweir bool PrinterController::isUIOptionEnabled( const rtl::OUString& i_rProperty ) const
1419*cdf0e10cSrcweir {
1420*cdf0e10cSrcweir     bool bEnabled = false;
1421*cdf0e10cSrcweir     std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator prop_it =
1422*cdf0e10cSrcweir         mpImplData->maPropertyToIndex.find( i_rProperty );
1423*cdf0e10cSrcweir     if( prop_it != mpImplData->maPropertyToIndex.end() )
1424*cdf0e10cSrcweir     {
1425*cdf0e10cSrcweir         bEnabled = mpImplData->maUIPropertyEnabled[prop_it->second];
1426*cdf0e10cSrcweir 
1427*cdf0e10cSrcweir         if( bEnabled )
1428*cdf0e10cSrcweir         {
1429*cdf0e10cSrcweir             // check control dependencies
1430*cdf0e10cSrcweir             vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
1431*cdf0e10cSrcweir                 mpImplData->maControlDependencies.find( i_rProperty );
1432*cdf0e10cSrcweir             if( it != mpImplData->maControlDependencies.end() )
1433*cdf0e10cSrcweir             {
1434*cdf0e10cSrcweir                 // check if the dependency is enabled
1435*cdf0e10cSrcweir                 // if the dependency is disabled, we are too
1436*cdf0e10cSrcweir                 bEnabled = isUIOptionEnabled( it->second.maDependsOnName );
1437*cdf0e10cSrcweir 
1438*cdf0e10cSrcweir                 if( bEnabled )
1439*cdf0e10cSrcweir                 {
1440*cdf0e10cSrcweir                     // does the dependency have the correct value ?
1441*cdf0e10cSrcweir                     const com::sun::star::beans::PropertyValue* pVal = getValue( it->second.maDependsOnName );
1442*cdf0e10cSrcweir                     OSL_ENSURE( pVal, "unknown property in dependency" );
1443*cdf0e10cSrcweir                     if( pVal )
1444*cdf0e10cSrcweir                     {
1445*cdf0e10cSrcweir                         sal_Int32 nDepVal = 0;
1446*cdf0e10cSrcweir                         sal_Bool bDepVal = sal_False;
1447*cdf0e10cSrcweir                         if( pVal->Value >>= nDepVal )
1448*cdf0e10cSrcweir                         {
1449*cdf0e10cSrcweir                             bEnabled = (nDepVal == it->second.mnDependsOnEntry) || (it->second.mnDependsOnEntry == -1);
1450*cdf0e10cSrcweir                         }
1451*cdf0e10cSrcweir                         else if( pVal->Value >>= bDepVal )
1452*cdf0e10cSrcweir                         {
1453*cdf0e10cSrcweir                             // could be a dependency on a checked boolean
1454*cdf0e10cSrcweir                             // in this case the dependency is on a non zero for checked value
1455*cdf0e10cSrcweir                             bEnabled = (   bDepVal && it->second.mnDependsOnEntry != 0) ||
1456*cdf0e10cSrcweir                                        ( ! bDepVal && it->second.mnDependsOnEntry == 0);
1457*cdf0e10cSrcweir                         }
1458*cdf0e10cSrcweir                         else
1459*cdf0e10cSrcweir                         {
1460*cdf0e10cSrcweir                             // if the type does not match something is awry
1461*cdf0e10cSrcweir                             OSL_ENSURE( 0, "strange type in control dependency" );
1462*cdf0e10cSrcweir                             bEnabled = false;
1463*cdf0e10cSrcweir                         }
1464*cdf0e10cSrcweir                     }
1465*cdf0e10cSrcweir                 }
1466*cdf0e10cSrcweir             }
1467*cdf0e10cSrcweir         }
1468*cdf0e10cSrcweir     }
1469*cdf0e10cSrcweir     return bEnabled;
1470*cdf0e10cSrcweir }
1471*cdf0e10cSrcweir 
1472*cdf0e10cSrcweir bool PrinterController::isUIChoiceEnabled( const rtl::OUString& i_rProperty, sal_Int32 i_nValue ) const
1473*cdf0e10cSrcweir {
1474*cdf0e10cSrcweir     bool bEnabled = true;
1475*cdf0e10cSrcweir     ImplPrinterControllerData::ChoiceDisableMap::const_iterator it =
1476*cdf0e10cSrcweir         mpImplData->maChoiceDisableMap.find( i_rProperty );
1477*cdf0e10cSrcweir     if(it != mpImplData->maChoiceDisableMap.end() )
1478*cdf0e10cSrcweir     {
1479*cdf0e10cSrcweir         const Sequence< sal_Bool >& rDisabled( it->second );
1480*cdf0e10cSrcweir         if( i_nValue >= 0 && i_nValue < rDisabled.getLength() )
1481*cdf0e10cSrcweir             bEnabled = ! rDisabled[i_nValue];
1482*cdf0e10cSrcweir     }
1483*cdf0e10cSrcweir     return bEnabled;
1484*cdf0e10cSrcweir }
1485*cdf0e10cSrcweir 
1486*cdf0e10cSrcweir rtl::OUString PrinterController::getDependency( const rtl::OUString& i_rProperty ) const
1487*cdf0e10cSrcweir {
1488*cdf0e10cSrcweir     rtl::OUString aDependency;
1489*cdf0e10cSrcweir 
1490*cdf0e10cSrcweir     vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
1491*cdf0e10cSrcweir         mpImplData->maControlDependencies.find( i_rProperty );
1492*cdf0e10cSrcweir     if( it != mpImplData->maControlDependencies.end() )
1493*cdf0e10cSrcweir         aDependency = it->second.maDependsOnName;
1494*cdf0e10cSrcweir 
1495*cdf0e10cSrcweir     return aDependency;
1496*cdf0e10cSrcweir }
1497*cdf0e10cSrcweir 
1498*cdf0e10cSrcweir rtl::OUString PrinterController::makeEnabled( const rtl::OUString& i_rProperty )
1499*cdf0e10cSrcweir {
1500*cdf0e10cSrcweir     rtl::OUString aDependency;
1501*cdf0e10cSrcweir 
1502*cdf0e10cSrcweir     vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
1503*cdf0e10cSrcweir         mpImplData->maControlDependencies.find( i_rProperty );
1504*cdf0e10cSrcweir     if( it != mpImplData->maControlDependencies.end() )
1505*cdf0e10cSrcweir     {
1506*cdf0e10cSrcweir         if( isUIOptionEnabled( it->second.maDependsOnName ) )
1507*cdf0e10cSrcweir         {
1508*cdf0e10cSrcweir            aDependency = it->second.maDependsOnName;
1509*cdf0e10cSrcweir            const com::sun::star::beans::PropertyValue* pVal = getValue( aDependency );
1510*cdf0e10cSrcweir            OSL_ENSURE( pVal, "unknown property in dependency" );
1511*cdf0e10cSrcweir            if( pVal )
1512*cdf0e10cSrcweir            {
1513*cdf0e10cSrcweir                sal_Int32 nDepVal = 0;
1514*cdf0e10cSrcweir                sal_Bool bDepVal = sal_False;
1515*cdf0e10cSrcweir                if( pVal->Value >>= nDepVal )
1516*cdf0e10cSrcweir                {
1517*cdf0e10cSrcweir                    if( it->second.mnDependsOnEntry != -1 )
1518*cdf0e10cSrcweir                    {
1519*cdf0e10cSrcweir                        setValue( aDependency, makeAny( sal_Int32( it->second.mnDependsOnEntry ) ) );
1520*cdf0e10cSrcweir                    }
1521*cdf0e10cSrcweir                }
1522*cdf0e10cSrcweir                else if( pVal->Value >>= bDepVal )
1523*cdf0e10cSrcweir                {
1524*cdf0e10cSrcweir                    setValue( aDependency, makeAny( sal_Bool( it->second.mnDependsOnEntry != 0 ) ) );
1525*cdf0e10cSrcweir                }
1526*cdf0e10cSrcweir                else
1527*cdf0e10cSrcweir                {
1528*cdf0e10cSrcweir                    // if the type does not match something is awry
1529*cdf0e10cSrcweir                    OSL_ENSURE( 0, "strange type in control dependency" );
1530*cdf0e10cSrcweir                }
1531*cdf0e10cSrcweir            }
1532*cdf0e10cSrcweir         }
1533*cdf0e10cSrcweir     }
1534*cdf0e10cSrcweir 
1535*cdf0e10cSrcweir     return aDependency;
1536*cdf0e10cSrcweir }
1537*cdf0e10cSrcweir 
1538*cdf0e10cSrcweir void PrinterController::setOptionChangeHdl( const Link& i_rHdl )
1539*cdf0e10cSrcweir {
1540*cdf0e10cSrcweir     mpImplData->maOptionChangeHdl = i_rHdl;
1541*cdf0e10cSrcweir }
1542*cdf0e10cSrcweir 
1543*cdf0e10cSrcweir void PrinterController::createProgressDialog()
1544*cdf0e10cSrcweir {
1545*cdf0e10cSrcweir     if( ! mpImplData->mpProgress )
1546*cdf0e10cSrcweir     {
1547*cdf0e10cSrcweir         sal_Bool bShow = sal_True;
1548*cdf0e10cSrcweir         beans::PropertyValue* pMonitor = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MonitorVisible" ) ) );
1549*cdf0e10cSrcweir         if( pMonitor )
1550*cdf0e10cSrcweir             pMonitor->Value >>= bShow;
1551*cdf0e10cSrcweir         else
1552*cdf0e10cSrcweir         {
1553*cdf0e10cSrcweir             const com::sun::star::beans::PropertyValue* pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsApi" ) ) );
1554*cdf0e10cSrcweir             if( pVal )
1555*cdf0e10cSrcweir             {
1556*cdf0e10cSrcweir                 sal_Bool bApi = sal_False;
1557*cdf0e10cSrcweir                 pVal->Value >>= bApi;
1558*cdf0e10cSrcweir                 bShow = ! bApi;
1559*cdf0e10cSrcweir             }
1560*cdf0e10cSrcweir         }
1561*cdf0e10cSrcweir 
1562*cdf0e10cSrcweir         if( bShow && ! Application::IsHeadlessModeEnabled() )
1563*cdf0e10cSrcweir         {
1564*cdf0e10cSrcweir             mpImplData->mpProgress = new PrintProgressDialog( NULL, getPageCountProtected() );
1565*cdf0e10cSrcweir             mpImplData->mpProgress->Show();
1566*cdf0e10cSrcweir         }
1567*cdf0e10cSrcweir     }
1568*cdf0e10cSrcweir     else
1569*cdf0e10cSrcweir         mpImplData->mpProgress->reset();
1570*cdf0e10cSrcweir }
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir bool PrinterController::isProgressCanceled() const
1573*cdf0e10cSrcweir {
1574*cdf0e10cSrcweir     return mpImplData->mpProgress && mpImplData->mpProgress->isCanceled();
1575*cdf0e10cSrcweir }
1576*cdf0e10cSrcweir 
1577*cdf0e10cSrcweir void PrinterController::setMultipage( const MultiPageSetup& i_rMPS )
1578*cdf0e10cSrcweir {
1579*cdf0e10cSrcweir     mpImplData->maMultiPage = i_rMPS;
1580*cdf0e10cSrcweir }
1581*cdf0e10cSrcweir 
1582*cdf0e10cSrcweir const PrinterController::MultiPageSetup& PrinterController::getMultipage() const
1583*cdf0e10cSrcweir {
1584*cdf0e10cSrcweir     return mpImplData->maMultiPage;
1585*cdf0e10cSrcweir }
1586*cdf0e10cSrcweir 
1587*cdf0e10cSrcweir void PrinterController::pushPropertiesToPrinter()
1588*cdf0e10cSrcweir {
1589*cdf0e10cSrcweir     sal_Int32 nCopyCount = 1;
1590*cdf0e10cSrcweir     // set copycount and collate
1591*cdf0e10cSrcweir     const beans::PropertyValue* pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyCount" ) ) );
1592*cdf0e10cSrcweir     if( pVal )
1593*cdf0e10cSrcweir         pVal->Value >>= nCopyCount;
1594*cdf0e10cSrcweir     sal_Bool bCollate = sal_False;
1595*cdf0e10cSrcweir     pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) );
1596*cdf0e10cSrcweir     if( pVal )
1597*cdf0e10cSrcweir         pVal->Value >>= bCollate;
1598*cdf0e10cSrcweir     mpImplData->mpPrinter->SetCopyCount( static_cast<sal_uInt16>(nCopyCount), bCollate );
1599*cdf0e10cSrcweir 
1600*cdf0e10cSrcweir     // duplex mode
1601*cdf0e10cSrcweir     pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DuplexMode" ) ) );
1602*cdf0e10cSrcweir     if( pVal )
1603*cdf0e10cSrcweir     {
1604*cdf0e10cSrcweir         sal_Int16 nDuplex = view::DuplexMode::UNKNOWN;
1605*cdf0e10cSrcweir         pVal->Value >>= nDuplex;
1606*cdf0e10cSrcweir         switch( nDuplex )
1607*cdf0e10cSrcweir         {
1608*cdf0e10cSrcweir         case view::DuplexMode::OFF: mpImplData->mpPrinter->SetDuplexMode( DUPLEX_OFF ); break;
1609*cdf0e10cSrcweir         case view::DuplexMode::LONGEDGE: mpImplData->mpPrinter->SetDuplexMode( DUPLEX_LONGEDGE ); break;
1610*cdf0e10cSrcweir         case view::DuplexMode::SHORTEDGE: mpImplData->mpPrinter->SetDuplexMode( DUPLEX_SHORTEDGE ); break;
1611*cdf0e10cSrcweir         }
1612*cdf0e10cSrcweir     }
1613*cdf0e10cSrcweir }
1614*cdf0e10cSrcweir 
1615*cdf0e10cSrcweir bool PrinterController::isShowDialogs() const
1616*cdf0e10cSrcweir {
1617*cdf0e10cSrcweir     sal_Bool bApi = getBoolProperty( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsApi" ) ), sal_False );
1618*cdf0e10cSrcweir     return ! bApi && ! Application::IsHeadlessModeEnabled();
1619*cdf0e10cSrcweir }
1620*cdf0e10cSrcweir 
1621*cdf0e10cSrcweir bool PrinterController::isDirectPrint() const
1622*cdf0e10cSrcweir {
1623*cdf0e10cSrcweir     sal_Bool bDirect = getBoolProperty( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDirect" ) ), sal_False );
1624*cdf0e10cSrcweir     return bDirect == sal_True;
1625*cdf0e10cSrcweir }
1626*cdf0e10cSrcweir 
1627*cdf0e10cSrcweir sal_Bool PrinterController::getBoolProperty( const rtl::OUString& i_rProperty, sal_Bool i_bFallback ) const
1628*cdf0e10cSrcweir {
1629*cdf0e10cSrcweir     sal_Bool bRet = i_bFallback;
1630*cdf0e10cSrcweir     const com::sun::star::beans::PropertyValue* pVal = getValue( i_rProperty );
1631*cdf0e10cSrcweir     if( pVal )
1632*cdf0e10cSrcweir         pVal->Value >>= bRet;
1633*cdf0e10cSrcweir     return bRet;
1634*cdf0e10cSrcweir }
1635*cdf0e10cSrcweir 
1636*cdf0e10cSrcweir /*
1637*cdf0e10cSrcweir  * PrinterOptionsHelper
1638*cdf0e10cSrcweir **/
1639*cdf0e10cSrcweir Any PrinterOptionsHelper::getValue( const rtl::OUString& i_rPropertyName ) const
1640*cdf0e10cSrcweir {
1641*cdf0e10cSrcweir     Any aRet;
1642*cdf0e10cSrcweir     std::hash_map< rtl::OUString, Any, rtl::OUStringHash >::const_iterator it =
1643*cdf0e10cSrcweir         m_aPropertyMap.find( i_rPropertyName );
1644*cdf0e10cSrcweir     if( it != m_aPropertyMap.end() )
1645*cdf0e10cSrcweir         aRet = it->second;
1646*cdf0e10cSrcweir     return aRet;
1647*cdf0e10cSrcweir }
1648*cdf0e10cSrcweir 
1649*cdf0e10cSrcweir void PrinterOptionsHelper::setValue( const rtl::OUString& i_rPropertyName, const Any& i_rValue )
1650*cdf0e10cSrcweir {
1651*cdf0e10cSrcweir     m_aPropertyMap[ i_rPropertyName ] = i_rValue;
1652*cdf0e10cSrcweir }
1653*cdf0e10cSrcweir 
1654*cdf0e10cSrcweir bool PrinterOptionsHelper::hasProperty( const rtl::OUString& i_rPropertyName ) const
1655*cdf0e10cSrcweir {
1656*cdf0e10cSrcweir     Any aRet;
1657*cdf0e10cSrcweir     std::hash_map< rtl::OUString, Any, rtl::OUStringHash >::const_iterator it =
1658*cdf0e10cSrcweir         m_aPropertyMap.find( i_rPropertyName );
1659*cdf0e10cSrcweir     return it != m_aPropertyMap.end();
1660*cdf0e10cSrcweir }
1661*cdf0e10cSrcweir 
1662*cdf0e10cSrcweir sal_Bool PrinterOptionsHelper::getBoolValue( const rtl::OUString& i_rPropertyName, sal_Bool i_bDefault ) const
1663*cdf0e10cSrcweir {
1664*cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1665*cdf0e10cSrcweir     Any aVal( getValue( i_rPropertyName ) );
1666*cdf0e10cSrcweir     return (aVal >>= bRet) ? bRet : i_bDefault;
1667*cdf0e10cSrcweir }
1668*cdf0e10cSrcweir 
1669*cdf0e10cSrcweir sal_Int64 PrinterOptionsHelper::getIntValue( const rtl::OUString& i_rPropertyName, sal_Int64 i_nDefault ) const
1670*cdf0e10cSrcweir {
1671*cdf0e10cSrcweir     sal_Int64 nRet = 0;
1672*cdf0e10cSrcweir     Any aVal( getValue( i_rPropertyName ) );
1673*cdf0e10cSrcweir     return (aVal >>= nRet) ? nRet : i_nDefault;
1674*cdf0e10cSrcweir }
1675*cdf0e10cSrcweir 
1676*cdf0e10cSrcweir rtl::OUString PrinterOptionsHelper::getStringValue( const rtl::OUString& i_rPropertyName, const rtl::OUString& i_rDefault ) const
1677*cdf0e10cSrcweir {
1678*cdf0e10cSrcweir     rtl::OUString aRet;
1679*cdf0e10cSrcweir     Any aVal( getValue( i_rPropertyName ) );
1680*cdf0e10cSrcweir     return (aVal >>= aRet) ? aRet : i_rDefault;
1681*cdf0e10cSrcweir }
1682*cdf0e10cSrcweir 
1683*cdf0e10cSrcweir bool PrinterOptionsHelper::processProperties( const Sequence< PropertyValue >& i_rNewProp,
1684*cdf0e10cSrcweir                                               std::set< rtl::OUString >* o_pChangeProp )
1685*cdf0e10cSrcweir {
1686*cdf0e10cSrcweir     bool bChanged = false;
1687*cdf0e10cSrcweir 
1688*cdf0e10cSrcweir     // clear the changed set
1689*cdf0e10cSrcweir     if( o_pChangeProp )
1690*cdf0e10cSrcweir         o_pChangeProp->clear();
1691*cdf0e10cSrcweir 
1692*cdf0e10cSrcweir     sal_Int32 nElements = i_rNewProp.getLength();
1693*cdf0e10cSrcweir     const PropertyValue* pVals = i_rNewProp.getConstArray();
1694*cdf0e10cSrcweir     for( sal_Int32 i = 0; i < nElements; i++ )
1695*cdf0e10cSrcweir     {
1696*cdf0e10cSrcweir         bool bElementChanged = false;
1697*cdf0e10cSrcweir         std::hash_map< rtl::OUString, Any, rtl::OUStringHash >::iterator it =
1698*cdf0e10cSrcweir             m_aPropertyMap.find( pVals[ i ].Name );
1699*cdf0e10cSrcweir         if( it != m_aPropertyMap.end() )
1700*cdf0e10cSrcweir         {
1701*cdf0e10cSrcweir             if( it->second != pVals[ i ].Value )
1702*cdf0e10cSrcweir                 bElementChanged = true;
1703*cdf0e10cSrcweir         }
1704*cdf0e10cSrcweir         else
1705*cdf0e10cSrcweir             bElementChanged = true;
1706*cdf0e10cSrcweir 
1707*cdf0e10cSrcweir         if( bElementChanged )
1708*cdf0e10cSrcweir         {
1709*cdf0e10cSrcweir             if( o_pChangeProp )
1710*cdf0e10cSrcweir                 o_pChangeProp->insert( pVals[ i ].Name );
1711*cdf0e10cSrcweir             m_aPropertyMap[ pVals[i].Name ] = pVals[i].Value;
1712*cdf0e10cSrcweir             bChanged = true;
1713*cdf0e10cSrcweir         }
1714*cdf0e10cSrcweir     }
1715*cdf0e10cSrcweir     return bChanged;
1716*cdf0e10cSrcweir }
1717*cdf0e10cSrcweir 
1718*cdf0e10cSrcweir void PrinterOptionsHelper::appendPrintUIOptions( uno::Sequence< beans::PropertyValue >& io_rProps ) const
1719*cdf0e10cSrcweir {
1720*cdf0e10cSrcweir     if( m_aUIProperties.getLength() > 0 )
1721*cdf0e10cSrcweir     {
1722*cdf0e10cSrcweir         sal_Int32 nIndex = io_rProps.getLength();
1723*cdf0e10cSrcweir         io_rProps.realloc( nIndex+1 );
1724*cdf0e10cSrcweir         PropertyValue aVal;
1725*cdf0e10cSrcweir         aVal.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExtraPrintUIOptions" ) );
1726*cdf0e10cSrcweir         aVal.Value = makeAny( m_aUIProperties );
1727*cdf0e10cSrcweir         io_rProps[ nIndex ] = aVal;
1728*cdf0e10cSrcweir     }
1729*cdf0e10cSrcweir }
1730*cdf0e10cSrcweir 
1731*cdf0e10cSrcweir Any PrinterOptionsHelper::getUIControlOpt( const rtl::OUString& i_rTitle,
1732*cdf0e10cSrcweir                                            const Sequence< rtl::OUString >& i_rHelpIds,
1733*cdf0e10cSrcweir                                            const rtl::OUString& i_rType,
1734*cdf0e10cSrcweir                                            const PropertyValue* i_pVal,
1735*cdf0e10cSrcweir                                            const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1736*cdf0e10cSrcweir                                            )
1737*cdf0e10cSrcweir {
1738*cdf0e10cSrcweir     sal_Int32 nElements =
1739*cdf0e10cSrcweir         1                                                               // ControlType
1740*cdf0e10cSrcweir         + (i_rTitle.getLength() ? 1 : 0)                                // Text
1741*cdf0e10cSrcweir         + (i_rHelpIds.getLength() ? 1 : 0)                              // HelpId
1742*cdf0e10cSrcweir         + (i_pVal ? 1 : 0)                                              // Property
1743*cdf0e10cSrcweir         + i_rControlOptions.maAddProps.getLength()                      // additional props
1744*cdf0e10cSrcweir         + (i_rControlOptions.maGroupHint.getLength() ? 1 : 0)           // grouping
1745*cdf0e10cSrcweir         + (i_rControlOptions.mbInternalOnly ? 1 : 0)                    // internal hint
1746*cdf0e10cSrcweir         + (i_rControlOptions.mbEnabled ? 0 : 1)                         // enabled
1747*cdf0e10cSrcweir         ;
1748*cdf0e10cSrcweir     if( i_rControlOptions.maDependsOnName.getLength() )
1749*cdf0e10cSrcweir     {
1750*cdf0e10cSrcweir         nElements += 1;
1751*cdf0e10cSrcweir         if( i_rControlOptions.mnDependsOnEntry != -1 )
1752*cdf0e10cSrcweir             nElements += 1;
1753*cdf0e10cSrcweir         if( i_rControlOptions.mbAttachToDependency )
1754*cdf0e10cSrcweir             nElements += 1;
1755*cdf0e10cSrcweir     }
1756*cdf0e10cSrcweir 
1757*cdf0e10cSrcweir     Sequence< PropertyValue > aCtrl( nElements );
1758*cdf0e10cSrcweir     sal_Int32 nUsed = 0;
1759*cdf0e10cSrcweir     if( i_rTitle.getLength() )
1760*cdf0e10cSrcweir     {
1761*cdf0e10cSrcweir         aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ) );
1762*cdf0e10cSrcweir         aCtrl[nUsed++].Value = makeAny( i_rTitle );
1763*cdf0e10cSrcweir     }
1764*cdf0e10cSrcweir     if( i_rHelpIds.getLength() )
1765*cdf0e10cSrcweir     {
1766*cdf0e10cSrcweir         aCtrl[nUsed  ].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpId" ) );
1767*cdf0e10cSrcweir         aCtrl[nUsed++].Value = makeAny( i_rHelpIds );
1768*cdf0e10cSrcweir     }
1769*cdf0e10cSrcweir     aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlType" ) );
1770*cdf0e10cSrcweir     aCtrl[nUsed++].Value = makeAny( i_rType );
1771*cdf0e10cSrcweir     if( i_pVal )
1772*cdf0e10cSrcweir     {
1773*cdf0e10cSrcweir         aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Property" ) );
1774*cdf0e10cSrcweir         aCtrl[nUsed++].Value = makeAny( *i_pVal );
1775*cdf0e10cSrcweir     }
1776*cdf0e10cSrcweir     if( i_rControlOptions.maDependsOnName.getLength() )
1777*cdf0e10cSrcweir     {
1778*cdf0e10cSrcweir         aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DependsOnName" ) );
1779*cdf0e10cSrcweir         aCtrl[nUsed++].Value = makeAny( i_rControlOptions.maDependsOnName );
1780*cdf0e10cSrcweir         if( i_rControlOptions.mnDependsOnEntry != -1 )
1781*cdf0e10cSrcweir         {
1782*cdf0e10cSrcweir             aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DependsOnEntry" ) );
1783*cdf0e10cSrcweir             aCtrl[nUsed++].Value = makeAny( i_rControlOptions.mnDependsOnEntry );
1784*cdf0e10cSrcweir         }
1785*cdf0e10cSrcweir         if( i_rControlOptions.mbAttachToDependency )
1786*cdf0e10cSrcweir         {
1787*cdf0e10cSrcweir             aCtrl[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AttachToDependency" ) );
1788*cdf0e10cSrcweir             aCtrl[nUsed++].Value = makeAny( i_rControlOptions.mbAttachToDependency );
1789*cdf0e10cSrcweir         }
1790*cdf0e10cSrcweir     }
1791*cdf0e10cSrcweir     if( i_rControlOptions.maGroupHint.getLength() )
1792*cdf0e10cSrcweir     {
1793*cdf0e10cSrcweir         aCtrl[nUsed  ].Name    = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GroupingHint" ) );
1794*cdf0e10cSrcweir         aCtrl[nUsed++].Value <<= i_rControlOptions.maGroupHint;
1795*cdf0e10cSrcweir     }
1796*cdf0e10cSrcweir     if( i_rControlOptions.mbInternalOnly )
1797*cdf0e10cSrcweir     {
1798*cdf0e10cSrcweir         aCtrl[nUsed  ].Name    = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InternalUIOnly" ) );
1799*cdf0e10cSrcweir         aCtrl[nUsed++].Value <<= sal_True;
1800*cdf0e10cSrcweir     }
1801*cdf0e10cSrcweir     if( ! i_rControlOptions.mbEnabled )
1802*cdf0e10cSrcweir     {
1803*cdf0e10cSrcweir         aCtrl[nUsed  ].Name    = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enabled" ) );
1804*cdf0e10cSrcweir         aCtrl[nUsed++].Value <<= sal_False;
1805*cdf0e10cSrcweir     }
1806*cdf0e10cSrcweir 
1807*cdf0e10cSrcweir     sal_Int32 nAddProps = i_rControlOptions.maAddProps.getLength();
1808*cdf0e10cSrcweir     for( sal_Int32 i = 0; i < nAddProps; i++ )
1809*cdf0e10cSrcweir         aCtrl[ nUsed++ ] = i_rControlOptions.maAddProps[i];
1810*cdf0e10cSrcweir 
1811*cdf0e10cSrcweir     DBG_ASSERT( nUsed == nElements, "nUsed != nElements, probable heap corruption" );
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir     return makeAny( aCtrl );
1814*cdf0e10cSrcweir }
1815*cdf0e10cSrcweir 
1816*cdf0e10cSrcweir Any PrinterOptionsHelper::getGroupControlOpt( const rtl::OUString& i_rTitle, const rtl::OUString& i_rHelpId )
1817*cdf0e10cSrcweir {
1818*cdf0e10cSrcweir     Sequence< rtl::OUString > aHelpId;
1819*cdf0e10cSrcweir     if( i_rHelpId.getLength() > 0 )
1820*cdf0e10cSrcweir     {
1821*cdf0e10cSrcweir         aHelpId.realloc( 1 );
1822*cdf0e10cSrcweir         *aHelpId.getArray() = i_rHelpId;
1823*cdf0e10cSrcweir     }
1824*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle, aHelpId, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Group" ) ) );
1825*cdf0e10cSrcweir }
1826*cdf0e10cSrcweir 
1827*cdf0e10cSrcweir Any PrinterOptionsHelper::getSubgroupControlOpt( const rtl::OUString& i_rTitle,
1828*cdf0e10cSrcweir                                                  const rtl::OUString& i_rHelpId,
1829*cdf0e10cSrcweir                                                  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1830*cdf0e10cSrcweir                                                  )
1831*cdf0e10cSrcweir {
1832*cdf0e10cSrcweir     Sequence< rtl::OUString > aHelpId;
1833*cdf0e10cSrcweir     if( i_rHelpId.getLength() > 0 )
1834*cdf0e10cSrcweir     {
1835*cdf0e10cSrcweir         aHelpId.realloc( 1 );
1836*cdf0e10cSrcweir         *aHelpId.getArray() = i_rHelpId;
1837*cdf0e10cSrcweir     }
1838*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle, aHelpId, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Subgroup" ) ),
1839*cdf0e10cSrcweir                             NULL, i_rControlOptions );
1840*cdf0e10cSrcweir }
1841*cdf0e10cSrcweir 
1842*cdf0e10cSrcweir Any PrinterOptionsHelper::getBoolControlOpt( const rtl::OUString& i_rTitle,
1843*cdf0e10cSrcweir                                              const rtl::OUString& i_rHelpId,
1844*cdf0e10cSrcweir                                              const rtl::OUString& i_rProperty,
1845*cdf0e10cSrcweir                                              sal_Bool i_bValue,
1846*cdf0e10cSrcweir                                              const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1847*cdf0e10cSrcweir                                              )
1848*cdf0e10cSrcweir {
1849*cdf0e10cSrcweir     Sequence< rtl::OUString > aHelpId;
1850*cdf0e10cSrcweir     if( i_rHelpId.getLength() > 0 )
1851*cdf0e10cSrcweir     {
1852*cdf0e10cSrcweir         aHelpId.realloc( 1 );
1853*cdf0e10cSrcweir         *aHelpId.getArray() = i_rHelpId;
1854*cdf0e10cSrcweir     }
1855*cdf0e10cSrcweir     PropertyValue aVal;
1856*cdf0e10cSrcweir     aVal.Name = i_rProperty;
1857*cdf0e10cSrcweir     aVal.Value = makeAny( i_bValue );
1858*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle, aHelpId, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Bool" ) ), &aVal, i_rControlOptions );
1859*cdf0e10cSrcweir }
1860*cdf0e10cSrcweir 
1861*cdf0e10cSrcweir Any PrinterOptionsHelper::getChoiceControlOpt( const rtl::OUString& i_rTitle,
1862*cdf0e10cSrcweir                                                const Sequence< rtl::OUString >& i_rHelpId,
1863*cdf0e10cSrcweir                                                const rtl::OUString& i_rProperty,
1864*cdf0e10cSrcweir                                                const Sequence< rtl::OUString >& i_rChoices,
1865*cdf0e10cSrcweir                                                sal_Int32 i_nValue,
1866*cdf0e10cSrcweir                                                const rtl::OUString& i_rType,
1867*cdf0e10cSrcweir                                                const Sequence< sal_Bool >& i_rDisabledChoices,
1868*cdf0e10cSrcweir                                                const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1869*cdf0e10cSrcweir                                                )
1870*cdf0e10cSrcweir {
1871*cdf0e10cSrcweir     UIControlOptions aOpt( i_rControlOptions );
1872*cdf0e10cSrcweir     sal_Int32 nUsed = aOpt.maAddProps.getLength();
1873*cdf0e10cSrcweir     aOpt.maAddProps.realloc( nUsed + 1 + (i_rDisabledChoices.getLength() ? 1 : 0) );
1874*cdf0e10cSrcweir     aOpt.maAddProps[nUsed].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Choices" ) );
1875*cdf0e10cSrcweir     aOpt.maAddProps[nUsed].Value = makeAny( i_rChoices );
1876*cdf0e10cSrcweir     if( i_rDisabledChoices.getLength() )
1877*cdf0e10cSrcweir     {
1878*cdf0e10cSrcweir         aOpt.maAddProps[nUsed+1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChoicesDisabled" ) );
1879*cdf0e10cSrcweir         aOpt.maAddProps[nUsed+1].Value = makeAny( i_rDisabledChoices );
1880*cdf0e10cSrcweir     }
1881*cdf0e10cSrcweir 
1882*cdf0e10cSrcweir     PropertyValue aVal;
1883*cdf0e10cSrcweir     aVal.Name = i_rProperty;
1884*cdf0e10cSrcweir     aVal.Value = makeAny( i_nValue );
1885*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle, i_rHelpId, i_rType, &aVal, aOpt );
1886*cdf0e10cSrcweir }
1887*cdf0e10cSrcweir 
1888*cdf0e10cSrcweir Any PrinterOptionsHelper::getRangeControlOpt( const rtl::OUString& i_rTitle,
1889*cdf0e10cSrcweir                                               const rtl::OUString& i_rHelpId,
1890*cdf0e10cSrcweir                                               const rtl::OUString& i_rProperty,
1891*cdf0e10cSrcweir                                               sal_Int32 i_nValue,
1892*cdf0e10cSrcweir                                               sal_Int32 i_nMinValue,
1893*cdf0e10cSrcweir                                               sal_Int32 i_nMaxValue,
1894*cdf0e10cSrcweir                                               const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1895*cdf0e10cSrcweir                                             )
1896*cdf0e10cSrcweir {
1897*cdf0e10cSrcweir     UIControlOptions aOpt( i_rControlOptions );
1898*cdf0e10cSrcweir     if( i_nMaxValue >= i_nMinValue )
1899*cdf0e10cSrcweir     {
1900*cdf0e10cSrcweir         sal_Int32 nUsed = aOpt.maAddProps.getLength();
1901*cdf0e10cSrcweir         aOpt.maAddProps.realloc( nUsed + 2 );
1902*cdf0e10cSrcweir         aOpt.maAddProps[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MinValue" ) );
1903*cdf0e10cSrcweir         aOpt.maAddProps[nUsed++].Value = makeAny( i_nMinValue );
1904*cdf0e10cSrcweir         aOpt.maAddProps[nUsed  ].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxValue" ) );
1905*cdf0e10cSrcweir         aOpt.maAddProps[nUsed++].Value = makeAny( i_nMaxValue );
1906*cdf0e10cSrcweir     }
1907*cdf0e10cSrcweir 
1908*cdf0e10cSrcweir     Sequence< rtl::OUString > aHelpId;
1909*cdf0e10cSrcweir     if( i_rHelpId.getLength() > 0 )
1910*cdf0e10cSrcweir     {
1911*cdf0e10cSrcweir         aHelpId.realloc( 1 );
1912*cdf0e10cSrcweir         *aHelpId.getArray() = i_rHelpId;
1913*cdf0e10cSrcweir     }
1914*cdf0e10cSrcweir     PropertyValue aVal;
1915*cdf0e10cSrcweir     aVal.Name = i_rProperty;
1916*cdf0e10cSrcweir     aVal.Value = makeAny( i_nValue );
1917*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle,
1918*cdf0e10cSrcweir                             aHelpId,
1919*cdf0e10cSrcweir                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Range" ) ),
1920*cdf0e10cSrcweir                             &aVal,
1921*cdf0e10cSrcweir                             aOpt
1922*cdf0e10cSrcweir                             );
1923*cdf0e10cSrcweir }
1924*cdf0e10cSrcweir 
1925*cdf0e10cSrcweir Any PrinterOptionsHelper::getEditControlOpt( const rtl::OUString& i_rTitle,
1926*cdf0e10cSrcweir                                              const rtl::OUString& i_rHelpId,
1927*cdf0e10cSrcweir                                              const rtl::OUString& i_rProperty,
1928*cdf0e10cSrcweir                                              const rtl::OUString& i_rValue,
1929*cdf0e10cSrcweir                                              const PrinterOptionsHelper::UIControlOptions& i_rControlOptions
1930*cdf0e10cSrcweir                                            )
1931*cdf0e10cSrcweir {
1932*cdf0e10cSrcweir     Sequence< rtl::OUString > aHelpId;
1933*cdf0e10cSrcweir     if( i_rHelpId.getLength() > 0 )
1934*cdf0e10cSrcweir     {
1935*cdf0e10cSrcweir         aHelpId.realloc( 1 );
1936*cdf0e10cSrcweir         *aHelpId.getArray() = i_rHelpId;
1937*cdf0e10cSrcweir     }
1938*cdf0e10cSrcweir     PropertyValue aVal;
1939*cdf0e10cSrcweir     aVal.Name = i_rProperty;
1940*cdf0e10cSrcweir     aVal.Value = makeAny( i_rValue );
1941*cdf0e10cSrcweir     return getUIControlOpt( i_rTitle,
1942*cdf0e10cSrcweir                             aHelpId,
1943*cdf0e10cSrcweir                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Edit" ) ),
1944*cdf0e10cSrcweir                             &aVal,
1945*cdf0e10cSrcweir                             i_rControlOptions
1946*cdf0e10cSrcweir                             );
1947*cdf0e10cSrcweir }
1948