1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
23
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
26
* Alternatively, the contents of this file may be used under the terms of
27
* either the GNU General Public License Version 2 or later (the "GPL"), or
28
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
* in which case the provisions of the GPL or the LGPL are applicable instead
30
* of those above. If you wish to allow use of your version of this file only
31
* under the terms of either the GPL or the LGPL, and not to allow others to
32
* use your version of this file under the terms of the NPL, indicate your
33
* decision by deleting the provisions above and replace them with the notice
34
* and other provisions required by the GPL or the LGPL. If you do not delete
35
* the provisions above, a recipient may use your version of this file under
36
* the terms of any one of the NPL, the GPL or the LGPL.
38
* ***** END LICENSE BLOCK ***** */
40
/* Store per-printer features in temp. prefs vars that the
41
* print dialog can pick them up... */
42
#define SET_PRINTER_FEATURES_VIA_PREFS 1
43
#define PRINTERFEATURES_PREF "print.tmp.printerfeatures"
46
#define FORCE_PR_LOG 1 /* Allow logging in the release build */
47
#endif /* MOZ_LOGGING */
52
#include "nsDeviceContextSpecXlib.h"
55
#include "prenv.h" /* for PR_GetEnv */
57
#include "nsPrintfCString.h"
58
#include "nsReadableUtils.h"
59
#include "nsIServiceManager.h"
62
#include "xprintutil.h"
63
#endif /* USE_XPRINT */
66
#include "nsPaperPS.h" /* Paper size list */
67
#endif /* USE_POSTSCRIPT */
69
/* Ensure that the result is always equal to either PR_TRUE or PR_FALSE */
70
#define MAKE_PR_BOOL(val) ((val)?(PR_TRUE):(PR_FALSE))
73
static PRLogModuleInfo *DeviceContextSpecXlibLM = PR_NewLogModule("DeviceContextSpecXlib");
74
#endif /* PR_LOGGING */
75
/* Macro to make lines shorter */
76
#define DO_PR_DEBUG_LOG(x) PR_LOG(DeviceContextSpecXlibLM, PR_LOG_DEBUG, x)
78
//----------------------------------------------------------------------------------
79
// The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecXlib
80
// The PrinterEnumerator creates the printer info
81
// but the nsDeviceContextSpecXlib cleans it up
82
// If it gets created (via the Page Setup Dialog) but the user never prints anything
83
// then it will never be delete, so this class takes care of that.
84
class GlobalPrinters {
86
static GlobalPrinters* GetInstance() { return &mGlobalPrinters; }
87
~GlobalPrinters() { FreeGlobalPrinters(); }
89
void FreeGlobalPrinters();
90
nsresult InitializeGlobalPrinters();
92
PRBool PrintersAreAllocated() { return mGlobalPrinterList != nsnull; }
93
PRInt32 GetNumPrinters() { return mGlobalNumPrinters; }
94
nsString* GetStringAt(PRInt32 aInx) { return mGlobalPrinterList->StringAt(aInx); }
95
void GetDefaultPrinterName(PRUnichar **aDefaultPrinterName);
100
static GlobalPrinters mGlobalPrinters;
101
static nsStringArray* mGlobalPrinterList;
102
static int mGlobalNumPrinters;
105
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
106
/* "Prototype" for the new nsPrinterFeatures service */
107
class nsPrinterFeatures {
109
nsPrinterFeatures( const char *printername );
110
~nsPrinterFeatures() {};
112
/* Does this printer allow to set/change the paper size ? */
113
void SetCanChangePaperSize( PRBool aCanSetPaperSize );
114
/* Does this Mozilla print module allow set/change the paper size ? */
115
void SetSupportsPaperSizeChange( PRBool aSupportsPaperSizeChange );
116
/* Set number of paper size records and the records itself */
117
void SetNumPaperSizeRecords( PRInt32 aCount );
118
void SetPaperRecord( PRInt32 aIndex, const char *aName, PRInt32 aWidthMM, PRInt32 aHeightMM, PRBool aIsInch );
120
/* Does this printer allow to set/change the content orientation ? */
121
void SetCanChangeOrientation( PRBool aCanSetOrientation );
122
/* Does this Mozilla print module allow set/change the content orientation ? */
123
void SetSupportsOrientationChange( PRBool aSupportsOrientationChange );
124
/* Set number of orientation records and the records itself */
125
void SetNumOrientationRecords( PRInt32 aCount );
126
void SetOrientationRecord( PRInt32 aIndex, const char *aName );
128
/* Does this printer allow to set/change the plex mode ? */
129
void SetCanChangePlex( PRBool aCanSetPlex );
130
/* Does this Mozilla print module allow set/change the plex mode ? */
131
void SetSupportsPlexChange( PRBool aSupportsPlexChange );
132
/* Set number of plex records and the records itself */
133
void SetNumPlexRecords( PRInt32 aCount );
134
void SetPlexRecord( PRInt32 aIndex, const char *aName );
136
/* Does this device allow to set/change the spooler command ? */
137
void SetCanChangeSpoolerCommand( PRBool aCanSetSpoolerCommand );
138
/* Does this printer allow to set/change the spooler command ? */
139
void SetSupportsSpoolerCommandChange( PRBool aSupportSpoolerCommandChange );
141
/* Does this device allow to set/change number of copies for an document ? */
142
void SetCanChangeNumCopies( PRBool aCanSetNumCopies );
144
/* Does this device allow multiple devicecontext instances to be used in
145
* parallel (e.g. print while the device is already in use by print-preview
146
* or printing while another print job is in progress) ? */
147
void SetMultipleConcurrentDeviceContextsSupported( PRBool aCanUseMultipleInstances );
150
/* private helper methods */
151
void SetBoolValue( const char *tagname, PRBool value );
152
void SetIntValue( const char *tagname, PRInt32 value );
153
void SetCharValue( const char *tagname, const char *value );
155
nsXPIDLCString mPrinterName;
156
nsCOMPtr<nsIPref> mPrefs;
159
void nsPrinterFeatures::SetBoolValue( const char *tagname, PRBool value )
161
mPrefs->SetBoolPref(nsPrintfCString(256, PRINTERFEATURES_PREF ".%s.%s", mPrinterName.get(), tagname).get(), value);
164
void nsPrinterFeatures::SetIntValue( const char *tagname, PRInt32 value )
166
mPrefs->SetIntPref(nsPrintfCString(256, PRINTERFEATURES_PREF ".%s.%s", mPrinterName.get(), tagname).get(), value);
169
void nsPrinterFeatures::SetCharValue( const char *tagname, const char *value )
171
mPrefs->SetCharPref(nsPrintfCString(256, PRINTERFEATURES_PREF ".%s.%s", mPrinterName.get(), tagname).get(), value);
174
nsPrinterFeatures::nsPrinterFeatures( const char *printername )
176
DO_PR_DEBUG_LOG(("nsPrinterFeatures::nsPrinterFeatures('%s')\n", printername));
177
mPrinterName.Assign(printername);
178
mPrefs = do_GetService(NS_PREF_CONTRACTID);
180
SetBoolValue("has_special_printerfeatures", PR_TRUE);
183
void nsPrinterFeatures::SetCanChangePaperSize( PRBool aCanSetPaperSize )
185
SetBoolValue("can_change_paper_size", aCanSetPaperSize);
188
void nsPrinterFeatures::SetSupportsPaperSizeChange( PRBool aSupportsPaperSizeChange )
190
SetBoolValue("supports_paper_size_change", aSupportsPaperSizeChange);
193
/* Set number of paper size records and the records itself */
194
void nsPrinterFeatures::SetNumPaperSizeRecords( PRInt32 aCount )
196
SetIntValue("paper.count", aCount);
199
void nsPrinterFeatures::SetPaperRecord(PRInt32 aIndex, const char *aPaperName, PRInt32 aWidthMM, PRInt32 aHeightMM, PRBool aIsInch)
201
SetCharValue(nsPrintfCString(256, "paper.%d.name", aIndex).get(), aPaperName);
202
SetIntValue( nsPrintfCString(256, "paper.%d.width_mm", aIndex).get(), aWidthMM);
203
SetIntValue( nsPrintfCString(256, "paper.%d.height_mm", aIndex).get(), aHeightMM);
204
SetBoolValue(nsPrintfCString(256, "paper.%d.is_inch", aIndex).get(), aIsInch);
207
void nsPrinterFeatures::SetCanChangeOrientation( PRBool aCanSetOrientation )
209
SetBoolValue("can_change_orientation", aCanSetOrientation);
212
void nsPrinterFeatures::SetSupportsOrientationChange( PRBool aSupportsOrientationChange )
214
SetBoolValue("supports_orientation_change", aSupportsOrientationChange);
217
void nsPrinterFeatures::SetNumOrientationRecords( PRInt32 aCount )
219
SetIntValue("orientation.count", aCount);
222
void nsPrinterFeatures::SetOrientationRecord( PRInt32 aIndex, const char *aOrientationName )
224
SetCharValue(nsPrintfCString(256, "orientation.%d.name", aIndex).get(), aOrientationName);
227
void nsPrinterFeatures::SetCanChangePlex( PRBool aCanSetPlex )
229
SetBoolValue("can_change_plex", aCanSetPlex);
232
void nsPrinterFeatures::SetSupportsPlexChange( PRBool aSupportsPlexChange )
234
SetBoolValue("supports_plex_change", aSupportsPlexChange);
237
void nsPrinterFeatures::SetNumPlexRecords( PRInt32 aCount )
239
SetIntValue("plex.count", aCount);
242
void nsPrinterFeatures::SetPlexRecord( PRInt32 aIndex, const char *aPlexName )
244
SetCharValue(nsPrintfCString(256, "plex.%d.name", aIndex).get(), aPlexName);
247
void nsPrinterFeatures::SetCanChangeSpoolerCommand( PRBool aCanSetSpoolerCommand )
249
SetBoolValue("can_change_spoolercommand", aCanSetSpoolerCommand);
252
void nsPrinterFeatures::SetSupportsSpoolerCommandChange( PRBool aSupportSpoolerCommandChange )
254
SetBoolValue("supports_spoolercommand_change", aSupportSpoolerCommandChange);
257
void nsPrinterFeatures::SetCanChangeNumCopies( PRBool aCanSetNumCopies )
259
SetBoolValue("can_change_num_copies", aCanSetNumCopies);
262
void nsPrinterFeatures::SetMultipleConcurrentDeviceContextsSupported( PRBool aCanUseMultipleInstances )
264
SetBoolValue("can_use_multiple_devicecontexts_concurrently", aCanUseMultipleInstances);
267
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
271
GlobalPrinters GlobalPrinters::mGlobalPrinters;
272
nsStringArray* GlobalPrinters::mGlobalPrinterList = nsnull;
273
int GlobalPrinters::mGlobalNumPrinters = 0;
276
nsDeviceContextSpecXlib::nsDeviceContextSpecXlib()
278
DO_PR_DEBUG_LOG(("nsDeviceContextSpecXlib::nsDeviceContextSpecXlib()\n"));
281
nsDeviceContextSpecXlib::~nsDeviceContextSpecXlib()
283
DO_PR_DEBUG_LOG(("nsDeviceContextSpecXlib::~nsDeviceContextSpecXlib()\n"));
286
/* Use both PostScript and Xprint module */
287
#if defined(USE_XPRINT) && defined(USE_POSTSCRIPT)
288
NS_IMPL_ISUPPORTS3(nsDeviceContextSpecXlib,
289
nsIDeviceContextSpec,
290
nsIDeviceContextSpecPS,
291
nsIDeviceContextSpecXp)
292
/* Use only PostScript module */
293
#elif !defined(USE_XPRINT) && defined(USE_POSTSCRIPT)
294
NS_IMPL_ISUPPORTS2(nsDeviceContextSpecXlib,
295
nsIDeviceContextSpec,
296
nsIDeviceContextSpecPS)
297
/* Use only Xprint module module */
298
#elif defined(USE_XPRINT) && !defined(USE_POSTSCRIPT)
299
NS_IMPL_ISUPPORTS2(nsDeviceContextSpecXlib,
300
nsIDeviceContextSpec,
301
nsIDeviceContextSpecXp)
302
/* Both Xprint and PostScript module are missing */
303
#elif !defined(USE_XPRINT) && !defined(USE_POSTSCRIPT)
304
NS_IMPL_ISUPPORTS1(nsDeviceContextSpecXlib,
305
nsIDeviceContextSpec)
307
#error "This should not happen"
310
/** -------------------------------------------------------
311
* Initialize the nsDeviceContextSpecXlib
315
* gisburn: Please note that this function exists as 1:1 copy in other
316
* toolkits including:
318
* file: mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp
319
* function: NS_IMETHODIMP nsDeviceContextSpecXlib::Init()
321
* file: mozilla/gfx/src/xlib/nsDeviceContextSpecXlib.cpp
322
* function: NS_IMETHODIMP nsDeviceContextSpecXlib::Init()
324
* file: mozilla/gfx/src/qt/nsDeviceContextSpecQT.cpp
325
* function: NS_IMETHODIMP nsDeviceContextSpecQT::Init()
327
* ** Please update the other toolkits when changing this function.
329
NS_IMETHODIMP nsDeviceContextSpecXlib::Init(nsIPrintSettings *aPS)
331
DO_PR_DEBUG_LOG(("nsDeviceContextSpecXlib::Init(aPS=%p)\n", aPS));
332
nsresult rv = NS_ERROR_FAILURE;
334
mPrintSettings = aPS;
336
// if there is a current selection then enable the "Selection" radio button
337
rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
342
GlobalPrinters::GetInstance()->FreeGlobalPrinters();
345
PRBool reversed = PR_FALSE;
346
PRBool color = PR_FALSE;
347
PRBool tofile = PR_FALSE;
348
PRInt16 printRange = nsIPrintSettings::kRangeAllPages;
349
PRInt32 orientation = NS_PORTRAIT;
350
PRInt32 fromPage = 1;
352
PRUnichar *command = nsnull;
354
PRUnichar *printer = nsnull;
355
PRUnichar *papername = nsnull;
356
PRUnichar *plexname = nsnull;
357
PRUnichar *printfile = nsnull;
361
double dbottom = 0.5;
363
aPS->GetPrinterName(&printer);
364
aPS->GetPrintReversed(&reversed);
365
aPS->GetPrintInColor(&color);
366
aPS->GetPaperName(&papername);
367
aPS->GetPlexName(&plexname);
368
aPS->GetOrientation(&orientation);
369
aPS->GetPrintCommand(&command);
370
aPS->GetPrintRange(&printRange);
371
aPS->GetToFileName(&printfile);
372
aPS->GetPrintToFile(&tofile);
373
aPS->GetStartPageRange(&fromPage);
374
aPS->GetEndPageRange(&toPage);
375
aPS->GetNumCopies(&copies);
376
aPS->GetMarginTop(&dtop);
377
aPS->GetMarginLeft(&dleft);
378
aPS->GetMarginBottom(&dbottom);
379
aPS->GetMarginRight(&dright);
382
PL_strncpyz(mPath, NS_ConvertUCS2toUTF8(printfile).get(), sizeof(mPath));
384
PL_strncpyz(mCommand, NS_ConvertUCS2toUTF8(command).get(), sizeof(mCommand));
386
PL_strncpyz(mPrinter, NS_ConvertUCS2toUTF8(printer).get(), sizeof(mPrinter));
388
PL_strncpyz(mPaperName, NS_ConvertUCS2toUTF8(papername).get(), sizeof(mPaperName));
390
PL_strncpyz(mPlexName, NS_ConvertUCS2toUTF8(plexname).get(), sizeof(mPlexName));
392
DO_PR_DEBUG_LOG(("margins: %5.2f,%5.2f,%5.2f,%5.2f\n", dtop, dleft, dbottom, dright));
393
DO_PR_DEBUG_LOG(("printRange %d\n", printRange));
394
DO_PR_DEBUG_LOG(("fromPage %d\n", fromPage));
395
DO_PR_DEBUG_LOG(("toPage %d\n", toPage));
396
DO_PR_DEBUG_LOG(("tofile %d\n", tofile));
397
DO_PR_DEBUG_LOG(("printfile '%s'\n", printfile? NS_ConvertUCS2toUTF8(printfile).get():"<NULL>"));
398
DO_PR_DEBUG_LOG(("command '%s'\n", command? NS_ConvertUCS2toUTF8(command).get():"<NULL>"));
399
DO_PR_DEBUG_LOG(("printer '%s'\n", printer? NS_ConvertUCS2toUTF8(printer).get():"<NULL>"));
400
DO_PR_DEBUG_LOG(("papername '%s'\n", papername? NS_ConvertUCS2toUTF8(papername).get():"<NULL>"));
401
DO_PR_DEBUG_LOG(("plexname '%s'\n", plexname? NS_ConvertUCS2toUTF8(plexname).get():"<NULL>"));
409
mOrientation = orientation;
410
mToPrinter = !tofile;
417
NS_IMETHODIMP nsDeviceContextSpecXlib::GetToPrinter(PRBool &aToPrinter)
419
aToPrinter = mToPrinter;
423
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPrinterName ( const char **aPrinter )
425
*aPrinter = mPrinter;
429
NS_IMETHODIMP nsDeviceContextSpecXlib::GetCopies ( int &aCopies )
435
NS_IMETHODIMP nsDeviceContextSpecXlib::GetFirstPageFirst(PRBool &aFpf)
441
NS_IMETHODIMP nsDeviceContextSpecXlib::GetGrayscale(PRBool &aGrayscale)
443
aGrayscale = mGrayscale;
447
NS_IMETHODIMP nsDeviceContextSpecXlib::GetLandscape(PRBool &aLandscape)
449
aLandscape = (mOrientation == NS_LANDSCAPE);
453
NS_IMETHODIMP nsDeviceContextSpecXlib::GetTopMargin(float &aValue)
459
NS_IMETHODIMP nsDeviceContextSpecXlib::GetBottomMargin(float &aValue)
465
NS_IMETHODIMP nsDeviceContextSpecXlib::GetRightMargin(float &aValue)
471
NS_IMETHODIMP nsDeviceContextSpecXlib::GetLeftMargin(float &aValue)
477
NS_IMETHODIMP nsDeviceContextSpecXlib::GetCommand(const char **aCommand)
479
*aCommand = mCommand;
483
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPath(const char **aPath)
489
NS_IMETHODIMP nsDeviceContextSpecXlib::GetUserCancelled(PRBool &aCancel)
495
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPaperName( const char **aPaperName )
497
*aPaperName = mPaperName;
501
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPlexName( const char **aPlexName )
503
*aPlexName = mPlexName;
507
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPageSizeInTwips(PRInt32 *aWidth, PRInt32 *aHeight)
509
return mPrintSettings->GetPageSizeInTwips(aWidth, aHeight);
512
NS_IMETHODIMP nsDeviceContextSpecXlib::GetPrintMethod(PrintMethod &aMethod)
514
return GetPrintMethod(mPrinter, aMethod);
518
nsresult nsDeviceContextSpecXlib::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod)
520
#if defined(USE_POSTSCRIPT) && defined(USE_XPRINT)
521
/* printer names for the PostScript module alwas start with
522
* the NS_POSTSCRIPT_DRIVER_NAME string */
523
if (strncmp(aPrinter, NS_POSTSCRIPT_DRIVER_NAME,
524
NS_POSTSCRIPT_DRIVER_NAME_LEN) != 0)
527
aMethod = pmPostScript;
529
#elif defined(USE_XPRINT)
532
#elif defined(USE_POSTSCRIPT)
533
aMethod = pmPostScript;
536
return NS_ERROR_UNEXPECTED;
540
NS_IMETHODIMP nsDeviceContextSpecXlib::ClosePrintManager()
545
/* Get prefs for printer
547
* - Get prefs per printer name and module name
548
* - Get prefs per printer name
549
* - Get prefs per module name
553
nsresult CopyPrinterCharPref(nsIPref *pref, const char *modulename, const char *printername, const char *prefname, char **return_buf)
555
DO_PR_DEBUG_LOG(("CopyPrinterCharPref('%s', '%s', '%s')\n", modulename, printername, prefname));
557
NS_ENSURE_ARG_POINTER(return_buf);
560
nsresult rv = NS_ERROR_FAILURE;
562
if (printername && modulename) {
563
/* Get prefs per printer name and module name */
564
name = nsPrintfCString(512, "print.%s.printer_%s.%s", modulename, printername, prefname);
565
DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
566
rv = pref->CopyCharPref(name, return_buf);
571
/* Get prefs per printer name */
572
name = nsPrintfCString(512, "print.printer_%s.%s", printername, prefname);
573
DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
574
rv = pref->CopyCharPref(name, return_buf);
579
/* Get prefs per module name */
580
name = nsPrintfCString(512, "print.%s.%s", modulename, prefname);
581
DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
582
rv = pref->CopyCharPref(name, return_buf);
587
name = nsPrintfCString(512, "print.%s", prefname);
588
DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
589
rv = pref->CopyCharPref(name, return_buf);
595
if (NS_SUCCEEDED(rv)) {
596
DO_PR_DEBUG_LOG(("CopyPrinterCharPref returning '%s'.\n", *return_buf));
600
DO_PR_DEBUG_LOG(("CopyPrinterCharPref failure.\n"));
607
// Printer Enumerator
608
nsPrinterEnumeratorXlib::nsPrinterEnumeratorXlib()
612
NS_IMPL_ISUPPORTS1(nsPrinterEnumeratorXlib, nsIPrinterEnumerator)
614
NS_IMETHODIMP nsPrinterEnumeratorXlib::EnumeratePrinters(PRUint32* aCount, PRUnichar*** aResult)
616
NS_ENSURE_ARG(aCount);
617
NS_ENSURE_ARG_POINTER(aResult);
622
return NS_ERROR_NULL_POINTER;
627
return NS_ERROR_NULL_POINTER;
629
nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
634
PRInt32 numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
636
PRUnichar** array = (PRUnichar**) nsMemory::Alloc(numPrinters * sizeof(PRUnichar*));
637
if (!array && numPrinters > 0) {
638
GlobalPrinters::GetInstance()->FreeGlobalPrinters();
639
return NS_ERROR_OUT_OF_MEMORY;
643
while( count < numPrinters )
645
PRUnichar *str = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(count));
648
for (int i = count - 1; i >= 0; i--)
649
nsMemory::Free(array[i]);
651
nsMemory::Free(array);
653
GlobalPrinters::GetInstance()->FreeGlobalPrinters();
654
return NS_ERROR_OUT_OF_MEMORY;
656
array[count++] = str;
661
GlobalPrinters::GetInstance()->FreeGlobalPrinters();
666
/* readonly attribute wstring defaultPrinterName; */
667
NS_IMETHODIMP nsPrinterEnumeratorXlib::GetDefaultPrinterName(PRUnichar **aDefaultPrinterName)
669
DO_PR_DEBUG_LOG(("nsPrinterEnumeratorXlib::GetDefaultPrinterName()\n"));
670
NS_ENSURE_ARG_POINTER(aDefaultPrinterName);
672
GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName);
674
DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUCS2toUTF8(*aDefaultPrinterName).get()));
678
/* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */
679
NS_IMETHODIMP nsPrinterEnumeratorXlib::InitPrintSettingsFromPrinter(const PRUnichar *aPrinterName, nsIPrintSettings *aPrintSettings)
681
DO_PR_DEBUG_LOG(("nsPrinterEnumeratorXlib::InitPrintSettingsFromPrinter()"));
684
NS_ENSURE_ARG_POINTER(aPrinterName);
685
NS_ENSURE_ARG_POINTER(aPrintSettings);
687
NS_ENSURE_TRUE(*aPrinterName, NS_ERROR_FAILURE);
688
NS_ENSURE_TRUE(aPrintSettings, NS_ERROR_FAILURE);
690
nsCOMPtr<nsIPref> pPrefs = do_GetService(NS_PREF_CONTRACTID, &rv);
694
nsXPIDLCString fullPrinterName, /* Full name of printer incl. driver-specific prefix */
695
printerName; /* "Stripped" name of printer */
696
fullPrinterName.Assign(NS_ConvertUCS2toUTF8(aPrinterName));
697
printerName.Assign(NS_ConvertUCS2toUTF8(aPrinterName));
698
DO_PR_DEBUG_LOG(("printerName='%s'\n", printerName.get()));
700
PrintMethod type = pmInvalid;
701
rv = nsDeviceContextSpecXlib::GetPrintMethod(printerName, type);
705
#ifdef USE_POSTSCRIPT
706
/* "Demangle" postscript printer name */
707
if (type == pmPostScript) {
708
/* Strip the leading NS_POSTSCRIPT_DRIVER_NAME from |printerName|,
709
* e.g. turn "PostScript/foobar" to "foobar" */
710
printerName.Cut(0, NS_POSTSCRIPT_DRIVER_NAME_LEN);
712
#endif /* USE_POSTSCRIPT */
714
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
715
/* Defaults to FALSE */
716
pPrefs->SetBoolPref(nsPrintfCString(256, PRINTERFEATURES_PREF ".%s.has_special_printerfeatures", fullPrinterName.get()).get(), PR_FALSE);
717
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
721
nsXPIDLCString filename;
722
if (NS_FAILED(CopyPrinterCharPref(pPrefs, nsnull, printerName, "filename", getter_Copies(filename)))) {
725
if (!(path = PR_GetEnv("PWD")))
726
path = PR_GetEnv("HOME");
729
filename = nsPrintfCString(PATH_MAX, "%s/mozilla.ps", path);
731
filename.Assign("mozilla.ps");
733
DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", filename.get()));
734
aPrintSettings->SetToFileName(NS_ConvertUTF8toUCS2(filename).get());
736
aPrintSettings->SetIsInitializedFromPrinter(PR_TRUE);
739
if (type == pmXprint) {
740
DO_PR_DEBUG_LOG(("InitPrintSettingsFromPrinter() for Xprint printer\n"));
742
/* Setup the capabilties list of Mozilla's Xprint print module */
743
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
744
nsPrinterFeatures printerFeatures(fullPrinterName);
746
printerFeatures.SetSupportsPaperSizeChange(PR_TRUE);
747
printerFeatures.SetSupportsOrientationChange(PR_TRUE);
748
printerFeatures.SetSupportsPlexChange(PR_TRUE);
749
printerFeatures.SetSupportsSpoolerCommandChange(PR_FALSE); /* won't work by design and very good reasons! */
750
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
752
/* Setup the capabilties list of this specific printer */
756
if (XpuGetPrinter(printerName, &pdpy, &pcontext) != 1)
757
return NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
759
XpuSupportedFlags supported_doc_attrs = XpuGetSupportedDocAttributes(pdpy, pcontext);
761
/* Setup orientation stuff */
762
XpuOrientationList olist;
764
XpuOrientationRec *default_orientation;
766
/* Setup plex stuff */
767
XpuPlexList plexlist;
769
XpuPlexRec *default_plex;
771
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
772
PRBool canSetOrientation = MAKE_PR_BOOL(supported_doc_attrs & XPUATTRIBUTESUPPORTED_CONTENT_ORIENTATION);
773
printerFeatures.SetCanChangeOrientation(canSetOrientation);
774
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
776
/* Get list of supported orientations */
777
olist = XpuGetOrientationList(pdpy, pcontext, &ocount);
779
default_orientation = &olist[0]; /* First entry is the default one */
781
if (!PL_strcasecmp(default_orientation->orientation, "portrait")) {
782
DO_PR_DEBUG_LOG(("setting default orientation to 'portrait'\n"));
783
aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
785
else if (!PL_strcasecmp(default_orientation->orientation, "landscape")) {
786
DO_PR_DEBUG_LOG(("setting default orientation to 'landscape'\n"));
787
aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
790
DO_PR_DEBUG_LOG(("Unknown default orientation '%s'\n", default_orientation->orientation));
793
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
795
for( i = 0 ; i < ocount ; i++ )
797
XpuOrientationRec *curr = &olist[i];
798
printerFeatures.SetOrientationRecord(i, curr->orientation);
800
printerFeatures.SetNumOrientationRecords(ocount);
801
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
803
XpuFreeOrientationList(olist);
806
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
807
PRBool canSetPlexMode = MAKE_PR_BOOL(supported_doc_attrs & XPUATTRIBUTESUPPORTED_PLEX);
808
printerFeatures.SetCanChangePlex(canSetPlexMode);
809
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
811
/* Get list of supported plex modes */
812
plexlist = XpuGetPlexList(pdpy, pcontext, &plexcount);
814
default_plex = &plexlist[0]; /* First entry is the default one */
816
DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", default_plex->plex));
817
aPrintSettings->SetPlexName(NS_ConvertUTF8toUCS2(default_plex->plex).get());
819
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
821
for( i = 0 ; i < plexcount ; i++ )
823
XpuPlexRec *curr = &plexlist[i];
824
printerFeatures.SetPlexRecord(i, curr->plex);
826
printerFeatures.SetNumPlexRecords(plexcount);
827
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
829
XpuFreePlexList(plexlist);
832
/* Setup Number of Copies */
833
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
834
PRBool canSetNumCopies = MAKE_PR_BOOL(supported_doc_attrs & XPUATTRIBUTESUPPORTED_COPY_COUNT);
835
printerFeatures.SetCanChangeNumCopies(canSetNumCopies);
836
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
838
if( XpuGetOneLongAttribute(pdpy, pcontext, XPDocAttr, "copy-count", &numCopies) != 1 )
840
/* Fallback on failure */
843
aPrintSettings->SetNumCopies(numCopies);
845
/* Setup paper size stuff */
846
XpuMediumSourceSizeList mlist;
848
XpuMediumSourceSizeRec *default_medium;
850
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
851
PRBool canSetPaperSize = MAKE_PR_BOOL(supported_doc_attrs & XPUATTRIBUTESUPPORTED_DEFAULT_MEDIUM);
852
printerFeatures.SetCanChangePaperSize(canSetPaperSize);
853
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
855
mlist = XpuGetMediumSourceSizeList(pdpy, pcontext, &mcount);
857
nsXPIDLCString papername;
859
default_medium = &mlist[0]; /* First entry is the default one */
860
double total_width = default_medium->ma1 + default_medium->ma2,
861
total_height = default_medium->ma3 + default_medium->ma4;
863
/* Either "paper" or "tray/paper" */
864
papername.Truncate();
865
if (default_medium->tray_name) {
866
papername.Append(default_medium->tray_name);
867
papername.Append("/");
869
papername.Append(default_medium->medium_name);
871
DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g/%g mm)\n", papername.get(), total_width, total_height));
872
aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined);
873
aPrintSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters);
874
aPrintSettings->SetPaperWidth(total_width);
875
aPrintSettings->SetPaperHeight(total_height);
876
aPrintSettings->SetPaperName(NS_ConvertUTF8toUCS2(papername).get());
878
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
880
for( i = 0 ; i < mcount ; i++ )
882
XpuMediumSourceSizeRec *curr = &mlist[i];
883
double total_width = curr->ma1 + curr->ma2,
884
total_height = curr->ma3 + curr->ma4;
886
papername.Truncate();
887
if (curr->tray_name) {
888
papername.Append(curr->tray_name);
889
papername.Append("/");
891
papername.Append(curr->medium_name);
893
printerFeatures.SetPaperRecord(i, papername, PRInt32(total_width), PRInt32(total_height), PR_FALSE);
895
printerFeatures.SetNumPaperSizeRecords(mcount);
896
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
898
XpuFreeMediumSourceSizeList(mlist);
901
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
902
/* Xprint does not allow the client to set a spooler command.
903
* Job spooling is the job of the server side (=Xprt) */
904
printerFeatures.SetCanChangeSpoolerCommand(PR_FALSE);
906
/* Mozilla's Xprint support allows multiple nsIDeviceContext instances
907
* be used in parallel */
908
printerFeatures.SetMultipleConcurrentDeviceContextsSupported(PR_TRUE);
909
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
911
XpuClosePrinterDisplay(pdpy, pcontext);
916
#endif /* USE_XPRINT */
918
#ifdef USE_POSTSCRIPT
919
if (type == pmPostScript) {
920
DO_PR_DEBUG_LOG(("InitPrintSettingsFromPrinter() for PostScript printer\n"));
922
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
923
nsPrinterFeatures printerFeatures(fullPrinterName);
925
printerFeatures.SetSupportsPaperSizeChange(PR_TRUE);
926
printerFeatures.SetSupportsOrientationChange(PR_TRUE);
927
printerFeatures.SetSupportsPlexChange(PR_FALSE);
928
printerFeatures.SetSupportsSpoolerCommandChange(PR_TRUE);
929
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
931
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
932
printerFeatures.SetCanChangeOrientation(PR_TRUE);
933
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
935
nsXPIDLCString orientation;
936
if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "orientation", getter_Copies(orientation)))) {
937
if (!PL_strcasecmp(orientation, "portrait")) {
938
DO_PR_DEBUG_LOG(("setting default orientation to 'portrait'\n"));
939
aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
941
else if (!PL_strcasecmp(orientation, "landscape")) {
942
DO_PR_DEBUG_LOG(("setting default orientation to 'landscape'\n"));
943
aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
946
DO_PR_DEBUG_LOG(("Unknown default orientation '%s'\n", orientation.get()));
950
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
951
printerFeatures.SetOrientationRecord(0, "portrait");
952
printerFeatures.SetOrientationRecord(1, "landscape");
953
printerFeatures.SetNumOrientationRecords(2);
954
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
956
/* PostScript module does not support changing the plex mode... */
957
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
958
printerFeatures.SetCanChangePlex(PR_FALSE);
959
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
960
DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", "default"));
961
aPrintSettings->SetPlexName(NS_LITERAL_STRING("default").get());
962
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
963
printerFeatures.SetPlexRecord(0, "default");
964
printerFeatures.SetNumPlexRecords(1);
965
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
967
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
968
printerFeatures.SetCanChangePaperSize(PR_TRUE);
969
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
970
nsXPIDLCString papername;
971
if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "paper_size", getter_Copies(papername)))) {
974
if (paper.Find(papername)) {
975
DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n",
976
paper.Name(), paper.Width_mm(), paper.Height_mm()));
977
aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined);
978
aPrintSettings->SetPaperSizeUnit(paper.IsMetric() ?
979
(int)nsIPrintSettings::kPaperSizeMillimeters :
980
(int)nsIPrintSettings::kPaperSizeInches);
981
aPrintSettings->SetPaperWidth(paper.Width_mm());
982
aPrintSettings->SetPaperHeight(paper.Height_mm());
983
aPrintSettings->SetPaperName(NS_ConvertASCIItoUCS2(paper.Name()).get());
986
DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get()));
988
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
991
while (!paper.AtEnd())
993
printerFeatures.SetPaperRecord(count++, paper.Name(),
994
(int)paper.Width_mm(), (int)paper.Height_mm(), !paper.IsMetric());
997
printerFeatures.SetNumPaperSizeRecords(count);
998
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
1001
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
1002
printerFeatures.SetCanChangeSpoolerCommand(PR_TRUE);
1003
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
1005
nsXPIDLCString command;
1006
if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "print_command", getter_Copies(command)))) {
1007
DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", command.get()));
1008
aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUCS2(command).get());
1011
#ifdef SET_PRINTER_FEATURES_VIA_PREFS
1012
printerFeatures.SetCanChangeNumCopies(PR_TRUE);
1013
#endif /* SET_PRINTER_FEATURES_VIA_PREFS */
1017
#endif /* USE_POSTSCRIPT */
1019
return NS_ERROR_UNEXPECTED;
1022
NS_IMETHODIMP nsPrinterEnumeratorXlib::DisplayPropertiesDlg(const PRUnichar *aPrinter, nsIPrintSettings *aPrintSettings)
1027
//----------------------------------------------------------------------
1028
nsresult GlobalPrinters::InitializeGlobalPrinters ()
1030
if (PrintersAreAllocated()) {
1034
mGlobalNumPrinters = 0;
1035
mGlobalPrinterList = new nsStringArray();
1036
if (!mGlobalPrinterList)
1037
return NS_ERROR_OUT_OF_MEMORY;
1040
XPPrinterList plist = XpuGetPrinterList(nsnull, &mGlobalNumPrinters);
1042
if (plist && (mGlobalNumPrinters > 0))
1045
for( i = 0 ; i < mGlobalNumPrinters ; i++ )
1047
mGlobalPrinterList->AppendString(nsString(NS_ConvertASCIItoUCS2(plist[i].name)));
1050
XpuFreePrinterList(plist);
1052
#endif /* USE_XPRINT */
1054
#ifdef USE_POSTSCRIPT
1055
nsCOMPtr<nsIPref> pPrefs = do_GetService(NS_PREF_CONTRACTID);
1056
PRBool psPrintModuleEnabled = PR_TRUE;
1058
const char *val = PR_GetEnv("MOZILLA_POSTSCRIPT_ENABLED");
1060
if (val[0] == '0' || !strcasecmp(val, "false"))
1061
psPrintModuleEnabled = PR_FALSE;
1066
if (NS_FAILED(pPrefs->GetBoolPref("print.postscript.enabled", &psPrintModuleEnabled))) {
1067
psPrintModuleEnabled = PR_TRUE;
1072
if (psPrintModuleEnabled) {
1073
/* Get the list of PostScript-module printers */
1074
char *printerList = nsnull;
1075
PRBool added_default_printer = PR_FALSE; /* Did we already add the default printer ? */
1077
/* The env var MOZILLA_POSTSCRIPT_PRINTER_LIST can "override" the prefs */
1078
printerList = PR_GetEnv("MOZILLA_POSTSCRIPT_PRINTER_LIST");
1082
(void) pPrefs->CopyCharPref("print.printer_list", &printerList);
1090
/* PL_strtok_r() will modify the string - copy it! */
1091
printerList = strdup(printerList);
1093
return NS_ERROR_OUT_OF_MEMORY;
1095
for( name = PL_strtok_r(printerList, " ", &tok_lasts) ;
1097
name = PL_strtok_r(nsnull, " ", &tok_lasts) )
1099
/* Is this the "default" printer ? */
1100
if (!strcmp(name, "default"))
1101
added_default_printer = PR_TRUE;
1103
mGlobalPrinterList->AppendString(
1104
nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME)) +
1105
nsString(NS_ConvertASCIItoUCS2(name)));
1106
mGlobalNumPrinters++;
1112
/* Add an entry for the default printer (see nsPostScriptObj.cpp) if we
1113
* did not add it already... */
1114
if (!added_default_printer)
1116
mGlobalPrinterList->AppendString(
1117
nsString(NS_ConvertASCIItoUCS2(NS_POSTSCRIPT_DRIVER_NAME "default")));
1118
mGlobalNumPrinters++;
1121
#endif /* USE_POSTSCRIPT */
1123
/* If there are no printers available after all checks, return an error */
1124
if (mGlobalNumPrinters == 0)
1126
/* Make sure we do not cache an empty printer list */
1127
FreeGlobalPrinters();
1130
/* Check if there are actually any Xprint servers available */
1131
if (!XpuXprintServersAvailable()) {
1132
return NS_ERROR_GFX_PRINTER_XPRINT_NO_XPRINT_SERVERS_FOUND;
1134
#endif /* USE_XPRINT */
1136
return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE;
1142
//----------------------------------------------------------------------
1143
void GlobalPrinters::FreeGlobalPrinters()
1145
if (mGlobalPrinterList) {
1146
delete mGlobalPrinterList;
1147
mGlobalPrinterList = nsnull;
1148
mGlobalNumPrinters = 0;
1153
GlobalPrinters::GetDefaultPrinterName(PRUnichar **aDefaultPrinterName)
1155
*aDefaultPrinterName = nsnull;
1157
PRBool allocate = (GlobalPrinters::GetInstance()->PrintersAreAllocated() == PR_FALSE);
1160
nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
1161
if (NS_FAILED(rv)) {
1165
NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters");
1167
if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0)
1170
*aDefaultPrinterName = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(0));
1173
GlobalPrinters::GetInstance()->FreeGlobalPrinters();