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