LCOV - code coverage report
Current view: top level - vcl/generic/print - genprnpsp.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 104 653 15.9 %
Date: 2014-11-03 Functions: 10 65 15.4 %
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             : /**
      21             :   this file implements the sal printer interface ( SalPrinter, SalInfoPrinter
      22             :   and some printer relevant methods of SalInstance and SalGraphicsData )
      23             : 
      24             :   as aunderlying library the printer features of psprint are used.
      25             : 
      26             :   The query methods of a SalInfoPrinter are implemented by querying psprint
      27             : 
      28             :   The job methods of a SalPrinter are implemented by calling psprint
      29             :   printer job functions.
      30             :  */
      31             : 
      32             : // For spawning PDF and FAX generation
      33             : #if defined( UNX )
      34             : #  include <unistd.h>
      35             : #  include <sys/wait.h>
      36             : #  include <sys/stat.h>
      37             : #endif
      38             : 
      39             : #include "rtl/ustring.hxx"
      40             : 
      41             : #include "vcl/button.hxx"
      42             : #include "vcl/dialog.hxx"
      43             : #include "vcl/edit.hxx"
      44             : #include "vcl/fixed.hxx"
      45             : #include "vcl/svapp.hxx"
      46             : #include "vcl/print.hxx"
      47             : #include "vcl/pdfwriter.hxx"
      48             : #include "vcl/printerinfomanager.hxx"
      49             : #include "vcl/settings.hxx"
      50             : #include "svids.hrc"
      51             : #include "saldatabasic.hxx"
      52             : #include "generic/genprn.h"
      53             : #include "generic/geninst.h"
      54             : #include "generic/genpspgraphics.h"
      55             : 
      56             : #include "jobset.h"
      57             : #include "print.h"
      58             : #include "prtsetup.hxx"
      59             : #include "salptype.hxx"
      60             : 
      61             : #include <com/sun/star/beans/PropertyValue.hpp>
      62             : 
      63             : using namespace psp;
      64             : using namespace com::sun::star;
      65             : 
      66             : /*
      67             :  *  static helpers
      68             :  */
      69           0 : static OUString getPdfDir( const PrinterInfo& rInfo )
      70             : {
      71           0 :     OUString aDir;
      72           0 :     sal_Int32 nIndex = 0;
      73           0 :     while( nIndex != -1 )
      74             :     {
      75           0 :         OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
      76           0 :         if( aToken.startsWith( "pdf=" ) )
      77             :         {
      78           0 :             sal_Int32 nPos = 0;
      79           0 :             aDir = aToken.getToken( 1, '=', nPos );
      80           0 :             if( aDir.isEmpty() && getenv( "HOME" ) )
      81           0 :                 aDir = OUString( getenv( "HOME" ), strlen( getenv( "HOME" ) ), osl_getThreadTextEncoding() );
      82           0 :             break;
      83             :         }
      84           0 :     }
      85           0 :     return aDir;
      86             : }
      87             : 
      88             : namespace
      89             : {
      90           0 :     class QueryString : public ModalDialog
      91             :     {
      92             :     private:
      93             :         OKButton*    m_pOKButton;
      94             :         FixedText*   m_pFixedText;
      95             :         Edit*        m_pEdit;
      96             :         OUString&    m_rReturnValue;
      97             : 
      98             :         DECL_LINK( ClickBtnHdl, Button* );
      99             : 
     100             :     public:
     101             :         // parent window, Query text, initial value
     102             :         QueryString(vcl::Window*, OUString &, OUString &);
     103             :     };
     104             : 
     105             :     /*
     106             :      *  QueryString
     107             :      */
     108           0 :     QueryString::QueryString(vcl::Window* pParent, OUString& rQuery, OUString& rRet)
     109             :         : ModalDialog(pParent, "QueryDialog",
     110             :             "vcl/ui/querydialog.ui" )
     111           0 :         , m_rReturnValue( rRet )
     112             :     {
     113           0 :         get(m_pOKButton, "ok");
     114           0 :         get(m_pFixedText, "label");
     115           0 :         get(m_pEdit, "entry");
     116             : 
     117           0 :         m_pOKButton->SetClickHdl(LINK(this, QueryString, ClickBtnHdl));
     118           0 :         m_pFixedText->SetText(rQuery);
     119           0 :         m_pEdit->SetText(m_rReturnValue);
     120           0 :         SetText(rQuery);
     121           0 :     }
     122             : 
     123           0 :     IMPL_LINK( QueryString, ClickBtnHdl, Button*, pButton )
     124             :     {
     125           0 :         if (pButton == m_pOKButton)
     126             :         {
     127           0 :             m_rReturnValue = m_pEdit->GetText();
     128           0 :             EndDialog( 1 );
     129             :         }
     130             :         else
     131           0 :             EndDialog(0);
     132           0 :         return 0;
     133             :     }
     134             : 
     135           0 :     int QueryFaxNumber(OUString& rNumber)
     136             :     {
     137           0 :         OUString aTmpString(VclResId(SV_PRINT_QUERYFAXNUMBER_TXT));
     138           0 :         QueryString aQuery(NULL, aTmpString, rNumber);
     139           0 :         return aQuery.Execute();
     140             :     }
     141             : }
     142             : 
     143           0 : inline int PtTo10Mu( int nPoints ) { return (int)((((double)nPoints)*35.27777778)+0.5); }
     144             : 
     145           0 : inline int TenMuToPt( int nUnits ) { return (int)((((double)nUnits)/35.27777778)+0.5); }
     146             : 
     147         100 : static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData )
     148             : {
     149         100 :     pJobSetup->meOrientation    = (Orientation)(rData.m_eOrientation == orientation::Landscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT);
     150             : 
     151             :     // copy page size
     152         100 :     OUString aPaper;
     153             :     int width, height;
     154             : 
     155         100 :     rData.m_aContext.getPageSize( aPaper, width, height );
     156         100 :     pJobSetup->mePaperFormat    = PaperInfo::fromPSName(OUStringToOString( aPaper, RTL_TEXTENCODING_ISO_8859_1 ));
     157             : 
     158         100 :     pJobSetup->mnPaperWidth     = 0;
     159         100 :     pJobSetup->mnPaperHeight    = 0;
     160         100 :     if( pJobSetup->mePaperFormat == PAPER_USER )
     161             :     {
     162             :         // transform to 100dth mm
     163           0 :         width               = PtTo10Mu( width );
     164           0 :         height              = PtTo10Mu( height );
     165             : 
     166           0 :         if( rData.m_eOrientation == psp::orientation::Portrait )
     167             :         {
     168           0 :             pJobSetup->mnPaperWidth = width;
     169           0 :             pJobSetup->mnPaperHeight= height;
     170             :         }
     171             :         else
     172             :         {
     173           0 :             pJobSetup->mnPaperWidth = height;
     174           0 :             pJobSetup->mnPaperHeight= width;
     175             :         }
     176             :     }
     177             : 
     178             :     // copy input slot
     179         100 :     const PPDKey* pKey = NULL;
     180         100 :     const PPDValue* pValue = NULL;
     181             : 
     182         100 :     pJobSetup->mnPaperBin = 0;
     183         100 :     if( rData.m_pParser )
     184         100 :         pKey                    = rData.m_pParser->getKey( OUString("InputSlot") );
     185         100 :     if( pKey )
     186           0 :         pValue                  = rData.m_aContext.getValue( pKey );
     187         100 :     if( pKey && pValue )
     188             :     {
     189           0 :         for( pJobSetup->mnPaperBin = 0;
     190           0 :              pValue != pKey->getValue( pJobSetup->mnPaperBin ) &&
     191           0 :                  pJobSetup->mnPaperBin < pKey->countValues();
     192             :              pJobSetup->mnPaperBin++ )
     193             :             ;
     194           0 :         if( pJobSetup->mnPaperBin >= pKey->countValues() )
     195           0 :             pJobSetup->mnPaperBin = 0;
     196             :     }
     197             : 
     198             :     // copy duplex
     199         100 :     pKey = NULL;
     200         100 :     pValue = NULL;
     201             : 
     202         100 :     pJobSetup->meDuplexMode = DUPLEX_UNKNOWN;
     203         100 :     if( rData.m_pParser )
     204         100 :         pKey = rData.m_pParser->getKey( OUString("Duplex") );
     205         100 :     if( pKey )
     206         100 :         pValue = rData.m_aContext.getValue( pKey );
     207         100 :     if( pKey && pValue )
     208             :     {
     209         100 :         if( pValue->m_aOption.equalsIgnoreAsciiCase( "None" ) ||
     210           0 :             pValue->m_aOption.startsWithIgnoreAsciiCase( "Simplex" )
     211             :            )
     212             :         {
     213         100 :             pJobSetup->meDuplexMode = DUPLEX_OFF;
     214             :         }
     215           0 :         else if( pValue->m_aOption.equalsIgnoreAsciiCase( "DuplexNoTumble" ) )
     216             :         {
     217           0 :             pJobSetup->meDuplexMode = DUPLEX_LONGEDGE;
     218             :         }
     219           0 :         else if( pValue->m_aOption.equalsIgnoreAsciiCase( "DuplexTumble" ) )
     220             :         {
     221           0 :             pJobSetup->meDuplexMode = DUPLEX_SHORTEDGE;
     222             :         }
     223             :     }
     224             : 
     225             :     // copy the whole context
     226         100 :     if( pJobSetup->mpDriverData )
     227         100 :         rtl_freeMemory( pJobSetup->mpDriverData );
     228             : 
     229             :     int nBytes;
     230         100 :     void* pBuffer = NULL;
     231         100 :     if( rData.getStreamBuffer( pBuffer, nBytes ) )
     232             :     {
     233         100 :         pJobSetup->mnDriverDataLen = nBytes;
     234         100 :         pJobSetup->mpDriverData = (sal_uInt8*)pBuffer;
     235             :     }
     236             :     else
     237             :     {
     238           0 :         pJobSetup->mnDriverDataLen = 0;
     239           0 :         pJobSetup->mpDriverData = NULL;
     240         100 :     }
     241         100 : }
     242             : 
     243             : // Needs a cleaner abstraction ...
     244             : #if defined( UNX )
     245           0 : static bool passFileToCommandLine( const OUString& rFilename, const OUString& rCommandLine, bool bRemoveFile = true )
     246             : {
     247           0 :     bool bSuccess = false;
     248             : 
     249           0 :     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
     250           0 :     OString aCmdLine(OUStringToOString(rCommandLine, aEncoding));
     251           0 :     OString aFilename(OUStringToOString(rFilename, aEncoding));
     252             : 
     253           0 :     bool bPipe = aCmdLine.indexOf( "(TMP)" ) != -1 ? false : true;
     254             : 
     255             :     // setup command line for exec
     256           0 :     if( ! bPipe )
     257           0 :         aCmdLine = aCmdLine.replaceAll(OString("(TMP)"), aFilename);
     258             : 
     259             : #if OSL_DEBUG_LEVEL > 1
     260             :     fprintf( stderr, "%s commandline: \"%s\"\n",
     261             :              bPipe ? "piping to" : "executing",
     262             :              aCmdLine.getStr() );
     263             :     struct stat aStat;
     264             :     if( stat( aFilename.getStr(), &aStat ) )
     265             :         fprintf( stderr, "stat( %s ) failed\n", aFilename.getStr() );
     266             :     fprintf( stderr, "Tmp file %s has modes: 0%03lo\n", aFilename.getStr(), (long)aStat.st_mode );
     267             : #endif
     268             :     const char* argv[4];
     269           0 :     if( ! ( argv[ 0 ] = getenv( "SHELL" ) ) )
     270           0 :         argv[ 0 ] = "/bin/sh";
     271           0 :     argv[ 1 ] = "-c";
     272           0 :     argv[ 2 ] = aCmdLine.getStr();
     273           0 :     argv[ 3 ] = 0;
     274             : 
     275           0 :     bool bHavePipes = false;
     276             :     int pid, fd[2];
     277             : 
     278           0 :     if( bPipe )
     279           0 :         bHavePipes = pipe( fd ) ? false : true;
     280           0 :     if( ( pid = fork() ) > 0 )
     281             :     {
     282           0 :         if( bPipe && bHavePipes )
     283             :         {
     284           0 :             close( fd[0] );
     285             :             char aBuffer[ 2048 ];
     286           0 :             FILE* fp = fopen( aFilename.getStr(), "r" );
     287           0 :             while (fp && !feof(fp))
     288             :             {
     289           0 :                 size_t nBytesRead = fread(aBuffer, 1, sizeof( aBuffer ), fp);
     290           0 :                 if (nBytesRead )
     291             :                 {
     292           0 :                     size_t nBytesWritten = write(fd[1], aBuffer, nBytesRead);
     293             :                     OSL_ENSURE(nBytesWritten == nBytesRead, "short write");
     294           0 :                     if (nBytesWritten != nBytesRead)
     295           0 :                         break;
     296             :                 }
     297             :             }
     298           0 :             fclose( fp );
     299           0 :             close( fd[ 1 ] );
     300             :         }
     301           0 :         int status = 0;
     302           0 :         if(waitpid( pid, &status, 0 ) != -1)
     303             :         {
     304           0 :             if( ! status )
     305           0 :                 bSuccess = true;
     306             :         }
     307             :     }
     308           0 :     else if( ! pid )
     309             :     {
     310           0 :         if( bPipe && bHavePipes )
     311             :         {
     312           0 :             close( fd[1] );
     313           0 :             if( fd[0] != STDIN_FILENO ) // not probable, but who knows :)
     314           0 :                 dup2( fd[0], STDIN_FILENO );
     315             :         }
     316           0 :         execv( argv[0], const_cast<char**>(argv) );
     317           0 :         fprintf( stderr, "failed to execute \"%s\"\n", aCmdLine.getStr() );
     318           0 :         _exit( 1 );
     319             :     }
     320             :     else
     321           0 :         fprintf( stderr, "failed to fork\n" );
     322             : 
     323             :     // clean up the mess
     324           0 :     if( bRemoveFile )
     325           0 :         unlink( aFilename.getStr() );
     326             : 
     327           0 :     return bSuccess;
     328             : }
     329             : #endif
     330             : 
     331           0 : static std::vector<OUString> getFaxNumbers()
     332             : {
     333           0 :     std::vector<OUString> aFaxNumbers;
     334             : 
     335           0 :     OUString aNewNr;
     336           0 :     if (QueryFaxNumber(aNewNr))
     337             :     {
     338           0 :         sal_Int32 nIndex = 0;
     339           0 :         do
     340             :         {
     341           0 :             OUString sToken = aNewNr.getToken( 0, ';', nIndex );
     342           0 :             aFaxNumbers.push_back(sToken);
     343             :         }
     344           0 :         while (nIndex >= 0);
     345             :     }
     346             : 
     347           0 :     return aFaxNumbers;
     348             : }
     349             : 
     350           0 : static bool createPdf( const OUString& rToFile, const OUString& rFromFile, const OUString& rCommandLine )
     351             : {
     352             : #if defined( UNX )
     353             :     OUString aCommandLine(
     354           0 :         rCommandLine.replaceAll("(OUTFILE)", rToFile));
     355             : 
     356           0 :     return passFileToCommandLine( rFromFile, aCommandLine );
     357             : #else
     358             :     (void)rToFile; (void)rFromFile; (void)rCommandLine;
     359             :     return false;
     360             : #endif
     361             : }
     362             : 
     363             : /*
     364             :  *  SalInstance
     365             :  */
     366             : 
     367           0 : void SalGenericInstance::configurePspInfoPrinter(PspSalInfoPrinter *pPrinter,
     368             :     SalPrinterQueueInfo* pQueueInfo, ImplJobSetup* pJobSetup)
     369             : {
     370           0 :     if( pJobSetup )
     371             :     {
     372           0 :         PrinterInfoManager& rManager( PrinterInfoManager::get() );
     373           0 :         PrinterInfo aInfo( rManager.getPrinterInfo( pQueueInfo->maPrinterName ) );
     374           0 :         pPrinter->m_aJobData = aInfo;
     375           0 :         pPrinter->m_aPrinterGfx.Init( pPrinter->m_aJobData );
     376             : 
     377           0 :         if( pJobSetup->mpDriverData )
     378           0 :             JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo );
     379             : 
     380           0 :         pJobSetup->mnSystem         = JOBSETUP_SYSTEM_UNIX;
     381           0 :         pJobSetup->maPrinterName    = pQueueInfo->maPrinterName;
     382           0 :         pJobSetup->maDriver         = aInfo.m_aDriverName;
     383           0 :         copyJobDataToJobSetup( pJobSetup, aInfo );
     384             :     }
     385           0 : }
     386             : 
     387           0 : SalInfoPrinter* SalGenericInstance::CreateInfoPrinter( SalPrinterQueueInfo*    pQueueInfo,
     388             :                                                    ImplJobSetup*            pJobSetup )
     389             : {
     390           0 :     mbPrinterInit = true;
     391             :     // create and initialize SalInfoPrinter
     392           0 :     PspSalInfoPrinter* pPrinter = new PspSalInfoPrinter();
     393           0 :     configurePspInfoPrinter(pPrinter, pQueueInfo, pJobSetup);
     394           0 :     return pPrinter;
     395             : }
     396             : 
     397           0 : void SalGenericInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
     398             : {
     399           0 :     delete pPrinter;
     400           0 : }
     401             : 
     402           0 : SalPrinter* SalGenericInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
     403             : {
     404           0 :     mbPrinterInit = true;
     405             :     // create and initialize SalPrinter
     406           0 :     PspSalPrinter* pPrinter = new PspSalPrinter( pInfoPrinter );
     407           0 :     pPrinter->m_aJobData = static_cast<PspSalInfoPrinter*>(pInfoPrinter)->m_aJobData;
     408             : 
     409           0 :     return pPrinter;
     410             : }
     411             : 
     412           0 : void SalGenericInstance::DestroyPrinter( SalPrinter* pPrinter )
     413             : {
     414           0 :     delete pPrinter;
     415           0 : }
     416             : 
     417           0 : void SalGenericInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
     418             : {
     419           0 :     mbPrinterInit = true;
     420           0 :     PrinterInfoManager& rManager( PrinterInfoManager::get() );
     421           0 :     static const char* pNoSyncDetection = getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
     422           0 :     if( ! pNoSyncDetection || ! *pNoSyncDetection )
     423             :     {
     424             :         // #i62663# synchronize possible asynchronouse printer detection now
     425           0 :         rManager.checkPrintersChanged( true );
     426             :     }
     427           0 :     ::std::list< OUString > aPrinters;
     428           0 :     rManager.listPrinters( aPrinters );
     429             : 
     430           0 :     for( ::std::list< OUString >::iterator it = aPrinters.begin(); it != aPrinters.end(); ++it )
     431             :     {
     432           0 :         const PrinterInfo& rInfo( rManager.getPrinterInfo( *it ) );
     433             :         // Neuen Eintrag anlegen
     434           0 :         SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
     435           0 :         pInfo->maPrinterName    = *it;
     436           0 :         pInfo->maDriver         = rInfo.m_aDriverName;
     437           0 :         pInfo->maLocation       = rInfo.m_aLocation;
     438           0 :         pInfo->maComment        = rInfo.m_aComment;
     439           0 :         pInfo->mpSysData        = NULL;
     440             : 
     441           0 :         sal_Int32 nIndex = 0;
     442           0 :         while( nIndex != -1 )
     443             :         {
     444           0 :             OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
     445           0 :             if( aToken.match( "pdf=" ) )
     446             :             {
     447           0 :                 pInfo->maLocation = getPdfDir( rInfo );
     448           0 :                 break;
     449             :             }
     450           0 :         }
     451             : 
     452           0 :         pList->Add( pInfo );
     453           0 :     }
     454           0 : }
     455             : 
     456           0 : void SalGenericInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
     457             : {
     458           0 :     delete pInfo;
     459           0 : }
     460             : 
     461           0 : void SalGenericInstance::GetPrinterQueueState( SalPrinterQueueInfo* )
     462             : {
     463           0 :     mbPrinterInit = true;
     464           0 : }
     465             : 
     466           0 : OUString SalGenericInstance::GetDefaultPrinter()
     467             : {
     468           0 :     mbPrinterInit = true;
     469           0 :     PrinterInfoManager& rManager( PrinterInfoManager::get() );
     470           0 :     return rManager.getDefaultPrinter();
     471             : }
     472             : 
     473         680 : PspSalInfoPrinter::PspSalInfoPrinter()
     474         680 :     : m_pGraphics( NULL )
     475             : {
     476         680 : }
     477             : 
     478        1354 : PspSalInfoPrinter::~PspSalInfoPrinter()
     479             : {
     480         677 :     if( m_pGraphics )
     481             :     {
     482           0 :         delete m_pGraphics;
     483           0 :         m_pGraphics = NULL;
     484             :     }
     485         677 : }
     486             : 
     487           0 : void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup* )
     488             : {
     489           0 :     m_aPaperFormats.clear();
     490           0 :     m_bPapersInit = true;
     491             : 
     492           0 :     if( m_aJobData.m_pParser )
     493             :     {
     494           0 :         const PPDKey* pKey = m_aJobData.m_pParser->getKey( OUString("PageSize") );
     495           0 :         if( pKey )
     496             :         {
     497           0 :             int nValues = pKey->countValues();
     498           0 :             for( int i = 0; i < nValues; i++ )
     499             :             {
     500           0 :                 const PPDValue* pValue = pKey->getValue( i );
     501           0 :                 int nWidth = 0, nHeight = 0;
     502           0 :                 m_aJobData.m_pParser->getPaperDimension( pValue->m_aOption, nWidth, nHeight );
     503           0 :                 PaperInfo aInfo(PtTo10Mu( nWidth ), PtTo10Mu( nHeight ));
     504           0 :                 m_aPaperFormats.push_back( aInfo );
     505             :             }
     506             :         }
     507             :     }
     508           0 : }
     509             : 
     510           0 : int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* )
     511             : {
     512           0 :     return 900;
     513             : }
     514             : 
     515         780 : SalGraphics* PspSalInfoPrinter::AcquireGraphics()
     516             : {
     517             :     // return a valid pointer only once
     518             :     // the reasoning behind this is that we could have different
     519             :     // SalGraphics that can run in multiple threads
     520             :     // (future plans)
     521         780 :     SalGraphics* pRet = NULL;
     522         780 :     if( ! m_pGraphics )
     523             :     {
     524         780 :         m_pGraphics = GetGenericInstance()->CreatePrintGraphics();
     525         780 :         m_pGraphics->Init(&m_aJobData, &m_aPrinterGfx, this);
     526         780 :         pRet = m_pGraphics;
     527             :     }
     528         780 :     return pRet;
     529             : }
     530             : 
     531         777 : void PspSalInfoPrinter::ReleaseGraphics( SalGraphics* pGraphics )
     532             : {
     533         777 :     if( pGraphics == m_pGraphics )
     534             :     {
     535         777 :         delete pGraphics;
     536         777 :         m_pGraphics = NULL;
     537             :     }
     538         777 :     return;
     539             : }
     540             : 
     541           0 : bool PspSalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pJobSetup )
     542             : {
     543           0 :     if( ! pFrame || ! pJobSetup )
     544           0 :         return false;
     545             : 
     546           0 :     PrinterInfoManager& rManager = PrinterInfoManager::get();
     547             : 
     548           0 :     PrinterInfo aInfo( rManager.getPrinterInfo( pJobSetup->maPrinterName ) );
     549           0 :     if ( pJobSetup->mpDriverData )
     550             :     {
     551           0 :         SetData( ~0, pJobSetup );
     552           0 :         JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo );
     553             :     }
     554             : 
     555           0 :     if (SetupPrinterDriver(aInfo))
     556             :     {
     557           0 :         aInfo.resolveDefaultBackend();
     558           0 :         rtl_freeMemory( pJobSetup->mpDriverData );
     559           0 :         pJobSetup->mpDriverData = NULL;
     560             : 
     561             :         int nBytes;
     562           0 :         void* pBuffer = NULL;
     563           0 :         aInfo.getStreamBuffer( pBuffer, nBytes );
     564           0 :         pJobSetup->mnDriverDataLen  = nBytes;
     565           0 :         pJobSetup->mpDriverData     = (sal_uInt8*)pBuffer;
     566             : 
     567             :         // copy everything to job setup
     568           0 :         copyJobDataToJobSetup( pJobSetup, aInfo );
     569           0 :         JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData );
     570           0 :         return true;
     571             :     }
     572           0 :     return false;
     573             : }
     574             : 
     575             : // This function gets the driver data and puts it into pJobSetup
     576             : // If pJobSetup->mpDriverData is NOT NULL, then the independent
     577             : // data should be merged into the driver data
     578             : // If pJobSetup->mpDriverData IS NULL, then the driver defaults
     579             : // should be merged into the independent data
     580         100 : bool PspSalInfoPrinter::SetPrinterData( ImplJobSetup* pJobSetup )
     581             : {
     582         100 :     if( pJobSetup->mpDriverData )
     583         100 :         return SetData( ~0, pJobSetup );
     584             : 
     585           0 :     copyJobDataToJobSetup( pJobSetup, m_aJobData );
     586             : 
     587           0 :     return true;
     588             : }
     589             : 
     590             : // This function merges the independ driver data
     591             : // and sets the new independ data in pJobSetup
     592             : // Only the data must be changed, where the bit
     593             : // in nGetDataFlags is set
     594         100 : bool PspSalInfoPrinter::SetData(
     595             :     sal_uLong nSetDataFlags,
     596             :     ImplJobSetup* pJobSetup )
     597             : {
     598         100 :     JobData aData;
     599         100 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     600             : 
     601         100 :     if( aData.m_pParser )
     602             :     {
     603             :         const PPDKey* pKey;
     604             :         const PPDValue* pValue;
     605             : 
     606             :         // merge papersize if necessary
     607         100 :         if( nSetDataFlags & SAL_JOBSET_PAPERSIZE )
     608             :         {
     609         100 :             OUString aPaper;
     610             : 
     611         100 :             if( pJobSetup->mePaperFormat == PAPER_USER )
     612           0 :                 aPaper = aData.m_pParser->matchPaper(
     613             :                     TenMuToPt( pJobSetup->mnPaperWidth ),
     614           0 :                     TenMuToPt( pJobSetup->mnPaperHeight ) );
     615             :             else
     616         100 :                 aPaper = OStringToOUString(PaperInfo::toPSName(pJobSetup->mePaperFormat), RTL_TEXTENCODING_ISO_8859_1);
     617             : 
     618         100 :             pKey = aData.m_pParser->getKey( OUString("PageSize") );
     619         100 :             pValue = pKey ? pKey->getValueCaseInsensitive( aPaper ) : NULL;
     620             : 
     621             :             // some PPD files do not specify the standard paper names (e.g. C5 instead of EnvC5)
     622             :             // try to find the correct paper anyway using the size
     623         100 :             if( pKey && ! pValue && pJobSetup->mePaperFormat != PAPER_USER )
     624             :             {
     625           0 :                 PaperInfo aInfo( pJobSetup->mePaperFormat );
     626           0 :                 aPaper = aData.m_pParser->matchPaper(
     627           0 :                     TenMuToPt( aInfo.getWidth() ),
     628           0 :                     TenMuToPt( aInfo.getHeight() ) );
     629           0 :                 pValue = pKey->getValueCaseInsensitive( aPaper );
     630             :             }
     631             : 
     632         100 :             if( ! ( pKey && pValue && aData.m_aContext.setValue( pKey, pValue, false ) == pValue ) )
     633           0 :                 return false;
     634             :         }
     635             : 
     636             :         // merge paperbin if necessary
     637         100 :         if( nSetDataFlags & SAL_JOBSET_PAPERBIN )
     638             :         {
     639         100 :             pKey = aData.m_pParser->getKey( OUString("InputSlot") );
     640         100 :             if( pKey )
     641             :             {
     642           0 :                 int nPaperBin = pJobSetup->mnPaperBin;
     643           0 :                 if( nPaperBin >= pKey->countValues() )
     644           0 :                     pValue = pKey->getDefaultValue();
     645             :                 else
     646           0 :                     pValue = pKey->getValue( pJobSetup->mnPaperBin );
     647             : 
     648             :                 // may fail due to constraints;
     649             :                 // real paper bin is copied back to jobsetup in that case
     650           0 :                 aData.m_aContext.setValue( pKey, pValue );
     651             :             }
     652             :             // if printer has no InputSlot key simply ignore this setting
     653             :             // (e.g. SGENPRT has no InputSlot)
     654             :         }
     655             : 
     656             :         // merge orientation if necessary
     657         100 :         if( nSetDataFlags & SAL_JOBSET_ORIENTATION )
     658         100 :             aData.m_eOrientation = pJobSetup->meOrientation == ORIENTATION_LANDSCAPE ? orientation::Landscape : orientation::Portrait;
     659             : 
     660             :         // merge duplex if necessary
     661         100 :         if( nSetDataFlags & SAL_JOBSET_DUPLEXMODE )
     662             :         {
     663         100 :             pKey = aData.m_pParser->getKey( OUString("Duplex") );
     664         100 :             if( pKey )
     665             :             {
     666         100 :                 pValue = NULL;
     667         100 :                 switch( pJobSetup->meDuplexMode )
     668             :                 {
     669             :                 case DUPLEX_OFF:
     670         100 :                     pValue = pKey->getValue( OUString("None") );
     671         100 :                     if( pValue == NULL )
     672           0 :                         pValue = pKey->getValue( OUString("SimplexNoTumble") );
     673         100 :                     break;
     674             :                 case DUPLEX_SHORTEDGE:
     675           0 :                     pValue = pKey->getValue( OUString("DuplexTumble") );
     676           0 :                     break;
     677             :                 case DUPLEX_LONGEDGE:
     678           0 :                     pValue = pKey->getValue( OUString("DuplexNoTumble") );
     679           0 :                     break;
     680             :                 case DUPLEX_UNKNOWN:
     681             :                 default:
     682           0 :                     pValue = 0;
     683           0 :                     break;
     684             :                 }
     685         100 :                 if( ! pValue )
     686           0 :                     pValue = pKey->getDefaultValue();
     687         100 :                 aData.m_aContext.setValue( pKey, pValue );
     688             :             }
     689             :         }
     690             : 
     691         100 :         m_aJobData = aData;
     692         100 :         copyJobDataToJobSetup( pJobSetup, aData );
     693         100 :         return true;
     694             :     }
     695             : 
     696           0 :     return false;
     697             : }
     698             : 
     699         780 : void PspSalInfoPrinter::GetPageInfo(
     700             :     const ImplJobSetup* pJobSetup,
     701             :     long& rOutWidth, long& rOutHeight,
     702             :     long& rPageOffX, long& rPageOffY,
     703             :     long& rPageWidth, long& rPageHeight )
     704             : {
     705         780 :     if( ! pJobSetup )
     706         780 :         return;
     707             : 
     708         780 :     JobData aData;
     709         780 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     710             : 
     711             :     // get the selected page size
     712         780 :     if( aData.m_pParser )
     713             :     {
     714             : 
     715         780 :         OUString aPaper;
     716             :         int width, height;
     717         780 :         int left = 0, top = 0, right = 0, bottom = 0;
     718         780 :         int nDPI = aData.m_aContext.getRenderResolution();
     719             : 
     720         780 :         if( aData.m_eOrientation == psp::orientation::Portrait )
     721             :         {
     722         780 :             aData.m_aContext.getPageSize( aPaper, width, height );
     723         780 :             aData.m_pParser->getMargins( aPaper, left, right, top, bottom );
     724             :         }
     725             :         else
     726             :         {
     727           0 :             aData.m_aContext.getPageSize( aPaper, height, width );
     728           0 :             aData.m_pParser->getMargins( aPaper, top, bottom, right, left );
     729             :         }
     730             : 
     731         780 :         rPageWidth  = width * nDPI / 72;
     732         780 :         rPageHeight = height * nDPI / 72;
     733         780 :         rPageOffX   = left * nDPI / 72;
     734         780 :         rPageOffY   = top * nDPI / 72;
     735         780 :         rOutWidth   = ( width  - left - right ) * nDPI / 72;
     736         780 :         rOutHeight  = ( height - top  - bottom ) * nDPI / 72;
     737         780 :     }
     738             : }
     739             : 
     740           0 : sal_uLong PspSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup )
     741             : {
     742           0 :     if( ! pJobSetup )
     743           0 :         return 0;
     744             : 
     745           0 :     JobData aData;
     746           0 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     747             : 
     748           0 :     const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( OUString("InputSlot") ): NULL;
     749           0 :     return pKey ? pKey->countValues() : 0;
     750             : }
     751             : 
     752           0 : OUString PspSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup, sal_uLong nPaperBin )
     753             : {
     754           0 :     JobData aData;
     755           0 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     756             : 
     757           0 :     OUString aRet;
     758           0 :     if( aData.m_pParser )
     759             :     {
     760           0 :         const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( OUString("InputSlot") ): NULL;
     761           0 :         if( ! pKey || nPaperBin >= (sal_uLong)pKey->countValues() )
     762           0 :             aRet = aData.m_pParser->getDefaultInputSlot();
     763             :         else
     764             :         {
     765           0 :             const PPDValue* pValue = pKey->getValue( nPaperBin );
     766           0 :             if( pValue )
     767           0 :                 aRet = aData.m_pParser->translateOption( pKey->getKey(), pValue->m_aOption );
     768             :         }
     769             :     }
     770             : 
     771           0 :     return aRet;
     772             : }
     773             : 
     774           0 : sal_uLong PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, sal_uInt16 nType )
     775             : {
     776           0 :     switch( nType )
     777             :     {
     778             :         case PRINTER_CAPABILITIES_SUPPORTDIALOG:
     779           0 :             return 1;
     780             :         case PRINTER_CAPABILITIES_COPIES:
     781           0 :             return 0xffff;
     782             :         case PRINTER_CAPABILITIES_COLLATECOPIES:
     783             :         {
     784             :             // PPDs don't mention the number of possible collated copies.
     785             :             // so let's guess as many as we want ?
     786           0 :             return 0xffff;
     787             :         }
     788             :         case PRINTER_CAPABILITIES_SETORIENTATION:
     789           0 :             return 1;
     790             :         case PRINTER_CAPABILITIES_SETDUPLEX:
     791           0 :             return 1;
     792             :         case PRINTER_CAPABILITIES_SETPAPERBIN:
     793           0 :             return 1;
     794             :         case PRINTER_CAPABILITIES_SETPAPERSIZE:
     795           0 :             return 1;
     796             :         case PRINTER_CAPABILITIES_SETPAPER:
     797           0 :             return 0;
     798             :         case PRINTER_CAPABILITIES_FAX:
     799             :             {
     800             :                 // see if the PPD contains the fax4CUPS "Dial" option and that it's not set
     801             :                 // to "manually"
     802           0 :                 JobData aData = PrinterInfoManager::get().getPrinterInfo(pJobSetup->maPrinterName);
     803           0 :                 if( pJobSetup->mpDriverData )
     804           0 :                     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     805           0 :                 const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey(OUString("Dial")) : NULL;
     806           0 :                 const PPDValue* pValue = pKey ? aData.m_aContext.getValue(pKey) : NULL;
     807           0 :                 if (pValue && !pValue->m_aOption.equalsIgnoreAsciiCase("Manually"))
     808           0 :                     return 1;
     809           0 :                 return 0;
     810             :             }
     811             : 
     812             :         case PRINTER_CAPABILITIES_PDF:
     813           0 :             if( PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "pdf" ) )
     814           0 :                 return 1;
     815             :             else
     816             :             {
     817             :                 // see if the PPD contains a value to set PDF device
     818           0 :                 JobData aData = PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName );
     819           0 :                 if( pJobSetup->mpDriverData )
     820           0 :                     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     821           0 :                 return aData.m_nPDFDevice > 0 ? 1 : 0;
     822             :             }
     823             :         case PRINTER_CAPABILITIES_EXTERNALDIALOG:
     824           0 :             return PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "external_dialog" ) ? 1 : 0;
     825             :         case PRINTER_CAPABILITIES_USEPULLMODEL:
     826             :         {
     827             :             // see if the PPD contains a value to set PDF device
     828           0 :             JobData aData = PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName );
     829           0 :             if( pJobSetup->mpDriverData )
     830           0 :                 JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
     831           0 :             return aData.m_nPDFDevice > 0 ? 1 : 0;
     832             :         }
     833           0 :         default: break;
     834             :     }
     835           0 :     return 0;
     836             : }
     837             : 
     838             : /*
     839             :  *  SalPrinter
     840             :  */
     841           0 : PspSalPrinter::PspSalPrinter( SalInfoPrinter* pInfoPrinter )
     842             :  : m_bPdf( false ),
     843             :    m_bIsPDFWriterJob( false ),
     844             :    m_pGraphics( NULL ),
     845             :    m_nCopies( 1 ),
     846             :    m_bCollate( false ),
     847           0 :    m_pInfoPrinter( pInfoPrinter )
     848             : {
     849           0 : }
     850             : 
     851           0 : PspSalPrinter::~PspSalPrinter()
     852             : {
     853           0 : }
     854             : 
     855           0 : static OUString getTmpName()
     856             : {
     857           0 :     OUString aTmp, aSys;
     858           0 :     osl_createTempFile( NULL, NULL, &aTmp.pData );
     859           0 :     osl_getSystemPathFromFileURL( aTmp.pData, &aSys.pData );
     860             : 
     861           0 :     return aSys;
     862             : }
     863             : 
     864           0 : bool PspSalPrinter::StartJob(
     865             :     const OUString* pFileName,
     866             :     const OUString& rJobName,
     867             :     const OUString& rAppName,
     868             :     sal_uLong nCopies,
     869             :     bool bCollate,
     870             :     bool bDirect,
     871             :     ImplJobSetup* pJobSetup )
     872             : {
     873             :     OSL_TRACE("PspSalPrinter::StartJob");
     874           0 :     GetSalData()->m_pInstance->jobStartedPrinterUpdate();
     875           0 :     m_bPdf      = false;
     876           0 :     m_aFileName = pFileName ? *pFileName : OUString();
     877           0 :     m_aTmpFile  = OUString();
     878           0 :     m_nCopies   = nCopies;
     879           0 :     m_bCollate  = bCollate;
     880             : 
     881           0 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData );
     882           0 :     if( m_nCopies > 1 )
     883             :     {
     884             :         // in case user did not do anything (m_nCopies=1)
     885             :         // take the default from jobsetup
     886           0 :         m_aJobData.m_nCopies = m_nCopies;
     887           0 :         m_aJobData.setCollate( bCollate );
     888             :     }
     889             : 
     890           0 :     int nMode = 0;
     891             : #if defined( UNX )
     892             :     // check whether this printer is configured as fax
     893           0 :     sal_Int32 nIndex = 0;
     894           0 :     const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
     895           0 :     while( nIndex != -1 )
     896             :     {
     897           0 :         OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
     898           0 :         if( aToken.startsWith( "pdf=" ) )
     899             :         {
     900           0 :             m_bPdf = true;
     901           0 :             m_aTmpFile = getTmpName();
     902           0 :             nMode = S_IRUSR | S_IWUSR;
     903             : 
     904           0 :             if( m_aFileName.isEmpty() )
     905             :             {
     906           0 :                 OUStringBuffer aFileName( getPdfDir( rInfo ) );
     907           0 :                 aFileName.append( '/' );
     908           0 :                 aFileName.append( rJobName );
     909           0 :                 aFileName.appendAscii( ".pdf" );
     910           0 :                 m_aFileName = aFileName.makeStringAndClear();
     911             :             }
     912           0 :             break;
     913             :         }
     914           0 :     }
     915             : #endif
     916           0 :     m_aPrinterGfx.Init( m_aJobData );
     917             : 
     918           0 :     return m_aPrintJob.StartJob( ! m_aTmpFile.isEmpty() ? m_aTmpFile : m_aFileName, nMode, rJobName, rAppName, m_aJobData, &m_aPrinterGfx, bDirect ) ? true : false;
     919             : }
     920             : 
     921           0 : bool PspSalPrinter::EndJob()
     922             : {
     923           0 :     bool bSuccess = false;
     924           0 :     if( m_bIsPDFWriterJob )
     925           0 :         bSuccess = true;
     926             :     else
     927             :     {
     928           0 :         bSuccess = m_aPrintJob.EndJob();
     929             :         OSL_TRACE("PspSalPrinter::EndJob %d", bSuccess);
     930             : 
     931           0 :         if( bSuccess && m_bPdf )
     932             :         {
     933           0 :             const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
     934           0 :             bSuccess = createPdf( m_aFileName, m_aTmpFile, rInfo.m_aCommand );
     935             :         }
     936             :     }
     937           0 :     GetSalData()->m_pInstance->jobEndedPrinterUpdate();
     938           0 :     return bSuccess;
     939             : }
     940             : 
     941           0 : bool PspSalPrinter::AbortJob()
     942             : {
     943           0 :     bool bAbort = m_aPrintJob.AbortJob() ? true : false;
     944           0 :     GetSalData()->m_pInstance->jobEndedPrinterUpdate();
     945           0 :     return bAbort;
     946             : }
     947             : 
     948           0 : SalGraphics* PspSalPrinter::StartPage( ImplJobSetup* pJobSetup, bool )
     949             : {
     950             :     OSL_TRACE("PspSalPrinter::StartPage");
     951             : 
     952           0 :     JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData );
     953           0 :     m_pGraphics = GetGenericInstance()->CreatePrintGraphics();
     954           0 :     m_pGraphics->Init(&m_aJobData, &m_aPrinterGfx, m_pInfoPrinter);
     955             : 
     956           0 :     if( m_nCopies > 1 )
     957             :     {
     958             :         // in case user did not do anything (m_nCopies=1)
     959             :         // take the default from jobsetup
     960           0 :         m_aJobData.m_nCopies = m_nCopies;
     961           0 :         m_aJobData.setCollate( m_nCopies > 1 && m_bCollate );
     962             :     }
     963             : 
     964           0 :     m_aPrintJob.StartPage( m_aJobData );
     965           0 :     m_aPrinterGfx.Init( m_aPrintJob );
     966             : 
     967           0 :     return m_pGraphics;
     968             : }
     969             : 
     970           0 : bool PspSalPrinter::EndPage()
     971             : {
     972           0 :     bool bResult = m_aPrintJob.EndPage();
     973           0 :     m_aPrinterGfx.Clear();
     974             :     OSL_TRACE("PspSalPrinter::EndPage");
     975           0 :     return bResult;
     976             : }
     977             : 
     978           0 : sal_uLong PspSalPrinter::GetErrorCode()
     979             : {
     980           0 :     return 0;
     981             : }
     982             : 
     983             : struct PDFNewJobParameters
     984             : {
     985             :     Size        maPageSize;
     986             :     sal_uInt16      mnPaperBin;
     987             : 
     988           0 :     PDFNewJobParameters( const Size& i_rSize = Size(),
     989             :                          sal_uInt16 i_nPaperBin = 0xffff )
     990           0 :     : maPageSize( i_rSize ), mnPaperBin( i_nPaperBin ) {}
     991             : 
     992           0 :     bool operator==(const PDFNewJobParameters& rComp ) const
     993             :     {
     994           0 :         const long nRotatedWidth = rComp.maPageSize.Height();
     995           0 :         const long nRotatedHeight = rComp.maPageSize.Width();
     996           0 :         Size aCompLSSize(nRotatedWidth, nRotatedHeight);
     997             :         return
     998           0 :             (maPageSize == rComp.maPageSize || maPageSize == aCompLSSize)
     999           0 :         &&  mnPaperBin == rComp.mnPaperBin
    1000             :         ;
    1001             :     }
    1002             : 
    1003           0 :     bool operator!=(const PDFNewJobParameters& rComp) const
    1004             :     {
    1005           0 :         return ! this->operator==(rComp);
    1006             :     }
    1007             : };
    1008             : 
    1009           0 : struct PDFPrintFile
    1010             : {
    1011             :     OUString       maTmpURL;
    1012             :     PDFNewJobParameters maParameters;
    1013             : 
    1014           0 :     PDFPrintFile( const OUString& i_rURL, const PDFNewJobParameters& i_rNewParameters )
    1015             :     : maTmpURL( i_rURL )
    1016           0 :     , maParameters( i_rNewParameters ) {}
    1017             : };
    1018             : 
    1019           0 : bool PspSalPrinter::StartJob( const OUString* i_pFileName, const OUString& i_rJobName, const OUString& i_rAppName,
    1020             :                               ImplJobSetup* i_pSetupData, vcl::PrinterController& i_rController )
    1021             : {
    1022             :     OSL_TRACE( "StartJob with controller: pFilename = %s", i_pFileName ? OUStringToOString( *i_pFileName, RTL_TEXTENCODING_UTF8 ).getStr() : "<nil>" );
    1023             :     // mark for endjob
    1024           0 :     m_bIsPDFWriterJob = true;
    1025             :     // reset IsLastPage
    1026           0 :     i_rController.setLastPage( false );
    1027             :     // is this a fax device
    1028           0 :     bool bFax = m_pInfoPrinter->GetCapabilities(i_pSetupData, PRINTER_CAPABILITIES_FAX) == 1;
    1029             : 
    1030             :     // update job data
    1031           0 :     if( i_pSetupData )
    1032           0 :         JobData::constructFromStreamBuffer( i_pSetupData->mpDriverData, i_pSetupData->mnDriverDataLen, m_aJobData );
    1033             : 
    1034             :     OSL_ASSERT( m_aJobData.m_nPDFDevice > 0 );
    1035           0 :     m_aJobData.m_nPDFDevice = 1;
    1036             : 
    1037             :     // possibly create one job for collated output
    1038           0 :     bool bSinglePrintJobs = false;
    1039           0 :     beans::PropertyValue* pSingleValue = i_rController.getValue( OUString( "PrintCollateAsSingleJobs" ) );
    1040           0 :     if( pSingleValue )
    1041             :     {
    1042           0 :         pSingleValue->Value >>= bSinglePrintJobs;
    1043             :     }
    1044             : 
    1045           0 :     int nCopies = i_rController.getPrinter()->GetCopyCount();
    1046           0 :     bool bCollate = i_rController.getPrinter()->IsCollateCopy();
    1047             : 
    1048             :     // notify start of real print job
    1049           0 :     i_rController.jobStarted();
    1050             : 
    1051             :     // setup PDFWriter context
    1052           0 :     vcl::PDFWriter::PDFWriterContext aContext;
    1053           0 :     aContext.Version            = vcl::PDFWriter::PDF_1_4;
    1054           0 :     aContext.Tagged             = false;
    1055           0 :     aContext.DocumentLocale     = Application::GetSettings().GetLanguageTag().getLocale();
    1056           0 :     aContext.ColorMode          = i_rController.getPrinter()->GetPrinterOptions().IsConvertToGreyscales()
    1057           0 :     ? vcl::PDFWriter::DrawGreyscale : vcl::PDFWriter::DrawColor;
    1058             : 
    1059             :     // prepare doc info
    1060           0 :     aContext.DocumentInfo.Title              = i_rJobName;
    1061           0 :     aContext.DocumentInfo.Creator            = i_rAppName;
    1062           0 :     aContext.DocumentInfo.Producer           = i_rAppName;
    1063             : 
    1064             :     // define how we handle metafiles in PDFWriter
    1065           0 :     vcl::PDFWriter::PlayMetafileContext aMtfContext;
    1066           0 :     aMtfContext.m_bOnlyLosslessCompression = true;
    1067             : 
    1068           0 :     boost::shared_ptr<vcl::PDFWriter> pWriter;
    1069           0 :     std::vector< PDFPrintFile > aPDFFiles;
    1070           0 :     boost::shared_ptr<Printer> pPrinter( i_rController.getPrinter() );
    1071           0 :     int nAllPages = i_rController.getFilteredPageCount();
    1072           0 :     i_rController.createProgressDialog();
    1073           0 :     bool bAborted = false;
    1074           0 :     PDFNewJobParameters aLastParm;
    1075             : 
    1076           0 :     aContext.DPIx = pPrinter->GetDPIX();
    1077           0 :     aContext.DPIy = pPrinter->GetDPIY();
    1078           0 :     for( int nPage = 0; nPage < nAllPages && ! bAborted; nPage++ )
    1079             :     {
    1080           0 :         if( nPage == nAllPages-1 )
    1081           0 :             i_rController.setLastPage( true );
    1082             : 
    1083             :         // get the page's metafile
    1084           0 :         GDIMetaFile aPageFile;
    1085           0 :         vcl::PrinterController::PageSize aPageSize = i_rController.getFilteredPageFile( nPage, aPageFile );
    1086           0 :         if( i_rController.isProgressCanceled() )
    1087             :         {
    1088           0 :             bAborted = true;
    1089           0 :             if( nPage != nAllPages-1 )
    1090             :             {
    1091           0 :                 i_rController.createProgressDialog();
    1092           0 :                 i_rController.setLastPage( true );
    1093           0 :                 i_rController.getFilteredPageFile( nPage, aPageFile );
    1094             :             }
    1095             :         }
    1096             :         else
    1097             :         {
    1098           0 :             pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) );
    1099           0 :             pPrinter->SetPaperSizeUser( aPageSize.aSize, true );
    1100           0 :             PDFNewJobParameters aNewParm( pPrinter->GetPaperSize(), pPrinter->GetPaperBin() );
    1101             : 
    1102             :             // create PDF writer on demand
    1103             :             // either on first page
    1104             :             // or on paper format change - cups does not support multiple paper formats per job (yet?)
    1105             :             // so we need to start a new job to get a new paper format from the printer
    1106             :             // orientation switches (that is switch of height and width) is handled transparently by CUPS
    1107           0 :             if( ! pWriter ||
    1108           0 :                 (aNewParm != aLastParm && ! i_pFileName ) )
    1109             :             {
    1110           0 :                 if( pWriter )
    1111             :                 {
    1112           0 :                     pWriter->Emit();
    1113             :                 }
    1114             :                 // produce PDF file
    1115           0 :                 OUString aPDFUrl;
    1116           0 :                 if( i_pFileName )
    1117           0 :                     aPDFUrl = *i_pFileName;
    1118             :                 else
    1119           0 :                     osl_createTempFile( NULL, NULL, &aPDFUrl.pData );
    1120             :                 // normalize to file URL
    1121           0 :                 if( !aPDFUrl.startsWith( "file:" ) )
    1122             :                 {
    1123             :                     // this is not a file URL, but it should
    1124             :                     // form it into a osl friendly file URL
    1125           0 :                     OUString aTmp;
    1126           0 :                     osl_getFileURLFromSystemPath( aPDFUrl.pData, &aTmp.pData );
    1127           0 :                     aPDFUrl = aTmp;
    1128             :                 }
    1129             :                 // save current file and paper format
    1130           0 :                 aLastParm = aNewParm;
    1131           0 :                 aPDFFiles.push_back( PDFPrintFile( aPDFUrl, aNewParm ) );
    1132             :                 // update context
    1133           0 :                 aContext.URL = aPDFUrl;
    1134             : 
    1135             :                 // create and initialize PDFWriter
    1136           0 :                 pWriter.reset( new vcl::PDFWriter( aContext, uno::Reference< beans::XMaterialHolder >() ) );
    1137             :             }
    1138             : 
    1139           0 :             pWriter->NewPage( TenMuToPt( aNewParm.maPageSize.Width() ),
    1140           0 :                               TenMuToPt( aNewParm.maPageSize.Height() ),
    1141           0 :                               vcl::PDFWriter::Portrait );
    1142             : 
    1143           0 :             pWriter->PlayMetafile( aPageFile, aMtfContext, NULL );
    1144             :         }
    1145           0 :     }
    1146             : 
    1147             :     // emit the last file
    1148           0 :     if( pWriter )
    1149           0 :         pWriter->Emit();
    1150             : 
    1151             :     // handle collate, copy count and multiple jobs correctly
    1152           0 :     int nOuterJobs = 1;
    1153           0 :     if( bSinglePrintJobs )
    1154             :     {
    1155           0 :         nOuterJobs = nCopies;
    1156           0 :         m_aJobData.m_nCopies = 1;
    1157             :     }
    1158             :     else
    1159             :     {
    1160           0 :         if( bCollate )
    1161             :         {
    1162           0 :             if( aPDFFiles.size() == 1 && pPrinter->HasSupport( SUPPORT_COLLATECOPY ) )
    1163             :             {
    1164           0 :                 m_aJobData.setCollate( true );
    1165           0 :                 m_aJobData.m_nCopies = nCopies;
    1166             :             }
    1167             :             else
    1168             :             {
    1169           0 :                 nOuterJobs = nCopies;
    1170           0 :                 m_aJobData.m_nCopies = 1;
    1171             :             }
    1172             :         }
    1173             :         else
    1174             :         {
    1175           0 :             m_aJobData.setCollate( false );
    1176           0 :             m_aJobData.m_nCopies = nCopies;
    1177             :         }
    1178             :     }
    1179             : 
    1180           0 :     std::vector<OUString> aFaxNumbers;
    1181             : 
    1182             :     // check for fax numbers
    1183           0 :     if (!bAborted && bFax)
    1184             :     {
    1185           0 :         aFaxNumbers = getFaxNumbers();
    1186           0 :         bAborted = aFaxNumbers.empty();
    1187             :     }
    1188             : 
    1189           0 :     bool bSuccess(true);
    1190             :     // spool files
    1191           0 :     if( ! i_pFileName && ! bAborted )
    1192             :     {
    1193           0 :         do
    1194             :         {
    1195           0 :             OUString sFaxNumber;
    1196           0 :             if (!aFaxNumbers.empty())
    1197             :             {
    1198           0 :                 sFaxNumber = aFaxNumbers.back();
    1199           0 :                 aFaxNumbers.pop_back();
    1200             :             }
    1201             : 
    1202           0 :             bool bFirstJob = true;
    1203           0 :             for( int nCurJob = 0; nCurJob < nOuterJobs; nCurJob++ )
    1204             :             {
    1205           0 :                 for( size_t i = 0; i < aPDFFiles.size(); i++ )
    1206             :                 {
    1207           0 :                     oslFileHandle pFile = NULL;
    1208           0 :                     osl_openFile( aPDFFiles[i].maTmpURL.pData, &pFile, osl_File_OpenFlag_Read );
    1209           0 :                     if (pFile && (osl_setFilePos(pFile, osl_Pos_Absolut, 0) == osl_File_E_None))
    1210             :                     {
    1211           0 :                         std::vector< char > buffer( 0x10000, 0 );
    1212             :                         // update job data with current page size
    1213           0 :                         Size aPageSize( aPDFFiles[i].maParameters.maPageSize );
    1214           0 :                         m_aJobData.setPaper( TenMuToPt( aPageSize.Width() ), TenMuToPt( aPageSize.Height() ) );
    1215             :                         // update job data with current paperbin
    1216           0 :                         m_aJobData.setPaperBin( aPDFFiles[i].maParameters.mnPaperBin );
    1217             : 
    1218             :                         // spool current file
    1219           0 :                         FILE* fp = PrinterInfoManager::get().startSpool( pPrinter->GetName(), i_rController.isDirectPrint() );
    1220           0 :                         if( fp )
    1221             :                         {
    1222           0 :                             sal_uInt64 nBytesRead = 0;
    1223           0 :                             do
    1224             :                             {
    1225           0 :                                 osl_readFile( pFile, &buffer[0], buffer.size(), &nBytesRead );
    1226           0 :                                 if( nBytesRead > 0 )
    1227             :                                 {
    1228           0 :                                     size_t nBytesWritten = fwrite(&buffer[0], 1, nBytesRead, fp);
    1229             :                                     OSL_ENSURE(nBytesRead == nBytesWritten, "short write");
    1230           0 :                                     if (nBytesRead != nBytesWritten)
    1231           0 :                                         break;
    1232             :                                 }
    1233           0 :                             } while( nBytesRead == buffer.size() );
    1234           0 :                             OUStringBuffer aBuf( i_rJobName.getLength() + 8 );
    1235           0 :                             aBuf.append( i_rJobName );
    1236           0 :                             if( i > 0 || nCurJob > 0 )
    1237             :                             {
    1238           0 :                                 aBuf.append( ' ' );
    1239           0 :                                 aBuf.append( sal_Int32( i + nCurJob * aPDFFiles.size() ) );
    1240             :                             }
    1241             :                             bSuccess &=
    1242           0 :                             PrinterInfoManager::get().endSpool( pPrinter->GetName(), aBuf.makeStringAndClear(), fp, m_aJobData, bFirstJob, sFaxNumber );
    1243           0 :                             bFirstJob = false;
    1244           0 :                         }
    1245             :                     }
    1246           0 :                     osl_closeFile( pFile );
    1247             :                 }
    1248           0 :             }
    1249             :         }
    1250           0 :         while (!aFaxNumbers.empty());
    1251             :     }
    1252             : 
    1253             :     // job has been spooled
    1254             :     i_rController.setJobState( (bAborted)
    1255             :             ? view::PrintableState_JOB_ABORTED
    1256             :             : ((bSuccess) ? view::PrintableState_JOB_SPOOLED
    1257           0 :                           : view::PrintableState_JOB_SPOOLING_FAILED));
    1258             : 
    1259             :     // clean up the temporary PDF files
    1260           0 :     if( ! i_pFileName || bAborted )
    1261             :     {
    1262           0 :         for( size_t i = 0; i < aPDFFiles.size(); i++ )
    1263             :         {
    1264           0 :             osl_removeFile( aPDFFiles[i].maTmpURL.pData );
    1265             :             OSL_TRACE( "removed print PDF file %s", OUStringToOString( aPDFFiles[i].maTmpURL, RTL_TEXTENCODING_UTF8 ).getStr() );
    1266             :         }
    1267             :     }
    1268             : 
    1269           0 :     return true;
    1270             : }
    1271             : 
    1272             : class PrinterUpdate
    1273             : {
    1274             :     static Timer* pPrinterUpdateTimer;
    1275             :     static int    nActiveJobs;
    1276             : 
    1277             :     static void doUpdate();
    1278             :     DECL_STATIC_LINK( PrinterUpdate, UpdateTimerHdl, void* );
    1279             : public:
    1280             :     static void update(SalGenericInstance &rInstance);
    1281           0 :     static void jobStarted() { nActiveJobs++; }
    1282             :     static void jobEnded();
    1283             : };
    1284             : 
    1285             : Timer* PrinterUpdate::pPrinterUpdateTimer = NULL;
    1286             : int PrinterUpdate::nActiveJobs = 0;
    1287             : 
    1288           0 : void PrinterUpdate::doUpdate()
    1289             : {
    1290           0 :     ::psp::PrinterInfoManager& rManager( ::psp::PrinterInfoManager::get() );
    1291           0 :     SalGenericInstance *pInst = static_cast<SalGenericInstance *>( GetSalData()->m_pInstance );
    1292           0 :     if( pInst && rManager.checkPrintersChanged( false ) )
    1293           0 :         pInst->PostPrintersChanged();
    1294           0 : }
    1295             : 
    1296           0 : IMPL_STATIC_LINK_NOINSTANCE( PrinterUpdate, UpdateTimerHdl, void*, EMPTYARG )
    1297             : {
    1298           0 :     if( nActiveJobs < 1 )
    1299             :     {
    1300           0 :         doUpdate();
    1301           0 :         delete pPrinterUpdateTimer;
    1302           0 :         pPrinterUpdateTimer = NULL;
    1303             :     }
    1304             :     else
    1305           0 :         pPrinterUpdateTimer->Start();
    1306             : 
    1307           0 :     return 0;
    1308             : }
    1309             : 
    1310           0 : void PrinterUpdate::update(SalGenericInstance &rInstance)
    1311             : {
    1312           0 :     if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
    1313           0 :         return;
    1314             : 
    1315           0 :     if( ! rInstance.isPrinterInit() )
    1316             :     {
    1317             :         // #i45389# start background printer detection
    1318           0 :         psp::PrinterInfoManager::get();
    1319           0 :         return;
    1320             :     }
    1321             : 
    1322           0 :     if( nActiveJobs < 1 )
    1323           0 :         doUpdate();
    1324           0 :     else if( ! pPrinterUpdateTimer )
    1325             :     {
    1326           0 :         pPrinterUpdateTimer = new Timer();
    1327           0 :         pPrinterUpdateTimer->SetTimeout( 500 );
    1328           0 :         pPrinterUpdateTimer->SetTimeoutHdl( STATIC_LINK( NULL, PrinterUpdate, UpdateTimerHdl ) );
    1329           0 :         pPrinterUpdateTimer->Start();
    1330             :     }
    1331             : }
    1332             : 
    1333           0 : void SalGenericInstance::updatePrinterUpdate()
    1334             : {
    1335           0 :     PrinterUpdate::update(*this);
    1336           0 : }
    1337             : 
    1338           0 : void SalGenericInstance::jobStartedPrinterUpdate()
    1339             : {
    1340           0 :     PrinterUpdate::jobStarted();
    1341           0 : }
    1342             : 
    1343           0 : void PrinterUpdate::jobEnded()
    1344             : {
    1345           0 :     nActiveJobs--;
    1346           0 :     if( nActiveJobs < 1 )
    1347             :     {
    1348           0 :         if( pPrinterUpdateTimer )
    1349             :         {
    1350           0 :             pPrinterUpdateTimer->Stop();
    1351           0 :             delete pPrinterUpdateTimer;
    1352           0 :             pPrinterUpdateTimer = NULL;
    1353           0 :             doUpdate();
    1354             :         }
    1355             :     }
    1356           0 : }
    1357             : 
    1358           0 : void SalGenericInstance::jobEndedPrinterUpdate()
    1359             : {
    1360           0 :     PrinterUpdate::jobEnded();
    1361        1233 : }
    1362             : 
    1363             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10