|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifdef MOZ_LOGGING |
|
7 #define FORCE_PR_LOG 1 /* Allow logging in the release build */ |
|
8 #endif /* MOZ_LOGGING */ |
|
9 #include "prlog.h" |
|
10 |
|
11 #include "plstr.h" |
|
12 |
|
13 #include "nsDeviceContextSpecG.h" |
|
14 |
|
15 #include "prenv.h" /* for PR_GetEnv */ |
|
16 |
|
17 #include "nsPrintfCString.h" |
|
18 #include "nsReadableUtils.h" |
|
19 #include "nsStringEnumerator.h" |
|
20 #include "nsIServiceManager.h" |
|
21 |
|
22 #include "nsPSPrinters.h" |
|
23 #include "nsPaperPS.h" /* Paper size list */ |
|
24 |
|
25 #include "nsPrintSettingsGTK.h" |
|
26 |
|
27 #include "nsIFileStreams.h" |
|
28 #include "nsIFile.h" |
|
29 #include "nsTArray.h" |
|
30 |
|
31 #include "mozilla/Preferences.h" |
|
32 |
|
33 #include <unistd.h> |
|
34 #include <sys/types.h> |
|
35 #include <sys/stat.h> |
|
36 |
|
37 using namespace mozilla; |
|
38 |
|
39 #ifdef PR_LOGGING |
|
40 static PRLogModuleInfo * |
|
41 GetDeviceContextSpecGTKLog() |
|
42 { |
|
43 static PRLogModuleInfo *sLog; |
|
44 if (!sLog) |
|
45 sLog = PR_NewLogModule("DeviceContextSpecGTK"); |
|
46 return sLog; |
|
47 } |
|
48 #endif /* PR_LOGGING */ |
|
49 /* Macro to make lines shorter */ |
|
50 #define DO_PR_DEBUG_LOG(x) PR_LOG(GetDeviceContextSpecGTKLog(), PR_LOG_DEBUG, x) |
|
51 |
|
52 //---------------------------------------------------------------------------------- |
|
53 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecGTK |
|
54 // The PrinterEnumerator creates the printer info |
|
55 // but the nsDeviceContextSpecGTK cleans it up |
|
56 // If it gets created (via the Page Setup Dialog) but the user never prints anything |
|
57 // then it will never be delete, so this class takes care of that. |
|
58 class GlobalPrinters { |
|
59 public: |
|
60 static GlobalPrinters* GetInstance() { return &mGlobalPrinters; } |
|
61 ~GlobalPrinters() { FreeGlobalPrinters(); } |
|
62 |
|
63 void FreeGlobalPrinters(); |
|
64 nsresult InitializeGlobalPrinters(); |
|
65 |
|
66 bool PrintersAreAllocated() { return mGlobalPrinterList != nullptr; } |
|
67 uint32_t GetNumPrinters() |
|
68 { return mGlobalPrinterList ? mGlobalPrinterList->Length() : 0; } |
|
69 nsString* GetStringAt(int32_t aInx) { return &mGlobalPrinterList->ElementAt(aInx); } |
|
70 void GetDefaultPrinterName(char16_t **aDefaultPrinterName); |
|
71 |
|
72 protected: |
|
73 GlobalPrinters() {} |
|
74 |
|
75 static GlobalPrinters mGlobalPrinters; |
|
76 static nsTArray<nsString>* mGlobalPrinterList; |
|
77 }; |
|
78 |
|
79 //--------------- |
|
80 // static members |
|
81 GlobalPrinters GlobalPrinters::mGlobalPrinters; |
|
82 nsTArray<nsString>* GlobalPrinters::mGlobalPrinterList = nullptr; |
|
83 //--------------- |
|
84 |
|
85 nsDeviceContextSpecGTK::nsDeviceContextSpecGTK() |
|
86 : mPrintJob(nullptr) |
|
87 , mGtkPrinter(nullptr) |
|
88 , mGtkPrintSettings(nullptr) |
|
89 , mGtkPageSetup(nullptr) |
|
90 { |
|
91 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()\n")); |
|
92 } |
|
93 |
|
94 nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK() |
|
95 { |
|
96 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()\n")); |
|
97 |
|
98 if (mGtkPageSetup) { |
|
99 g_object_unref(mGtkPageSetup); |
|
100 } |
|
101 |
|
102 if (mGtkPrintSettings) { |
|
103 g_object_unref(mGtkPrintSettings); |
|
104 } |
|
105 } |
|
106 |
|
107 NS_IMPL_ISUPPORTS(nsDeviceContextSpecGTK, |
|
108 nsIDeviceContextSpec) |
|
109 |
|
110 #include "gfxPDFSurface.h" |
|
111 #include "gfxPSSurface.h" |
|
112 NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurface) |
|
113 { |
|
114 *aSurface = nullptr; |
|
115 |
|
116 const char *path; |
|
117 GetPath(&path); |
|
118 |
|
119 double width, height; |
|
120 mPrintSettings->GetEffectivePageSize(&width, &height); |
|
121 |
|
122 // convert twips to points |
|
123 width /= TWIPS_PER_POINT_FLOAT; |
|
124 height /= TWIPS_PER_POINT_FLOAT; |
|
125 |
|
126 DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", path, width, height)); |
|
127 nsresult rv; |
|
128 |
|
129 // Spool file. Use Glib's temporary file function since we're |
|
130 // already dependent on the gtk software stack. |
|
131 gchar *buf; |
|
132 gint fd = g_file_open_tmp("XXXXXX.tmp", &buf, nullptr); |
|
133 if (-1 == fd) |
|
134 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; |
|
135 close(fd); |
|
136 |
|
137 rv = NS_NewNativeLocalFile(nsDependentCString(buf), false, |
|
138 getter_AddRefs(mSpoolFile)); |
|
139 if (NS_FAILED(rv)) { |
|
140 unlink(buf); |
|
141 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; |
|
142 } |
|
143 |
|
144 mSpoolName = buf; |
|
145 g_free(buf); |
|
146 |
|
147 mSpoolFile->SetPermissions(0600); |
|
148 |
|
149 nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); |
|
150 rv = stream->Init(mSpoolFile, -1, -1, 0); |
|
151 if (NS_FAILED(rv)) |
|
152 return rv; |
|
153 |
|
154 int16_t format; |
|
155 mPrintSettings->GetOutputFormat(&format); |
|
156 |
|
157 nsRefPtr<gfxASurface> surface; |
|
158 gfxSize surfaceSize(width, height); |
|
159 |
|
160 // Determine the real format with some GTK magic |
|
161 if (format == nsIPrintSettings::kOutputFormatNative) { |
|
162 if (mIsPPreview) { |
|
163 // There is nothing to detect on Print Preview, use PS. |
|
164 format = nsIPrintSettings::kOutputFormatPS; |
|
165 } else { |
|
166 const gchar* fmtGTK = gtk_print_settings_get(mGtkPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT); |
|
167 if (!fmtGTK && GTK_IS_PRINTER(mGtkPrinter)) { |
|
168 // Likely not print-to-file, check printer's capabilities |
|
169 |
|
170 // Prior to gtk 2.24, gtk_printer_accepts_pdf() and |
|
171 // gtk_printer_accepts_ps() always returned true regardless of the |
|
172 // printer's capability. |
|
173 if (gtk_major_version > 2 || |
|
174 (gtk_major_version == 2 && gtk_minor_version >= 24)) { |
|
175 format = |
|
176 gtk_printer_accepts_pdf(mGtkPrinter) ? |
|
177 static_cast<int16_t>(nsIPrintSettings::kOutputFormatPDF) : |
|
178 static_cast<int16_t>(nsIPrintSettings::kOutputFormatPS); |
|
179 } else { |
|
180 format = nsIPrintSettings::kOutputFormatPS; |
|
181 } |
|
182 |
|
183 } else if (nsDependentCString(fmtGTK).EqualsIgnoreCase("pdf")) { |
|
184 format = nsIPrintSettings::kOutputFormatPDF; |
|
185 } else { |
|
186 format = nsIPrintSettings::kOutputFormatPS; |
|
187 } |
|
188 } |
|
189 } |
|
190 |
|
191 if (format == nsIPrintSettings::kOutputFormatPDF) { |
|
192 surface = new gfxPDFSurface(stream, surfaceSize); |
|
193 } else { |
|
194 int32_t orientation; |
|
195 mPrintSettings->GetOrientation(&orientation); |
|
196 if (nsIPrintSettings::kPortraitOrientation == orientation) { |
|
197 surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::PORTRAIT); |
|
198 } else { |
|
199 surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::LANDSCAPE); |
|
200 } |
|
201 } |
|
202 |
|
203 if (!surface) |
|
204 return NS_ERROR_OUT_OF_MEMORY; |
|
205 |
|
206 surface.swap(*aSurface); |
|
207 |
|
208 return NS_OK; |
|
209 } |
|
210 |
|
211 /** ------------------------------------------------------- |
|
212 * Initialize the nsDeviceContextSpecGTK |
|
213 * @update dc 2/15/98 |
|
214 * @update syd 3/2/99 |
|
215 */ |
|
216 NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget, |
|
217 nsIPrintSettings* aPS, |
|
218 bool aIsPrintPreview) |
|
219 { |
|
220 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::Init(aPS=%p)\n", aPS)); |
|
221 |
|
222 if (gtk_major_version < 2 || |
|
223 (gtk_major_version == 2 && gtk_minor_version < 10)) |
|
224 return NS_ERROR_NOT_AVAILABLE; // I'm so sorry bz |
|
225 |
|
226 mPrintSettings = aPS; |
|
227 mIsPPreview = aIsPrintPreview; |
|
228 |
|
229 // This is only set by embedders |
|
230 bool toFile; |
|
231 aPS->GetPrintToFile(&toFile); |
|
232 |
|
233 mToPrinter = !toFile && !aIsPrintPreview; |
|
234 |
|
235 nsCOMPtr<nsPrintSettingsGTK> printSettingsGTK(do_QueryInterface(aPS)); |
|
236 if (!printSettingsGTK) |
|
237 return NS_ERROR_NO_INTERFACE; |
|
238 |
|
239 mGtkPrinter = printSettingsGTK->GetGtkPrinter(); |
|
240 mGtkPrintSettings = printSettingsGTK->GetGtkPrintSettings(); |
|
241 mGtkPageSetup = printSettingsGTK->GetGtkPageSetup(); |
|
242 |
|
243 // This is a horrible workaround for some printer driver bugs that treat custom page sizes different |
|
244 // to standard ones. If our paper object matches one of a standard one, use a standard paper size |
|
245 // object instead. See bug 414314 for more info. |
|
246 GtkPaperSize* geckosHackishPaperSize = gtk_page_setup_get_paper_size(mGtkPageSetup); |
|
247 GtkPaperSize* standardGtkPaperSize = gtk_paper_size_new(gtk_paper_size_get_name(geckosHackishPaperSize)); |
|
248 |
|
249 mGtkPageSetup = gtk_page_setup_copy(mGtkPageSetup); |
|
250 mGtkPrintSettings = gtk_print_settings_copy(mGtkPrintSettings); |
|
251 |
|
252 GtkPaperSize* properPaperSize; |
|
253 if (gtk_paper_size_is_equal(geckosHackishPaperSize, standardGtkPaperSize)) { |
|
254 properPaperSize = standardGtkPaperSize; |
|
255 } else { |
|
256 properPaperSize = geckosHackishPaperSize; |
|
257 } |
|
258 gtk_print_settings_set_paper_size(mGtkPrintSettings, properPaperSize); |
|
259 gtk_page_setup_set_paper_size_and_default_margins(mGtkPageSetup, properPaperSize); |
|
260 gtk_paper_size_free(standardGtkPaperSize); |
|
261 |
|
262 return NS_OK; |
|
263 } |
|
264 |
|
265 NS_IMETHODIMP nsDeviceContextSpecGTK::GetPath(const char **aPath) |
|
266 { |
|
267 *aPath = mPath; |
|
268 return NS_OK; |
|
269 } |
|
270 |
|
271 /* static !! */ |
|
272 nsresult nsDeviceContextSpecGTK::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod) |
|
273 { |
|
274 aMethod = pmPostScript; |
|
275 return NS_OK; |
|
276 } |
|
277 |
|
278 static void |
|
279 #if (MOZ_WIDGET_GTK == 3) |
|
280 print_callback(GtkPrintJob *aJob, gpointer aData, const GError *aError) { |
|
281 #else |
|
282 print_callback(GtkPrintJob *aJob, gpointer aData, GError *aError) { |
|
283 #endif |
|
284 g_object_unref(aJob); |
|
285 ((nsIFile*) aData)->Remove(false); |
|
286 } |
|
287 |
|
288 static void |
|
289 ns_release_macro(gpointer aData) { |
|
290 nsIFile* spoolFile = (nsIFile*) aData; |
|
291 NS_RELEASE(spoolFile); |
|
292 } |
|
293 |
|
294 NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, char16_t * aPrintToFileName, |
|
295 int32_t aStartPage, int32_t aEndPage) |
|
296 { |
|
297 if (mToPrinter) { |
|
298 if (!GTK_IS_PRINTER(mGtkPrinter)) |
|
299 return NS_ERROR_FAILURE; |
|
300 |
|
301 mPrintJob = gtk_print_job_new(NS_ConvertUTF16toUTF8(aTitle).get(), mGtkPrinter, |
|
302 mGtkPrintSettings, mGtkPageSetup); |
|
303 } |
|
304 |
|
305 return NS_OK; |
|
306 } |
|
307 |
|
308 NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument() |
|
309 { |
|
310 if (mToPrinter) { |
|
311 if (!mPrintJob) |
|
312 return NS_OK; // The operation was aborted. |
|
313 |
|
314 if (!gtk_print_job_set_source_file(mPrintJob, mSpoolName.get(), nullptr)) |
|
315 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; |
|
316 |
|
317 NS_ADDREF(mSpoolFile.get()); |
|
318 gtk_print_job_send(mPrintJob, print_callback, mSpoolFile, ns_release_macro); |
|
319 } else { |
|
320 // Handle print-to-file ourselves for the benefit of embedders |
|
321 nsXPIDLString targetPath; |
|
322 nsCOMPtr<nsIFile> destFile; |
|
323 mPrintSettings->GetToFileName(getter_Copies(targetPath)); |
|
324 |
|
325 nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), |
|
326 false, getter_AddRefs(destFile)); |
|
327 NS_ENSURE_SUCCESS(rv, rv); |
|
328 |
|
329 nsAutoString destLeafName; |
|
330 rv = destFile->GetLeafName(destLeafName); |
|
331 NS_ENSURE_SUCCESS(rv, rv); |
|
332 |
|
333 nsCOMPtr<nsIFile> destDir; |
|
334 rv = destFile->GetParent(getter_AddRefs(destDir)); |
|
335 NS_ENSURE_SUCCESS(rv, rv); |
|
336 |
|
337 rv = mSpoolFile->MoveTo(destDir, destLeafName); |
|
338 NS_ENSURE_SUCCESS(rv, rv); |
|
339 |
|
340 // This is the standard way to get the UNIX umask. Ugh. |
|
341 mode_t mask = umask(0); |
|
342 umask(mask); |
|
343 // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions |
|
344 // (thats because files and directories have different numbers of bits for their permissions) |
|
345 destFile->SetPermissions(0666 & ~(mask)); |
|
346 } |
|
347 return NS_OK; |
|
348 } |
|
349 |
|
350 /* Get prefs for printer |
|
351 * Search order: |
|
352 * - Get prefs per printer name and module name |
|
353 * - Get prefs per printer name |
|
354 * - Get prefs per module name |
|
355 * - Get prefs |
|
356 */ |
|
357 static |
|
358 nsresult CopyPrinterCharPref(const char *modulename, const char *printername, |
|
359 const char *prefname, nsCString &return_buf) |
|
360 { |
|
361 DO_PR_DEBUG_LOG(("CopyPrinterCharPref('%s', '%s', '%s')\n", modulename, printername, prefname)); |
|
362 |
|
363 nsresult rv = NS_ERROR_FAILURE; |
|
364 |
|
365 if (printername && modulename) { |
|
366 /* Get prefs per printer name and module name */ |
|
367 nsPrintfCString name("print.%s.printer_%s.%s", modulename, printername, prefname); |
|
368 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); |
|
369 rv = Preferences::GetCString(name.get(), &return_buf); |
|
370 } |
|
371 |
|
372 if (NS_FAILED(rv)) { |
|
373 if (printername) { |
|
374 /* Get prefs per printer name */ |
|
375 nsPrintfCString name("print.printer_%s.%s", printername, prefname); |
|
376 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); |
|
377 rv = Preferences::GetCString(name.get(), &return_buf); |
|
378 } |
|
379 |
|
380 if (NS_FAILED(rv)) { |
|
381 if (modulename) { |
|
382 /* Get prefs per module name */ |
|
383 nsPrintfCString name("print.%s.%s", modulename, prefname); |
|
384 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); |
|
385 rv = Preferences::GetCString(name.get(), &return_buf); |
|
386 } |
|
387 |
|
388 if (NS_FAILED(rv)) { |
|
389 /* Get prefs */ |
|
390 nsPrintfCString name("print.%s", prefname); |
|
391 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); |
|
392 rv = Preferences::GetCString(name.get(), &return_buf); |
|
393 } |
|
394 } |
|
395 } |
|
396 |
|
397 #ifdef PR_LOG |
|
398 if (NS_SUCCEEDED(rv)) { |
|
399 DO_PR_DEBUG_LOG(("CopyPrinterCharPref returning '%s'.\n", return_buf.get())); |
|
400 } |
|
401 else |
|
402 { |
|
403 DO_PR_DEBUG_LOG(("CopyPrinterCharPref failure.\n")); |
|
404 } |
|
405 #endif /* PR_LOG */ |
|
406 |
|
407 return rv; |
|
408 } |
|
409 |
|
410 // Printer Enumerator |
|
411 nsPrinterEnumeratorGTK::nsPrinterEnumeratorGTK() |
|
412 { |
|
413 } |
|
414 |
|
415 NS_IMPL_ISUPPORTS(nsPrinterEnumeratorGTK, nsIPrinterEnumerator) |
|
416 |
|
417 NS_IMETHODIMP nsPrinterEnumeratorGTK::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList) |
|
418 { |
|
419 NS_ENSURE_ARG_POINTER(aPrinterNameList); |
|
420 *aPrinterNameList = nullptr; |
|
421 |
|
422 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); |
|
423 if (NS_FAILED(rv)) { |
|
424 return rv; |
|
425 } |
|
426 |
|
427 uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters(); |
|
428 nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters); |
|
429 if (!printers) { |
|
430 GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
|
431 return NS_ERROR_OUT_OF_MEMORY; |
|
432 } |
|
433 |
|
434 uint32_t count = 0; |
|
435 while( count < numPrinters ) |
|
436 { |
|
437 printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++)); |
|
438 } |
|
439 GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
|
440 |
|
441 return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); |
|
442 } |
|
443 |
|
444 /* readonly attribute wstring defaultPrinterName; */ |
|
445 NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(char16_t **aDefaultPrinterName) |
|
446 { |
|
447 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::GetDefaultPrinterName()\n")); |
|
448 NS_ENSURE_ARG_POINTER(aDefaultPrinterName); |
|
449 |
|
450 GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName); |
|
451 |
|
452 DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get())); |
|
453 return NS_OK; |
|
454 } |
|
455 |
|
456 /* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */ |
|
457 NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings) |
|
458 { |
|
459 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter()")); |
|
460 nsresult rv; |
|
461 |
|
462 NS_ENSURE_ARG_POINTER(aPrinterName); |
|
463 NS_ENSURE_ARG_POINTER(aPrintSettings); |
|
464 |
|
465 NS_ENSURE_TRUE(*aPrinterName, NS_ERROR_FAILURE); |
|
466 NS_ENSURE_TRUE(aPrintSettings, NS_ERROR_FAILURE); |
|
467 |
|
468 nsXPIDLCString fullPrinterName, /* Full name of printer incl. driver-specific prefix */ |
|
469 printerName; /* "Stripped" name of printer */ |
|
470 fullPrinterName.Assign(NS_ConvertUTF16toUTF8(aPrinterName)); |
|
471 printerName.Assign(NS_ConvertUTF16toUTF8(aPrinterName)); |
|
472 DO_PR_DEBUG_LOG(("printerName='%s'\n", printerName.get())); |
|
473 |
|
474 PrintMethod type = pmInvalid; |
|
475 rv = nsDeviceContextSpecGTK::GetPrintMethod(printerName, type); |
|
476 if (NS_FAILED(rv)) |
|
477 return rv; |
|
478 |
|
479 /* "Demangle" postscript printer name */ |
|
480 if (type == pmPostScript) { |
|
481 /* Strip the printing method name from the printer, |
|
482 * e.g. turn "PostScript/foobar" to "foobar" */ |
|
483 int32_t slash = printerName.FindChar('/'); |
|
484 if (kNotFound != slash) |
|
485 printerName.Cut(0, slash + 1); |
|
486 } |
|
487 |
|
488 /* Set filename */ |
|
489 nsAutoCString filename; |
|
490 if (NS_FAILED(CopyPrinterCharPref(nullptr, printerName, "filename", filename))) { |
|
491 const char *path; |
|
492 |
|
493 if (!(path = PR_GetEnv("PWD"))) |
|
494 path = PR_GetEnv("HOME"); |
|
495 |
|
496 if (path) |
|
497 filename = nsPrintfCString("%s/mozilla.pdf", path); |
|
498 else |
|
499 filename.AssignLiteral("mozilla.pdf"); |
|
500 } |
|
501 DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", filename.get())); |
|
502 aPrintSettings->SetToFileName(NS_ConvertUTF8toUTF16(filename).get()); |
|
503 |
|
504 aPrintSettings->SetIsInitializedFromPrinter(true); |
|
505 |
|
506 if (type == pmPostScript) { |
|
507 DO_PR_DEBUG_LOG(("InitPrintSettingsFromPrinter() for PostScript printer\n")); |
|
508 |
|
509 nsAutoCString orientation; |
|
510 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName, |
|
511 "orientation", orientation))) { |
|
512 if (orientation.LowerCaseEqualsLiteral("portrait")) { |
|
513 DO_PR_DEBUG_LOG(("setting default orientation to 'portrait'\n")); |
|
514 aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation); |
|
515 } |
|
516 else if (orientation.LowerCaseEqualsLiteral("landscape")) { |
|
517 DO_PR_DEBUG_LOG(("setting default orientation to 'landscape'\n")); |
|
518 aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); |
|
519 } |
|
520 else { |
|
521 DO_PR_DEBUG_LOG(("Unknown default orientation '%s'\n", orientation.get())); |
|
522 } |
|
523 } |
|
524 |
|
525 /* PostScript module does not support changing the plex mode... */ |
|
526 DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", "default")); |
|
527 aPrintSettings->SetPlexName(MOZ_UTF16("default")); |
|
528 |
|
529 /* PostScript module does not support changing the resolution mode... */ |
|
530 DO_PR_DEBUG_LOG(("setting default resolution to '%s'\n", "default")); |
|
531 aPrintSettings->SetResolutionName(MOZ_UTF16("default")); |
|
532 |
|
533 /* PostScript module does not support changing the colorspace... */ |
|
534 DO_PR_DEBUG_LOG(("setting default colorspace to '%s'\n", "default")); |
|
535 aPrintSettings->SetColorspace(MOZ_UTF16("default")); |
|
536 |
|
537 nsAutoCString papername; |
|
538 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName, |
|
539 "paper_size", papername))) { |
|
540 nsPaperSizePS paper; |
|
541 |
|
542 if (paper.Find(papername.get())) { |
|
543 DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n", |
|
544 paper.Name(), paper.Width_mm(), paper.Height_mm())); |
|
545 aPrintSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters); |
|
546 aPrintSettings->SetPaperWidth(paper.Width_mm()); |
|
547 aPrintSettings->SetPaperHeight(paper.Height_mm()); |
|
548 aPrintSettings->SetPaperName(NS_ConvertASCIItoUTF16(paper.Name()).get()); |
|
549 } |
|
550 else { |
|
551 DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get())); |
|
552 } |
|
553 } |
|
554 |
|
555 bool hasSpoolerCmd = (nsPSPrinterList::kTypePS == |
|
556 nsPSPrinterList::GetPrinterType(fullPrinterName)); |
|
557 |
|
558 if (hasSpoolerCmd) { |
|
559 nsAutoCString command; |
|
560 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", |
|
561 printerName, "print_command", command))) { |
|
562 DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", |
|
563 command.get())); |
|
564 aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUTF16(command).get()); |
|
565 } |
|
566 } |
|
567 |
|
568 return NS_OK; |
|
569 } |
|
570 |
|
571 return NS_ERROR_UNEXPECTED; |
|
572 } |
|
573 |
|
574 NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const char16_t *aPrinter, nsIPrintSettings *aPrintSettings) |
|
575 { |
|
576 return NS_OK; |
|
577 } |
|
578 |
|
579 //---------------------------------------------------------------------- |
|
580 nsresult GlobalPrinters::InitializeGlobalPrinters () |
|
581 { |
|
582 if (PrintersAreAllocated()) { |
|
583 return NS_OK; |
|
584 } |
|
585 |
|
586 mGlobalPrinterList = new nsTArray<nsString>(); |
|
587 |
|
588 nsPSPrinterList psMgr; |
|
589 if (psMgr.Enabled()) { |
|
590 /* Get the list of PostScript-module printers */ |
|
591 // XXX: this function is the only user of GetPrinterList |
|
592 // So it may be interesting to convert the nsCStrings |
|
593 // in this function, we would save one loop here |
|
594 nsTArray<nsCString> printerList; |
|
595 psMgr.GetPrinterList(printerList); |
|
596 for (uint32_t i = 0; i < printerList.Length(); i++) |
|
597 { |
|
598 mGlobalPrinterList->AppendElement(NS_ConvertUTF8toUTF16(printerList[i])); |
|
599 } |
|
600 } |
|
601 |
|
602 /* If there are no printers available after all checks, return an error */ |
|
603 if (!mGlobalPrinterList->Length()) |
|
604 { |
|
605 /* Make sure we do not cache an empty printer list */ |
|
606 FreeGlobalPrinters(); |
|
607 |
|
608 return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; |
|
609 } |
|
610 |
|
611 return NS_OK; |
|
612 } |
|
613 |
|
614 //---------------------------------------------------------------------- |
|
615 void GlobalPrinters::FreeGlobalPrinters() |
|
616 { |
|
617 if (mGlobalPrinterList) { |
|
618 delete mGlobalPrinterList; |
|
619 mGlobalPrinterList = nullptr; |
|
620 } |
|
621 } |
|
622 |
|
623 void |
|
624 GlobalPrinters::GetDefaultPrinterName(char16_t **aDefaultPrinterName) |
|
625 { |
|
626 *aDefaultPrinterName = nullptr; |
|
627 |
|
628 bool allocate = !GlobalPrinters::GetInstance()->PrintersAreAllocated(); |
|
629 |
|
630 if (allocate) { |
|
631 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); |
|
632 if (NS_FAILED(rv)) { |
|
633 return; |
|
634 } |
|
635 } |
|
636 NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters"); |
|
637 |
|
638 if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0) |
|
639 return; |
|
640 |
|
641 *aDefaultPrinterName = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(0)); |
|
642 |
|
643 if (allocate) { |
|
644 GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
|
645 } |
|
646 } |
|
647 |