? unxmacxp.pro Index: inc/psprint/printerinfomanager.hxx =================================================================== RCS file: /cvs/oo/gsl/psprint/inc/psprint/printerinfomanager.hxx,v retrieving revision 1.2 diff -u -r1.2 printerinfomanager.hxx --- inc/psprint/printerinfomanager.hxx 2001/06/15 11:06:33 1.2 +++ inc/psprint/printerinfomanager.hxx 2002/10/09 16:13:26 @@ -81,6 +81,34 @@ #include #endif +#ifdef MACOSX +/* MacOS X print system discovery constants: + * + * These values enumerate Apple OS printing systems we could use. + * They are used as indications _as well as_ indexes into the + * aParms structure used below for print commands. + */ +#define kApplePrintingFailure 0 /* For whatever reason, we can't print at all */ +#define kApplePrintingLPR 1 /* Darwin 5.x style LPR printing */ +#define kApplePrintingCUPS 2 /* MacOS X 10.2/Darwin 6 style CUPS (also CUPS installed by users on 10.1) */ +#define kApplePrintingPrintCenter 3 /* MacOS X 10.1 /usr/sbin/Print printing */ + +/* Constants for PostScript vs PDF printing */ +#define kApplePrintingUsePDF 1 /* Default; Run PS through ps2pdf first (requires GhostScript) */ +#define kApplePrintingUsePS 2 /* Optional, print PS directly to printer (less compatible, requires PS printer) */ + +/* Defines printing command for MacOS X 10.1 Print Center Printing */ +#define kApplePCPrintCommand "/usr/sbin/Print" +#define kApplePS2PDFLocation "/usr/local/bin/ps2pdf" + +/* Prototype for print method discovery function. Returns + * a constant defined in printerinfomanager.hxx + */ +sal_Int32 macxp_GetSystemPrintMethod( void ); +sal_Int32 macxp_GetSystemPrintFormat( void ); +#endif + + namespace psp { struct PrinterInfo : JobData Index: source/printer/printerinfomanager.cxx =================================================================== RCS file: /cvs/oo/gsl/psprint/source/printer/printerinfomanager.cxx,v retrieving revision 1.11.8.1 diff -u -r1.11.8.1 printerinfomanager.cxx --- source/printer/printerinfomanager.cxx 2002/04/06 09:56:35 1.11.8.1 +++ source/printer/printerinfomanager.cxx 2002/10/09 16:13:29 @@ -66,6 +66,10 @@ #include #include +#ifdef MACOSX +#include +#endif + // filename of configuration files #define PRINT_FILENAME "psprint.conf" // the group of the global defaults @@ -887,6 +891,16 @@ { "/usr/sbin/lpc status", "lpr -P (PRINTER)", "", ":", 0 }, { "lpc status", "lpr -P (PRINTER)", "", ":", 0 }, { "LANG=C;LC_ALL=C;export LANG LC_ALL;lpstat -s", "lp -d (PRINTER)", "system for ", ": ", 1 } +#elif defined(MACOSX) + /* These elements correspond to the constants defined for Apple printing in + * printerinfomanager.hxx and are indexed by those constants. ORDER IS IMPORTANT!!! + */ + /* Apple LPR printing (kApplePrintingLPR) */ + { "/usr/bin/lpc status", "lpr -P (PRINTER)", "", ":", 0 }, + /* Apple CUPS printing (kApplePrintingCUPS) */ + { "LANG=C;LC_ALL=C;export LANG LC_ALL;/usr/bin/lpstat -s", "lp -d (PRINTER)", "system for ", ": ", 1 }, + /* Apple Print Center printing (kApplePrintingPrintCenter) */ + { "Apple Print Center Default Printer", kApplePCPrintCommand, "", ":", 0 } #else { "LANG=C;LC_ALL=C;export LANG LC_ALL;lpstat -s", "lp -d (PRINTER)", "system for ", ": ", 1 }, { "/usr/sbin/lpc status", "lpr -P (PRINTER)", "", ":", 0 }, @@ -894,7 +908,6 @@ #endif }; - const ::std::list< OUString >& PrinterInfoManager::getSystemPrintQueues() { if( m_aSystemPrintQueues.begin() == m_aSystemPrintQueues.end() ) @@ -906,18 +919,35 @@ bool bSuccess = false; ::std::list< ByteString > aLines; rtl_TextEncoding aEncoding = gsl_getSystemTextEncoding(); - +#ifdef MACOSX + sal_Int32 applePrintSysType; + + /* Get our OS specific printing scheme for MacOS X */ + applePrintSysType = macxp_GetSystemPrintMethod(); +#endif + +#ifdef MACOSX + /* Don't need to figure out which method works for MacOS X as we did this already */ + aLines.clear(); + aPrtQueueCmd = aParms[ applePrintSysType-1 ].pQueueCommand; + m_aSystemPrintCommand = OUString::createFromAscii( aParms[applePrintSysType-1].pPrintCommand ); + aForeToken = aParms[ applePrintSysType-1 ].pForeToken; + aAftToken = aParms[ applePrintSysType-1 ].pAftToken; + nForeTokenCount = aParms[ applePrintSysType-1 ].nForeTokenCount; +#else + /* Normal Unix printer discovery (non-MacOS X) */ for( i = 0; i < sizeof(aParms)/sizeof(aParms[0]) && ! bSuccess; i++ ) { aLines.clear(); - aPrtQueueCmd = aParms[i].pQueueCommand; - m_aSystemPrintCommand = OUString::createFromAscii( aParms[i].pPrintCommand ); + aPrtQueueCmd = aParms[i].pQueueCommand; + m_aSystemPrintCommand = OUString::createFromAscii( aParms[i].pPrintCommand ); aForeToken = aParms[i].pForeToken; aAftToken = aParms[i].pAftToken; nForeTokenCount = aParms[i].nForeTokenCount; -#if defined DEBUG + + #if defined DEBUG fprintf( stderr, "trying print queue command \"%s\" ... ", aParms[i].pQueueCommand ); -#endif + #endif if( pPipe = popen( aPrtQueueCmd.GetBuffer(), "r" ) ) { while( fgets( pBuffer, 1024, pPipe ) ) @@ -925,36 +955,55 @@ if( ! pclose( pPipe ) ) bSuccess = TRUE; } -#if defined DEBUG + #if defined DEBUG fprintf( stderr, "%s\n", bSuccess ? "success" : "failed" ); -#endif + #endif } +#endif /* MACOSX */ - while( aLines.begin() != aLines.end() ) - { - int nPos = 0, nAftPos; +#ifdef MACOSX + /* Since we only print to the default printer for MacOS X 10.1, + * queue discovery serves no purpose. + */ + if ( applePrintSysType == kApplePrintingPrintCenter ) + { + m_aSystemPrintQueues.push_back( OUString::createFromAscii(aParms[applePrintSysType-1].pQueueCommand) ); + #ifdef DEBUG + fprintf( stderr, "printerinfomanager.cxx: using Print Center print queue %s.\n", aParms[applePrintSysType-1].pQueueCommand ); + #endif + } + else +#endif /* MACOSX */ + { + /* Normal Unix print queue discovery, also used for Darwin 5 LPR printing + * and MacOS X 10.2/Darwin 6 CUPS printing. + */ + while( aLines.begin() != aLines.end() ) + { + int nPos = 0, nAftPos; - ByteString aOutLine( aLines.front() ); - aLines.pop_front(); + ByteString aOutLine( aLines.front() ); + aLines.pop_front(); - for( int i = 0; i < nForeTokenCount && nPos != STRING_NOTFOUND; i++ ) - { - nPos = aOutLine.Search( aForeToken, nPos ); - if( nPos != STRING_NOTFOUND && aOutLine.Len() >= nPos+aForeToken.Len() ) - nPos += aForeToken.Len(); - } - if( nPos != STRING_NOTFOUND ) - { - nAftPos = aOutLine.Search( aAftToken, nPos ); - if( nAftPos != STRING_NOTFOUND ) - { - OUString aSysQueue( String( aOutLine.Copy( nPos, nAftPos - nPos ), aEncoding ) ); - // do not insert doubles (e.g. lpstat tends to produce such lines) - ::std::list< OUString >::const_iterator it; - for( it = m_aSystemPrintQueues.begin(); it != m_aSystemPrintQueues.end() && *it != aSysQueue; ++it ) - ; - if( it == m_aSystemPrintQueues.end() ) - m_aSystemPrintQueues.push_back( aSysQueue ); + for( int i = 0; i < nForeTokenCount && nPos != STRING_NOTFOUND; i++ ) + { + nPos = aOutLine.Search( aForeToken, nPos ); + if( nPos != STRING_NOTFOUND && aOutLine.Len() >= nPos+aForeToken.Len() ) + nPos += aForeToken.Len(); + } + if( nPos != STRING_NOTFOUND ) + { + nAftPos = aOutLine.Search( aAftToken, nPos ); + if( nAftPos != STRING_NOTFOUND ) + { + OUString aSysQueue( String( aOutLine.Copy( nPos, nAftPos - nPos ), aEncoding ) ); + // do not insert doubles (e.g. lpstat tends to produce such lines) + ::std::list< OUString >::const_iterator it; + for( it = m_aSystemPrintQueues.begin(); it != m_aSystemPrintQueues.end() && *it != aSysQueue; ++it ) + ; + if( it == m_aSystemPrintQueues.end() ) + m_aSystemPrintQueues.push_back( aSysQueue ); + } } } } @@ -975,3 +1024,118 @@ rCommands.push_back( aCmd ); } } + + +#ifdef MACOSX + +/* On Apple systems printing gets more complicated... + * 1) Darwin 5: use straight lpr system, user has to configure lpr correctly + * 2) MacOS X 10.1: use /usr/sbin/Print which prints to default Print Center printer + * 3) MacOS X 10.2: use CUPS duo of lpstat/lp + * 4) Darwin 6: Like MacOS X 10.2, use CUPS + * + * --- FIXME --- We don't support printer choosing on MacOS X 10.1 at this time, + * only printing to default Print Center printer. The user can + * change the default Print Center printer at any point however. + */ + +/* + * macxp_GetSystemPrintMethod() + * + * Find out which printing system/OS we are using. + * + * Darwin 5 is the fallback case. To check for 10.1 printing we try to see if + * /usr/sbin/Print exists. For 10.2/Darwin 6, we attempt to find lpstat. Users + * might also have installed CUPS on Darwin 5 or MacOS X 10.1, but we default to + * Print Center (/usr/sbin/Print) printing on 10.1. + * + */ +sal_Int32 macxp_GetSystemPrintMethod( void ) +{ + int applePrintSysType; + int err; + struct stat status; + + /* Attempt to find out which OS we are on... */ + applePrintSysType = kApplePrintingLPR; + + /* Check for MacOS X 10.1 first. */ + err = stat( "/usr/sbin/Print", &status ); + if ( err == 0 ) + { + applePrintSysType = kApplePrintingPrintCenter; + #ifdef DEBUG + fprintf( stderr, "printerinfomanager.cxx: found MacOS X 10.1-type printing system.\n" ); + #endif + } + else + { + /* Test for MacOS X 10.2/Darwin6 CUPS printing */ + err = stat( "/usr/bin/lpstat", &status ); + if ( err == 0 ) + { + applePrintSysType = kApplePrintingCUPS; + #ifdef DEBUG + fprintf( stderr, "printerinfomanager.cxx: found MacOS X 10.2-type CUPS-based printing system.\n" ); + #endif + } + } + + #ifdef DEBUG + if ( applePrintSysType == kApplePrintingLPR ) + fprintf( stderr, "printerinfomanager.cxx: falling back to Darwin5-type LPR printing system.\n" ); + #endif + + return( applePrintSysType ); +} + +/* + * macxp_GetSystemPrintFormat() + * + * There are two ways to print: using PostScript (PS) and using PDF. + * Because MacOS X 10.2 CUPS printing has PDF converts built in for + * almost every printer, it is very easy to print using PDF. For 10.1, + * extra steps must be taken to print with PDF, but it is still more + * compatible. For Darwin 5 and 6, we default to PS printing. + * + * The user may still wish to print PS to PS compatible printers and + * therefore the environment variable OOO_PRINT_PS_DIRECTLY, if set, + * forces OOo to NOT undergo the PS -> PDF translation by default. + */ +sal_Int32 macxp_GetSystemPrintFormat( void ) +{ + int printFormat; + int err; + struct stat status; + sal_Char *pPDFOverride = NULL; + + printFormat = kApplePrintingUsePS; + + /* Check for presence of OSAScript executable, which is + * believed to be MacOS X only (ie not present on Darwin). + */ + err = stat( "/usr/bin/osascript", &status ); + if ( err == 0 ) + { + /* Check to see if the user wants to print PS anyway */ + pPDFOverride = getenv( "OOO_PRINT_PS_DIRECTLY" ); + if ( pPDFOverride == NULL ) + { + /* Now we have to check for ps2pdf to make sure we can do the conversion */ + err = stat( kApplePS2PDFLocation, &status ); + if ( err == 0 ) + { + printFormat = kApplePrintingUsePDF; + #ifdef DEBUG + fprintf( stderr, "printerinfomanager.cxx: Will print in PDF format using PS->PDF coversion filters.\n" ); + #endif + } + } + } + + return( printFormat ); +} +#endif + + + Index: source/printergfx/printerjob.cxx =================================================================== RCS file: /cvs/oo/gsl/psprint/source/printergfx/printerjob.cxx,v retrieving revision 1.15.4.3.2.1 diff -u -r1.15.4.3.2.1 printerjob.cxx --- source/printergfx/printerjob.cxx 2002/08/14 05:57:32 1.15.4.3.2.1 +++ source/printergfx/printerjob.cxx 2002/10/09 16:13:30 @@ -499,6 +499,12 @@ PrinterJob::EndJob () { // write document trailer according to Document Structuring Conventions (DSC) +#ifdef MACOSX + sal_Int32 applePrintSysType; + sal_Int32 applePrintFormat; + char *spoolFileName = NULL; +#endif + sal_Char pPageNr [16]; sal_Int32 nSz = getValueOf((sal_Int32)maPageList.size(), pPageNr); pPageNr [nSz] = '\0'; @@ -536,10 +542,44 @@ const rtl::OString aShellCommand = rtl::OUStringToOString (rCommand, RTL_TEXTENCODING_ISO_8859_1); - - pDestFILE = popen (aShellCommand.getStr(), "w"); - if (pDestFILE == NULL) - return sal_False; + + #ifdef MACOSX + /* Ascertain the printing system and printing doc format */ + applePrintSysType = macxp_GetSystemPrintMethod(); + applePrintFormat = macxp_GetSystemPrintFormat(); + #endif + + #ifdef MACOSX + /* Open a pipe only if we are using (1) Darwin5 LPR printing or (2) 10.2/Darwin6 PS printing. + * All other cases use spool to file. + */ + if ( (applePrintSysType==kApplePrintingLPR) || ((applePrintSysType==kApplePrintingCUPS)&&(applePrintFormat==kApplePrintingUsePS)) ) + { + #endif + pDestFILE = popen (aShellCommand.getStr(), "w"); + if (pDestFILE == NULL) + return sal_False; + #ifdef MACOSX + } + else + { + /* Spool to file instead. Cases here: + * 1) kApplePrintingPrintCenter && kApplePrintingUsePDF + * 2) kApplePrintingPrintCenter && kApplePrintingUsePS + * 3) kApplePrintingCUPS && kApplePrintingUsePDF + */ + + /* Get a temporary file name for the spool file */ + spoolFileName = macxp_tempnam( NULL, "ooopj" ); + if ( spoolFileName == NULL ) + return sal_False; + + /* Create temporary spool file */ + pDestFILE = fopen( spoolFileName, "w" ); + if ( pDestFILE == NULL ) + return sal_False; + } + #endif } /* spool the document parts to the destination */ @@ -577,7 +617,133 @@ if (bSpoolToFile) fclose (pDestFILE); else - pclose (pDestFILE); + { + #ifdef MACOSX + /* Handle cases for MacOS X printing that don't pipe directly to LPR */ + if ( (applePrintSysType==kApplePrintingPrintCenter) && (applePrintFormat==kApplePrintingUsePS) ) + { + char sysCommandBuffer[ 1024 ]; + int printCmdErr; + + fclose( pDestFILE ); + /* Now pass the file to /usr/sbin/Print for printing. */ + snprintf( sysCommandBuffer, 1023, "%s -M ps %s", kApplePCPrintCommand, spoolFileName ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing doc with command '%s'\n", sysCommandBuffer ); + #endif + printCmdErr = system( sysCommandBuffer ); + #ifdef DEBUG + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: printing error, system() returned %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: printing successful, system() returned 0.\n" ); + #endif + /* macxp_tempname() returns a malloc()'ed string, must free it when done. */ + unlink( spoolFileName ); + free( spoolFileName ); + } + else if ( (applePrintSysType==kApplePrintingPrintCenter) && (applePrintFormat==kApplePrintingUsePDF) ) + { + char sysCommandBuffer[ 1024 ]; + char pdfFileName[ 1024 ]; + int printCmdErr; + char *c; + + fclose( pDestFILE ); + + /* Create the file name for the converted PDF and assemble the conversion command */ + snprintf( pdfFileName, 1023, "%s.pdf", spoolFileName ); + snprintf( sysCommandBuffer, 1023, "sh -c PATH=${PATH}:/usr/local/bin;%s %s %s", kApplePS2PDFLocation, spoolFileName, pdfFileName ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: converting document to PDF with command '%s'\n", sysCommandBuffer ); + #endif + /* Convert the PS spool file to a PDF */ + printCmdErr = system( sysCommandBuffer ); + #ifdef DEBUG + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: pdf conversion error, system() returned %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: pdf conversion successful, system() returned 0.\n" ); + #endif + + /* AppleScript expects MacOS-style paths, so convert Unix path to MacOS Style */ + while ( (c=strchr(pdfFileName,'/')) != NULL ) + *c = ':'; + if ( *pdfFileName == ':' ) + sprintf( pdfFileName, "%s", (pdfFileName+1) ); + + /* Construct and execute the actual printing command using AppleScript */ + snprintf( sysCommandBuffer, 1023, "/usr/bin/osascript -e 'tell application \"Finder\"' -e 'print {file \"%s\"}' -e 'end tell'", pdfFileName ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing PDF with command '%s'\n", sysCommandBuffer ); + #endif + printCmdErr = system( sysCommandBuffer ); + #ifdef DEBUG + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: printing error, system() returned %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: printing successful, system() returned 0.\n" ); + #endif + /* macxp_tempname() returns a malloc()'ed string, must free it when done. */ + unlink( spoolFileName ); + free( spoolFileName ); + } + else if ( (applePrintSysType==kApplePrintingCUPS) && (applePrintFormat==kApplePrintingUsePDF) ) + { + char sysCommandBuffer[ 1024 ]; + char pdfFileName[ 1024 ]; + int printCmdErr; + + /* Grab the printing command */ + const PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get (); + const rtl::OUString& rPrinter = m_aLastJobData.m_aPrinterName; + const PrinterInfo& rPrinterInfo = rPrinterInfoManager.getPrinterInfo (rPrinter); + const rtl::OUString& rCommand = rPrinterInfo.m_aCommand; + const rtl::OString aShellCommand = rtl::OUStringToOString (rCommand, RTL_TEXTENCODING_ISO_8859_1); + + fclose( pDestFILE ); + + /* Create the file name for the converted PDF and assemble the conversion command */ + snprintf( pdfFileName, 1023, "%s.pdf", spoolFileName ); + snprintf( sysCommandBuffer, 1023, "sh -c PATH=$PATH:/usr/local/bin;%s %s %s", kApplePS2PDFLocation, spoolFileName, pdfFileName ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: converting document to PDF with command '%s'\n", sysCommandBuffer ); + #endif + /* Convert the PS spool file to a PDF */ + printCmdErr = system( sysCommandBuffer ); + #ifdef DEBUG + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: pdf conversion error, system() returned %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: pdf conversion successful, system() returned 0.\n" ); + #endif + + /* Construct and execute the printing command */ + snprintf( sysCommandBuffer, 1023, "cat %s | %s", pdfFileName, aShellCommand.getStr() ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing PDF with command '%s'\n", sysCommandBuffer ); + #endif + /* Convert the PS spool file to a PDF */ + printCmdErr = system( sysCommandBuffer ); + #ifdef DEBUG + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: printing error, system() returned %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: printing successful, system() returned 0.\n" ); + #endif + /* macxp_tempname() returns a malloc()'ed string, must free it when done. */ + unlink( spoolFileName ); + unlink( pdfFileName ); + free( spoolFileName ); + } + else + { + #endif + pclose (pDestFILE); + #ifdef MACOSX + } + #endif + } return sal_True; }