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 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include "vcl/svapp.hxx"
32 #include "vcl/jobset.h"
33 #include "vcl/print.h"
34 #include "vcl/salptype.hxx"
35 #include "vcl/timer.hxx"
36 #include "vcl/printerinfomanager.hxx"
39 #include "svppspgraphics.hxx"
40 #include "svpinst.hxx"
53 static String
getPdfDir( const PrinterInfo
& rInfo
)
59 OUString
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
60 if( ! aToken
.compareToAscii( "pdf=", 4 ) )
63 aDir
= aToken
.getToken( 1, '=', nPos
);
65 aDir
= String( ByteString( getenv( "HOME" ) ), osl_getThreadTextEncoding() );
72 inline int PtTo10Mu( int nPoints
) { return (int)((((double)nPoints
)*35.27777778)+0.5); }
74 inline int TenMuToPt( int nUnits
) { return (int)((((double)nUnits
)/35.27777778)+0.5); }
76 static void copyJobDataToJobSetup( ImplJobSetup
* pJobSetup
, JobData
& rData
)
78 pJobSetup
->meOrientation
= (Orientation
)(rData
.m_eOrientation
== orientation::Landscape
? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT
);
84 rData
.m_aContext
.getPageSize( aPaper
, width
, height
);
85 pJobSetup
->mePaperFormat
= PaperInfo::fromPSName(OUStringToOString( aPaper
, RTL_TEXTENCODING_ISO_8859_1
));
86 pJobSetup
->mnPaperWidth
= 0;
87 pJobSetup
->mnPaperHeight
= 0;
88 if( pJobSetup
->mePaperFormat
== PAPER_USER
)
90 // transform to 100dth mm
91 width
= PtTo10Mu( width
);
92 height
= PtTo10Mu( height
);
94 if( rData
.m_eOrientation
== psp::orientation::Portrait
)
96 pJobSetup
->mnPaperWidth
= width
;
97 pJobSetup
->mnPaperHeight
= height
;
101 pJobSetup
->mnPaperWidth
= height
;
102 pJobSetup
->mnPaperHeight
= width
;
107 const PPDKey
* pKey
= NULL
;
108 const PPDValue
* pValue
= NULL
;
110 pJobSetup
->mnPaperBin
= 0xffff;
111 if( rData
.m_pParser
)
112 pKey
= rData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
114 pValue
= rData
.m_aContext
.getValue( pKey
);
117 for( pJobSetup
->mnPaperBin
= 0;
118 pValue
!= pKey
->getValue( pJobSetup
->mnPaperBin
) &&
119 pJobSetup
->mnPaperBin
< pKey
->countValues();
120 pJobSetup
->mnPaperBin
++ )
122 if( pJobSetup
->mnPaperBin
>= pKey
->countValues() || pValue
== pKey
->getDefaultValue() )
123 pJobSetup
->mnPaperBin
= 0xffff;
127 // copy the whole context
128 if( pJobSetup
->mpDriverData
)
129 rtl_freeMemory( pJobSetup
->mpDriverData
);
132 void* pBuffer
= NULL
;
133 if( rData
.getStreamBuffer( pBuffer
, nBytes
) )
135 pJobSetup
->mnDriverDataLen
= nBytes
;
136 pJobSetup
->mpDriverData
= (BYTE
*)pBuffer
;
140 pJobSetup
->mnDriverDataLen
= 0;
141 pJobSetup
->mpDriverData
= NULL
;
145 static bool passFileToCommandLine( const String
& rFilename
, const String
& rCommandLine
, bool bRemoveFile
= true )
147 bool bSuccess
= false;
149 rtl_TextEncoding aEncoding
= osl_getThreadTextEncoding();
150 ByteString
aCmdLine( rCommandLine
, aEncoding
);
151 ByteString
aFilename( rFilename
, aEncoding
);
153 bool bPipe
= aCmdLine
.Search( "(TMP)" ) != STRING_NOTFOUND
? false : true;
155 // setup command line for exec
157 while( aCmdLine
.SearchAndReplace( "(TMP)", aFilename
) != STRING_NOTFOUND
)
160 #if OSL_DEBUG_LEVEL > 1
161 fprintf( stderr
, "%s commandline: \"%s\"\n",
162 bPipe
? "piping to" : "executing",
163 aCmdLine
.GetBuffer() );
165 if( stat( aFilename
.GetBuffer(), &aStat
) )
166 fprintf( stderr
, "stat( %s ) failed\n", aFilename
.GetBuffer() );
167 fprintf( stderr
, "Tmp file %s has modes: 0%03lo\n", aFilename
.GetBuffer(), (long)aStat
.st_mode
);
170 if( ! ( argv
[ 0 ] = getenv( "SHELL" ) ) )
171 argv
[ 0 ] = "/bin/sh";
173 argv
[ 2 ] = aCmdLine
.GetBuffer();
176 bool bHavePipes
= false;
180 bHavePipes
= pipe( fd
) ? false : true;
181 if( ( pid
= fork() ) > 0 )
183 if( bPipe
&& bHavePipes
)
186 char aBuffer
[ 2048 ];
187 FILE* fp
= fopen( aFilename
.GetBuffer(), "r" );
188 while( fp
&& ! feof( fp
) )
190 int nBytes
= fread( aBuffer
, 1, sizeof( aBuffer
), fp
);
192 write( fd
[ 1 ], aBuffer
, nBytes
);
198 waitpid( pid
, &status
, 0 );
204 if( bPipe
&& bHavePipes
)
207 if( fd
[0] != STDIN_FILENO
) // not probable, but who knows :)
208 dup2( fd
[0], STDIN_FILENO
);
210 execv( argv
[0], const_cast<char**>(argv
) );
211 fprintf( stderr
, "failed to execute \"%s\"\n", aCmdLine
.GetBuffer() );
215 fprintf( stderr
, "failed to fork\n" );
219 unlink( aFilename
.GetBuffer() );
224 static bool sendAFax( const String
& rFaxNumber
, const String
& rFileName
, const String
& rCommand
)
226 std::list
< OUString
> aFaxNumbers
;
228 if( ! rFaxNumber
.Len() )
231 sal_Int32 nIndex
= 0;
232 OUString
aFaxes( rFaxNumber
);
233 OUString
aBeginToken( RTL_CONSTASCII_USTRINGPARAM("<Fax#>") );
234 OUString
aEndToken( RTL_CONSTASCII_USTRINGPARAM("</Fax#>") );
235 while( nIndex
!= -1 )
237 nIndex
= aFaxes
.indexOf( aBeginToken
, nIndex
);
240 sal_Int32 nBegin
= nIndex
+ aBeginToken
.getLength();
241 nIndex
= aFaxes
.indexOf( aEndToken
, nIndex
);
244 aFaxNumbers
.push_back( aFaxes
.copy( nBegin
, nIndex
-nBegin
) );
245 nIndex
+= aEndToken
.getLength();
250 bool bSuccess
= true;
251 if( aFaxNumbers
.begin() != aFaxNumbers
.end() )
253 while( aFaxNumbers
.begin() != aFaxNumbers
.end() && bSuccess
)
255 String
aCmdLine( rCommand
);
256 String
aFaxNumber( aFaxNumbers
.front() );
257 aFaxNumbers
.pop_front();
258 while( aCmdLine
.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(PHONE)" ) ), aFaxNumber
) != STRING_NOTFOUND
)
260 #if OSL_DEBUG_LEVEL > 1
261 fprintf( stderr
, "sending fax to \"%s\"\n", OUStringToOString( aFaxNumber
, osl_getThreadTextEncoding() ).getStr() );
263 bSuccess
= passFileToCommandLine( rFileName
, aCmdLine
, false );
269 // clean up temp file
270 unlink( ByteString( rFileName
, osl_getThreadTextEncoding() ).GetBuffer() );
275 static bool createPdf( const String
& rToFile
, const String
& rFromFile
, const String
& rCommandLine
)
277 String
aCommandLine( rCommandLine
);
278 while( aCommandLine
.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(OUTFILE)" ) ), rToFile
) != STRING_NOTFOUND
)
280 return passFileToCommandLine( rFromFile
, aCommandLine
);
287 // -----------------------------------------------------------------------
289 SalInfoPrinter
* SvpSalInstance::CreateInfoPrinter( SalPrinterQueueInfo
* pQueueInfo
,
290 ImplJobSetup
* pJobSetup
)
292 // create and initialize SalInfoPrinter
293 PspSalInfoPrinter
* pPrinter
= new PspSalInfoPrinter
;
297 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
298 PrinterInfo
aInfo( rManager
.getPrinterInfo( pQueueInfo
->maPrinterName
) );
299 pPrinter
->m_aJobData
= aInfo
;
300 pPrinter
->m_aPrinterGfx
.Init( pPrinter
->m_aJobData
);
302 if( pJobSetup
->mpDriverData
)
303 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aInfo
);
305 pJobSetup
->mnSystem
= JOBSETUP_SYSTEM_UNIX
;
306 pJobSetup
->maPrinterName
= pQueueInfo
->maPrinterName
;
307 pJobSetup
->maDriver
= aInfo
.m_aDriverName
;
308 copyJobDataToJobSetup( pJobSetup
, aInfo
);
310 // set/clear backwards compatibility flag
311 bool bStrictSO52Compatibility
= false;
312 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
313 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
314 if( compat_it
!= pJobSetup
->maValueMap
.end() )
316 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
317 bStrictSO52Compatibility
= true;
319 pPrinter
->m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
326 // -----------------------------------------------------------------------
328 void SvpSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
333 // -----------------------------------------------------------------------
335 SalPrinter
* SvpSalInstance::CreatePrinter( SalInfoPrinter
* pInfoPrinter
)
337 // create and initialize SalPrinter
338 PspSalPrinter
* pPrinter
= new PspSalPrinter( pInfoPrinter
);
339 pPrinter
->m_aJobData
= static_cast<PspSalInfoPrinter
*>(pInfoPrinter
)->m_aJobData
;
344 // -----------------------------------------------------------------------
346 void SvpSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
351 // -----------------------------------------------------------------------
353 void SvpSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
355 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
356 static const char* pNoSyncDetection
= getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
357 if( ! pNoSyncDetection
|| ! *pNoSyncDetection
)
359 // #i62663# synchronize possible asynchronouse printer detection now
360 rManager
.checkPrintersChanged( true );
362 ::std::list
< OUString
> aPrinters
;
363 rManager
.listPrinters( aPrinters
);
365 for( ::std::list
< OUString
>::iterator it
= aPrinters
.begin(); it
!= aPrinters
.end(); ++it
)
367 const PrinterInfo
& rInfo( rManager
.getPrinterInfo( *it
) );
368 // Neuen Eintrag anlegen
369 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
370 pInfo
->maPrinterName
= *it
;
371 pInfo
->maDriver
= rInfo
.m_aDriverName
;
372 pInfo
->maLocation
= rInfo
.m_aLocation
;
373 pInfo
->maComment
= rInfo
.m_aComment
;
374 pInfo
->mpSysData
= NULL
;
376 sal_Int32 nIndex
= 0;
377 while( nIndex
!= -1 )
379 String
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
380 if( aToken
.CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL
)
382 pInfo
->maLocation
= getPdfDir( rInfo
);
391 // -----------------------------------------------------------------------
393 void SvpSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo
* pInfo
)
398 // -----------------------------------------------------------------------
400 void SvpSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* )
404 // -----------------------------------------------------------------------
406 String
SvpSalInstance::GetDefaultPrinter()
408 PrinterInfoManager
& rManager( PrinterInfoManager::get() );
409 return rManager
.getDefaultPrinter();
412 // =======================================================================
414 PspSalInfoPrinter::PspSalInfoPrinter()
417 m_bPapersInit
= false;
420 // -----------------------------------------------------------------------
422 PspSalInfoPrinter::~PspSalInfoPrinter()
431 // -----------------------------------------------------------------------
433 void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup
* )
435 m_aPaperFormats
.clear();
436 m_bPapersInit
= true;
438 if( m_aJobData
.m_pParser
)
440 const PPDKey
* pKey
= m_aJobData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
443 int nValues
= pKey
->countValues();
444 for( int i
= 0; i
< nValues
; i
++ )
446 const PPDValue
* pValue
= pKey
->getValue( i
);
447 int nWidth
= 0, nHeight
= 0;
448 m_aJobData
.m_pParser
->getPaperDimension( pValue
->m_aOption
, nWidth
, nHeight
);
449 PaperInfo
aInfo(PtTo10Mu( nWidth
), PtTo10Mu( nHeight
));
450 m_aPaperFormats
.push_back( aInfo
);
456 // -----------------------------------------------------------------------
458 DuplexMode
PspSalInfoPrinter::GetDuplexMode( const ImplJobSetup
* pJobSetup
)
460 DuplexMode aRet
= DUPLEX_UNKNOWN
;
461 PrinterInfo
aInfo( PrinterInfoManager::get().getPrinterInfo( pJobSetup
->maPrinterName
) );
462 if ( pJobSetup
->mpDriverData
)
463 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aInfo
);
464 if( aInfo
.m_pParser
)
466 const PPDKey
* pKey
= aInfo
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
469 const PPDValue
* pVal
= aInfo
.m_aContext
.getValue( pKey
);
471 pVal
->m_aOption
.EqualsIgnoreCaseAscii( "None" ) ||
472 pVal
->m_aOption
.EqualsIgnoreCaseAscii( "Simplex", 0, 7 )
484 // -----------------------------------------------------------------------
486 int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup
* )
491 // -----------------------------------------------------------------------
493 SalGraphics
* PspSalInfoPrinter::GetGraphics()
495 // return a valid pointer only once
496 // the reasoning behind this is that we could have different
497 // SalGraphics that can run in multiple threads
499 SalGraphics
* pRet
= NULL
;
502 m_pGraphics
= new PspGraphics( &m_aJobData
, &m_aPrinterGfx
, NULL
, false, this );
503 m_pGraphics
->SetLayout( 0 );
509 // -----------------------------------------------------------------------
511 void PspSalInfoPrinter::ReleaseGraphics( SalGraphics
* pGraphics
)
513 if( pGraphics
== m_pGraphics
)
521 // -----------------------------------------------------------------------
523 BOOL
PspSalInfoPrinter::Setup( SalFrame
*, ImplJobSetup
* )
528 // -----------------------------------------------------------------------
530 // This function gets the driver data and puts it into pJobSetup
531 // If pJobSetup->mpDriverData is NOT NULL, then the independend
532 // data should be merged into the driver data
533 // If pJobSetup->mpDriverData IS NULL, then the driver defaults
534 // should be merged into the independent data
535 BOOL
PspSalInfoPrinter::SetPrinterData( ImplJobSetup
* pJobSetup
)
537 if( pJobSetup
->mpDriverData
)
538 return SetData( ~0, pJobSetup
);
540 copyJobDataToJobSetup( pJobSetup
, m_aJobData
);
542 // set/clear backwards compatibility flag
543 bool bStrictSO52Compatibility
= false;
544 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
545 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
546 if( compat_it
!= pJobSetup
->maValueMap
.end() )
548 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
549 bStrictSO52Compatibility
= true;
551 m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
556 // -----------------------------------------------------------------------
558 // This function merges the independ driver data
559 // and sets the new independ data in pJobSetup
560 // Only the data must be changed, where the bit
561 // in nGetDataFlags is set
562 BOOL
PspSalInfoPrinter::SetData(
564 ImplJobSetup
* pJobSetup
)
567 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
569 if( aData
.m_pParser
)
572 const PPDValue
* pValue
;
574 // merge papersize if necessary
575 if( nSetDataFlags
& SAL_JOBSET_PAPERSIZE
)
578 if( pJobSetup
->meOrientation
== ORIENTATION_PORTRAIT
)
580 nWidth
= pJobSetup
->mnPaperWidth
;
581 nHeight
= pJobSetup
->mnPaperHeight
;
585 nWidth
= pJobSetup
->mnPaperHeight
;
586 nHeight
= pJobSetup
->mnPaperWidth
;
590 if( pJobSetup
->mePaperFormat
== PAPER_USER
)
591 aPaper
= aData
.m_pParser
->matchPaper(
592 TenMuToPt( pJobSetup
->mnPaperWidth
),
593 TenMuToPt( pJobSetup
->mnPaperHeight
) );
595 aPaper
= rtl::OStringToOUString(PaperInfo::toPSName(pJobSetup
->mePaperFormat
), RTL_TEXTENCODING_ISO_8859_1
);
597 pKey
= aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
598 pValue
= pKey
? pKey
->getValue( aPaper
) : NULL
;
599 if( ! ( pKey
&& pValue
&& aData
.m_aContext
.setValue( pKey
, pValue
, false ) == pValue
) )
603 // merge paperbin if necessary
604 if( nSetDataFlags
& SAL_JOBSET_PAPERBIN
)
606 pKey
= aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
609 int nPaperBin
= pJobSetup
->mnPaperBin
;
610 if( nPaperBin
== 0xffff )
611 pValue
= pKey
->getDefaultValue();
613 pValue
= pKey
->getValue( pJobSetup
->mnPaperBin
);
615 // may fail due to constraints;
616 // real paper bin is copied back to jobsetup in that case
617 aData
.m_aContext
.setValue( pKey
, pValue
);
619 // if printer has no InputSlot key simply ignore this setting
620 // (e.g. SGENPRT has no InputSlot)
623 // merge orientation if necessary
624 if( nSetDataFlags
& SAL_JOBSET_ORIENTATION
)
625 aData
.m_eOrientation
= pJobSetup
->meOrientation
== ORIENTATION_LANDSCAPE
? orientation::Landscape
: orientation::Portrait
;
628 copyJobDataToJobSetup( pJobSetup
, aData
);
635 // -----------------------------------------------------------------------
637 void PspSalInfoPrinter::GetPageInfo(
638 const ImplJobSetup
* pJobSetup
,
639 long& rOutWidth
, long& rOutHeight
,
640 long& rPageOffX
, long& rPageOffY
,
641 long& rPageWidth
, long& rPageHeight
)
647 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
649 // get the selected page size
650 if( aData
.m_pParser
)
655 int left
= 0, top
= 0, right
= 0, bottom
= 0;
656 int nDPI
= aData
.m_aContext
.getRenderResolution();
659 if( aData
.m_eOrientation
== psp::orientation::Portrait
)
661 aData
.m_aContext
.getPageSize( aPaper
, width
, height
);
662 aData
.m_pParser
->getMargins( aPaper
, left
, right
, top
, bottom
);
666 aData
.m_aContext
.getPageSize( aPaper
, height
, width
);
667 aData
.m_pParser
->getMargins( aPaper
, top
, bottom
, right
, left
);
670 rPageWidth
= width
* nDPI
/ 72;
671 rPageHeight
= height
* nDPI
/ 72;
672 rPageOffX
= left
* nDPI
/ 72;
673 rPageOffY
= top
* nDPI
/ 72;
674 rOutWidth
= ( width
- left
- right
) * nDPI
/ 72;
675 rOutHeight
= ( height
- top
- bottom
) * nDPI
/ 72;
679 // -----------------------------------------------------------------------
681 ULONG
PspSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pJobSetup
)
687 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
689 const PPDKey
* pKey
= aData
.m_pParser
? aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL
;
690 return pKey
? pKey
->countValues() : 0;
693 // -----------------------------------------------------------------------
695 String
PspSalInfoPrinter::GetPaperBinName( const ImplJobSetup
* pJobSetup
, ULONG nPaperBin
)
698 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, aData
);
701 if( aData
.m_pParser
)
703 const PPDKey
* pKey
= aData
.m_pParser
? aData
.m_pParser
->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL
;
704 if( nPaperBin
== 0xffff || ! pKey
)
705 aRet
= aData
.m_pParser
->getDefaultInputSlot();
708 const PPDValue
* pValue
= pKey
->getValue( nPaperBin
);
710 aRet
= pValue
->m_aOptionTranslation
.Len() ? pValue
->m_aOptionTranslation
: pValue
->m_aOption
;
717 // -----------------------------------------------------------------------
719 ULONG
PspSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pJobSetup
, USHORT nType
)
723 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
725 case PRINTER_CAPABILITIES_COPIES
:
727 case PRINTER_CAPABILITIES_COLLATECOPIES
:
729 case PRINTER_CAPABILITIES_SETORIENTATION
:
731 case PRINTER_CAPABILITIES_SETPAPERBIN
:
733 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
735 case PRINTER_CAPABILITIES_SETPAPER
:
737 case PRINTER_CAPABILITIES_FAX
:
739 PrinterInfoManager
& rManager
= PrinterInfoManager::get();
740 PrinterInfo
aInfo( rManager
.getPrinterInfo( pJobSetup
->maPrinterName
) );
741 String
aFeatures( aInfo
.m_aFeatures
);
742 int nTokenCount
= aFeatures
.GetTokenCount( ',' );
743 for( int i
= 0; i
< nTokenCount
; i
++ )
745 if( aFeatures
.GetToken( i
).CompareToAscii( "fax", 3 ) == COMPARE_EQUAL
)
750 case PRINTER_CAPABILITIES_PDF
:
752 PrinterInfoManager
& rManager
= PrinterInfoManager::get();
753 PrinterInfo
aInfo( rManager
.getPrinterInfo( pJobSetup
->maPrinterName
) );
754 String
aFeatures( aInfo
.m_aFeatures
);
755 int nTokenCount
= aFeatures
.GetTokenCount( ',' );
756 for( int i
= 0; i
< nTokenCount
; i
++ )
758 if( aFeatures
.GetToken( i
).CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL
)
768 // =======================================================================
774 PspSalPrinter::PspSalPrinter( SalInfoPrinter
* pInfoPrinter
)
777 m_bSwallowFaxNo( false ),
780 m_pInfoPrinter( pInfoPrinter
)
784 // -----------------------------------------------------------------------
786 PspSalPrinter::~PspSalPrinter()
790 // -----------------------------------------------------------------------
792 static String
getTmpName()
794 rtl::OUString aTmp
, aSys
;
795 osl_createTempFile( NULL
, NULL
, &aTmp
.pData
);
796 osl_getSystemPathFromFileURL( aTmp
.pData
, &aSys
.pData
);
801 BOOL
PspSalPrinter::StartJob(
802 const XubString
* pFileName
,
803 const XubString
& rJobName
,
804 const XubString
& rAppName
,
805 ULONG nCopies
, BOOL
/*bCollate*/,
806 ImplJobSetup
* pJobSetup
)
808 vcl_sal::PrinterUpdate::jobStarted();
812 m_aFileName
= pFileName
? *pFileName
: String();
813 m_aTmpFile
= String();
816 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, m_aJobData
);
818 // in case user did not do anything (m_nCopies=1)
819 // take the default from jobsetup
820 m_aJobData
.m_nCopies
= m_nCopies
;
822 // check wether this printer is configured as fax
824 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
825 sal_Int32 nIndex
= 0;
826 while( nIndex
!= -1 )
828 OUString
aToken( rInfo
.m_aFeatures
.getToken( 0, ',', nIndex
) );
829 if( ! aToken
.compareToAscii( "fax", 3 ) )
832 m_aTmpFile
= getTmpName();
833 nMode
= S_IRUSR
| S_IWUSR
;
835 ::std::hash_map
< ::rtl::OUString
, ::rtl::OUString
, ::rtl::OUStringHash
>::const_iterator it
;
836 it
= pJobSetup
->maValueMap
.find( ::rtl::OUString::createFromAscii( "FAX#" ) );
837 if( it
!= pJobSetup
->maValueMap
.end() )
838 m_aFaxNr
= it
->second
;
841 m_bSwallowFaxNo
= ! aToken
.getToken( 1, '=', nPos
).compareToAscii( "swallow", 7 ) ? true : false;
845 if( ! aToken
.compareToAscii( "pdf=", 4 ) )
848 m_aTmpFile
= getTmpName();
849 nMode
= S_IRUSR
| S_IWUSR
;
851 if( ! m_aFileName
.Len() )
853 m_aFileName
= getPdfDir( rInfo
);
854 m_aFileName
.Append( '/' );
855 m_aFileName
.Append( rJobName
);
856 m_aFileName
.AppendAscii( ".pdf" );
861 m_aPrinterGfx
.Init( m_aJobData
);
863 // set/clear backwards compatibility flag
864 bool bStrictSO52Compatibility
= false;
865 std::hash_map
<rtl::OUString
, rtl::OUString
, rtl::OUStringHash
>::const_iterator compat_it
=
866 pJobSetup
->maValueMap
.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
867 if( compat_it
!= pJobSetup
->maValueMap
.end() )
869 if( compat_it
->second
.equalsIgnoreAsciiCaseAscii( "true" ) )
870 bStrictSO52Compatibility
= true;
872 m_aPrinterGfx
.setStrictSO52Compatibility( bStrictSO52Compatibility
);
874 return m_aPrintJob
.StartJob( m_aTmpFile
.Len() ? m_aTmpFile
: m_aFileName
, nMode
, rJobName
, rAppName
, m_aJobData
, &m_aPrinterGfx
, false ) ? TRUE
: FALSE
;
877 // -----------------------------------------------------------------------
879 BOOL
PspSalPrinter::EndJob()
881 BOOL bSuccess
= m_aPrintJob
.EndJob();
889 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
890 // sendAFax removes the file after use
891 bSuccess
= sendAFax( m_aFaxNr
, m_aTmpFile
, rInfo
.m_aCommand
);
895 const PrinterInfo
& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData
.m_aPrinterName
) );
896 bSuccess
= createPdf( m_aFileName
, m_aTmpFile
, rInfo
.m_aCommand
);
899 vcl_sal::PrinterUpdate::jobEnded();
903 // -----------------------------------------------------------------------
905 BOOL
PspSalPrinter::AbortJob()
907 BOOL bAbort
= m_aPrintJob
.AbortJob() ? TRUE
: FALSE
;
908 vcl_sal::PrinterUpdate::jobEnded();
912 // -----------------------------------------------------------------------
914 SalGraphics
* PspSalPrinter::StartPage( ImplJobSetup
* pJobSetup
, BOOL
)
916 JobData::constructFromStreamBuffer( pJobSetup
->mpDriverData
, pJobSetup
->mnDriverDataLen
, m_aJobData
);
917 m_pGraphics
= new PspGraphics( &m_aJobData
, &m_aPrinterGfx
, m_bFax
? &m_aFaxNr
: NULL
, m_bSwallowFaxNo
, m_pInfoPrinter
);
918 m_pGraphics
->SetLayout( 0 );
920 // in case user did not do anything (m_nCopies=1)
921 // take the default from jobsetup
922 m_aJobData
.m_nCopies
= m_nCopies
;
924 m_aPrintJob
.StartPage( m_aJobData
);
925 m_aPrinterGfx
.Init( m_aPrintJob
);
930 // -----------------------------------------------------------------------
932 BOOL
PspSalPrinter::EndPage()
934 sal_Bool bResult
= m_aPrintJob
.EndPage();
935 m_aPrinterGfx
.Clear();
936 return bResult
? TRUE
: FALSE
;
939 // -----------------------------------------------------------------------
941 ULONG
PspSalPrinter::GetErrorCode()
950 Timer
* vcl_sal::PrinterUpdate::pPrinterUpdateTimer
= NULL
;
951 int vcl_sal::PrinterUpdate::nActiveJobs
= 0;
953 void vcl_sal::PrinterUpdate::doUpdate()
955 ::psp::PrinterInfoManager
& rManager( ::psp::PrinterInfoManager::get() );
956 if( rManager
.checkPrintersChanged( false ) && SvpSalInstance::s_pDefaultInstance
)
958 const std::list
< SalFrame
* >& rList
= SvpSalInstance::s_pDefaultInstance
->getFrames();
959 for( std::list
< SalFrame
* >::const_iterator it
= rList
.begin();
960 it
!= rList
.end(); ++it
)
961 SvpSalInstance::s_pDefaultInstance
->PostEvent( *it
, NULL
, SALEVENT_PRINTERCHANGED
);
965 // -----------------------------------------------------------------------
967 IMPL_STATIC_LINK_NOINSTANCE( vcl_sal::PrinterUpdate
, UpdateTimerHdl
, void*, )
969 if( nActiveJobs
< 1 )
972 delete pPrinterUpdateTimer
;
973 pPrinterUpdateTimer
= NULL
;
976 pPrinterUpdateTimer
->Start();
981 // -----------------------------------------------------------------------
983 void vcl_sal::PrinterUpdate::update()
985 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
988 static bool bOnce
= false;
992 // start background printer detection
993 psp::PrinterInfoManager::get();
997 if( nActiveJobs
< 1 )
999 else if( ! pPrinterUpdateTimer
)
1001 pPrinterUpdateTimer
= new Timer();
1002 pPrinterUpdateTimer
->SetTimeout( 500 );
1003 pPrinterUpdateTimer
->SetTimeoutHdl( STATIC_LINK( NULL
, vcl_sal::PrinterUpdate
, UpdateTimerHdl
) );
1004 pPrinterUpdateTimer
->Start();
1008 // -----------------------------------------------------------------------
1010 void vcl_sal::PrinterUpdate::jobEnded()
1013 if( nActiveJobs
< 1 )
1015 if( pPrinterUpdateTimer
)
1017 pPrinterUpdateTimer
->Stop();
1018 delete pPrinterUpdateTimer
;
1019 pPrinterUpdateTimer
= NULL
;