зеркало из https://github.com/mozilla/gecko-dev.git
Bug 257381: Refactor postscript printer list logic & support printing
through CUPS. r/sr=roc.
This commit is contained in:
Родитель
37a2d640af
Коммит
b8f65ebb36
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
|
||||
* Ken Herron <kherron+mozilla@fmailbox.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче