From e6f29e4ec25a71e8a9855fffd261a221aa69a0e7 Mon Sep 17 00:00:00 2001 From: "kjh-5727%comcast.net" Date: Tue, 7 Sep 2004 17:55:27 +0000 Subject: [PATCH] Bug 257381: Refactor postscript printer list logic & support printing through CUPS. r/sr=roc. --- allmakefiles.sh | 1 + gfx/src/Makefile.in | 16 +- gfx/src/gtk/Makefile.in | 1 + gfx/src/gtk/nsDeviceContextSpecG.cpp | 196 +++++------------------ gfx/src/ps/Makefile.in | 2 +- gfx/src/ps/nsPrintJobFactoryPS.cpp | 87 ---------- gfx/src/ps/nsPrintJobPS.cpp | 83 +++++++++- gfx/src/ps/nsPrintJobPS.h | 18 +++ gfx/src/psshared/Makefile.in | 67 ++++++++ gfx/src/psshared/nsCUPSShim.cpp | 86 ++++++++++ gfx/src/psshared/nsCUPSShim.h | 112 +++++++++++++ gfx/src/psshared/nsPSPrinters.cpp | 160 ++++++++++++++++++ gfx/src/psshared/nsPSPrinters.h | 101 ++++++++++++ gfx/src/psshared/nsPaperPS.cpp | 72 +++++++++ gfx/src/psshared/nsPaperPS.h | 126 +++++++++++++++ gfx/src/psshared/psshared.pkg | 4 + gfx/src/xlib/Makefile.in | 1 + gfx/src/xlib/nsDeviceContextSpecXlib.cpp | 124 +++++--------- 18 files changed, 920 insertions(+), 337 deletions(-) create mode 100644 gfx/src/psshared/Makefile.in create mode 100644 gfx/src/psshared/nsCUPSShim.cpp create mode 100644 gfx/src/psshared/nsCUPSShim.h create mode 100644 gfx/src/psshared/nsPSPrinters.cpp create mode 100644 gfx/src/psshared/nsPSPrinters.h create mode 100644 gfx/src/psshared/nsPaperPS.cpp create mode 100644 gfx/src/psshared/nsPaperPS.h create mode 100644 gfx/src/psshared/psshared.pkg diff --git a/allmakefiles.sh b/allmakefiles.sh index 2f53dd3aa6b..de08101962d 100755 --- a/allmakefiles.sh +++ b/allmakefiles.sh @@ -151,6 +151,7 @@ gfx/src/Makefile gfx/src/beos/Makefile gfx/src/gtk/Makefile gfx/src/ps/Makefile +gfx/src/psshared/Makefile gfx/src/photon/Makefile gfx/src/mac/Makefile gfx/src/xlib/Makefile diff --git a/gfx/src/Makefile.in b/gfx/src/Makefile.in index 6b24c55bada..60347f5e73d 100644 --- a/gfx/src/Makefile.in +++ b/gfx/src/Makefile.in @@ -67,7 +67,7 @@ DIRS += freetype endif ifdef MOZ_ENABLE_POSTSCRIPT -DIRS += ps +DIRS += psshared ps endif ifeq ($(MOZ_GFX_TOOLKIT),cocoa) @@ -152,13 +152,6 @@ EXPORTS += \ $(NULL) endif -ifdef MOZ_ENABLE_POSTSCRIPT -PS_LCPPSRCS = nsPaperPS.cpp -CPPSRCS += \ - $(PS_LCPPSRCS) \ - $(NULL) -endif - EXTRA_DSO_LDOPTS = \ $(DIST)/lib/$(LIB_PREFIX)mozutil_s.$(LIB_SUFFIX) \ $(MOZ_UNICHARUTIL_LIBS) \ @@ -177,10 +170,3 @@ FORCE_USE_PIC = 1 include $(topsrcdir)/config/rules.mk DEFINES += -D_IMPL_NS_GFX - -ifdef MOZ_ENABLE_POSTSCRIPT -GARBAGE += $(PS_LCPPSRCS) - -export:: $(addprefix $(srcdir)/ps/,$(PS_LCPPSRCS)) - $(INSTALL) $^ . -endif diff --git a/gfx/src/gtk/Makefile.in b/gfx/src/gtk/Makefile.in index b4f3ee1b500..4d9966e70c8 100644 --- a/gfx/src/gtk/Makefile.in +++ b/gfx/src/gtk/Makefile.in @@ -223,6 +223,7 @@ endif ifdef MOZ_ENABLE_POSTSCRIPT DEFINES += -DUSE_POSTSCRIPT +EXTRA_DSO_LDOPTS += -lgfxpsshar endif ifdef MOZ_ENABLE_XPRINT diff --git a/gfx/src/gtk/nsDeviceContextSpecG.cpp b/gfx/src/gtk/nsDeviceContextSpecG.cpp index eec3d3e8345..6a54fa3b233 100644 --- a/gfx/src/gtk/nsDeviceContextSpecG.cpp +++ b/gfx/src/gtk/nsDeviceContextSpecG.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Roland Mainz + * Ken Herron * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -62,34 +63,10 @@ #endif /* USE_XPRINT */ #ifdef USE_POSTSCRIPT +#include "nsPSPrinters.h" #include "nsPaperPS.h" /* Paper size list */ #endif /* USE_POSTSCRIPT */ -#include "prlink.h" - -typedef struct /**** Printer Options ****/ -{ - char *name; /* Name of option */ - char *value; /* Value of option */ -} cups_option_t; - -typedef struct /**** Destination ****/ -{ - char *name, /* Printer or class name */ - *instance; /* Local instance name or NULL */ - int is_default; /* Is this printer the default? */ - int num_options; /* Number of options */ - cups_option_t *options; /* Options */ -} cups_dest_t; - -typedef int (PR_CALLBACK *CupsGetDestsType)(cups_dest_t **dests); -typedef cups_dest_t * (PR_CALLBACK *CupsGetDestType)(const char *name, - const char *instance, - int num_dests, - cups_dest_t *dests); -typedef int (PR_CALLBACK *CupsFreeDestsType)(int num_dests, - cups_dest_t *dests); - /* Ensure that the result is always equal to either PR_TRUE or PR_FALSE */ #define MAKE_PR_BOOL(val) ((val)?(PR_TRUE):(PR_FALSE)) @@ -114,7 +91,8 @@ public: nsresult InitializeGlobalPrinters(); PRBool PrintersAreAllocated() { return mGlobalPrinterList != nsnull; } - PRInt32 GetNumPrinters() { return mGlobalNumPrinters; } + PRInt32 GetNumPrinters() + { return mGlobalPrinterList ? mGlobalPrinterList->Count() : 0; } nsString* GetStringAt(PRInt32 aInx) { return mGlobalPrinterList->StringAt(aInx); } void GetDefaultPrinterName(PRUnichar **aDefaultPrinterName); @@ -123,7 +101,6 @@ protected: static GlobalPrinters mGlobalPrinters; static nsStringArray* mGlobalPrinterList; - static int mGlobalNumPrinters; }; #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -294,7 +271,6 @@ void nsPrinterFeatures::SetMultipleConcurrentDeviceContextsSupported( PRBool aCa // static members GlobalPrinters GlobalPrinters::mGlobalPrinters; nsStringArray* GlobalPrinters::mGlobalPrinterList = nsnull; -int GlobalPrinters::mGlobalNumPrinters = 0; //--------------- nsDeviceContextSpecGTK::nsDeviceContextSpecGTK() @@ -548,10 +524,8 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetPrintMethod(PrintMethod &aMethod) nsresult nsDeviceContextSpecGTK::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod) { #if defined(USE_POSTSCRIPT) && defined(USE_XPRINT) - /* printer names for the PostScript module alwas start with - * the NS_POSTSCRIPT_DRIVER_NAME string */ - if (strncmp(aPrinter, NS_POSTSCRIPT_DRIVER_NAME, - NS_POSTSCRIPT_DRIVER_NAME_LEN) != 0) + if (nsPSPrinterList::kTypeUnknown == + nsPSPrinterList::GetPrinterType(nsDependentCString(aPrinter))) aMethod = pmXprint; else aMethod = pmPostScript; @@ -735,9 +709,11 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const PRUnich #ifdef USE_POSTSCRIPT /* "Demangle" postscript printer name */ if (type == pmPostScript) { - /* Strip the leading NS_POSTSCRIPT_DRIVER_NAME from |printerName|, + /* Strip the printing method name from the printer, * e.g. turn "PostScript/foobar" to "foobar" */ - printerName.Cut(0, NS_POSTSCRIPT_DRIVER_NAME_LEN); + PRInt32 slash = printerName.FindChar('/'); + if (kNotFound != slash) + printerName.Cut(0, slash + 1); } #endif /* USE_POSTSCRIPT */ @@ -955,7 +931,6 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const PRUnich printerFeatures.SetSupportsPaperSizeChange(PR_TRUE); printerFeatures.SetSupportsOrientationChange(PR_TRUE); printerFeatures.SetSupportsPlexChange(PR_FALSE); - printerFeatures.SetSupportsSpoolerCommandChange(PR_TRUE); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -1027,14 +1002,21 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const PRUnich #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ } + PRBool hasSpoolerCmd = (nsPSPrinterList::kTypePS == + nsPSPrinterList::GetPrinterType(fullPrinterName)); #ifdef SET_PRINTER_FEATURES_VIA_PREFS - printerFeatures.SetCanChangeSpoolerCommand(PR_TRUE); + printerFeatures.SetSupportsSpoolerCommandChange(hasSpoolerCmd); + printerFeatures.SetCanChangeSpoolerCommand(hasSpoolerCmd); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ - nsXPIDLCString command; - if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "print_command", getter_Copies(command)))) { - DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", command.get())); - aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUCS2(command).get()); + if (hasSpoolerCmd) { + nsXPIDLCString command; + if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", + printerName, "print_command", getter_Copies(command)))) { + DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", + command.get())); + aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUCS2(command).get()); + } } #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -1053,6 +1035,18 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const PRUnichar *aPri return NS_OK; } + +//---------------------------------------------------------------------- +//String array enumeration callback to append a printer to the global +//printer list. +static PRBool +GlobalPrinterEnumFunc(nsCString& aName, void *aData) +{ + nsStringArray *a = (nsStringArray *)aData; + a->AppendString(NS_ConvertUTF8toUTF16(aName)); + return PR_TRUE; +} + //---------------------------------------------------------------------- nsresult GlobalPrinters::InitializeGlobalPrinters () { @@ -1060,7 +1054,6 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () return NS_OK; } - mGlobalNumPrinters = 0; mGlobalPrinterList = new nsStringArray(); if (!mGlobalPrinterList) return NS_ERROR_OUT_OF_MEMORY; @@ -1071,12 +1064,13 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () return rv; #ifdef USE_XPRINT - XPPrinterList plist = XpuGetPrinterList(nsnull, &mGlobalNumPrinters); + int printerCount; + XPPrinterList plist = XpuGetPrinterList(nsnull, &printerCount); - if (plist && (mGlobalNumPrinters > 0)) + if (plist) { int i; - for( i = 0 ; i < mGlobalNumPrinters ; i++ ) + for( i = 0 ; i < printerCount ; i++ ) { /* Add name to our list of printers... */ mGlobalPrinterList->AppendString(nsString(NS_ConvertUTF8toUCS2(plist[i].name))); @@ -1090,118 +1084,17 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () #endif /* USE_XPRINT */ #ifdef USE_POSTSCRIPT - PRBool psPrintModuleEnabled = PR_TRUE; - - const char *val = PR_GetEnv("MOZILLA_POSTSCRIPT_ENABLED"); - if (val) { - if (val[0] == '0' || !strcasecmp(val, "false")) - psPrintModuleEnabled = PR_FALSE; - } - else - { - if (NS_FAILED(pPrefs->GetBoolPref("print.postscript.enabled", &psPrintModuleEnabled))) { - psPrintModuleEnabled = PR_TRUE; - } - } - - if (psPrintModuleEnabled) { + nsPSPrinterList psMgr; + if (NS_SUCCEEDED(psMgr.Init()) && psMgr.Enabled()) { /* Get the list of PostScript-module printers */ - char *printerList = nsnull; - PRBool added_default_printer = PR_FALSE; /* Did we already add the default printer ? */ - - /* The env var MOZILLA_POSTSCRIPT_PRINTER_LIST can "override" the prefs */ - printerList = PR_GetEnv("MOZILLA_POSTSCRIPT_PRINTER_LIST"); - - if (!printerList) { - (void) pPrefs->CopyCharPref("print.printer_list", &printerList); - } - - if (printerList && *printerList) { - char *tok_lasts; - const char *name; - - /* PL_strtok_r() will modify the string - copy it! */ - printerList = strdup(printerList); - if (!printerList) - return NS_ERROR_OUT_OF_MEMORY; - - for( name = PL_strtok_r(printerList, " ", &tok_lasts) ; - name != nsnull ; - name = PL_strtok_r(nsnull, " ", &tok_lasts) ) - { - /* Is this the "default" printer ? */ - if (!strcmp(name, "default")) - added_default_printer = PR_TRUE; - - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME)) + - nsString(NS_ConvertASCIItoUCS2(name))); - mGlobalNumPrinters++; - } - - free(printerList); - } else { - /* Try to use CUPS */ - PRLibrary *clib = PR_LoadLibrary("libcups.so.2"); - if (clib) { - CupsGetDestsType CupsGetDests; - CupsGetDestType CupsGetDest; - CupsFreeDestsType CupsFreeDests; - - CupsGetDests = (CupsGetDestsType) PR_FindSymbol( clib, "cupsGetDests"); - CupsGetDest = (CupsGetDestType) PR_FindSymbol( clib, "cupsGetDest"); - CupsFreeDests = (CupsFreeDestsType) PR_FindSymbol( clib, "cupsFreeDests"); - - if (CupsGetDests && CupsGetDest && CupsFreeDests) { - int num_dests; - cups_dest_t *dests; - - /* Get the list of destinations */ - num_dests = (*CupsGetDests)(&dests); - - if (num_dests > 0) { - int i; - cups_dest_t *defdest; - - /* Get the default destination */ - defdest = (*CupsGetDest)(NULL, NULL, num_dests, dests); - - /* Add default destination as first in list */ - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME)) + - nsString(NS_ConvertASCIItoUCS2(defdest->name))); - mGlobalNumPrinters++; - added_default_printer = PR_TRUE; - - for (i = 0; i < num_dests; i ++) { - /* Don't add the default printer again */ - if (strcmp(dests[i].name, defdest->name) != 0) { - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME)) + - nsString(NS_ConvertASCIItoUCS2(dests[i].name))); - mGlobalNumPrinters++; - } - } - (*CupsFreeDests)(num_dests, dests); - } - } - PR_UnloadLibrary(clib); - } - } - - /* Add an entry for the default printer (see nsPostScriptObj.cpp) if we - * did not add it already... */ - if (!added_default_printer) - { - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME "default"))); - mGlobalNumPrinters++; - } + nsCStringArray printerList; + psMgr.GetPrinterList(printerList); + printerList.EnumerateForwards(GlobalPrinterEnumFunc, mGlobalPrinterList); } #endif /* USE_POSTSCRIPT */ /* If there are no printers available after all checks, return an error */ - if (mGlobalNumPrinters == 0) + if (!mGlobalPrinterList->Count()) { /* Make sure we do not cache an empty printer list */ FreeGlobalPrinters(); @@ -1225,7 +1118,6 @@ void GlobalPrinters::FreeGlobalPrinters() if (mGlobalPrinterList) { delete mGlobalPrinterList; mGlobalPrinterList = nsnull; - mGlobalNumPrinters = 0; } } diff --git a/gfx/src/ps/Makefile.in b/gfx/src/ps/Makefile.in index 92adad10d84..53eb78b9b2f 100644 --- a/gfx/src/ps/Makefile.in +++ b/gfx/src/ps/Makefile.in @@ -80,7 +80,6 @@ EXPORTS = \ nsGfxPSCID.h \ nsIDeviceContextSpecPS.h \ nsTempfilePS.h \ - nsPaperPS.h \ $(NULL) EXPORT_RESOURCE = \ @@ -90,6 +89,7 @@ EXTRA_DSO_LDOPTS = \ -L$(DIST)/bin \ -L$(DIST)/lib \ -lgfxshared_s \ + -lgfxpsshar \ $(EXTRA_DSO_LIBS) \ $(MOZ_COMPONENT_LIBS) \ $(MOZ_UNICHARUTIL_LIBS) \ diff --git a/gfx/src/ps/nsPrintJobFactoryPS.cpp b/gfx/src/ps/nsPrintJobFactoryPS.cpp index 11adbb474f1..e69de29bb2d 100644 --- a/gfx/src/ps/nsPrintJobFactoryPS.cpp +++ b/gfx/src/ps/nsPrintJobFactoryPS.cpp @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Kenneth Herron . - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#include "nsDebug.h" -#include "nsPrintJobFactoryPS.h" -#include "nsIDeviceContextSpecPS.h" -#include "nsPrintJobPS.h" - -/** - * Construct a print job object for the given device context spec. - * - * @param aSpec An nsIDeviceContextSpecPS object for the print - * job in question. - * @param aPrintJob A pointer to a print job object which will - * handle the print job. - * @return NS_OK if all is well, or a suitable error value. - */ - -nsresult -nsPrintJobFactoryPS::CreatePrintJob(nsIDeviceContextSpecPS *aSpec, - nsIPrintJobPS* &aPrintJob) -{ - NS_PRECONDITION(nsnull != aSpec, "aSpec is NULL"); - - nsIPrintJobPS *newPJ; - - PRBool setting; - aSpec->GetIsPrintPreview(setting); - if (setting) - newPJ = new nsPrintJobPreviewPS(); - else { - aSpec->GetToPrinter(setting); - if (setting) -#ifdef VMS - newPJ = new nsPrintJobVMSCmdPS(); -#else - newPJ = new nsPrintJobPipePS(); -#endif - else - newPJ = new nsPrintJobFilePS(); - } - if (!newPJ) - return NS_ERROR_OUT_OF_MEMORY; - - nsresult rv = newPJ->Init(aSpec); - if (NS_FAILED(rv)) - delete newPJ; - else - aPrintJob = newPJ; - return rv; -} diff --git a/gfx/src/ps/nsPrintJobPS.cpp b/gfx/src/ps/nsPrintJobPS.cpp index e6fc3f0ce41..fd4b31a8bc5 100644 --- a/gfx/src/ps/nsPrintJobPS.cpp +++ b/gfx/src/ps/nsPrintJobPS.cpp @@ -42,6 +42,7 @@ #include "nsIDeviceContextPS.h" // NS_POSTSCRIPT_DRIVER_NAME_LEN #include "nsIDeviceContextSpecPS.h" #include "nsPrintJobPS.h" +#include "nsPSPrinters.h" #include "nsReadableUtils.h" #include "prenv.h" @@ -51,6 +52,7 @@ #include #include +#include /* Routines to set environment variables. These are defined toward @@ -174,7 +176,9 @@ nsPrintJobVMSCmdPS::Init(nsIDeviceContextSpecPS *aSpec) const char *printerName; aSpec->GetPrinterName(&printerName); if (printerName) { - printerName += NS_POSTSCRIPT_DRIVER_NAME_LEN; + const char *slash = strchr(printerName, '/'); + if (slash) + printerName = slash + 1; if (0 != strcmp(printerName, "default")) mPrinterName = printerName; } @@ -285,7 +289,9 @@ nsPrintJobPipePS::Init(nsIDeviceContextSpecPS *aSpec) const char *printerName; aSpec->GetPrinterName(&printerName); if (printerName) { - printerName += NS_POSTSCRIPT_DRIVER_NAME_LEN; + const char *slash = strchr(printerName, '/'); + if (slash) + printerName = slash + 1; if (0 != strcmp(printerName, "default")) mPrinterName = printerName; } @@ -332,6 +338,79 @@ nsPrintJobPipePS::FinishSubmission() } +/**** Print via CUPS ****/ + +/** + * Initialize a print-to-CUPS object. + * See nsIPrintJobPS.h and nsPrintJobPS.h for details. + */ +nsresult +nsPrintJobCUPS::Init(nsIDeviceContextSpecPS *aSpec) +{ + NS_PRECONDITION(aSpec, "argument must not be NULL"); +#ifdef DEBUG + PRBool toPrinter; + aSpec->GetToPrinter(toPrinter); + NS_PRECONDITION(toPrinter, "Wrong class for this print job"); +#endif + + NS_ENSURE_TRUE(mCups.Init(), NS_ERROR_NOT_INITIALIZED); + + /* Printer name */ + const char *printerName = nsnull; + aSpec->GetPrinterName(&printerName); + NS_ENSURE_TRUE(printerName, NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND); + + const char *slash = strchr(printerName, '/'); + mPrinterName = slash ? slash + 1 : printerName; + return NS_OK; +} + +nsresult +nsPrintJobCUPS::StartSubmission(FILE **aHandle) +{ + NS_ENSURE_TRUE(mCups.IsInitialized(), NS_ERROR_NOT_INITIALIZED); + + int fd; + char buf[FILENAME_MAX]; + + fd = (mCups.mCupsTempFd)(buf, sizeof buf); + // The CUPS manual doesn't describe what cupsTempFd() returns to + // indicate failure. -1 is a likely value. + NS_ENSURE_TRUE(fd > 0, NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE); + + SetDestHandle(fdopen(fd, "r+")); + if (!GetDestHandle()) { + close(fd); + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; + } + SetDestination(buf); + *aHandle = GetDestHandle(); + return NS_OK; +} + + +nsresult +nsPrintJobCUPS::FinishSubmission() +{ + NS_ENSURE_TRUE(mCups.IsInitialized(), NS_ERROR_NOT_INITIALIZED); + NS_PRECONDITION(GetDestHandle(), "No destination file handle"); + NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination"); + + fclose(GetDestHandle()); + SetDestHandle(nsnull); + + int result = (mCups.mCupsPrintFile)(mPrinterName.get(), + GetDestination().get(), "Mozilla print job", 0, nsnull); + unlink(GetDestination().get()); + + // cupsPrintFile() result codes below 0x0300 indicate success. + // Individual success codes are defined in the cups headers, but + // we're not including those. + return (result < 0x0300) ? NS_OK : NS_ERROR_GFX_PRINTER_CMD_FAILURE; +} + + #endif /* VMS */ diff --git a/gfx/src/ps/nsPrintJobPS.h b/gfx/src/ps/nsPrintJobPS.h index 27db8f3d4a7..efe846847b1 100644 --- a/gfx/src/ps/nsPrintJobPS.h +++ b/gfx/src/ps/nsPrintJobPS.h @@ -39,6 +39,7 @@ #ifndef nsPrintJobPS_h__ #define nsPrintJobPS_h__ +#include "nsCUPSShim.h" #include "nsDebug.h" #include "nsIDeviceContext.h" // for NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED #include "nsILocalFile.h" @@ -154,6 +155,23 @@ class nsPrintJobPipePS : public nsPrintJobFilePS { nsCString mPrinterName; }; + +/* This class submits print jobs through CUPS. mDestHandle and + * mDestination point to a temporary file used to assemble the + * final print job. + */ +class nsPrintJobCUPS : public nsPrintJobFilePS { + public: + nsresult StartSubmission(FILE **aHandle); + nsresult FinishSubmission(); + + protected: + nsresult Init(nsIDeviceContextSpecPS *); + + private: + nsCUPSShim mCups; + nsCString mPrinterName; +}; #endif /* VMS */ #endif /* nsPrintJobPS_h__ */ diff --git a/gfx/src/psshared/Makefile.in b/gfx/src/psshared/Makefile.in new file mode 100644 index 00000000000..9ebafdfb26c --- /dev/null +++ b/gfx/src/psshared/Makefile.in @@ -0,0 +1,67 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Ken Herron +# Portions created by the Initial Developer are Copyright (C) 2004 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = gfx +LIBRARY_NAME = gfxpsshar +EXPORT_LIBRARY = 1 +GRE_MODULE = 1 +REQUIRES = pref \ + string \ + widget \ + xpcom \ + $(NULL) + +PACKAGE_FILE = psshared.pkg + +EXPORTS = nsCUPSShim.h \ + nsPaperPS.h \ + nsPSPrinters.h\ + $(NULL) + +CPPSRCS = nsCUPSShim.cpp \ + nsPaperPS.cpp \ + nsPSPrinters.cpp \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/gfx/src/psshared/nsCUPSShim.cpp b/gfx/src/psshared/nsCUPSShim.cpp new file mode 100644 index 00000000000..a5a3ed18767 --- /dev/null +++ b/gfx/src/psshared/nsCUPSShim.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla PostScript driver printer list component. + * + * The Initial Developer of the Original Code is + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsDebug.h" +#include "nsCUPSShim.h" +#include "prlink.h" + + +// List of symbols to find in libcups. Must match symAddr[] defined in Init(). +// Making this an array of arrays instead of pointers allows storing the +// whole thing in read-only memory. +static const char gSymName[][sizeof("cupsPrintFile")] = { + { "cupsGetDests" }, + { "cupsFreeDests" }, + { "cupsPrintFile" }, + { "cupsTempFd" }, +}; +static const int gSymNameCt = sizeof(gSymName) / sizeof(gSymName[0]); + + +PRBool +nsCUPSShim::Init() +{ + mCupsLib = PR_LoadLibrary("libcups.so.2"); + if (!mCupsLib) + return PR_FALSE; + + // List of symbol pointers. Must match gSymName[] defined above. + void **symAddr[] = { + (void **)&mCupsGetDests, + (void **)&mCupsFreeDests, + (void **)&mCupsPrintFile, + (void **)&mCupsTempFd, + }; + + for (int i = gSymNameCt; i--; ) { + *(symAddr[i]) = PR_FindSymbol(mCupsLib, gSymName[i]); + if (! *(symAddr[i])) { + PR_UnloadLibrary(mCupsLib); + mCupsLib = nsnull; + return PR_FALSE; + } + } + return PR_TRUE; +} + +nsCUPSShim::~nsCUPSShim() +{ + if (mCupsLib) + PR_UnloadLibrary(mCupsLib); +} diff --git a/gfx/src/psshared/nsCUPSShim.h b/gfx/src/psshared/nsCUPSShim.h new file mode 100644 index 00000000000..0f82a950b7a --- /dev/null +++ b/gfx/src/psshared/nsCUPSShim.h @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla PostScript driver printer list component. + * + * The Initial Developer of the Original Code is + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsCUPSShim_h___ +#define nsCUPSShim_h___ + +#include "prtypes.h" + + +/* Various CUPS data types. We don't #include cups headers to avoid + * requiring CUPS to be installed on the build host (and to avoid having + * to test for CUPS in configure). + */ +typedef struct /**** Printer Options ****/ +{ + char *name; /* Name of option */ + char *value; /* Value of option */ +} cups_option_t; + +typedef struct /**** Destination ****/ +{ + char *name, /* Printer or class name */ + *instance; /* Local instance name or NULL */ + int is_default; /* Is this printer the default? */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ +} cups_dest_t; + +typedef int (PR_CALLBACK *CupsGetDestsType)(cups_dest_t **dests); +typedef int (PR_CALLBACK *CupsFreeDestsType)(int num_dests, + cups_dest_t *dests); +typedef int (PR_CALLBACK *CupsPrintFileType)(const char *printer, + const char *filename, + const char *title, + int num_options, + cups_option_t *options); +typedef int (PR_CALLBACK *CupsTempFdType)(char *filename, + int length); + +struct PRLibrary; + +class nsCUPSShim { + public: + nsCUPSShim() : mCupsLib(nsnull) { } + ~nsCUPSShim(); + + /** + * Initialize this object. Attempt to load the CUPS shared + * library and find function pointers for the supported + * functions (see below). + * @return PR_FALSE if the shared library could not be loaded, or if + * any of the functions could not be found. + * PR_TRUE for successful initialization. + */ + PRBool Init(); + + /** + * @return PR_TRUE if the object was initialized successfully. + * PR_FALSE otherwise. + */ + PRBool IsInitialized() { return nsnull != mCupsLib; } + + /* Function pointers for supported functions. These are only + * valid after successful initialization. + */ + CupsGetDestsType mCupsGetDests; + CupsFreeDestsType mCupsFreeDests; + CupsPrintFileType mCupsPrintFile; + CupsTempFdType mCupsTempFd; + + private: + PRLibrary *mCupsLib; +}; + + + +#endif /* nsCUPSShim_h___ */ diff --git a/gfx/src/psshared/nsPSPrinters.cpp b/gfx/src/psshared/nsPSPrinters.cpp new file mode 100644 index 00000000000..f82fd25fcca --- /dev/null +++ b/gfx/src/psshared/nsPSPrinters.cpp @@ -0,0 +1,160 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla PostScript driver printer list component. + * + * The Initial Developer of the Original Code is + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nscore.h" +#include "nsCUPSShim.h" +#include "nsIDeviceContext.h" // GFX error codes +#include "nsIDeviceContextSpecPS.h" // NS_POSTSCRIPT_DRIVER_NAME +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsIServiceManager.h" +#include "nsPrintfCString.h" +#include "nsPSPrinters.h" +#include "nsReadableUtils.h" // StringBeginsWith() + +#include "prlink.h" +#include "prenv.h" +#include "plstr.h" + +#define NS_CUPS_PRINTER "CUPS/" +#define NS_CUPS_PRINTER_LEN (sizeof(NS_CUPS_PRINTER) - 1) + + +/* Initialize the printer manager object */ +nsresult +nsPSPrinterList::Init() +{ + nsresult rv; + + mPrefSvc = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + rv = mPrefSvc->GetBranch("print.", getter_AddRefs(mPref)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_INITIALIZED); + + // Should we try cups? + PRBool useCups; + rv = mPref->GetBoolPref("postscript.cups.enabled", &useCups); + if (useCups) + mCups.Init(); + return NS_OK; +} + + +/* Check whether the PostScript module has been disabled at runtime */ +PRBool +nsPSPrinterList::Enabled() +{ + const char *val = PR_GetEnv("MOZILLA_POSTSCRIPT_ENABLED"); + if (val && (val[0] == '0' || !strcasecmp(val, "false"))) + return PR_FALSE; + + // is the PS module enabled? + PRBool setting = PR_TRUE; + mPref->GetBoolPref("postscript.enabled", &setting); + return setting; +} + + +/* Fetch a list of printers handled by the PostsScript module */ +void +nsPSPrinterList::GetPrinterList(nsCStringArray& aList) +{ + aList.Clear(); + + // Query CUPS for a printer list. The default printer goes to the + // head of the output list; others are appended. + if (mCups.IsInitialized()) { + cups_dest_t *dests; + + int num_dests = (mCups.mCupsGetDests)(&dests); + if (num_dests) { + for (int i = 0; i < num_dests; i++) { + nsCAutoString fullName(NS_CUPS_PRINTER); + fullName.Append(dests[i].name); + if (dests[i].is_default) + aList.InsertCStringAt(fullName, 0); + else + aList.AppendCString(fullName); + } + } + (mCups.mCupsFreeDests)(num_dests, dests); + } + + // Build the "classic" list of printers -- those accessed by running + // an opaque command. This list always contains a printer named "default". + // In addition, we look for either an environment variable + // MOZILLA_POSTSCRIPT_PRINTER_LIST or a preference setting + // print.printer_list, which contains a space-separated list of printer + // names. + aList.AppendCString( + NS_LITERAL_CSTRING(NS_POSTSCRIPT_DRIVER_NAME "default")); + + nsXPIDLCString list; + list.Assign(PR_GetEnv("MOZILLA_POSTSCRIPT_PRINTER_LIST")); + if (list.IsEmpty()) + mPref->GetCharPref("printer_list", getter_Copies(list)); + if (!list.IsEmpty()) { + // For each printer (except "default" which was already added), + // construct a string "PostScript/" and append it to the list. + char *state; + + for (char *name = PL_strtok_r(list.BeginWriting(), " ", &state); + nsnull != name; + name = PL_strtok_r(nsnull, " ", &state) + ) { + if (0 != strcmp(name, "default")) { + nsCAutoString fullName(NS_POSTSCRIPT_DRIVER_NAME); + fullName.Append(name); + aList.AppendCString(fullName); + } + } + } +} + + +/* Identify the printer type */ +nsPSPrinterList::PrinterType +nsPSPrinterList::GetPrinterType(const nsACString& aName) +{ + if (StringBeginsWith(aName, NS_LITERAL_CSTRING(NS_POSTSCRIPT_DRIVER_NAME))) + return kTypePS; + else if (StringBeginsWith(aName, NS_LITERAL_CSTRING(NS_CUPS_PRINTER))) + return kTypeCUPS; + else + return kTypeUnknown; +} diff --git a/gfx/src/psshared/nsPSPrinters.h b/gfx/src/psshared/nsPSPrinters.h new file mode 100644 index 00000000000..07e49ef075d --- /dev/null +++ b/gfx/src/psshared/nsPSPrinters.h @@ -0,0 +1,101 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla PostScript driver printer list component. + * + * The Initial Developer of the Original Code is + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsPSPrinters_h___ +#define nsPSPrinters_h___ + +#include "nsString.h" +#include "nsVoidArray.h" +#include "prtypes.h" +#include "nsCUPSShim.h" + +class nsIPrefService; +class nsIPrefBranch; +class nsCUPSShim; + +class nsPSPrinterList { + public: + /** + * Initialize a printer manager object. + * @return NS_ERROR_NOT_INITIALIZED if unable to access prefs + * NS_OK for successful initialization. + */ + nsresult Init(); + + /** + * Is the PostScript module enabled or disabled? + * @return PR_TRUE if enabled, + * PR_FALSE if not. + */ + PRBool Enabled(); + + /** + * Obtain a list of printers (print destinations) supported by the + * PostScript module, Each entry will be in the form /, + * where is a printer type string, and is the actual + * printer name. + * + * @param aList Upon return, this is populated with the list of + * printer names as described above, replacing any + * previous contents. Each entry is a UTF8 string. + * There should always be at least one entry. The + * first entry is the default print destination. + */ + void GetPrinterList(nsCStringArray& aList); + + enum PrinterType { + kTypeUnknown, // Not actually handled by the PS module + kTypePS, // Generic postscript module printer + kTypeCUPS, // CUPS printer + }; + + /** + * Identify a printer's type from its name. + * @param aName The printer's full name as a UTF8 string, including + * the portion as described for GetPrinterList(). + * @return The PrinterType value for this name. + */ + static PrinterType GetPrinterType(const nsACString& aName); + + private: + nsCOMPtr mPrefSvc; + nsCOMPtr mPref; + nsCUPSShim mCups; +}; + +#endif /* nsPSPrinters_h___ */ diff --git a/gfx/src/psshared/nsPaperPS.cpp b/gfx/src/psshared/nsPaperPS.cpp new file mode 100644 index 00000000000..4f5d29d4ee3 --- /dev/null +++ b/gfx/src/psshared/nsPaperPS.cpp @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is developed for mozilla. The tables of paper sizes + * and paper orientations are based on tables from nsPostScriptObj.h. + * + * The Initial Developer of the Original Code is + * Kenneth Herron . + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include "nsPaperPS.h" +#include "plstr.h" + +#define COUNTOF(x) (sizeof(x) / sizeof((x)[0])) + +const nsPaperSizePS_ nsPaperSizePS::mList[] = +{ +#define SIZE_MM(x) (x) +#define SIZE_INCH(x) ((x) * 25.4) + { "A5", SIZE_MM(148), SIZE_MM(210), PR_TRUE }, + { "A4", SIZE_MM(210), SIZE_MM(297), PR_TRUE }, + { "A3", SIZE_MM(297), SIZE_MM(420), PR_TRUE }, + { "Letter", SIZE_INCH(8.5), SIZE_INCH(11), PR_FALSE }, + { "Legal", SIZE_INCH(8.5), SIZE_INCH(14), PR_FALSE }, + { "Executive", SIZE_INCH(7.5), SIZE_INCH(10), PR_FALSE }, +#undef SIZE_INCH +#undef SIZE_MM +}; + +const unsigned int nsPaperSizePS::mCount = COUNTOF(mList); + +PRBool +nsPaperSizePS::Find(const char *aName) +{ + for (int i = mCount; i--; ) { + if (!PL_strcasecmp(aName, mList[i].name)) { + mCurrent = i; + return PR_TRUE; + } + } + return PR_FALSE; +} diff --git a/gfx/src/psshared/nsPaperPS.h b/gfx/src/psshared/nsPaperPS.h new file mode 100644 index 00000000000..2d5e79c4831 --- /dev/null +++ b/gfx/src/psshared/nsPaperPS.h @@ -0,0 +1,126 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is developed for mozilla. + * + * The Initial Developer of the Original Code is + * Kenneth Herron . + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef _PAPERPS_H_ +#define _PAPERPS_H_ + +#include "prtypes.h" +#include "nsDebug.h" + +struct nsPaperSizePS_ { + const char *name; + float width_mm; + float height_mm; + PRBool isMetric; // Present to the user in metric, if possible +}; + +class nsPaperSizePS { + public: + /** --------------------------------------------------- + * Constructor + */ + nsPaperSizePS() { mCurrent = 0; } + + /** --------------------------------------------------- + * @return PR_TRUE if the cursor points past the last item. + */ + PRBool AtEnd() { return mCurrent >= mCount; } + + /** --------------------------------------------------- + * Position the cursor at the beginning of the paper size list. + * @return VOID + */ + void First() { mCurrent = 0; } + + /** --------------------------------------------------- + * Advance the cursor to the next item. + * @return VOID + */ + void Next() { + NS_WARN_IF_FALSE(!AtEnd(), "Invalid current item"); + mCurrent++; + } + + /** --------------------------------------------------- + * Point the cursor to the entry with the given paper name. + * @return PR_TRUE if pointing to a valid entry. + */ + PRBool Find(const char *aName); + + /** --------------------------------------------------- + * @return a pointer to the name of the current paper size + */ + const char *Name() { + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return mList[mCurrent].name; + } + + /** --------------------------------------------------- + * @return the width of the page in millimeters + */ + float Width_mm() { + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return mList[mCurrent].width_mm; + } + + /** --------------------------------------------------- + * @return the height of the page in millimeters + */ + float Height_mm() { + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return mList[mCurrent].height_mm; + } + + /** --------------------------------------------------- + * @return PR_TRUE if the paper should be presented to + * the user in metric units. + */ + PRBool IsMetric() { + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return mList[mCurrent].isMetric; + } + + private: + unsigned int mCurrent; + static const nsPaperSizePS_ mList[]; + static const unsigned int mCount; +}; + +#endif + diff --git a/gfx/src/psshared/psshared.pkg b/gfx/src/psshared/psshared.pkg new file mode 100644 index 00000000000..81976c1468a --- /dev/null +++ b/gfx/src/psshared/psshared.pkg @@ -0,0 +1,4 @@ +[gecko] +#if SHARED_LIBRARY +dist/bin/@SHARED_LIBRARY@ +#endif diff --git a/gfx/src/xlib/Makefile.in b/gfx/src/xlib/Makefile.in index fbf6a63804c..1cc8e949512 100644 --- a/gfx/src/xlib/Makefile.in +++ b/gfx/src/xlib/Makefile.in @@ -129,6 +129,7 @@ DEFINES += -DUSE_MOZILLA_TYPES ifdef MOZ_ENABLE_POSTSCRIPT DEFINES += -DUSE_POSTSCRIPT +EXTRA_DSO_LDOPTS += -lgfxpsshar endif ifdef MOZ_ENABLE_XPRINT diff --git a/gfx/src/xlib/nsDeviceContextSpecXlib.cpp b/gfx/src/xlib/nsDeviceContextSpecXlib.cpp index d6c5bd797f8..c4215281b26 100644 --- a/gfx/src/xlib/nsDeviceContextSpecXlib.cpp +++ b/gfx/src/xlib/nsDeviceContextSpecXlib.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Roland Mainz + * Ken Herron * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -62,6 +63,7 @@ #endif /* USE_XPRINT */ #ifdef USE_POSTSCRIPT +#include "nsPSPrinters.h" #include "nsPaperPS.h" /* Paper size list */ #endif /* USE_POSTSCRIPT */ @@ -89,7 +91,8 @@ public: nsresult InitializeGlobalPrinters(); PRBool PrintersAreAllocated() { return mGlobalPrinterList != nsnull; } - PRInt32 GetNumPrinters() { return mGlobalNumPrinters; } + PRInt32 GetNumPrinters() + { return mGlobalPrinterList ? mGlobalPrinterList->Count() : 0; } nsString* GetStringAt(PRInt32 aInx) { return mGlobalPrinterList->StringAt(aInx); } void GetDefaultPrinterName(PRUnichar **aDefaultPrinterName); @@ -98,7 +101,6 @@ protected: static GlobalPrinters mGlobalPrinters; static nsStringArray* mGlobalPrinterList; - static int mGlobalNumPrinters; }; #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -269,7 +271,6 @@ void nsPrinterFeatures::SetMultipleConcurrentDeviceContextsSupported( PRBool aCa // static members GlobalPrinters GlobalPrinters::mGlobalPrinters; nsStringArray* GlobalPrinters::mGlobalPrinterList = nsnull; -int GlobalPrinters::mGlobalNumPrinters = 0; //--------------- nsDeviceContextSpecXlib::nsDeviceContextSpecXlib() @@ -523,10 +524,8 @@ NS_IMETHODIMP nsDeviceContextSpecXlib::GetPrintMethod(PrintMethod &aMethod) nsresult nsDeviceContextSpecXlib::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod) { #if defined(USE_POSTSCRIPT) && defined(USE_XPRINT) - /* printer names for the PostScript module alwas start with - * the NS_POSTSCRIPT_DRIVER_NAME string */ - if (strncmp(aPrinter, NS_POSTSCRIPT_DRIVER_NAME, - NS_POSTSCRIPT_DRIVER_NAME_LEN) != 0) + if (nsPSPrinterList::kTypeUnknown == + nsPSPrinterList::GetPrinterType(nsDependentCString(aPrinter))) aMethod = pmXprint; else aMethod = pmPostScript; @@ -710,9 +709,11 @@ NS_IMETHODIMP nsPrinterEnumeratorXlib::InitPrintSettingsFromPrinter(const PRUnic #ifdef USE_POSTSCRIPT /* "Demangle" postscript printer name */ if (type == pmPostScript) { - /* Strip the leading NS_POSTSCRIPT_DRIVER_NAME from |printerName|, + /* Strip the printing method name from the printer, * e.g. turn "PostScript/foobar" to "foobar" */ - printerName.Cut(0, NS_POSTSCRIPT_DRIVER_NAME_LEN); + PRInt32 slash = printerName.FindChar('/'); + if (kNotFound != slash) + printerName.Cut(0, slash + 1); } #endif /* USE_POSTSCRIPT */ @@ -930,7 +931,6 @@ NS_IMETHODIMP nsPrinterEnumeratorXlib::InitPrintSettingsFromPrinter(const PRUnic printerFeatures.SetSupportsPaperSizeChange(PR_TRUE); printerFeatures.SetSupportsOrientationChange(PR_TRUE); printerFeatures.SetSupportsPlexChange(PR_FALSE); - printerFeatures.SetSupportsSpoolerCommandChange(PR_TRUE); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -1003,14 +1003,21 @@ NS_IMETHODIMP nsPrinterEnumeratorXlib::InitPrintSettingsFromPrinter(const PRUnic #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ } + PRBool hasSpoolerCmd = (nsPSPrinterList::kTypePS == + nsPSPrinterList::GetPrinterType(fullPrinterName)); #ifdef SET_PRINTER_FEATURES_VIA_PREFS - printerFeatures.SetCanChangeSpoolerCommand(PR_TRUE); + printerFeatures.SetSupportsSpoolerCommandChange(hasSpoolerCmd); + printerFeatures.SetCanChangeSpoolerCommand(hasSpoolerCmd); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ - nsXPIDLCString command; - if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "print_command", getter_Copies(command)))) { - DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", command.get())); - aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUCS2(command).get()); + if (hasSpoolerCmd) { + nsXPIDLCString command; + if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", + printerName, "print_command", getter_Copies(command)))) { + DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", + command.get())); + aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUCS2(command).get()); + } } #ifdef SET_PRINTER_FEATURES_VIA_PREFS @@ -1029,6 +1036,18 @@ NS_IMETHODIMP nsPrinterEnumeratorXlib::DisplayPropertiesDlg(const PRUnichar *aPr return NS_OK; } + +//---------------------------------------------------------------------- +//String array enumeration callback to append a printer to the global +//printer list. +static PRBool +GlobalPrinterEnumFunc(nsCString& aName, void *aData) +{ + nsStringArray *a = (nsStringArray *)aData; + a->AppendString(NS_ConvertUTF8toUTF16(aName)); + return PR_TRUE; +} + //---------------------------------------------------------------------- nsresult GlobalPrinters::InitializeGlobalPrinters () { @@ -1036,7 +1055,6 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () return NS_OK; } - mGlobalNumPrinters = 0; mGlobalPrinterList = new nsStringArray(); if (!mGlobalPrinterList) return NS_ERROR_OUT_OF_MEMORY; @@ -1047,12 +1065,13 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () return rv; #ifdef USE_XPRINT - XPPrinterList plist = XpuGetPrinterList(nsnull, &mGlobalNumPrinters); + int printerCount; + XPPrinterList plist = XpuGetPrinterList(nsnull, &printerCount); - if (plist && (mGlobalNumPrinters > 0)) + if (plist) { int i; - for( i = 0 ; i < mGlobalNumPrinters ; i++ ) + for( i = 0 ; i < printerCount ; i++ ) { /* Add name to our list of printers... */ mGlobalPrinterList->AppendString(nsString(NS_ConvertUTF8toUCS2(plist[i].name))); @@ -1066,71 +1085,17 @@ nsresult GlobalPrinters::InitializeGlobalPrinters () #endif /* USE_XPRINT */ #ifdef USE_POSTSCRIPT - PRBool psPrintModuleEnabled = PR_TRUE; - - const char *val = PR_GetEnv("MOZILLA_POSTSCRIPT_ENABLED"); - if (val) { - if (val[0] == '0' || !strcasecmp(val, "false")) - psPrintModuleEnabled = PR_FALSE; - } - else - { - if (NS_FAILED(pPrefs->GetBoolPref("print.postscript.enabled", &psPrintModuleEnabled))) { - psPrintModuleEnabled = PR_TRUE; - } - } - - if (psPrintModuleEnabled) { + nsPSPrinterList psMgr; + if (NS_SUCCEEDED(psMgr.Init()) && psMgr.Enabled()) { /* Get the list of PostScript-module printers */ - char *printerList = nsnull; - PRBool added_default_printer = PR_FALSE; /* Did we already add the default printer ? */ - - /* The env var MOZILLA_POSTSCRIPT_PRINTER_LIST can "override" the prefs */ - printerList = PR_GetEnv("MOZILLA_POSTSCRIPT_PRINTER_LIST"); - - if (!printerList) { - (void) pPrefs->CopyCharPref("print.printer_list", &printerList); - } - - if (printerList) { - char *tok_lasts; - const char *name; - - /* PL_strtok_r() will modify the string - copy it! */ - printerList = strdup(printerList); - if (!printerList) - return NS_ERROR_OUT_OF_MEMORY; - - for( name = PL_strtok_r(printerList, " ", &tok_lasts) ; - name != nsnull ; - name = PL_strtok_r(nsnull, " ", &tok_lasts) ) - { - /* Is this the "default" printer ? */ - if (!strcmp(name, "default")) - added_default_printer = PR_TRUE; - - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME)) + - nsString(NS_ConvertASCIItoUCS2(name))); - mGlobalNumPrinters++; - } - - free(printerList); - } - - /* Add an entry for the default printer (see nsPostScriptObj.cpp) if we - * did not add it already... */ - if (!added_default_printer) - { - mGlobalPrinterList->AppendString( - nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME "default"))); - mGlobalNumPrinters++; - } + nsCStringArray printerList; + psMgr.GetPrinterList(printerList); + printerList.EnumerateForwards(GlobalPrinterEnumFunc, mGlobalPrinterList); } #endif /* USE_POSTSCRIPT */ /* If there are no printers available after all checks, return an error */ - if (mGlobalNumPrinters == 0) + if (!mGlobalPrinterList->Count()) { /* Make sure we do not cache an empty printer list */ FreeGlobalPrinters(); @@ -1154,7 +1119,6 @@ void GlobalPrinters::FreeGlobalPrinters() if (mGlobalPrinterList) { delete mGlobalPrinterList; mGlobalPrinterList = nsnull; - mGlobalNumPrinters = 0; } }