xref: /aoo41x/main/vcl/unx/headless/svpprn.cxx (revision 9f62ea84)
1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9f62ea84SAndrew Rist  * distributed with this work for additional information
6*9f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*9f62ea84SAndrew Rist  *
11*9f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*9f62ea84SAndrew Rist  *
13*9f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist  * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9f62ea84SAndrew Rist  * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist  * under the License.
19*9f62ea84SAndrew Rist  *
20*9f62ea84SAndrew Rist  *************************************************************/
21*9f62ea84SAndrew Rist 
22*9f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <unistd.h>
28cdf0e10cSrcweir #include <sys/stat.h>
29cdf0e10cSrcweir #include <sys/wait.h>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "vcl/svapp.hxx"
32cdf0e10cSrcweir #include "vcl/timer.hxx"
33cdf0e10cSrcweir #include "vcl/printerinfomanager.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "jobset.h"
36cdf0e10cSrcweir #include "print.h"
37cdf0e10cSrcweir #include "salptype.hxx"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include "svpprn.hxx"
40cdf0e10cSrcweir #include "svppspgraphics.hxx"
41cdf0e10cSrcweir #include "svpinst.hxx"
42cdf0e10cSrcweir 
43cdf0e10cSrcweir using namespace psp;
44cdf0e10cSrcweir using namespace rtl;
45cdf0e10cSrcweir 
46cdf0e10cSrcweir /*
47cdf0e10cSrcweir  *	static helpers
48cdf0e10cSrcweir  */
49cdf0e10cSrcweir 
getPdfDir(const PrinterInfo & rInfo)50cdf0e10cSrcweir static String getPdfDir( const PrinterInfo& rInfo )
51cdf0e10cSrcweir {
52cdf0e10cSrcweir 	String aDir;
53cdf0e10cSrcweir     sal_Int32 nIndex = 0;
54cdf0e10cSrcweir     while( nIndex != -1 )
55cdf0e10cSrcweir 	{
56cdf0e10cSrcweir 		OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
57cdf0e10cSrcweir 		if( ! aToken.compareToAscii( "pdf=", 4 ) )
58cdf0e10cSrcweir 		{
59cdf0e10cSrcweir             sal_Int32 nPos = 0;
60cdf0e10cSrcweir 			aDir = aToken.getToken( 1, '=', nPos );
61cdf0e10cSrcweir 			if( ! aDir.Len() )
62cdf0e10cSrcweir 				aDir = String( ByteString( getenv( "HOME" ) ), osl_getThreadTextEncoding() );
63cdf0e10cSrcweir 			break;
64cdf0e10cSrcweir 		}
65cdf0e10cSrcweir 	}
66cdf0e10cSrcweir 	return aDir;
67cdf0e10cSrcweir }
68cdf0e10cSrcweir 
PtTo10Mu(int nPoints)69cdf0e10cSrcweir inline int PtTo10Mu( int nPoints ) { return (int)((((double)nPoints)*35.27777778)+0.5); }
70cdf0e10cSrcweir 
TenMuToPt(int nUnits)71cdf0e10cSrcweir inline int TenMuToPt( int nUnits ) { return (int)((((double)nUnits)/35.27777778)+0.5); }
72cdf0e10cSrcweir 
copyJobDataToJobSetup(ImplJobSetup * pJobSetup,JobData & rData)73cdf0e10cSrcweir static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir 	pJobSetup->meOrientation	= (Orientation)(rData.m_eOrientation == orientation::Landscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT);
76cdf0e10cSrcweir 
77cdf0e10cSrcweir 	// copy page size
78cdf0e10cSrcweir 	String aPaper;
79cdf0e10cSrcweir 	int width, height;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 	rData.m_aContext.getPageSize( aPaper, width, height );
82cdf0e10cSrcweir 	pJobSetup->mePaperFormat	= PaperInfo::fromPSName(OUStringToOString( aPaper, RTL_TEXTENCODING_ISO_8859_1 ));
83cdf0e10cSrcweir 	pJobSetup->mnPaperWidth		= 0;
84cdf0e10cSrcweir 	pJobSetup->mnPaperHeight	= 0;
85cdf0e10cSrcweir 	if( pJobSetup->mePaperFormat == PAPER_USER )
86cdf0e10cSrcweir 	{
87cdf0e10cSrcweir 		// transform to 100dth mm
88cdf0e10cSrcweir 		width				= PtTo10Mu( width );
89cdf0e10cSrcweir 		height				= PtTo10Mu( height );
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         if( rData.m_eOrientation == psp::orientation::Portrait )
92cdf0e10cSrcweir         {
93cdf0e10cSrcweir             pJobSetup->mnPaperWidth	= width;
94cdf0e10cSrcweir             pJobSetup->mnPaperHeight= height;
95cdf0e10cSrcweir         }
96cdf0e10cSrcweir         else
97cdf0e10cSrcweir         {
98cdf0e10cSrcweir             pJobSetup->mnPaperWidth	= height;
99cdf0e10cSrcweir             pJobSetup->mnPaperHeight= width;
100cdf0e10cSrcweir         }
101cdf0e10cSrcweir 	}
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 	// copy input slot
104cdf0e10cSrcweir 	const PPDKey* pKey = NULL;
105cdf0e10cSrcweir 	const PPDValue* pValue = NULL;
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     pJobSetup->mnPaperBin = 0xffff;
108cdf0e10cSrcweir     if( rData.m_pParser )
109cdf0e10cSrcweir 	    pKey					= rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
110cdf0e10cSrcweir     if( pKey )
111cdf0e10cSrcweir         pValue					= rData.m_aContext.getValue( pKey );
112cdf0e10cSrcweir     if( pKey && pValue )
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         for( pJobSetup->mnPaperBin = 0;
115cdf0e10cSrcweir              pValue != pKey->getValue( pJobSetup->mnPaperBin ) &&
116cdf0e10cSrcweir                  pJobSetup->mnPaperBin < pKey->countValues();
117cdf0e10cSrcweir              pJobSetup->mnPaperBin++ )
118cdf0e10cSrcweir             ;
119cdf0e10cSrcweir         if( pJobSetup->mnPaperBin >= pKey->countValues() || pValue == pKey->getDefaultValue() )
120cdf0e10cSrcweir             pJobSetup->mnPaperBin = 0xffff;
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     // copy duplex
124cdf0e10cSrcweir     pKey = NULL;
125cdf0e10cSrcweir     pValue = NULL;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir     pJobSetup->meDuplexMode = DUPLEX_UNKNOWN;
128cdf0e10cSrcweir     if( rData.m_pParser )
129cdf0e10cSrcweir         pKey = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
130cdf0e10cSrcweir     if( pKey )
131cdf0e10cSrcweir         pValue = rData.m_aContext.getValue( pKey );
132cdf0e10cSrcweir     if( pKey && pValue )
133cdf0e10cSrcweir     {
134cdf0e10cSrcweir         if( pValue->m_aOption.EqualsIgnoreCaseAscii( "None" ) ||
135cdf0e10cSrcweir             pValue->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 )
136cdf0e10cSrcweir            )
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             pJobSetup->meDuplexMode = DUPLEX_OFF;
139cdf0e10cSrcweir         }
140cdf0e10cSrcweir         else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexNoTumble" ) )
141cdf0e10cSrcweir         {
142cdf0e10cSrcweir             pJobSetup->meDuplexMode = DUPLEX_LONGEDGE;
143cdf0e10cSrcweir         }
144cdf0e10cSrcweir         else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexTumble" ) )
145cdf0e10cSrcweir         {
146cdf0e10cSrcweir             pJobSetup->meDuplexMode = DUPLEX_SHORTEDGE;
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 	// copy the whole context
151cdf0e10cSrcweir 	if( pJobSetup->mpDriverData )
152cdf0e10cSrcweir 		rtl_freeMemory( pJobSetup->mpDriverData );
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	int nBytes;
155cdf0e10cSrcweir 	void* pBuffer = NULL;
156cdf0e10cSrcweir 	if( rData.getStreamBuffer( pBuffer, nBytes ) )
157cdf0e10cSrcweir 	{
158cdf0e10cSrcweir 		pJobSetup->mnDriverDataLen = nBytes;
159cdf0e10cSrcweir 		pJobSetup->mpDriverData = (sal_uInt8*)pBuffer;
160cdf0e10cSrcweir 	}
161cdf0e10cSrcweir 	else
162cdf0e10cSrcweir 	{
163cdf0e10cSrcweir 		pJobSetup->mnDriverDataLen = 0;
164cdf0e10cSrcweir 		pJobSetup->mpDriverData = NULL;
165cdf0e10cSrcweir 	}
166cdf0e10cSrcweir }
167cdf0e10cSrcweir 
passFileToCommandLine(const String & rFilename,const String & rCommandLine,bool bRemoveFile=true)168cdf0e10cSrcweir static bool passFileToCommandLine( const String& rFilename, const String& rCommandLine, bool bRemoveFile = true )
169cdf0e10cSrcweir {
170cdf0e10cSrcweir 	bool bSuccess = false;
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
173cdf0e10cSrcweir 	ByteString aCmdLine( rCommandLine, aEncoding );
174cdf0e10cSrcweir 	ByteString aFilename( rFilename, aEncoding );
175cdf0e10cSrcweir 
176cdf0e10cSrcweir 	bool bPipe = aCmdLine.Search( "(TMP)" ) != STRING_NOTFOUND ? false : true;
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 	// setup command line for exec
179cdf0e10cSrcweir 	if( ! bPipe )
180cdf0e10cSrcweir 		while( aCmdLine.SearchAndReplace( "(TMP)", aFilename ) != STRING_NOTFOUND )
181cdf0e10cSrcweir 			;
182cdf0e10cSrcweir 
183cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
184cdf0e10cSrcweir 	fprintf( stderr, "%s commandline: \"%s\"\n",
185cdf0e10cSrcweir 			 bPipe ? "piping to" : "executing",
186cdf0e10cSrcweir 			 aCmdLine.GetBuffer() );
187cdf0e10cSrcweir     struct stat aStat;
188cdf0e10cSrcweir     if( stat( aFilename.GetBuffer(), &aStat ) )
189cdf0e10cSrcweir         fprintf( stderr, "stat( %s ) failed\n", aFilename.GetBuffer() );
190cdf0e10cSrcweir     fprintf( stderr, "Tmp file %s has modes: 0%03lo\n", aFilename.GetBuffer(), (long)aStat.st_mode );
191cdf0e10cSrcweir #endif
192cdf0e10cSrcweir 	const char* argv[4];
193cdf0e10cSrcweir 	if( ! ( argv[ 0 ] = getenv( "SHELL" ) ) )
194cdf0e10cSrcweir 		argv[ 0 ] = "/bin/sh";
195cdf0e10cSrcweir 	argv[ 1 ] = "-c";
196cdf0e10cSrcweir 	argv[ 2 ] = aCmdLine.GetBuffer();
197cdf0e10cSrcweir 	argv[ 3 ] = 0;
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 	bool bHavePipes = false;
200cdf0e10cSrcweir 	int pid, fd[2];
201cdf0e10cSrcweir 
202cdf0e10cSrcweir 	if( bPipe )
203cdf0e10cSrcweir 		bHavePipes = pipe( fd ) ? false : true;
204cdf0e10cSrcweir 	if( ( pid = fork() ) > 0 )
205cdf0e10cSrcweir 	{
206cdf0e10cSrcweir 		if( bPipe && bHavePipes )
207cdf0e10cSrcweir 		{
208cdf0e10cSrcweir 			close( fd[0] );
209cdf0e10cSrcweir 			char aBuffer[ 2048 ];
210cdf0e10cSrcweir 			FILE* fp = fopen( aFilename.GetBuffer(), "r" );
211cdf0e10cSrcweir 			while( fp && ! feof( fp ) )
212cdf0e10cSrcweir 			{
213cdf0e10cSrcweir 				int nBytes = fread( aBuffer, 1, sizeof( aBuffer ), fp );
214cdf0e10cSrcweir 				if( nBytes )
215cdf0e10cSrcweir 					write( fd[ 1 ], aBuffer, nBytes );
216cdf0e10cSrcweir 			}
217cdf0e10cSrcweir 			fclose( fp );
218cdf0e10cSrcweir 			close( fd[ 1 ] );
219cdf0e10cSrcweir 		}
220cdf0e10cSrcweir 		int status = 0;
221cdf0e10cSrcweir 		waitpid( pid, &status, 0 );
222cdf0e10cSrcweir 		if( ! status )
223cdf0e10cSrcweir 			bSuccess = true;
224cdf0e10cSrcweir 	}
225cdf0e10cSrcweir 	else if( ! pid )
226cdf0e10cSrcweir 	{
227cdf0e10cSrcweir 		if( bPipe && bHavePipes )
228cdf0e10cSrcweir 		{
229cdf0e10cSrcweir 			close( fd[1] );
230cdf0e10cSrcweir 			if( fd[0] != STDIN_FILENO ) // not probable, but who knows :)
231cdf0e10cSrcweir 				dup2( fd[0], STDIN_FILENO );
232cdf0e10cSrcweir 		}
233cdf0e10cSrcweir 		execv( argv[0], const_cast<char**>(argv) );
234cdf0e10cSrcweir 		fprintf( stderr, "failed to execute \"%s\"\n", aCmdLine.GetBuffer() );
235cdf0e10cSrcweir 		_exit( 1 );
236cdf0e10cSrcweir 	}
237cdf0e10cSrcweir 	else
238cdf0e10cSrcweir 		fprintf( stderr, "failed to fork\n" );
239cdf0e10cSrcweir 
240cdf0e10cSrcweir 	// clean up the mess
241cdf0e10cSrcweir     if( bRemoveFile )
242cdf0e10cSrcweir         unlink( aFilename.GetBuffer() );
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 	return bSuccess;
245cdf0e10cSrcweir }
246cdf0e10cSrcweir 
sendAFax(const String & rFaxNumber,const String & rFileName,const String & rCommand)247cdf0e10cSrcweir static bool sendAFax( const String& rFaxNumber, const String& rFileName, const String& rCommand )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir     std::list< OUString > aFaxNumbers;
250cdf0e10cSrcweir 
251cdf0e10cSrcweir 	if( ! rFaxNumber.Len() )
252cdf0e10cSrcweir         return false;
253cdf0e10cSrcweir 
254cdf0e10cSrcweir     sal_Int32 nIndex = 0;
255cdf0e10cSrcweir     OUString aFaxes( rFaxNumber );
256cdf0e10cSrcweir     OUString aBeginToken( RTL_CONSTASCII_USTRINGPARAM("<Fax#>") );
257cdf0e10cSrcweir     OUString aEndToken( RTL_CONSTASCII_USTRINGPARAM("</Fax#>") );
258cdf0e10cSrcweir     while( nIndex != -1 )
259cdf0e10cSrcweir     {
260cdf0e10cSrcweir         nIndex = aFaxes.indexOf( aBeginToken, nIndex );
261cdf0e10cSrcweir         if( nIndex != -1 )
262cdf0e10cSrcweir         {
263cdf0e10cSrcweir             sal_Int32 nBegin = nIndex + aBeginToken.getLength();
264cdf0e10cSrcweir             nIndex = aFaxes.indexOf( aEndToken, nIndex );
265cdf0e10cSrcweir             if( nIndex != -1 )
266cdf0e10cSrcweir             {
267cdf0e10cSrcweir                 aFaxNumbers.push_back( aFaxes.copy( nBegin, nIndex-nBegin ) );
268cdf0e10cSrcweir                 nIndex += aEndToken.getLength();
269cdf0e10cSrcweir             }
270cdf0e10cSrcweir         }
271cdf0e10cSrcweir     }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     bool bSuccess = true;
274cdf0e10cSrcweir     if( aFaxNumbers.begin() != aFaxNumbers.end() )
275cdf0e10cSrcweir 	{
276cdf0e10cSrcweir         while( aFaxNumbers.begin() != aFaxNumbers.end() && bSuccess )
277cdf0e10cSrcweir         {
278cdf0e10cSrcweir             String aCmdLine( rCommand );
279cdf0e10cSrcweir             String aFaxNumber( aFaxNumbers.front() );
280cdf0e10cSrcweir             aFaxNumbers.pop_front();
281cdf0e10cSrcweir             while( aCmdLine.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(PHONE)" ) ), aFaxNumber ) != STRING_NOTFOUND )
282cdf0e10cSrcweir                 ;
283cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
284cdf0e10cSrcweir             fprintf( stderr, "sending fax to \"%s\"\n", OUStringToOString( aFaxNumber, osl_getThreadTextEncoding() ).getStr() );
285cdf0e10cSrcweir #endif
286cdf0e10cSrcweir             bSuccess = passFileToCommandLine( rFileName, aCmdLine, false );
287cdf0e10cSrcweir         }
288cdf0e10cSrcweir 	}
289cdf0e10cSrcweir     else
290cdf0e10cSrcweir         bSuccess = false;
291cdf0e10cSrcweir 
292cdf0e10cSrcweir     // clean up temp file
293cdf0e10cSrcweir     unlink( ByteString( rFileName, osl_getThreadTextEncoding() ).GetBuffer() );
294cdf0e10cSrcweir 
295cdf0e10cSrcweir     return bSuccess;
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
createPdf(const String & rToFile,const String & rFromFile,const String & rCommandLine)298cdf0e10cSrcweir static bool createPdf( const String& rToFile, const String& rFromFile, const String& rCommandLine )
299cdf0e10cSrcweir {
300cdf0e10cSrcweir 	String aCommandLine( rCommandLine );
301cdf0e10cSrcweir 	while( aCommandLine.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "(OUTFILE)" ) ), rToFile ) != STRING_NOTFOUND )
302cdf0e10cSrcweir 		;
303cdf0e10cSrcweir 	return passFileToCommandLine( rFromFile, aCommandLine );
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir /*
307cdf0e10cSrcweir  *	SalInstance
308cdf0e10cSrcweir  */
309cdf0e10cSrcweir 
310cdf0e10cSrcweir // -----------------------------------------------------------------------
311cdf0e10cSrcweir 
CreateInfoPrinter(SalPrinterQueueInfo * pQueueInfo,ImplJobSetup * pJobSetup)312cdf0e10cSrcweir SalInfoPrinter* SvpSalInstance::CreateInfoPrinter( SalPrinterQueueInfo*	pQueueInfo,
313cdf0e10cSrcweir                                                    ImplJobSetup*			pJobSetup )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir 	// create and initialize SalInfoPrinter
316cdf0e10cSrcweir 	PspSalInfoPrinter* pPrinter = new PspSalInfoPrinter;
317cdf0e10cSrcweir 
318cdf0e10cSrcweir 	if( pJobSetup )
319cdf0e10cSrcweir 	{
320cdf0e10cSrcweir 		PrinterInfoManager& rManager( PrinterInfoManager::get() );
321cdf0e10cSrcweir 		PrinterInfo aInfo( rManager.getPrinterInfo( pQueueInfo->maPrinterName ) );
322cdf0e10cSrcweir 		pPrinter->m_aJobData = aInfo;
323cdf0e10cSrcweir 		pPrinter->m_aPrinterGfx.Init( pPrinter->m_aJobData );
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 		if( pJobSetup->mpDriverData )
326cdf0e10cSrcweir 			JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo );
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 		pJobSetup->mnSystem			= JOBSETUP_SYSTEM_UNIX;
329cdf0e10cSrcweir 		pJobSetup->maPrinterName	= pQueueInfo->maPrinterName;
330cdf0e10cSrcweir 		pJobSetup->maDriver			= aInfo.m_aDriverName;
331cdf0e10cSrcweir 		copyJobDataToJobSetup( pJobSetup, aInfo );
332cdf0e10cSrcweir 
333cdf0e10cSrcweir         // set/clear backwards compatibility flag
334cdf0e10cSrcweir         bool bStrictSO52Compatibility = false;
335cdf0e10cSrcweir         std::hash_map<rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator compat_it =
336cdf0e10cSrcweir             pJobSetup->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
337cdf0e10cSrcweir         if( compat_it != pJobSetup->maValueMap.end() )
338cdf0e10cSrcweir         {
339cdf0e10cSrcweir             if( compat_it->second.equalsIgnoreAsciiCaseAscii( "true" ) )
340cdf0e10cSrcweir                 bStrictSO52Compatibility = true;
341cdf0e10cSrcweir         }
342cdf0e10cSrcweir         pPrinter->m_aPrinterGfx.setStrictSO52Compatibility( bStrictSO52Compatibility );
343cdf0e10cSrcweir 	}
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 
346cdf0e10cSrcweir 	return pPrinter;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir // -----------------------------------------------------------------------
350cdf0e10cSrcweir 
DestroyInfoPrinter(SalInfoPrinter * pPrinter)351cdf0e10cSrcweir void SvpSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
352cdf0e10cSrcweir {
353cdf0e10cSrcweir 	delete pPrinter;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir // -----------------------------------------------------------------------
357cdf0e10cSrcweir 
CreatePrinter(SalInfoPrinter * pInfoPrinter)358cdf0e10cSrcweir SalPrinter* SvpSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
359cdf0e10cSrcweir {
360cdf0e10cSrcweir 	// create and initialize SalPrinter
361cdf0e10cSrcweir 	PspSalPrinter* pPrinter = new PspSalPrinter( pInfoPrinter );
362cdf0e10cSrcweir 	pPrinter->m_aJobData = static_cast<PspSalInfoPrinter*>(pInfoPrinter)->m_aJobData;
363cdf0e10cSrcweir 
364cdf0e10cSrcweir 	return pPrinter;
365cdf0e10cSrcweir }
366cdf0e10cSrcweir 
367cdf0e10cSrcweir // -----------------------------------------------------------------------
368cdf0e10cSrcweir 
DestroyPrinter(SalPrinter * pPrinter)369cdf0e10cSrcweir void SvpSalInstance::DestroyPrinter( SalPrinter* pPrinter )
370cdf0e10cSrcweir {
371cdf0e10cSrcweir 	delete pPrinter;
372cdf0e10cSrcweir }
373cdf0e10cSrcweir 
374cdf0e10cSrcweir // -----------------------------------------------------------------------
375cdf0e10cSrcweir 
GetPrinterQueueInfo(ImplPrnQueueList * pList)376cdf0e10cSrcweir void SvpSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
377cdf0e10cSrcweir {
378cdf0e10cSrcweir 	PrinterInfoManager& rManager( PrinterInfoManager::get() );
379cdf0e10cSrcweir     static const char* pNoSyncDetection = getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
380cdf0e10cSrcweir     if( ! pNoSyncDetection || ! *pNoSyncDetection )
381cdf0e10cSrcweir     {
382cdf0e10cSrcweir         // #i62663# synchronize possible asynchronouse printer detection now
383cdf0e10cSrcweir         rManager.checkPrintersChanged( true );
384cdf0e10cSrcweir     }
385cdf0e10cSrcweir 	::std::list< OUString > aPrinters;
386cdf0e10cSrcweir 	rManager.listPrinters( aPrinters );
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 	for( ::std::list< OUString >::iterator it = aPrinters.begin(); it != aPrinters.end(); ++it )
389cdf0e10cSrcweir 	{
390cdf0e10cSrcweir 		const PrinterInfo& rInfo( rManager.getPrinterInfo( *it ) );
391cdf0e10cSrcweir 		// Neuen Eintrag anlegen
392cdf0e10cSrcweir 		SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
393cdf0e10cSrcweir 		pInfo->maPrinterName	= *it;
394cdf0e10cSrcweir 		pInfo->maDriver			= rInfo.m_aDriverName;
395cdf0e10cSrcweir 		pInfo->maLocation		= rInfo.m_aLocation;
396cdf0e10cSrcweir 		pInfo->maComment      	= rInfo.m_aComment;
397cdf0e10cSrcweir 		pInfo->mpSysData		= NULL;
398cdf0e10cSrcweir 
399cdf0e10cSrcweir         sal_Int32 nIndex = 0;
400cdf0e10cSrcweir         while( nIndex != -1 )
401cdf0e10cSrcweir 		{
402cdf0e10cSrcweir 			String aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
403cdf0e10cSrcweir 			if( aToken.CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL )
404cdf0e10cSrcweir 			{
405cdf0e10cSrcweir 				pInfo->maLocation = getPdfDir( rInfo );
406cdf0e10cSrcweir 				break;
407cdf0e10cSrcweir 			}
408cdf0e10cSrcweir 		}
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 		pList->Add( pInfo );
411cdf0e10cSrcweir 	}
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir // -----------------------------------------------------------------------
415cdf0e10cSrcweir 
DeletePrinterQueueInfo(SalPrinterQueueInfo * pInfo)416cdf0e10cSrcweir void SvpSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir 	delete pInfo;
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir // -----------------------------------------------------------------------
422cdf0e10cSrcweir 
GetPrinterQueueState(SalPrinterQueueInfo *)423cdf0e10cSrcweir void SvpSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* )
424cdf0e10cSrcweir {
425cdf0e10cSrcweir }
426cdf0e10cSrcweir 
427cdf0e10cSrcweir // -----------------------------------------------------------------------
428cdf0e10cSrcweir 
GetDefaultPrinter()429cdf0e10cSrcweir String SvpSalInstance::GetDefaultPrinter()
430cdf0e10cSrcweir {
431cdf0e10cSrcweir 	PrinterInfoManager& rManager( PrinterInfoManager::get() );
432cdf0e10cSrcweir 	return rManager.getDefaultPrinter();
433cdf0e10cSrcweir }
434cdf0e10cSrcweir 
435cdf0e10cSrcweir // =======================================================================
436cdf0e10cSrcweir 
PspSalInfoPrinter()437cdf0e10cSrcweir PspSalInfoPrinter::PspSalInfoPrinter()
438cdf0e10cSrcweir {
439cdf0e10cSrcweir 	m_pGraphics = NULL;
440cdf0e10cSrcweir     m_bPapersInit = false;
441cdf0e10cSrcweir }
442cdf0e10cSrcweir 
443cdf0e10cSrcweir // -----------------------------------------------------------------------
444cdf0e10cSrcweir 
~PspSalInfoPrinter()445cdf0e10cSrcweir PspSalInfoPrinter::~PspSalInfoPrinter()
446cdf0e10cSrcweir {
447cdf0e10cSrcweir 	if( m_pGraphics )
448cdf0e10cSrcweir 	{
449cdf0e10cSrcweir 		delete m_pGraphics;
450cdf0e10cSrcweir 		m_pGraphics = NULL;
451cdf0e10cSrcweir 	}
452cdf0e10cSrcweir }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir // -----------------------------------------------------------------------
455cdf0e10cSrcweir 
InitPaperFormats(const ImplJobSetup *)456cdf0e10cSrcweir void PspSalInfoPrinter::InitPaperFormats( const ImplJobSetup* )
457cdf0e10cSrcweir {
458cdf0e10cSrcweir     m_aPaperFormats.clear();
459cdf0e10cSrcweir     m_bPapersInit = true;
460cdf0e10cSrcweir 
461cdf0e10cSrcweir     if( m_aJobData.m_pParser )
462cdf0e10cSrcweir     {
463cdf0e10cSrcweir         const PPDKey* pKey = m_aJobData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
464cdf0e10cSrcweir         if( pKey )
465cdf0e10cSrcweir         {
466cdf0e10cSrcweir             int nValues = pKey->countValues();
467cdf0e10cSrcweir             for( int i = 0; i < nValues; i++ )
468cdf0e10cSrcweir             {
469cdf0e10cSrcweir                 const PPDValue* pValue = pKey->getValue( i );
470cdf0e10cSrcweir                 int nWidth = 0, nHeight = 0;
471cdf0e10cSrcweir                 m_aJobData.m_pParser->getPaperDimension( pValue->m_aOption, nWidth, nHeight );
472cdf0e10cSrcweir                 PaperInfo aInfo(PtTo10Mu( nWidth ), PtTo10Mu( nHeight ));
473cdf0e10cSrcweir                 m_aPaperFormats.push_back( aInfo );
474cdf0e10cSrcweir             }
475cdf0e10cSrcweir         }
476cdf0e10cSrcweir     }
477cdf0e10cSrcweir }
478cdf0e10cSrcweir 
479cdf0e10cSrcweir // -----------------------------------------------------------------------
480cdf0e10cSrcweir 
GetLandscapeAngle(const ImplJobSetup *)481cdf0e10cSrcweir int PspSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* )
482cdf0e10cSrcweir {
483cdf0e10cSrcweir     return 900;
484cdf0e10cSrcweir }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir // -----------------------------------------------------------------------
487cdf0e10cSrcweir 
GetGraphics()488cdf0e10cSrcweir SalGraphics* PspSalInfoPrinter::GetGraphics()
489cdf0e10cSrcweir {
490cdf0e10cSrcweir 	// return a valid pointer only once
491cdf0e10cSrcweir 	// the reasoning behind this is that we could have different
492cdf0e10cSrcweir 	// SalGraphics that can run in multiple threads
493cdf0e10cSrcweir 	// (future plans)
494cdf0e10cSrcweir 	SalGraphics* pRet = NULL;
495cdf0e10cSrcweir 	if( ! m_pGraphics )
496cdf0e10cSrcweir 	{
497cdf0e10cSrcweir 		m_pGraphics = new PspGraphics( &m_aJobData, &m_aPrinterGfx, NULL, false, this );
498cdf0e10cSrcweir         m_pGraphics->SetLayout( 0 );
499cdf0e10cSrcweir 		pRet = m_pGraphics;
500cdf0e10cSrcweir 	}
501cdf0e10cSrcweir 	return pRet;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
504cdf0e10cSrcweir // -----------------------------------------------------------------------
505cdf0e10cSrcweir 
ReleaseGraphics(SalGraphics * pGraphics)506cdf0e10cSrcweir void PspSalInfoPrinter::ReleaseGraphics( SalGraphics* pGraphics )
507cdf0e10cSrcweir {
508cdf0e10cSrcweir 	if( pGraphics == m_pGraphics )
509cdf0e10cSrcweir 	{
510cdf0e10cSrcweir 		delete pGraphics;
511cdf0e10cSrcweir 		m_pGraphics = NULL;
512cdf0e10cSrcweir 	}
513cdf0e10cSrcweir 	return;
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir // -----------------------------------------------------------------------
517cdf0e10cSrcweir 
Setup(SalFrame *,ImplJobSetup *)518cdf0e10cSrcweir sal_Bool PspSalInfoPrinter::Setup( SalFrame*, ImplJobSetup* )
519cdf0e10cSrcweir {
520cdf0e10cSrcweir 	return sal_False;
521cdf0e10cSrcweir }
522cdf0e10cSrcweir 
523cdf0e10cSrcweir // -----------------------------------------------------------------------
524cdf0e10cSrcweir 
525cdf0e10cSrcweir // This function gets the driver data and puts it into pJobSetup
526cdf0e10cSrcweir // If pJobSetup->mpDriverData is NOT NULL, then the independend
527cdf0e10cSrcweir // data should be merged into the driver data
528cdf0e10cSrcweir // If pJobSetup->mpDriverData IS NULL, then the driver defaults
529cdf0e10cSrcweir // should be merged into the independent data
SetPrinterData(ImplJobSetup * pJobSetup)530cdf0e10cSrcweir sal_Bool PspSalInfoPrinter::SetPrinterData( ImplJobSetup* pJobSetup )
531cdf0e10cSrcweir {
532cdf0e10cSrcweir 	if( pJobSetup->mpDriverData )
533cdf0e10cSrcweir 		return SetData( ~0, pJobSetup );
534cdf0e10cSrcweir 
535cdf0e10cSrcweir 	copyJobDataToJobSetup( pJobSetup, m_aJobData );
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     // set/clear backwards compatibility flag
538cdf0e10cSrcweir     bool bStrictSO52Compatibility = false;
539cdf0e10cSrcweir     std::hash_map<rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator compat_it =
540cdf0e10cSrcweir         pJobSetup->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
541cdf0e10cSrcweir     if( compat_it != pJobSetup->maValueMap.end() )
542cdf0e10cSrcweir     {
543cdf0e10cSrcweir         if( compat_it->second.equalsIgnoreAsciiCaseAscii( "true" ) )
544cdf0e10cSrcweir             bStrictSO52Compatibility = true;
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir     m_aPrinterGfx.setStrictSO52Compatibility( bStrictSO52Compatibility );
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 	return sal_True;
549cdf0e10cSrcweir }
550cdf0e10cSrcweir 
551cdf0e10cSrcweir // -----------------------------------------------------------------------
552cdf0e10cSrcweir 
553cdf0e10cSrcweir // This function merges the independ driver data
554cdf0e10cSrcweir // and sets the new independ data in pJobSetup
555cdf0e10cSrcweir // Only the data must be changed, where the bit
556cdf0e10cSrcweir // in nGetDataFlags is set
SetData(sal_uLong nSetDataFlags,ImplJobSetup * pJobSetup)557cdf0e10cSrcweir sal_Bool PspSalInfoPrinter::SetData(
558cdf0e10cSrcweir 	sal_uLong nSetDataFlags,
559cdf0e10cSrcweir 	ImplJobSetup* pJobSetup )
560cdf0e10cSrcweir {
561cdf0e10cSrcweir 	JobData aData;
562cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
563cdf0e10cSrcweir 
564cdf0e10cSrcweir 	if( aData.m_pParser )
565cdf0e10cSrcweir 	{
566cdf0e10cSrcweir 		const PPDKey* pKey;
567cdf0e10cSrcweir 		const PPDValue* pValue;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 		// merge papersize if necessary
570cdf0e10cSrcweir 		if( nSetDataFlags & SAL_JOBSET_PAPERSIZE )
571cdf0e10cSrcweir 		{
572cdf0e10cSrcweir             int nWidth, nHeight;
573cdf0e10cSrcweir             if( pJobSetup->meOrientation == ORIENTATION_PORTRAIT )
574cdf0e10cSrcweir             {
575cdf0e10cSrcweir                 nWidth	= pJobSetup->mnPaperWidth;
576cdf0e10cSrcweir                 nHeight	= pJobSetup->mnPaperHeight;
577cdf0e10cSrcweir             }
578cdf0e10cSrcweir             else
579cdf0e10cSrcweir             {
580cdf0e10cSrcweir                 nWidth	= pJobSetup->mnPaperHeight;
581cdf0e10cSrcweir                 nHeight	= pJobSetup->mnPaperWidth;
582cdf0e10cSrcweir             }
583cdf0e10cSrcweir 			String aPaper;
584cdf0e10cSrcweir 
585cdf0e10cSrcweir             if( pJobSetup->mePaperFormat == PAPER_USER )
586cdf0e10cSrcweir                 aPaper = aData.m_pParser->matchPaper(
587cdf0e10cSrcweir                     TenMuToPt( pJobSetup->mnPaperWidth ),
588cdf0e10cSrcweir                     TenMuToPt( pJobSetup->mnPaperHeight ) );
589cdf0e10cSrcweir             else
590cdf0e10cSrcweir 				aPaper = rtl::OStringToOUString(PaperInfo::toPSName(pJobSetup->mePaperFormat), RTL_TEXTENCODING_ISO_8859_1);
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 			pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
593cdf0e10cSrcweir 			pValue = pKey ? pKey->getValue( aPaper ) : NULL;
594cdf0e10cSrcweir 			if( ! ( pKey && pValue && aData.m_aContext.setValue( pKey, pValue, false ) == pValue ) )
595cdf0e10cSrcweir 				return sal_False;
596cdf0e10cSrcweir 		}
597cdf0e10cSrcweir 
598cdf0e10cSrcweir 		// merge paperbin if necessary
599cdf0e10cSrcweir 		if( nSetDataFlags & SAL_JOBSET_PAPERBIN )
600cdf0e10cSrcweir 		{
601cdf0e10cSrcweir 			pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
602cdf0e10cSrcweir 			if( pKey )
603cdf0e10cSrcweir 			{
604cdf0e10cSrcweir 				int nPaperBin = pJobSetup->mnPaperBin;
605cdf0e10cSrcweir 				if( nPaperBin == 0xffff )
606cdf0e10cSrcweir 					pValue = pKey->getDefaultValue();
607cdf0e10cSrcweir 				else
608cdf0e10cSrcweir                     pValue = pKey->getValue( pJobSetup->mnPaperBin );
609cdf0e10cSrcweir 
610cdf0e10cSrcweir                 // may fail due to constraints;
611cdf0e10cSrcweir                 // real paper bin is copied back to jobsetup in that case
612cdf0e10cSrcweir 				aData.m_aContext.setValue( pKey, pValue );
613cdf0e10cSrcweir 			}
614cdf0e10cSrcweir 			// if printer has no InputSlot key simply ignore this setting
615cdf0e10cSrcweir 			// (e.g. SGENPRT has no InputSlot)
616cdf0e10cSrcweir 		}
617cdf0e10cSrcweir 
618cdf0e10cSrcweir 		// merge orientation if necessary
619cdf0e10cSrcweir 		if( nSetDataFlags & SAL_JOBSET_ORIENTATION )
620cdf0e10cSrcweir 			aData.m_eOrientation = pJobSetup->meOrientation == ORIENTATION_LANDSCAPE ? orientation::Landscape : orientation::Portrait;
621cdf0e10cSrcweir 
622cdf0e10cSrcweir         // merge duplex if necessary
623cdf0e10cSrcweir         if( nSetDataFlags & SAL_JOBSET_DUPLEXMODE )
624cdf0e10cSrcweir         {
625cdf0e10cSrcweir             pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
626cdf0e10cSrcweir             if( pKey )
627cdf0e10cSrcweir             {
628cdf0e10cSrcweir                 pValue = NULL;
629cdf0e10cSrcweir                 switch( pJobSetup->meDuplexMode )
630cdf0e10cSrcweir                 {
631cdf0e10cSrcweir                 case DUPLEX_OFF:
632cdf0e10cSrcweir                     pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
633cdf0e10cSrcweir                     if( pValue == NULL )
634cdf0e10cSrcweir                         pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "SimplexNoTumble" ) ) );
635cdf0e10cSrcweir                     break;
636cdf0e10cSrcweir                 case DUPLEX_SHORTEDGE:
637cdf0e10cSrcweir                     pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexTumble" ) ) );
638cdf0e10cSrcweir                     break;
639cdf0e10cSrcweir                 case DUPLEX_LONGEDGE:
640cdf0e10cSrcweir                     pValue = pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "DuplexNoTumble" ) ) );
641cdf0e10cSrcweir                     break;
642cdf0e10cSrcweir                 case DUPLEX_UNKNOWN:
643cdf0e10cSrcweir                 default:
644cdf0e10cSrcweir                     pValue = 0;
645cdf0e10cSrcweir                     break;
646cdf0e10cSrcweir                 }
647cdf0e10cSrcweir                 if( ! pValue )
648cdf0e10cSrcweir                     pValue = pKey->getDefaultValue();
649cdf0e10cSrcweir                 aData.m_aContext.setValue( pKey, pValue );
650cdf0e10cSrcweir             }
651cdf0e10cSrcweir         }
652cdf0e10cSrcweir 
653cdf0e10cSrcweir 		m_aJobData = aData;
654cdf0e10cSrcweir 		copyJobDataToJobSetup( pJobSetup, aData );
655cdf0e10cSrcweir 		return sal_True;
656cdf0e10cSrcweir 	}
657cdf0e10cSrcweir 
658cdf0e10cSrcweir 	return sal_False;
659cdf0e10cSrcweir }
660cdf0e10cSrcweir 
661cdf0e10cSrcweir // -----------------------------------------------------------------------
662cdf0e10cSrcweir 
GetPageInfo(const ImplJobSetup * pJobSetup,long & rOutWidth,long & rOutHeight,long & rPageOffX,long & rPageOffY,long & rPageWidth,long & rPageHeight)663cdf0e10cSrcweir void PspSalInfoPrinter::GetPageInfo(
664cdf0e10cSrcweir 	const ImplJobSetup* pJobSetup,
665cdf0e10cSrcweir 	long& rOutWidth, long& rOutHeight,
666cdf0e10cSrcweir 	long& rPageOffX, long& rPageOffY,
667cdf0e10cSrcweir 	long& rPageWidth, long& rPageHeight )
668cdf0e10cSrcweir {
669cdf0e10cSrcweir 	if( ! pJobSetup )
670cdf0e10cSrcweir 		return;
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 	JobData aData;
673cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
674cdf0e10cSrcweir 
675cdf0e10cSrcweir 	// get the selected page size
676cdf0e10cSrcweir 	if( aData.m_pParser )
677cdf0e10cSrcweir 	{
678cdf0e10cSrcweir 
679cdf0e10cSrcweir 		String aPaper;
680cdf0e10cSrcweir 		int width, height;
681cdf0e10cSrcweir 		int left = 0, top = 0, right = 0, bottom = 0;
682cdf0e10cSrcweir 		int nDPI = aData.m_aContext.getRenderResolution();
683cdf0e10cSrcweir 
684cdf0e10cSrcweir 
685cdf0e10cSrcweir         if( aData.m_eOrientation == psp::orientation::Portrait )
686cdf0e10cSrcweir         {
687cdf0e10cSrcweir             aData.m_aContext.getPageSize( aPaper, width, height );
688cdf0e10cSrcweir             aData.m_pParser->getMargins( aPaper, left, right, top, bottom );
689cdf0e10cSrcweir         }
690cdf0e10cSrcweir         else
691cdf0e10cSrcweir         {
692cdf0e10cSrcweir             aData.m_aContext.getPageSize( aPaper, height, width );
693cdf0e10cSrcweir             aData.m_pParser->getMargins( aPaper, top, bottom, right, left );
694cdf0e10cSrcweir         }
695cdf0e10cSrcweir 
696cdf0e10cSrcweir 		rPageWidth	= width * nDPI / 72;
697cdf0e10cSrcweir 		rPageHeight	= height * nDPI / 72;
698cdf0e10cSrcweir 		rPageOffX	= left * nDPI / 72;
699cdf0e10cSrcweir 		rPageOffY	= top * nDPI / 72;
700cdf0e10cSrcweir 		rOutWidth	= ( width  - left - right ) * nDPI / 72;
701cdf0e10cSrcweir 		rOutHeight	= ( height - top  - bottom ) * nDPI / 72;
702cdf0e10cSrcweir 	}
703cdf0e10cSrcweir }
704cdf0e10cSrcweir 
705cdf0e10cSrcweir // -----------------------------------------------------------------------
706cdf0e10cSrcweir 
GetPaperBinCount(const ImplJobSetup * pJobSetup)707cdf0e10cSrcweir sal_uLong PspSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup )
708cdf0e10cSrcweir {
709cdf0e10cSrcweir 	if( ! pJobSetup )
710cdf0e10cSrcweir 		return 0;
711cdf0e10cSrcweir 
712cdf0e10cSrcweir 	JobData aData;
713cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
714cdf0e10cSrcweir 
715cdf0e10cSrcweir 	const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL;
716cdf0e10cSrcweir     return pKey ? pKey->countValues() : 0;
717cdf0e10cSrcweir }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir // -----------------------------------------------------------------------
720cdf0e10cSrcweir 
GetPaperBinName(const ImplJobSetup * pJobSetup,sal_uLong nPaperBin)721cdf0e10cSrcweir String PspSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup, sal_uLong nPaperBin )
722cdf0e10cSrcweir {
723cdf0e10cSrcweir 	JobData aData;
724cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
725cdf0e10cSrcweir 
726cdf0e10cSrcweir 	String aRet;
727cdf0e10cSrcweir 	if( aData.m_pParser )
728cdf0e10cSrcweir 	{
729cdf0e10cSrcweir 		const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL;
730cdf0e10cSrcweir 		if( nPaperBin == 0xffff || ! pKey )
731cdf0e10cSrcweir 			aRet = aData.m_pParser->getDefaultInputSlot();
732cdf0e10cSrcweir 		else
733cdf0e10cSrcweir         {
734cdf0e10cSrcweir             const PPDValue* pValue = pKey->getValue( nPaperBin );
735cdf0e10cSrcweir             if( pValue )
736cdf0e10cSrcweir                 aRet = aData.m_pParser->translateOption( pKey->getKey(), pValue->m_aOption );
737cdf0e10cSrcweir         }
738cdf0e10cSrcweir 	}
739cdf0e10cSrcweir 
740cdf0e10cSrcweir 	return aRet;
741cdf0e10cSrcweir }
742cdf0e10cSrcweir 
743cdf0e10cSrcweir // -----------------------------------------------------------------------
744cdf0e10cSrcweir 
GetCapabilities(const ImplJobSetup * pJobSetup,sal_uInt16 nType)745cdf0e10cSrcweir sal_uLong PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, sal_uInt16 nType )
746cdf0e10cSrcweir {
747cdf0e10cSrcweir 	switch( nType )
748cdf0e10cSrcweir 	{
749cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SUPPORTDIALOG:
750cdf0e10cSrcweir 			return 1;
751cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_COPIES:
752cdf0e10cSrcweir 			return 0xffff;
753cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_COLLATECOPIES:
754cdf0e10cSrcweir         {
755cdf0e10cSrcweir             // see if the PPD contains a value to set Collate to True
756cdf0e10cSrcweir             JobData aData;
757cdf0e10cSrcweir             JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
758cdf0e10cSrcweir 
759cdf0e10cSrcweir             const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Collate" ) ) ) : NULL;
760cdf0e10cSrcweir             const PPDValue* pVal = pKey ? pKey->getValue( String( RTL_CONSTASCII_USTRINGPARAM( "True" ) ) ) : NULL;
761cdf0e10cSrcweir 
762cdf0e10cSrcweir             // PPDs don't mention the number of possible collated copies.
763cdf0e10cSrcweir             // so let's guess as many as we want ?
764cdf0e10cSrcweir 			return pVal ? 0xffff : 0;
765cdf0e10cSrcweir         }
766cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SETORIENTATION:
767cdf0e10cSrcweir 			return 1;
768cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SETDUPLEX:
769cdf0e10cSrcweir 			return 1;
770cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SETPAPERBIN:
771cdf0e10cSrcweir 			return 1;
772cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SETPAPERSIZE:
773cdf0e10cSrcweir 			return 1;
774cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_SETPAPER:
775cdf0e10cSrcweir 			return 0;
776cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_FAX:
777cdf0e10cSrcweir 		{
778cdf0e10cSrcweir 			PrinterInfoManager& rManager = PrinterInfoManager::get();
779cdf0e10cSrcweir 			PrinterInfo aInfo( rManager.getPrinterInfo( pJobSetup->maPrinterName ) );
780cdf0e10cSrcweir 			String aFeatures( aInfo.m_aFeatures );
781cdf0e10cSrcweir 			int nTokenCount = aFeatures.GetTokenCount( ',' );
782cdf0e10cSrcweir 			for( int i = 0; i < nTokenCount; i++ )
783cdf0e10cSrcweir 			{
784cdf0e10cSrcweir 				if( aFeatures.GetToken( i ).CompareToAscii( "fax", 3 ) == COMPARE_EQUAL )
785cdf0e10cSrcweir 					return 1;
786cdf0e10cSrcweir 			}
787cdf0e10cSrcweir 			return 0;
788cdf0e10cSrcweir 		}
789cdf0e10cSrcweir 		case PRINTER_CAPABILITIES_PDF:
790cdf0e10cSrcweir 		{
791cdf0e10cSrcweir 			PrinterInfoManager& rManager = PrinterInfoManager::get();
792cdf0e10cSrcweir 			PrinterInfo aInfo( rManager.getPrinterInfo( pJobSetup->maPrinterName ) );
793cdf0e10cSrcweir 			String aFeatures( aInfo.m_aFeatures );
794cdf0e10cSrcweir 			int nTokenCount = aFeatures.GetTokenCount( ',' );
795cdf0e10cSrcweir 			for( int i = 0; i < nTokenCount; i++ )
796cdf0e10cSrcweir 			{
797cdf0e10cSrcweir 				if( aFeatures.GetToken( i ).CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL )
798cdf0e10cSrcweir 					return 1;
799cdf0e10cSrcweir 			}
800cdf0e10cSrcweir 			return 0;
801cdf0e10cSrcweir 		}
802cdf0e10cSrcweir 		default: break;
803cdf0e10cSrcweir 	};
804cdf0e10cSrcweir 	return 0;
805cdf0e10cSrcweir }
806cdf0e10cSrcweir 
807cdf0e10cSrcweir // =======================================================================
808cdf0e10cSrcweir 
809cdf0e10cSrcweir /*
810cdf0e10cSrcweir  *	SalPrinter
811cdf0e10cSrcweir  */
812cdf0e10cSrcweir 
PspSalPrinter(SalInfoPrinter * pInfoPrinter)813cdf0e10cSrcweir PspSalPrinter::PspSalPrinter( SalInfoPrinter* pInfoPrinter )
814cdf0e10cSrcweir  : m_bFax( false ),
815cdf0e10cSrcweir    m_bPdf( false ),
816cdf0e10cSrcweir    m_bSwallowFaxNo( false ),
817cdf0e10cSrcweir    m_pGraphics( NULL ),
818cdf0e10cSrcweir    m_nCopies( 1 ),
819cdf0e10cSrcweir    m_bCollate( false ),
820cdf0e10cSrcweir    m_pInfoPrinter( pInfoPrinter )
821cdf0e10cSrcweir {
822cdf0e10cSrcweir }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir // -----------------------------------------------------------------------
825cdf0e10cSrcweir 
~PspSalPrinter()826cdf0e10cSrcweir PspSalPrinter::~PspSalPrinter()
827cdf0e10cSrcweir {
828cdf0e10cSrcweir }
829cdf0e10cSrcweir 
830cdf0e10cSrcweir // -----------------------------------------------------------------------
831cdf0e10cSrcweir 
getTmpName()832cdf0e10cSrcweir static String getTmpName()
833cdf0e10cSrcweir {
834cdf0e10cSrcweir     rtl::OUString aTmp, aSys;
835cdf0e10cSrcweir     osl_createTempFile( NULL, NULL, &aTmp.pData );
836cdf0e10cSrcweir     osl_getSystemPathFromFileURL( aTmp.pData, &aSys.pData );
837cdf0e10cSrcweir 
838cdf0e10cSrcweir     return aSys;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir 
StartJob(const XubString * pFileName,const XubString & rJobName,const XubString & rAppName,sal_uLong nCopies,bool bCollate,bool,ImplJobSetup * pJobSetup)841cdf0e10cSrcweir sal_Bool PspSalPrinter::StartJob(
842cdf0e10cSrcweir 	const XubString* pFileName,
843cdf0e10cSrcweir 	const XubString& rJobName,
844cdf0e10cSrcweir 	const XubString& rAppName,
845cdf0e10cSrcweir 	sal_uLong nCopies,
846cdf0e10cSrcweir     bool bCollate,
847cdf0e10cSrcweir     bool /*bDirect*/,
848cdf0e10cSrcweir 	ImplJobSetup* pJobSetup )
849cdf0e10cSrcweir {
850cdf0e10cSrcweir     vcl_sal::PrinterUpdate::jobStarted();
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 	m_bFax		= false;
853cdf0e10cSrcweir 	m_bPdf		= false;
854cdf0e10cSrcweir 	m_aFileName	= pFileName ? *pFileName : String();
855cdf0e10cSrcweir 	m_aTmpFile	= String();
856cdf0e10cSrcweir     m_nCopies   = nCopies;
857cdf0e10cSrcweir     m_bCollate  = bCollate;
858cdf0e10cSrcweir 
859cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData );
860cdf0e10cSrcweir     if( m_nCopies > 1 )
861cdf0e10cSrcweir     {
862cdf0e10cSrcweir         // in case user did not do anything (m_nCopies=1)
863cdf0e10cSrcweir         // take the default from jobsetup
864cdf0e10cSrcweir         m_aJobData.m_nCopies = m_nCopies;
865cdf0e10cSrcweir         m_aJobData.setCollate( bCollate );
866cdf0e10cSrcweir     }
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 	// check wether this printer is configured as fax
869cdf0e10cSrcweir     int nMode = 0;
870cdf0e10cSrcweir 	const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
871cdf0e10cSrcweir     sal_Int32 nIndex = 0;
872cdf0e10cSrcweir     while( nIndex != -1 )
873cdf0e10cSrcweir 	{
874cdf0e10cSrcweir 		OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
875cdf0e10cSrcweir 		if( ! aToken.compareToAscii( "fax", 3 ) )
876cdf0e10cSrcweir 		{
877cdf0e10cSrcweir 			m_bFax = true;
878cdf0e10cSrcweir 			m_aTmpFile = getTmpName();
879cdf0e10cSrcweir             nMode = S_IRUSR | S_IWUSR;
880cdf0e10cSrcweir 
881cdf0e10cSrcweir 			::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash >::const_iterator it;
882cdf0e10cSrcweir 			it = pJobSetup->maValueMap.find( ::rtl::OUString::createFromAscii( "FAX#" ) );
883cdf0e10cSrcweir 			if( it != pJobSetup->maValueMap.end() )
884cdf0e10cSrcweir 				m_aFaxNr = it->second;
885cdf0e10cSrcweir 
886cdf0e10cSrcweir             sal_Int32 nPos = 0;
887cdf0e10cSrcweir 			m_bSwallowFaxNo = ! aToken.getToken( 1, '=', nPos ).compareToAscii( "swallow", 7 ) ? true : false;
888cdf0e10cSrcweir 
889cdf0e10cSrcweir 			break;
890cdf0e10cSrcweir 		}
891cdf0e10cSrcweir 		if( ! aToken.compareToAscii( "pdf=", 4 ) )
892cdf0e10cSrcweir 		{
893cdf0e10cSrcweir 			m_bPdf = true;
894cdf0e10cSrcweir 			m_aTmpFile = getTmpName();
895cdf0e10cSrcweir             nMode = S_IRUSR | S_IWUSR;
896cdf0e10cSrcweir 
897cdf0e10cSrcweir 			if( ! m_aFileName.Len() )
898cdf0e10cSrcweir 			{
899cdf0e10cSrcweir 				m_aFileName = getPdfDir( rInfo );
900cdf0e10cSrcweir 				m_aFileName.Append( '/' );
901cdf0e10cSrcweir 				m_aFileName.Append( rJobName );
902cdf0e10cSrcweir 				m_aFileName.AppendAscii( ".pdf" );
903cdf0e10cSrcweir 			}
904cdf0e10cSrcweir 			break;
905cdf0e10cSrcweir 		}
906cdf0e10cSrcweir 	}
907cdf0e10cSrcweir 	m_aPrinterGfx.Init( m_aJobData );
908cdf0e10cSrcweir 
909cdf0e10cSrcweir     // set/clear backwards compatibility flag
910cdf0e10cSrcweir     bool bStrictSO52Compatibility = false;
911cdf0e10cSrcweir     std::hash_map<rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator compat_it =
912cdf0e10cSrcweir         pJobSetup->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
913cdf0e10cSrcweir     if( compat_it != pJobSetup->maValueMap.end() )
914cdf0e10cSrcweir     {
915cdf0e10cSrcweir         if( compat_it->second.equalsIgnoreAsciiCaseAscii( "true" ) )
916cdf0e10cSrcweir             bStrictSO52Compatibility = true;
917cdf0e10cSrcweir     }
918cdf0e10cSrcweir     m_aPrinterGfx.setStrictSO52Compatibility( bStrictSO52Compatibility );
919cdf0e10cSrcweir 
920cdf0e10cSrcweir 	return m_aPrintJob.StartJob( m_aTmpFile.Len() ? m_aTmpFile : m_aFileName, nMode, rJobName, rAppName, m_aJobData, &m_aPrinterGfx, false ) ? sal_True : sal_False;
921cdf0e10cSrcweir }
922cdf0e10cSrcweir 
923cdf0e10cSrcweir // -----------------------------------------------------------------------
924cdf0e10cSrcweir 
EndJob()925cdf0e10cSrcweir sal_Bool PspSalPrinter::EndJob()
926cdf0e10cSrcweir {
927cdf0e10cSrcweir 	sal_Bool bSuccess = m_aPrintJob.EndJob();
928cdf0e10cSrcweir 
929cdf0e10cSrcweir 	if( bSuccess )
930cdf0e10cSrcweir 	{
931cdf0e10cSrcweir 		// check for fax
932cdf0e10cSrcweir 		if( m_bFax )
933cdf0e10cSrcweir 		{
934cdf0e10cSrcweir 
935cdf0e10cSrcweir 			const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
936cdf0e10cSrcweir 			// sendAFax removes the file after use
937cdf0e10cSrcweir 			bSuccess = sendAFax( m_aFaxNr, m_aTmpFile, rInfo.m_aCommand );
938cdf0e10cSrcweir 		}
939cdf0e10cSrcweir 		else if( m_bPdf )
940cdf0e10cSrcweir 		{
941cdf0e10cSrcweir 			const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
942cdf0e10cSrcweir 			bSuccess = createPdf( m_aFileName, m_aTmpFile, rInfo.m_aCommand );
943cdf0e10cSrcweir 		}
944cdf0e10cSrcweir 	}
945cdf0e10cSrcweir     vcl_sal::PrinterUpdate::jobEnded();
946cdf0e10cSrcweir 	return bSuccess;
947cdf0e10cSrcweir }
948cdf0e10cSrcweir 
949cdf0e10cSrcweir // -----------------------------------------------------------------------
950cdf0e10cSrcweir 
AbortJob()951cdf0e10cSrcweir sal_Bool PspSalPrinter::AbortJob()
952cdf0e10cSrcweir {
953cdf0e10cSrcweir     sal_Bool bAbort = m_aPrintJob.AbortJob() ? sal_True : sal_False;
954cdf0e10cSrcweir     vcl_sal::PrinterUpdate::jobEnded();
955cdf0e10cSrcweir 	return bAbort;
956cdf0e10cSrcweir }
957cdf0e10cSrcweir 
958cdf0e10cSrcweir // -----------------------------------------------------------------------
959cdf0e10cSrcweir 
StartPage(ImplJobSetup * pJobSetup,sal_Bool)960cdf0e10cSrcweir SalGraphics* PspSalPrinter::StartPage( ImplJobSetup* pJobSetup, sal_Bool )
961cdf0e10cSrcweir {
962cdf0e10cSrcweir 	JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, m_aJobData );
963cdf0e10cSrcweir 	m_pGraphics = new PspGraphics( &m_aJobData, &m_aPrinterGfx, m_bFax ? &m_aFaxNr : NULL, m_bSwallowFaxNo, m_pInfoPrinter  );
964cdf0e10cSrcweir     m_pGraphics->SetLayout( 0 );
965cdf0e10cSrcweir     if( m_nCopies > 1 )
966cdf0e10cSrcweir     {
967cdf0e10cSrcweir         // in case user did not do anything (m_nCopies=1)
968cdf0e10cSrcweir         // take the default from jobsetup
969cdf0e10cSrcweir         m_aJobData.m_nCopies = m_nCopies;
970cdf0e10cSrcweir         m_aJobData.setCollate( m_nCopies > 1 && m_bCollate );
971cdf0e10cSrcweir     }
972cdf0e10cSrcweir 
973cdf0e10cSrcweir 	m_aPrintJob.StartPage( m_aJobData );
974cdf0e10cSrcweir 	m_aPrinterGfx.Init( m_aPrintJob );
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 	return m_pGraphics;
977cdf0e10cSrcweir }
978cdf0e10cSrcweir 
979cdf0e10cSrcweir // -----------------------------------------------------------------------
980cdf0e10cSrcweir 
EndPage()981cdf0e10cSrcweir sal_Bool PspSalPrinter::EndPage()
982cdf0e10cSrcweir {
983cdf0e10cSrcweir 	sal_Bool bResult = m_aPrintJob.EndPage();
984cdf0e10cSrcweir 	m_aPrinterGfx.Clear();
985cdf0e10cSrcweir 	return bResult ? sal_True : sal_False;
986cdf0e10cSrcweir }
987cdf0e10cSrcweir 
988cdf0e10cSrcweir // -----------------------------------------------------------------------
989cdf0e10cSrcweir 
GetErrorCode()990cdf0e10cSrcweir sal_uLong PspSalPrinter::GetErrorCode()
991cdf0e10cSrcweir {
992cdf0e10cSrcweir 	return 0;
993cdf0e10cSrcweir }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir /*
996cdf0e10cSrcweir  *  vcl::PrinterUpdate
997cdf0e10cSrcweir  */
998cdf0e10cSrcweir 
999cdf0e10cSrcweir Timer* vcl_sal::PrinterUpdate::pPrinterUpdateTimer = NULL;
1000cdf0e10cSrcweir int vcl_sal::PrinterUpdate::nActiveJobs = 0;
1001cdf0e10cSrcweir 
doUpdate()1002cdf0e10cSrcweir void vcl_sal::PrinterUpdate::doUpdate()
1003cdf0e10cSrcweir {
1004cdf0e10cSrcweir     ::psp::PrinterInfoManager& rManager( ::psp::PrinterInfoManager::get() );
1005cdf0e10cSrcweir     if( rManager.checkPrintersChanged( false ) && SvpSalInstance::s_pDefaultInstance )
1006cdf0e10cSrcweir     {
1007cdf0e10cSrcweir         const std::list< SalFrame* >& rList = SvpSalInstance::s_pDefaultInstance->getFrames();
1008cdf0e10cSrcweir         for( std::list< SalFrame* >::const_iterator it = rList.begin();
1009cdf0e10cSrcweir              it != rList.end(); ++it )
1010cdf0e10cSrcweir              SvpSalInstance::s_pDefaultInstance->PostEvent( *it, NULL, SALEVENT_PRINTERCHANGED );
1011cdf0e10cSrcweir     }
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir // -----------------------------------------------------------------------
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir IMPL_STATIC_LINK_NOINSTANCE( vcl_sal::PrinterUpdate, UpdateTimerHdl, void*, )
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir     if( nActiveJobs < 1 )
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir         doUpdate();
1021cdf0e10cSrcweir         delete pPrinterUpdateTimer;
1022cdf0e10cSrcweir         pPrinterUpdateTimer = NULL;
1023cdf0e10cSrcweir     }
1024cdf0e10cSrcweir     else
1025cdf0e10cSrcweir         pPrinterUpdateTimer->Start();
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir     return 0;
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir // -----------------------------------------------------------------------
1031cdf0e10cSrcweir 
update()1032cdf0e10cSrcweir void vcl_sal::PrinterUpdate::update()
1033cdf0e10cSrcweir {
1034cdf0e10cSrcweir     if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
1035cdf0e10cSrcweir         return;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir     static bool bOnce = false;
1038cdf0e10cSrcweir     if( ! bOnce )
1039cdf0e10cSrcweir     {
1040cdf0e10cSrcweir         bOnce = true;
1041cdf0e10cSrcweir         // start background printer detection
1042cdf0e10cSrcweir         psp::PrinterInfoManager::get();
1043cdf0e10cSrcweir         return;
1044cdf0e10cSrcweir     }
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir     if( nActiveJobs < 1 )
1047cdf0e10cSrcweir         doUpdate();
1048cdf0e10cSrcweir     else if( ! pPrinterUpdateTimer )
1049cdf0e10cSrcweir     {
1050cdf0e10cSrcweir         pPrinterUpdateTimer = new Timer();
1051cdf0e10cSrcweir         pPrinterUpdateTimer->SetTimeout( 500 );
1052cdf0e10cSrcweir         pPrinterUpdateTimer->SetTimeoutHdl( STATIC_LINK( NULL, vcl_sal::PrinterUpdate, UpdateTimerHdl ) );
1053cdf0e10cSrcweir         pPrinterUpdateTimer->Start();
1054cdf0e10cSrcweir     }
1055cdf0e10cSrcweir }
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir // -----------------------------------------------------------------------
1058cdf0e10cSrcweir 
jobEnded()1059cdf0e10cSrcweir void vcl_sal::PrinterUpdate::jobEnded()
1060cdf0e10cSrcweir {
1061cdf0e10cSrcweir     nActiveJobs--;
1062cdf0e10cSrcweir     if( nActiveJobs < 1 )
1063cdf0e10cSrcweir     {
1064cdf0e10cSrcweir         if( pPrinterUpdateTimer )
1065cdf0e10cSrcweir         {
1066cdf0e10cSrcweir             pPrinterUpdateTimer->Stop();
1067cdf0e10cSrcweir             delete pPrinterUpdateTimer;
1068cdf0e10cSrcweir             pPrinterUpdateTimer = NULL;
1069cdf0e10cSrcweir             doUpdate();
1070cdf0e10cSrcweir         }
1071cdf0e10cSrcweir     }
1072cdf0e10cSrcweir }
1073