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