1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salprnpsp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 this file implements the sal printer interface ( SalPrinter, SalInfoPrinter
36 and some printer relevant methods of SalInstance and SalGraphicsData )
38 as aunderlying library the printer features of psprint are used.
40 The query methods of a SalInfoPrinter are implemented by querying psprint
42 The job methods of a SalPrinter are implemented by calling psprint
43 printer job functions.
51 #include "saldisp.hxx"
55 #include "pspgraphics.h"
56 #include "saldata.hxx"
57 #include "vcl/svapp.hxx"
58 #include "vcl/jobset.h"
59 #include "vcl/print.h"
60 #include "vcl/salptype.hxx"
61 #include "vcl/printerinfomanager.hxx"
63 #include "rtl/ustring.hxx"
65 #include "osl/module.h"
74 #include "rtsname.hxx"
76 static oslModule driverLib
= NULL
;
79 typedef int(*setupFunction
)(PrinterInfo
&);
80 static setupFunction pSetupFunction
= NULL
;
81 typedef int(*faxFunction
)(String
&);
82 static faxFunction pFaxNrFunction
= NULL
;
85 static String
getPdfDir( const PrinterInfo
& rInfo
)
91 OUString
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
92 if( ! aToken
.compareToAscii( "pdf=", 4 ) )
95 aDir
= aToken
.getToken( 1, '=', nPos
);
97 aDir
= String( ByteString( getenv( "HOME" ) ), osl_getThreadTextEncoding() );
104 static void getPaLib()
108 OUString
aLibName( RTL_CONSTASCII_USTRINGPARAM( _XSALSET_LIBNAME
) );
109 driverLib
= osl_loadModuleRelative( (oslGenericFunction
)getPaLib
, aLibName
.pData
, SAL_LOADMODULE_DEFAULT
);
115 pSetupFunction
= (setupFunction
)osl_getAsciiFunctionSymbol( driverLib
, "Sal_SetupPrinterDriver" );
116 if ( !pSetupFunction
)
117 fprintf( stderr
, "could not resolve Sal_SetupPrinterDriver\n" );
119 pFaxNrFunction
= (faxFunction
)osl_getAsciiFunctionSymbol( driverLib
, "Sal_queryFaxNumber" );
120 if ( !pFaxNrFunction
)
121 fprintf( stderr
, "could not resolve Sal_queryFaxNumber\n" );
125 inline int PtTo10Mu( int nPoints
) { return (int)((((double)nPoints
)*35.27777778)+0.5); }
127 inline int TenMuToPt( int nUnits
) { return (int)((((double)nUnits
)/35.27777778)+0.5); }
129 static void copyJobDataToJobSetup( ImplJobSetup
* pJobSetup
, JobData
& rData
)
131 pJobSetup
->meOrientation
= (Orientation
)(rData
.m_eOrientation
== orientation::Landscape
? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT
);
137 rData
.m_aContext
.getPageSize( aPaper
, width
, height
);
138 pJobSetup
->mePaperFormat
= PaperInfo::fromPSName(OUStringToOString( aPaper
, RTL_TEXTENCODING_ISO_8859_1
));
140 pJobSetup
->mnPaperWidth
= 0;
141 pJobSetup
->mnPaperHeight
= 0;
142 if( pJobSetup
->mePaperFormat
== PAPER_USER
)
144 // transform to 100dth mm
145 width
= PtTo10Mu( width
);
146 height
= PtTo10Mu( height
);
148 if( rData
.m_eOrientation
== psp::orientation::Portrait
)
150 pJobSetup
->mnPaperWidth
= width
;
151 pJobSetup
->mnPaperHeight
= height
;
155 pJobSetup
->mnPaperWidth
= height
;
156 pJobSetup
->mnPaperHeight
= width
;
161 const PPDKey
* pKey
= NULL
;
162 const PPDValue
* pValue
= NULL
;
164 pJobSetup
->mnPaperBin
= 0;
165 if( rData
.m_pParser
)
166 pKey
= rData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
168 pValue
= rData
.m_aContext
.getValue( pKey
);
171 for( pJobSetup
->mnPaperBin
= 0;
172 pValue
!= pKey
->getValue( pJobSetup
->mnPaperBin
) &&
173 pJobSetup
->mnPaperBin
< pKey
->countValues();
174 pJobSetup
->mnPaperBin
++ )
176 if( pJobSetup
->mnPaperBin
>= pKey
->countValues() )
177 pJobSetup
->mnPaperBin
= 0;
181 // copy the whole context
182 if( pJobSetup
->mpDriverData
)
183 rtl_freeMemory( pJobSetup
->mpDriverData
);
186 void* pBuffer
= NULL
;
187 if( rData
.getStreamBuffer( pBuffer
, nBytes
) )
189 pJobSetup
->mnDriverDataLen
= nBytes
;
190 pJobSetup
->mpDriverData
= (BYTE
*)pBuffer
;
194 pJobSetup
->mnDriverDataLen
= 0;
195 pJobSetup
->mpDriverData
= NULL
;
199 static bool passFileToCommandLine( const String
& rFilename
, const String
& rCommandLine
, bool bRemoveFile
= true )
201 bool bSuccess
= false;
203 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
204 ByteString
aCmdLine( rCommandLine
, aEncoding
);
205 ByteString
aFilename( rFilename
, aEncoding
);
207 bool bPipe
= aCmdLine
.Search( "(TMP)" ) != STRING_NOTFOUND
? false : true;
209 // setup command line for exec
211 while( aCmdLine
.SearchAndReplace( "(TMP)", aFilename
) != STRING_NOTFOUND
)
214 #if OSL_DEBUG_LEVEL > 1
215 fprintf( stderr
, "%s commandline: \"%s\"\n",
216 bPipe
? "piping to" : "executing",
217 aCmdLine
.GetBuffer() );
219 if( stat( aFilename
.GetBuffer(), &aStat
) )
220 fprintf( stderr
, "stat( %s ) failed\n", aFilename
.GetBuffer() );
221 fprintf( stderr
, "Tmp file %s has modes: 0%03lo\n", aFilename
.GetBuffer(), (long)aStat
.st_mode
);
224 if( ! ( argv
[ 0 ] = getenv( "SHELL" ) ) )
225 argv
[ 0 ] = "/bin/sh";
227 argv
[ 2 ] = aCmdLine
.GetBuffer();
230 bool bHavePipes
= false;
234 bHavePipes
= pipe( fd
) ? false : true;
235 if( ( pid
= fork() ) > 0 )
237 if( bPipe
&& bHavePipes
)
240 char aBuffer
[ 2048 ];
241 FILE* fp
= fopen( aFilename
.GetBuffer(), "r" );
242 while( fp
&& ! feof( fp
) )
244 int nBytes
= fread( aBuffer
, 1, sizeof( aBuffer
), fp
);
246 write( fd
[ 1 ], aBuffer
, nBytes
);
252 waitpid( pid
, &status
, 0 );
258 if( bPipe
&& bHavePipes
)
261 if( fd
[0] != STDIN_FILENO
) // not probable, but who knows :)
262 dup2( fd
[0], STDIN_FILENO
);
264 execv( argv
[0], const_cast<char**>(argv
) );
265 fprintf( stderr
, "failed to execute \"%s\"\n", aCmdLine
.GetBuffer() );
269 fprintf( stderr
, "failed to fork\n" );
273 unlink( aFilename
.GetBuffer() );
278 static bool sendAFax( const String
& rFaxNumber
, const String
& rFileName
, const String
& rCommand
)
280 std::list
< OUString
> aFaxNumbers
;
282 if( ! rFaxNumber
.Len() )
288 if( pFaxNrFunction( aNewNr
) )
289 aFaxNumbers
.push_back( OUString( aNewNr
) );
294 sal_Int32 nIndex
= 0;
295 OUString
aFaxes( rFaxNumber
);
296 OUString
aBeginToken( RTL_CONSTASCII_USTRINGPARAM("<Fax#>") );
297 OUString
aEndToken( RTL_CONSTASCII_USTRINGPARAM("</Fax#>") );
298 while( nIndex
!= -1 )
300 nIndex
= aFaxes
.indexOf( aBeginToken
, nIndex
);
303 sal_Int32 nBegin
= nIndex
+ aBeginToken
.getLength();
304 nIndex
= aFaxes
.indexOf( aEndToken
, nIndex
);
307 aFaxNumbers
.push_back( aFaxes
.copy( nBegin
, nIndex
-nBegin
) );
308 nIndex
+= aEndToken
.getLength();
314 bool bSuccess
= true;
315 if( aFaxNumbers
.begin() != aFaxNumbers
.end() )
317 while( aFaxNumbers
.begin() != aFaxNumbers
.end() && bSuccess
)
319 String
aCmdLine( rCommand
);
320 String
aFaxNumber( aFaxNumbers
.front() );
321 aFaxNumbers
.pop_front();
322 while( aCmdLine
.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(PHONE)" ) ), aFaxNumber
) != STRING_NOTFOUND
)
324 #if OSL_DEBUG_LEVEL > 1
325 fprintf( stderr
, "sending fax to \"%s\"\n", OUStringToOString( aFaxNumber
, osl_getThreadTextEncoding() ).getStr() );
327 bSuccess
= passFileToCommandLine( rFileName
, aCmdLine
, false );
333 // clean up temp file
334 unlink( ByteString( rFileName
, osl_getThreadTextEncoding() ).GetBuffer() );
339 static bool createPdf( const String
& rToFile
, const String
& rFromFile
, const String
& rCommandLine
)
341 String
aCommandLine( rCommandLine
);
342 while( aCommandLine
.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(OUTFILE)" ) ), rToFile
) != STRING_NOTFOUND
)
344 return passFileToCommandLine( rFromFile
, aCommandLine
);
351 // -----------------------------------------------------------------------
353 SalInfoPrinter
* X11SalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
354 ImplJobSetup
* pJobSetup
)
356 mbPrinterInit
= true;
357 // create and initialize SalInfoPrinter
358 PspSalInfoPrinter
* pPrinter
= new PspSalInfoPrinter
;
362 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
363 PrinterInfo
aInfo( rManager
.getPrinterInfo( pQueueInfo
->maPrinterName
) );
364 pPrinter
->m_aJobData
= aInfo
;
365 pPrinter
->m_aPrinterGfx
.Init( pPrinter
->m_aJobData
);
367 if( pJobSetup
->mpDriverData
)
368 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aInfo
);
370 pJobSetup
->mnSystem
= JOBSETUP_SYSTEM_UNIX
;
371 pJobSetup
->maPrinterName
= pQueueInfo
->maPrinterName
;
372 pJobSetup
->maDriver
= aInfo
.m_aDriverName
;
373 copyJobDataToJobSetup( pJobSetup
, aInfo
);
375 // set/clear backwards compatibility flag
376 bool bStrictSO52Compatibility
= false;
377 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
378 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
380 if( compat_it
!= pJobSetup
->maValueMap
.end() )
382 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
383 bStrictSO52Compatibility
= true;
385 pPrinter
->m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
392 // -----------------------------------------------------------------------
394 void X11SalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
399 // -----------------------------------------------------------------------
401 SalPrinter
* X11SalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
403 mbPrinterInit
= true;
404 // create and initialize SalPrinter
405 PspSalPrinter
* pPrinter
= new PspSalPrinter( pInfoPrinter
);
406 pPrinter
->m_aJobData
= static_cast<PspSalInfoPrinter
*>(pInfoPrinter
)->m_aJobData
;
411 // -----------------------------------------------------------------------
413 void X11SalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
418 // -----------------------------------------------------------------------
420 void X11SalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
422 mbPrinterInit
= true;
423 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
424 static const char* pNoSyncDetection
= getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
425 if( ! pNoSyncDetection
|| ! *pNoSyncDetection
)
427 // #i62663# synchronize possible asynchronouse printer detection now
428 rManager
.checkPrintersChanged( true );
430 ::std::list
< OUString
> aPrinters
;
431 rManager
.listPrinters( aPrinters
);
433 for( ::std::list
< OUString
>::iterator it
= aPrinters
.begin(); it
!= aPrinters
.end(); ++it
)
435 const PrinterInfo
& rInfo( rManager
.getPrinterInfo( *it
) );
436 // Neuen Eintrag anlegen
437 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
438 pInfo
->maPrinterName
= *it
;
439 pInfo
->maDriver
= rInfo
.m_aDriverName
;
440 pInfo
->maLocation
= rInfo
.m_aLocation
;
441 pInfo
->maComment
= rInfo
.m_aComment
;
442 pInfo
->mpSysData
= NULL
;
444 sal_Int32 nIndex
= 0;
445 while( nIndex
!= -1 )
447 String
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
448 if( aToken
.CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL
)
450 pInfo
->maLocation
= getPdfDir( rInfo
);
459 // -----------------------------------------------------------------------
461 void X11SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
466 // -----------------------------------------------------------------------
468 void X11SalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* )
470 mbPrinterInit
= true;
473 // -----------------------------------------------------------------------
475 String
X11SalInstance::GetDefaultPrinter()
477 mbPrinterInit
= true;
478 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
479 return rManager
.getDefaultPrinter();
482 // =======================================================================
484 PspSalInfoPrinter::PspSalInfoPrinter()
487 m_bPapersInit
= false;
490 // -----------------------------------------------------------------------
492 PspSalInfoPrinter::~PspSalInfoPrinter()
501 // -----------------------------------------------------------------------
503 void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup
* )
505 m_aPaperFormats
.clear();
506 m_bPapersInit
= true;
508 if( m_aJobData
.m_pParser
)
510 const PPDKey
* pKey
= m_aJobData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
513 int nValues
= pKey
->countValues();
514 for( int i
= 0; i
< nValues
; i
++ )
516 const PPDValue
* pValue
= pKey
->getValue( i
);
517 int nWidth
= 0, nHeight
= 0;
518 m_aJobData
.m_pParser
->getPaperDimension( pValue
->m_aOption
, nWidth
, nHeight
);
519 PaperInfo
aInfo(PtTo10Mu( nWidth
), PtTo10Mu( nHeight
));
520 m_aPaperFormats
.push_back( aInfo
);
526 // -----------------------------------------------------------------------
528 DuplexMode
PspSalInfoPrinter::GetDuplexMode( const ImplJobSetup
* pJobSetup
)
530 DuplexMode aRet
= DUPLEX_UNKNOWN
;
531 PrinterInfo
aInfo( PrinterInfoManager::get().getPrinterInfo( pJobSetup
->maPrinterName
) );
532 if ( pJobSetup
->mpDriverData
)
533 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aInfo
);
534 if( aInfo
.m_pParser
)
536 const PPDKey
* pKey
= aInfo
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
539 const PPDValue
* pVal
= aInfo
.m_aContext
.getValue( pKey
);
541 pVal
->m_aOption
.EqualsIgnoreCaseAscii( "None" ) ||
542 pVal
->m_aOption
.EqualsIgnoreCaseAscii( "Simplex", 0, 7 )
554 // -----------------------------------------------------------------------
556 int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup
* )
561 // -----------------------------------------------------------------------
563 SalGraphics
* PspSalInfoPrinter::GetGraphics()
565 // return a valid pointer only once
566 // the reasoning behind this is that we could have different
567 // SalGraphics that can run in multiple threads
569 SalGraphics
* pRet
= NULL
;
572 m_pGraphics
= new PspGraphics( &m_aJobData
, &m_aPrinterGfx
, NULL
, false, this );
573 m_pGraphics
->SetLayout( 0 );
579 // -----------------------------------------------------------------------
581 void PspSalInfoPrinter::ReleaseGraphics( SalGraphics
* pGraphics
)
583 if( pGraphics
== m_pGraphics
)
591 // -----------------------------------------------------------------------
593 BOOL
PspSalInfoPrinter::Setup( SalFrame
* pFrame
, ImplJobSetup
* pJobSetup
)
595 if( ! pFrame
|| ! pJobSetup
)
600 if( ! pSetupFunction
)
603 PrinterInfoManager
& rManager
= PrinterInfoManager::get();
605 PrinterInfo
aInfo( rManager
.getPrinterInfo( pJobSetup
->maPrinterName
) );
606 if ( pJobSetup
->mpDriverData
)
608 SetData( ~0, pJobSetup
);
609 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aInfo
);
612 if( pSetupFunction( aInfo
) )
614 rtl_freeMemory( pJobSetup
->mpDriverData
);
615 pJobSetup
->mpDriverData
= NULL
;
618 void* pBuffer
= NULL
;
619 aInfo
.getStreamBuffer( pBuffer
, nBytes
);
620 pJobSetup
->mnDriverDataLen
= nBytes
;
621 pJobSetup
->mpDriverData
= (BYTE
*)pBuffer
;
623 // copy everything to job setup
624 copyJobDataToJobSetup( pJobSetup
, aInfo
);
630 // -----------------------------------------------------------------------
632 // This function gets the driver data and puts it into pJobSetup
633 // If pJobSetup->mpDriverData is NOT NULL, then the independend
634 // data should be merged into the driver data
635 // If pJobSetup->mpDriverData IS NULL, then the driver defaults
636 // should be merged into the independent data
637 BOOL
PspSalInfoPrinter::SetPrinterData( ImplJobSetup
* pJobSetup
)
639 // set/clear backwards compatibility flag
640 bool bStrictSO52Compatibility
= false;
641 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
642 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
644 if( compat_it
!= pJobSetup
->maValueMap
.end() )
646 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
647 bStrictSO52Compatibility
= true;
649 m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
651 if( pJobSetup
->mpDriverData
)
652 return SetData( ~0, pJobSetup
);
654 copyJobDataToJobSetup( pJobSetup
, m_aJobData
);
659 // -----------------------------------------------------------------------
661 // This function merges the independ driver data
662 // and sets the new independ data in pJobSetup
663 // Only the data must be changed, where the bit
664 // in nGetDataFlags is set
665 BOOL
PspSalInfoPrinter::SetData(
667 ImplJobSetup
* pJobSetup
)
670 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
672 if( aData
.m_pParser
)
675 const PPDValue
* pValue
;
677 // merge papersize if necessary
678 if( nSetDataFlags
& SAL_JOBSET_PAPERSIZE
)
681 if( pJobSetup
->meOrientation
== ORIENTATION_PORTRAIT
)
683 nWidth
= pJobSetup
->mnPaperWidth
;
684 nHeight
= pJobSetup
->mnPaperHeight
;
688 nWidth
= pJobSetup
->mnPaperHeight
;
689 nHeight
= pJobSetup
->mnPaperWidth
;
693 if( pJobSetup
->mePaperFormat
== PAPER_USER
)
694 aPaper
= aData
.m_pParser
->matchPaper(
695 TenMuToPt( pJobSetup
->mnPaperWidth
),
696 TenMuToPt( pJobSetup
->mnPaperHeight
) );
698 aPaper
= rtl::OStringToOUString(PaperInfo::toPSName(pJobSetup
->mePaperFormat
), RTL_TEXTENCODING_ISO_8859_1
);
700 pKey
= aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
701 pValue
= pKey
? pKey
->getValueCaseInsensitive( aPaper
) : NULL
;
702 if( ! ( pKey
&& pValue
&& aData
.m_aContext
.setValue( pKey
, pValue
, false ) == pValue
) )
706 // merge paperbin if necessary
707 if( nSetDataFlags
& SAL_JOBSET_PAPERBIN
)
709 pKey
= aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
712 int nPaperBin
= pJobSetup
->mnPaperBin
;
713 if( nPaperBin
>= pKey
->countValues() )
714 pValue
= pKey
->getDefaultValue();
716 pValue
= pKey
->getValue( pJobSetup
->mnPaperBin
);
718 // may fail due to constraints;
719 // real paper bin is copied back to jobsetup in that case
720 aData
.m_aContext
.setValue( pKey
, pValue
);
722 // if printer has no InputSlot key simply ignore this setting
723 // (e.g. SGENPRT has no InputSlot)
726 // merge orientation if necessary
727 if( nSetDataFlags
& SAL_JOBSET_ORIENTATION
)
728 aData
.m_eOrientation
= pJobSetup
->meOrientation
== ORIENTATION_LANDSCAPE
? orientation::Landscape
: orientation::Portrait
;
731 copyJobDataToJobSetup( pJobSetup
, aData
);
738 // -----------------------------------------------------------------------
740 void PspSalInfoPrinter::GetPageInfo(
741 const ImplJobSetup
* pJobSetup
,
742 long& rOutWidth
, long& rOutHeight
,
743 long& rPageOffX
, long& rPageOffY
,
744 long& rPageWidth
, long& rPageHeight
)
750 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
752 // get the selected page size
753 if( aData
.m_pParser
)
758 int left
= 0, top
= 0, right
= 0, bottom
= 0;
759 int nDPI
= aData
.m_aContext
.getRenderResolution();
762 if( aData
.m_eOrientation
== psp::orientation::Portrait
)
764 aData
.m_aContext
.getPageSize( aPaper
, width
, height
);
765 aData
.m_pParser
->getMargins( aPaper
, left
, right
, top
, bottom
);
769 aData
.m_aContext
.getPageSize( aPaper
, height
, width
);
770 aData
.m_pParser
->getMargins( aPaper
, top
, bottom
, right
, left
);
773 rPageWidth
= width
* nDPI
/ 72;
774 rPageHeight
= height
* nDPI
/ 72;
775 rPageOffX
= left
* nDPI
/ 72;
776 rPageOffY
= top
* nDPI
/ 72;
777 rOutWidth
= ( width
- left
- right
) * nDPI
/ 72;
778 rOutHeight
= ( height
- top
- bottom
) * nDPI
/ 72;
782 // -----------------------------------------------------------------------
784 ULONG
PspSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pJobSetup
)
790 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
792 const PPDKey
* pKey
= aData
.m_pParser
? aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL
;
793 return pKey
? pKey
->countValues() : 0;
796 // -----------------------------------------------------------------------
798 String
PspSalInfoPrinter::GetPaperBinName( const ImplJobSetup
* pJobSetup
, ULONG nPaperBin
)
801 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
804 if( aData
.m_pParser
)
806 const PPDKey
* pKey
= aData
.m_pParser
? aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL
;
807 if( ! pKey
|| nPaperBin
>= (ULONG
)pKey
->countValues() )
808 aRet
= aData
.m_pParser
->getDefaultInputSlot();
811 const PPDValue
* pValue
= pKey
->getValue( nPaperBin
);
813 aRet
= pValue
->m_aOptionTranslation
.Len() ? pValue
->m_aOptionTranslation
: pValue
->m_aOption
;
820 // -----------------------------------------------------------------------
822 ULONG
PspSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pJobSetup
, USHORT nType
)
826 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
828 case PRINTER_CAPABILITIES_COPIES
:
830 case PRINTER_CAPABILITIES_COLLATECOPIES
:
832 case PRINTER_CAPABILITIES_SETORIENTATION
:
834 case PRINTER_CAPABILITIES_SETPAPERBIN
:
836 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
838 case PRINTER_CAPABILITIES_SETPAPER
:
840 case PRINTER_CAPABILITIES_FAX
:
841 return PrinterInfoManager::get().checkFeatureToken( pJobSetup
->maPrinterName
, "fax" ) ? 1 : 0;
842 case PRINTER_CAPABILITIES_PDF
:
843 return PrinterInfoManager::get().checkFeatureToken( pJobSetup
->maPrinterName
, "pdf" ) ? 1 : 0;
844 case PRINTER_CAPABILITIES_EXTERNALDIALOG
:
845 return PrinterInfoManager::get().checkFeatureToken( pJobSetup
->maPrinterName
, "external_dialog" ) ? 1 : 0;
851 // =======================================================================
857 PspSalPrinter::PspSalPrinter( SalInfoPrinter
* pInfoPrinter
)
860 m_bSwallowFaxNo( false ),
863 m_pInfoPrinter( pInfoPrinter
)
867 // -----------------------------------------------------------------------
869 PspSalPrinter::~PspSalPrinter()
873 // -----------------------------------------------------------------------
875 static String
getTmpName()
877 rtl::OUString aTmp
, aSys
;
878 osl_createTempFile( NULL
, NULL
, &aTmp
.pData
);
879 osl_getSystemPathFromFileURL( aTmp
.pData
, &aSys
.pData
);
884 BOOL
PspSalPrinter::StartJob(
885 const XubString
* pFileName
,
886 const XubString
& rJobName
,
887 const XubString
& rAppName
,
888 ULONG nCopies
, BOOL
/*bCollate*/,
889 ImplJobSetup
* pJobSetup
)
891 vcl_sal::PrinterUpdate::jobStarted();
895 m_aFileName
= pFileName
? *pFileName
: String();
896 m_aTmpFile
= String();
899 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, m_aJobData
);
901 // in case user did not do anything (m_nCopies=1)
902 // take the default from jobsetup
903 m_aJobData
.m_nCopies
= m_nCopies
;
905 // check wether this printer is configured as fax
907 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
908 sal_Int32 nIndex
= 0;
909 while( nIndex
!= -1 )
911 OUString
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
912 if( ! aToken
.compareToAscii( "fax", 3 ) )
915 m_aTmpFile
= getTmpName();
916 nMode
= S_IRUSR
| S_IWUSR
;
918 ::std::hash_map
< ::rtl::OUString
, ::rtl::OUString
, ::rtl::OUStringHash
>::const_iterator it
;
919 it
= pJobSetup
->maValueMap
.find( ::rtl::OUString::createFromAscii( "FAX#" ) );
920 if( it
!= pJobSetup
->maValueMap
.end() )
921 m_aFaxNr
= it
->second
;
924 m_bSwallowFaxNo
= ! aToken
.getToken( 1, '=', nPos
).compareToAscii( "swallow", 7 ) ? true : false;
928 if( ! aToken
.compareToAscii( "pdf=", 4 ) )
931 m_aTmpFile
= getTmpName();
932 nMode
= S_IRUSR
| S_IWUSR
;
934 if( ! m_aFileName
.Len() )
936 m_aFileName
= getPdfDir( rInfo
);
937 m_aFileName
.Append( '/' );
938 m_aFileName
.Append( rJobName
);
939 m_aFileName
.AppendAscii( ".pdf" );
944 m_aPrinterGfx
.Init( m_aJobData
);
946 bool bIsQuickJob
= false;
947 std::hash_map
< rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator quick_it
=
948 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ) );
949 if( quick_it
!= pJobSetup
->maValueMap
.end() )
951 if( quick_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
955 // set/clear backwards compatibility flag
956 bool bStrictSO52Compatibility
= false;
957 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
958 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
960 if( compat_it
!= pJobSetup
->maValueMap
.end() )
962 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
963 bStrictSO52Compatibility
= true;
965 m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
967 return m_aPrintJob
.StartJob( m_aTmpFile
.Len() ? m_aTmpFile
: m_aFileName
, nMode
, rJobName
, rAppName
, m_aJobData
, &m_aPrinterGfx
, bIsQuickJob
) ? TRUE
: FALSE
;
970 // -----------------------------------------------------------------------
972 BOOL
PspSalPrinter::EndJob()
974 BOOL bSuccess
= m_aPrintJob
.EndJob();
982 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
983 // sendAFax removes the file after use
984 bSuccess
= sendAFax( m_aFaxNr
, m_aTmpFile
, rInfo
.m_aCommand
);
988 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
989 bSuccess
= createPdf( m_aFileName
, m_aTmpFile
, rInfo
.m_aCommand
);
992 vcl_sal::PrinterUpdate::jobEnded();
996 // -----------------------------------------------------------------------
998 BOOL
PspSalPrinter::AbortJob()
1000 BOOL bAbort
= m_aPrintJob
.AbortJob() ? TRUE
: FALSE
;
1001 vcl_sal::PrinterUpdate::jobEnded();
1005 // -----------------------------------------------------------------------
1007 SalGraphics
* PspSalPrinter::StartPage( ImplJobSetup
* pJobSetup
, BOOL
)
1009 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, m_aJobData
);
1010 m_pGraphics
= new PspGraphics( &m_aJobData
, &m_aPrinterGfx
, m_bFax
? &m_aFaxNr
: NULL
, m_bSwallowFaxNo
, m_pInfoPrinter
);
1011 m_pGraphics
->SetLayout( 0 );
1013 // in case user did not do anything (m_nCopies=1)
1014 // take the default from jobsetup
1015 m_aJobData
.m_nCopies
= m_nCopies
;
1017 m_aPrintJob
.StartPage( m_aJobData
);
1018 m_aPrinterGfx
.Init( m_aPrintJob
);
1023 // -----------------------------------------------------------------------
1025 BOOL
PspSalPrinter::EndPage()
1027 sal_Bool bResult
= m_aPrintJob
.EndPage();
1028 m_aPrinterGfx
.Clear();
1029 return bResult
? TRUE
: FALSE
;
1032 // -----------------------------------------------------------------------
1034 ULONG
PspSalPrinter::GetErrorCode()
1040 * vcl::PrinterUpdate
1043 Timer
* vcl_sal::PrinterUpdate::pPrinterUpdateTimer
= NULL
;
1044 int vcl_sal::PrinterUpdate::nActiveJobs
= 0;
1046 void vcl_sal::PrinterUpdate::doUpdate()
1048 ::psp::PrinterInfoManager
& rManager( ::psp::PrinterInfoManager::get() );
1049 if( rManager
.checkPrintersChanged( false ) )
1051 SalDisplay
* pDisp
= GetX11SalData()->GetDisplay();
1052 const std::list
< SalFrame
* >& rList
= pDisp
->getFrames();
1053 for( std::list
< SalFrame
* >::const_iterator it
= rList
.begin();
1054 it
!= rList
.end(); ++it
)
1055 pDisp
->SendInternalEvent( *it
, NULL
, SALEVENT_PRINTERCHANGED
);
1059 // -----------------------------------------------------------------------
1061 IMPL_STATIC_LINK_NOINSTANCE( vcl_sal::PrinterUpdate
, UpdateTimerHdl
, void*, EMPTYARG
)
1063 if( nActiveJobs
< 1 )
1066 delete pPrinterUpdateTimer
;
1067 pPrinterUpdateTimer
= NULL
;
1070 pPrinterUpdateTimer
->Start();
1075 // -----------------------------------------------------------------------
1077 void vcl_sal::PrinterUpdate::update()
1079 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
1082 if( ! static_cast< X11SalInstance
* >(GetSalData()->m_pInstance
)->isPrinterInit() )
1084 // #i45389# start background printer detection
1085 psp::PrinterInfoManager::get();
1089 if( nActiveJobs
< 1 )
1091 else if( ! pPrinterUpdateTimer
)
1093 pPrinterUpdateTimer
= new Timer();
1094 pPrinterUpdateTimer
->SetTimeout( 500 );
1095 pPrinterUpdateTimer
->SetTimeoutHdl( STATIC_LINK( NULL
, vcl_sal::PrinterUpdate
, UpdateTimerHdl
) );
1096 pPrinterUpdateTimer
->Start();
1100 // -----------------------------------------------------------------------
1102 void vcl_sal::PrinterUpdate::jobEnded()
1105 if( nActiveJobs
< 1 )
1107 if( pPrinterUpdateTimer
)
1109 pPrinterUpdateTimer
->Stop();
1110 delete pPrinterUpdateTimer
;
1111 pPrinterUpdateTimer
= NULL
;