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