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

Generated by: LCOV version 1.10