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

Generated by: LCOV version 1.10