LCOV - code coverage report
Current view: top level - vcl/source/gdi - print3.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 158 1059 14.9 %
Date: 2015-06-13 12:38:46 Functions: 15 91 16.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11