diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-02-02 17:57:16 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-02-02 17:57:16 +0000 |
commit | a699b59b2223305a67d39e2958c73fda9de15f63 (patch) | |
tree | c9b907b64b3fbfde0cf66634928f7020b2a83800 /psprint | |
parent | 15181c17f7242d456681838ebb2193987bcb23b5 (diff) |
INTEGRATION: CWS geordi2q14 (1.23.6); FILE MERGED
2004/01/29 18:04:28 hr 1.23.6.2: #111934#: merge CWS ooo111fix2
2004/01/28 15:46:57 hr 1.23.6.1: #111934#: merge CWS vcl7pp1r3
Diffstat (limited to 'psprint')
-rw-r--r-- | psprint/source/printergfx/printerjob.cxx | 401 |
1 files changed, 391 insertions, 10 deletions
diff --git a/psprint/source/printergfx/printerjob.cxx b/psprint/source/printergfx/printerjob.cxx index 7c766345bbd4..0e5229a32d10 100644 --- a/psprint/source/printergfx/printerjob.cxx +++ b/psprint/source/printergfx/printerjob.cxx @@ -2,9 +2,9 @@ * * $RCSfile: printerjob.cxx,v $ * - * $Revision: 1.23 $ + * $Revision: 1.24 $ * - * last change: $Author: vg $ $Date: 2003-12-17 20:22:49 $ + * last change: $Author: hr $ $Date: 2004-02-02 18:57:16 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -109,6 +109,19 @@ using namespace psp ; +#ifdef MACOSX +// Prototype our MacOS X printing help function +void macxp_ProcessAndPrintDocument( sal_Int32 applePrintSysType, + char *spoolFileName, + FILE *pDestFile, + const rtl::OString psprintPrintCmd, + const rtl::OString psprintDriverName, + const JobData pJobData, + const rtl::OUString *aJobName, + sal_uInt32 jobDPI ); +int macxp_ConvertPSFileToPDF( char *psFileName, char *pdfFileName, int pdfFileNameBufferLen, sal_uInt32 jobDPI ); +#endif + // forward declaration #define nBLOCKSIZE 0x2000 @@ -433,6 +446,7 @@ PrinterJob::StartJob ( maFileName = rFileName; mnFileMode = nMode; maSpoolDirName = createSpoolDir (); + maJobName = rJobName; rtl::OUString aExt = rtl::OUString::createFromAscii (".ps"); mpJobHeader = CreateSpoolFile (rtl::OUString::createFromAscii("psp_head"), aExt); @@ -500,6 +514,11 @@ PrinterJob::StartJob ( sal_Bool PrinterJob::EndJob () { +#ifdef MACOSX + sal_Int32 applePrintSysType; + char *spoolFileName = NULL; +#endif + // write document setup (done here because it // includes the accumulated fonts if( mpJobHeader ) @@ -526,8 +545,12 @@ PrinterJob::EndJob () FILE* pDestFILE = NULL; - /* create a destination either as file or as a pipe */ +#ifdef MACOSX + /* Ascertain the printing system */ + applePrintSysType = macxp_GetSystemPrintMethod(); +#endif + /* create a destination either as file or as a pipe */ sal_Bool bSpoolToFile = maFileName.getLength() > 0 ? sal_True : sal_False; if (bSpoolToFile) { @@ -565,9 +588,48 @@ PrinterJob::EndJob () const rtl::OString aShellCommand = rtl::OUStringToOString (rCommand, RTL_TEXTENCODING_ISO_8859_1); - pDestFILE = popen (aShellCommand.getStr(), "w"); - if (pDestFILE == NULL) - return sal_False; + /* Mac OS X: open a pipe only if we are using (1) Darwin5 LPR printing. + * All other OS X/Darwin cases use spool to file. + * Other UNIX: always open a pipe. + */ + if ( + #ifdef MACOSX + applePrintSysType == kApplePrintingLPR + #else + sal_True + #endif + ) + { + pDestFILE = popen (aShellCommand.getStr(), "w"); + if (pDestFILE == NULL) + return sal_False; + } + #ifdef MACOSX + else + { + /* Spool to file instead so we can convert it. Cases used here: + * 1) kApplePrintingPrintCenter && kApplePrintingUsePDF + * 2) kApplePrintingPrintCenter && kApplePrintingUsePS + * 3) kApplePrintingCUPS && kApplePrintingUsePDF + * 4) kApplePrintingCUPS && kApplePrintingUsePS + */ + + /* Get a temporary file name for the spool file. + * This name must be free()ed later. + */ + spoolFileName = macxp_tempnam( NULL, "ooopj" ); + if ( spoolFileName == NULL ) + return sal_False; + + /* Create temporary spool file */ + pDestFILE = fopen( spoolFileName, "w" ); + if ( pDestFILE == NULL ) + { + free( spoolFileName ); + return sal_False; + } + } + #endif } /* spool the document parts to the destination */ @@ -616,11 +678,328 @@ PrinterJob::EndJob () if (bSpoolToFile) fclose (pDestFILE); else - pclose (pDestFILE); + { + #ifdef MACOSX + sal_uInt32 nXdpi; + sal_uInt32 nYdpi; + + /* For Mac OS X/Darwin, process and spool the file to the printing subsystem + * if required. + */ + const rtl::OUString& rPrinter = m_aLastJobData.m_aPrinterName; + const PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get(); + const PrinterInfo& rPrinterInfo = rPrinterInfoManager.getPrinterInfo( rPrinter ); + + // Grab printer's spool command + const rtl::OUString& rCommand = rPrinterInfo.m_aCommand; + const rtl::OString aShellCommand = rtl::OUStringToOString( rCommand, RTL_TEXTENCODING_ISO_8859_1 ); + + // Grab the printer's PPD file name + const rtl::OUString& rDriverName = rPrinterInfo.m_aDriverName; + const rtl::OString aDriverName = rtl::OUStringToOString( rDriverName, RTL_TEXTENCODING_ISO_8859_1 ); + + /* Grab the resolution for the job, for use in PS->PDF conversion */ +/* GetResolution( nXdpi, nYdpi );*/ + + macxp_ProcessAndPrintDocument( applePrintSysType, + spoolFileName, + pDestFILE, + aShellCommand, + aDriverName, + m_aLastJobData, + &maJobName, + mnResolution ); + #else + pclose (pDestFILE); + #endif + } + +#ifdef MACOSX + /* If we created a spool file for our Mac OS X/Darwin job, + * delete it. Also free the variable, since it is malloc()ed in macxp_tempnam() + * and otherwise we'd leak memory. + */ + if ( spoolFileName ) + { + unlink( spoolFileName ); + free( spoolFileName ); + } +#endif return bSuccess; } +#ifdef MACOSX +// Because the printing on MacOS X and Darwin is a bit more complicated, +// its got its own routine. + +#define kSysCommandBufferLen 1024 +#define kPDFFileNameBufferLen 1024 + +void macxp_ProcessAndPrintDocument( sal_Int32 applePrintSysType, + char *spoolFileName, + FILE *pDestFile, + const rtl::OString psprintPrintCmd, + const rtl::OString psprintDriverName, + const JobData pJobData, + const rtl::OUString *aJobName, + sal_uInt32 jobDPI ) +{ + char sysCommandBuffer[ kSysCommandBufferLen ]; + int printCmdErr; + sal_Int32 printFormat; + + if ( applePrintSysType == kApplePrintingLPR ) + { + /* Job is to be printed with Darwin5 lpr. It has already + * been piped to lp/lpr above in EndJob(), so simply + * close the pipe. + */ + pclose( pDestFile ); + } + else + { + /* Handle cases for MacOS X printing that don't pipe directly to lp/lpr */ + + /* Close the intermediate file */ + fclose( pDestFile ); + + /* Determine if we are going to print with PostScript, or with PS->PDF conversion. + * We assume we are to use PS->PDF conversion unless proven otherwise. Most printers + * will have a PPD, except Rendezvous-shared ones. If the PPD _doesn't_ have the + * "cupsFilter" key, or if the "cupsFilter" key _doesn't_ contain "application/pdf", + * then we print directly with PostScript. + */ + printFormat = kApplePrintingUsePDF; + if ( (sal_False == psprintDriverName.equals("SGENPRT")) && (sal_False == psprintDriverName.equals("MacShared")) ) + { + /* The should exist a valid PPD for this printer */ + if ( pJobData.m_pParser ) + { + const PPDKey *pCupsFilterKey; + const PPDValue *pCupsFilterValue; + + pCupsFilterKey = pJobData.m_pParser->getKey( String(RTL_CONSTASCII_USTRINGPARAM("cupsFilter")) ); + pCupsFilterValue = pCupsFilterKey != NULL ? pJobData.m_aContext.getValue( pCupsFilterKey ) : NULL; + if ( pCupsFilterValue ) + { + ByteString aCupsFilterString( pCupsFilterValue->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ); + if ( aCupsFilterString.Search("application/pdf") == 0 ) + { + /* cupsFilter didn't have application/pdf */ + printFormat = kApplePrintingUsePS; + } + } + else + { + /* No "cupsFilter" key */ + printFormat = kApplePrintingUsePS; + } + } + } + + if ( (applePrintSysType==kApplePrintingPrintCenter) && (printFormat==kApplePrintingUsePS) ) + { + /* Now pass the PS file to /usr/sbin/Print for printing. */ + snprintf( sysCommandBuffer, kSysCommandBufferLen-1, "%s -M ps \"%s\"", kApplePCPrintCommand, spoolFileName ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing doc with command '%s'\n", sysCommandBuffer ); + #endif + + printCmdErr = system( sysCommandBuffer ); + } + else if ( (applePrintSysType==kApplePrintingPrintCenter) && (printFormat==kApplePrintingUsePDF) ) + { + char pdfFileName[ kPDFFileNameBufferLen ]; + char pdfFileNameMacFormat[ kPDFFileNameBufferLen ]; + char *c; + + /* Convert file to PDF using GhostScript */ + printCmdErr = macxp_ConvertPSFileToPDF( spoolFileName, pdfFileName, kPDFFileNameBufferLen, jobDPI ); + if ( printCmdErr == 0 ) + { + /* AppleScript expects MacOS-style paths, so convert Unix path to Mac OS Style. + * If the Unix path is absolute, get rid of the starting slash + */ + strncpy( pdfFileNameMacFormat, pdfFileName, kPDFFileNameBufferLen-1 ); + if ( *pdfFileNameMacFormat == '/' ) + sprintf( pdfFileNameMacFormat, "%s", (pdfFileNameMacFormat+1) ); + while ( (c=strchr(pdfFileNameMacFormat,'/')) != NULL ) + *c = ':'; + + /* Construct and execute the actual printing command using AppleScript */ + snprintf( sysCommandBuffer, kSysCommandBufferLen-1, "/usr/bin/osascript -e 'tell application \"Finder\"' -e 'print {file \"%s\"}' -e 'end tell'", pdfFileNameMacFormat ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing PDF with command '%s'\n", sysCommandBuffer ); + #endif + printCmdErr = system( sysCommandBuffer ); + } + unlink( pdfFileName ); + } + else if ( (applePrintSysType==kApplePrintingCUPS) && ((printFormat==kApplePrintingUsePDF) || (printFormat==kApplePrintingUsePS)) ) + { + char pdfFileName[ kPDFFileNameBufferLen ]; + char numCopiesSwitch[ 5 ]; + sal_uInt32 index; + + /* Convert file to PDF using GhostScript if using PS->PDF conversion */ + if ( printFormat == kApplePrintingUsePDF ) + printCmdErr = macxp_ConvertPSFileToPDF( spoolFileName, pdfFileName, kPDFFileNameBufferLen, jobDPI ); + else + { + strncpy( pdfFileName, spoolFileName, kPDFFileNameBufferLen ); + printCmdErr = 0; + } + + if ( printCmdErr == 0 ) + { + #define kJobOptionsStringSize 500 + char jobOptions[ kJobOptionsStringSize ]; + + jobOptions[ 0 ] = NULL; + /* Based on job options, find out what parameters to pass to the printer. */ + if ( pJobData.m_pParser ) + { + const PPDKey *pSizeKey; + const PPDValue *pSizeValue; + const PPDKey *pSlotKey; + const PPDValue *pSlotValue; + BOOL needComma = FALSE; + + // Only CUPS PS->PDF printers require the page size options + if ( printFormat == kApplePrintingUsePDF ) + { + // Add page size option if necessary + pSizeKey = pJobData.m_pParser->getKey( String(RTL_CONSTASCII_USTRINGPARAM("PageSize")) ); + pSizeValue = pSizeKey != NULL ? pJobData.m_aContext.getValue( pSizeKey ) : NULL; + if ( pSizeValue ) + { + ByteString aSizeString( pSizeValue->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ); + snprintf( jobOptions, kJobOptionsStringSize, "-o \"media=" ); + strncat( jobOptions, aSizeString.GetBuffer(), kJobOptionsStringSize-strlen(jobOptions) ); + needComma = TRUE; + } + } + + // Add paper tray option if necessary + pSlotKey = pJobData.m_pParser->getKey( String(RTL_CONSTASCII_USTRINGPARAM("InputSlot")) ); + pSlotValue = pSlotKey != NULL ? pJobData.m_aContext.getValue( pSlotKey ) : NULL; + if ( pSlotValue ) + { + ByteString aSlotString( pSlotValue->m_aOption, RTL_TEXTENCODING_ISO_8859_1 ); + // If the string wasn't created from PageSize, create it now + if ( strlen(jobOptions) == 0 ) + snprintf( jobOptions, kJobOptionsStringSize, "-o \"media=" ); + if ( TRUE == needComma ) + strncat( jobOptions, ",", kJobOptionsStringSize - strlen(jobOptions) ); + + strncat( jobOptions, aSlotString.GetBuffer(), kJobOptionsStringSize - strlen(jobOptions) ); + } + + // Add on the ending " to the media= part + if ( strlen(jobOptions) > 0 ) + strncat( jobOptions, "\"", kJobOptionsStringSize - strlen(jobOptions) ); + + /* Deal with landscape orientation */ + // Disable for the moment since testers say it has undesired effects + // if ( pJobData.m_eOrientation == orientation::Landscape ) + // strncat( jobOptions, " -o landscape ", kJobOptionsStringSize - strlen(jobOptions) ); + + /* Attach a job title */ + ByteString jobTitle( aJobName->getStr(), RTL_TEXTENCODING_UTF8 ); + if ( strstr(psprintPrintCmd.getStr(), "lpr ") > 0 ) + snprintf( jobOptions, kJobOptionsStringSize, "%s -T \"%s\"", jobOptions, jobTitle.GetBuffer() ); + else if ( strstr(psprintPrintCmd.getStr(), "lp ") > 0 ) + snprintf( jobOptions, kJobOptionsStringSize, "%s -t \"%s\"", jobOptions, jobTitle.GetBuffer() ); + } + + /* Construct and execute the printing command */ + snprintf( sysCommandBuffer, kSysCommandBufferLen-1, "cat \"%s\" | %s %s", pdfFileName, psprintPrintCmd.getStr(), jobOptions ); + #ifdef DEBUG + fprintf( stderr, "printerjob.cxx: printing PDF with command '%s'\n", sysCommandBuffer ); + #endif + + /* Stupid lp and lpr on 10.2 don't actually honor their respective # copies arguments. + * So we have to just keep printing the job over and over for multiple copies for PS->PDF + * printers. Direct-to-PostScript printers can handle the # copies _inside_ the PostScript + * document we are sending to them. + */ + int numCopies = (printFormat == kApplePrintingUsePDF ) ? pJobData.m_nCopies : 1; + for( index = 1; index <= numCopies; index++ ) + printCmdErr = system( sysCommandBuffer ); + } + unlink( pdfFileName ); + } + + #ifdef DEBUG + /* A printCmdErr of -1 will usually be an error in PS->PDF conversion, + * otherwise its an error returned by system(). + */ + if ( printCmdErr != 0 ) + fprintf( stderr, "printerjob.cxx: printing error, got %d.\n", printCmdErr ); + else + fprintf( stderr, "printerjob.cxx: printing successful, system() returned 0.\n" ); + #endif + } +} + +#define kSysPrintSetupString "sh -c 'PATH=$PATH:/usr/local/bin" +#define kPDFFileExtension ".pdf" + +// Convert PostScript files to PDF for easy printing, using GhostScript. +// Returns: 0 if no error +// -1 if error +int macxp_ConvertPSFileToPDF( char *psFileName, char *pdfFileName, int pdfFileNameBufferLen, sal_uInt32 jobDPI ) +{ + int returnVal = 0; + int printCmdErr = 0; + + /* Make sure we've got the space to play with file names/paths */ + if ( (strlen(psFileName) + strlen(kPDFFileExtension)) >= pdfFileNameBufferLen-1 ) + { + fprintf( stderr, "printerjob.cxx: Cannot convert print job to PDF because the file's path is too long.\n" ); + returnVal = -1; + } + else + { + char *sysCommandBuffer; + + /* Create the file name for the converted PDF and assemble the conversion command */ + snprintf( pdfFileName, pdfFileNameBufferLen-1, "%s%s", psFileName, kPDFFileExtension ); + + sysCommandBuffer = (char *)malloc( sizeof(char) * ( strlen(kSysPrintSetupString) + + strlen(kApplePS2PDFLocation) + + 10 + /* For " -r<DPI>" */ + strlen(psFileName) + + strlen(pdfFileName) + + 10) ); /* 10 bytes fudge factor */ + if ( sysCommandBuffer == NULL ) + returnVal = -1; + else + { + sprintf( sysCommandBuffer, "%s;%s -r%d \"%s\" \"%s\"'", kSysPrintSetupString, kApplePS2PDFLocation, jobDPI, psFileName, 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 ); + free( 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 + returnVal = (printCmdErr != 0) ? -1 : 0; + } + } + + return( returnVal ); +} +#endif /* MACOSX */ + sal_Bool PrinterJob::AbortJob () { @@ -735,8 +1114,8 @@ PrinterJob::EndPage () sal_Char pTrailer[256]; sal_Int32 nChar = 0; - nChar = psp::appendStr ("showpage\n", pTrailer); - nChar += psp::appendStr ("grestore grestore\n", pTrailer + nChar); + nChar = psp::appendStr ("grestore grestore\n", pTrailer); + nChar += psp::appendStr ("showpage\n", pTrailer + nChar); nChar += psp::appendStr ("%%PageTrailer\n\n", pTrailer + nChar); WritePS (pPageBody, pTrailer); @@ -821,7 +1200,9 @@ bool PrinterJob::writeFeatureList( osl::File* pFile, const JobData& rJob, bool b && pValue->m_eType == eInvocation && pValue->m_aValue.Len() && ( m_aLastJobData.m_pParser == NULL - || m_aLastJobData.m_aContext.getValue( pKey ) != pValue ) + || m_aLastJobData.m_aContext.getValue( pKey ) != pValue + || bDocumentSetup + ) ) { // try to avoid PS level 2 feature commands if level is set to 1 |