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