1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gtk/nsDeviceContextSpecG.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,647 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifdef MOZ_LOGGING 1.10 +#define FORCE_PR_LOG 1 /* Allow logging in the release build */ 1.11 +#endif /* MOZ_LOGGING */ 1.12 +#include "prlog.h" 1.13 + 1.14 +#include "plstr.h" 1.15 + 1.16 +#include "nsDeviceContextSpecG.h" 1.17 + 1.18 +#include "prenv.h" /* for PR_GetEnv */ 1.19 + 1.20 +#include "nsPrintfCString.h" 1.21 +#include "nsReadableUtils.h" 1.22 +#include "nsStringEnumerator.h" 1.23 +#include "nsIServiceManager.h" 1.24 + 1.25 +#include "nsPSPrinters.h" 1.26 +#include "nsPaperPS.h" /* Paper size list */ 1.27 + 1.28 +#include "nsPrintSettingsGTK.h" 1.29 + 1.30 +#include "nsIFileStreams.h" 1.31 +#include "nsIFile.h" 1.32 +#include "nsTArray.h" 1.33 + 1.34 +#include "mozilla/Preferences.h" 1.35 + 1.36 +#include <unistd.h> 1.37 +#include <sys/types.h> 1.38 +#include <sys/stat.h> 1.39 + 1.40 +using namespace mozilla; 1.41 + 1.42 +#ifdef PR_LOGGING 1.43 +static PRLogModuleInfo * 1.44 +GetDeviceContextSpecGTKLog() 1.45 +{ 1.46 + static PRLogModuleInfo *sLog; 1.47 + if (!sLog) 1.48 + sLog = PR_NewLogModule("DeviceContextSpecGTK"); 1.49 + return sLog; 1.50 +} 1.51 +#endif /* PR_LOGGING */ 1.52 +/* Macro to make lines shorter */ 1.53 +#define DO_PR_DEBUG_LOG(x) PR_LOG(GetDeviceContextSpecGTKLog(), PR_LOG_DEBUG, x) 1.54 + 1.55 +//---------------------------------------------------------------------------------- 1.56 +// The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecGTK 1.57 +// The PrinterEnumerator creates the printer info 1.58 +// but the nsDeviceContextSpecGTK cleans it up 1.59 +// If it gets created (via the Page Setup Dialog) but the user never prints anything 1.60 +// then it will never be delete, so this class takes care of that. 1.61 +class GlobalPrinters { 1.62 +public: 1.63 + static GlobalPrinters* GetInstance() { return &mGlobalPrinters; } 1.64 + ~GlobalPrinters() { FreeGlobalPrinters(); } 1.65 + 1.66 + void FreeGlobalPrinters(); 1.67 + nsresult InitializeGlobalPrinters(); 1.68 + 1.69 + bool PrintersAreAllocated() { return mGlobalPrinterList != nullptr; } 1.70 + uint32_t GetNumPrinters() 1.71 + { return mGlobalPrinterList ? mGlobalPrinterList->Length() : 0; } 1.72 + nsString* GetStringAt(int32_t aInx) { return &mGlobalPrinterList->ElementAt(aInx); } 1.73 + void GetDefaultPrinterName(char16_t **aDefaultPrinterName); 1.74 + 1.75 +protected: 1.76 + GlobalPrinters() {} 1.77 + 1.78 + static GlobalPrinters mGlobalPrinters; 1.79 + static nsTArray<nsString>* mGlobalPrinterList; 1.80 +}; 1.81 + 1.82 +//--------------- 1.83 +// static members 1.84 +GlobalPrinters GlobalPrinters::mGlobalPrinters; 1.85 +nsTArray<nsString>* GlobalPrinters::mGlobalPrinterList = nullptr; 1.86 +//--------------- 1.87 + 1.88 +nsDeviceContextSpecGTK::nsDeviceContextSpecGTK() 1.89 + : mPrintJob(nullptr) 1.90 + , mGtkPrinter(nullptr) 1.91 + , mGtkPrintSettings(nullptr) 1.92 + , mGtkPageSetup(nullptr) 1.93 +{ 1.94 + DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()\n")); 1.95 +} 1.96 + 1.97 +nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK() 1.98 +{ 1.99 + DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()\n")); 1.100 + 1.101 + if (mGtkPageSetup) { 1.102 + g_object_unref(mGtkPageSetup); 1.103 + } 1.104 + 1.105 + if (mGtkPrintSettings) { 1.106 + g_object_unref(mGtkPrintSettings); 1.107 + } 1.108 +} 1.109 + 1.110 +NS_IMPL_ISUPPORTS(nsDeviceContextSpecGTK, 1.111 + nsIDeviceContextSpec) 1.112 + 1.113 +#include "gfxPDFSurface.h" 1.114 +#include "gfxPSSurface.h" 1.115 +NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurface) 1.116 +{ 1.117 + *aSurface = nullptr; 1.118 + 1.119 + const char *path; 1.120 + GetPath(&path); 1.121 + 1.122 + double width, height; 1.123 + mPrintSettings->GetEffectivePageSize(&width, &height); 1.124 + 1.125 + // convert twips to points 1.126 + width /= TWIPS_PER_POINT_FLOAT; 1.127 + height /= TWIPS_PER_POINT_FLOAT; 1.128 + 1.129 + DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", path, width, height)); 1.130 + nsresult rv; 1.131 + 1.132 + // Spool file. Use Glib's temporary file function since we're 1.133 + // already dependent on the gtk software stack. 1.134 + gchar *buf; 1.135 + gint fd = g_file_open_tmp("XXXXXX.tmp", &buf, nullptr); 1.136 + if (-1 == fd) 1.137 + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; 1.138 + close(fd); 1.139 + 1.140 + rv = NS_NewNativeLocalFile(nsDependentCString(buf), false, 1.141 + getter_AddRefs(mSpoolFile)); 1.142 + if (NS_FAILED(rv)) { 1.143 + unlink(buf); 1.144 + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; 1.145 + } 1.146 + 1.147 + mSpoolName = buf; 1.148 + g_free(buf); 1.149 + 1.150 + mSpoolFile->SetPermissions(0600); 1.151 + 1.152 + nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); 1.153 + rv = stream->Init(mSpoolFile, -1, -1, 0); 1.154 + if (NS_FAILED(rv)) 1.155 + return rv; 1.156 + 1.157 + int16_t format; 1.158 + mPrintSettings->GetOutputFormat(&format); 1.159 + 1.160 + nsRefPtr<gfxASurface> surface; 1.161 + gfxSize surfaceSize(width, height); 1.162 + 1.163 + // Determine the real format with some GTK magic 1.164 + if (format == nsIPrintSettings::kOutputFormatNative) { 1.165 + if (mIsPPreview) { 1.166 + // There is nothing to detect on Print Preview, use PS. 1.167 + format = nsIPrintSettings::kOutputFormatPS; 1.168 + } else { 1.169 + const gchar* fmtGTK = gtk_print_settings_get(mGtkPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT); 1.170 + if (!fmtGTK && GTK_IS_PRINTER(mGtkPrinter)) { 1.171 + // Likely not print-to-file, check printer's capabilities 1.172 + 1.173 + // Prior to gtk 2.24, gtk_printer_accepts_pdf() and 1.174 + // gtk_printer_accepts_ps() always returned true regardless of the 1.175 + // printer's capability. 1.176 + if (gtk_major_version > 2 || 1.177 + (gtk_major_version == 2 && gtk_minor_version >= 24)) { 1.178 + format = 1.179 + gtk_printer_accepts_pdf(mGtkPrinter) ? 1.180 + static_cast<int16_t>(nsIPrintSettings::kOutputFormatPDF) : 1.181 + static_cast<int16_t>(nsIPrintSettings::kOutputFormatPS); 1.182 + } else { 1.183 + format = nsIPrintSettings::kOutputFormatPS; 1.184 + } 1.185 + 1.186 + } else if (nsDependentCString(fmtGTK).EqualsIgnoreCase("pdf")) { 1.187 + format = nsIPrintSettings::kOutputFormatPDF; 1.188 + } else { 1.189 + format = nsIPrintSettings::kOutputFormatPS; 1.190 + } 1.191 + } 1.192 + } 1.193 + 1.194 + if (format == nsIPrintSettings::kOutputFormatPDF) { 1.195 + surface = new gfxPDFSurface(stream, surfaceSize); 1.196 + } else { 1.197 + int32_t orientation; 1.198 + mPrintSettings->GetOrientation(&orientation); 1.199 + if (nsIPrintSettings::kPortraitOrientation == orientation) { 1.200 + surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::PORTRAIT); 1.201 + } else { 1.202 + surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::LANDSCAPE); 1.203 + } 1.204 + } 1.205 + 1.206 + if (!surface) 1.207 + return NS_ERROR_OUT_OF_MEMORY; 1.208 + 1.209 + surface.swap(*aSurface); 1.210 + 1.211 + return NS_OK; 1.212 +} 1.213 + 1.214 +/** ------------------------------------------------------- 1.215 + * Initialize the nsDeviceContextSpecGTK 1.216 + * @update dc 2/15/98 1.217 + * @update syd 3/2/99 1.218 + */ 1.219 +NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget, 1.220 + nsIPrintSettings* aPS, 1.221 + bool aIsPrintPreview) 1.222 +{ 1.223 + DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::Init(aPS=%p)\n", aPS)); 1.224 + 1.225 + if (gtk_major_version < 2 || 1.226 + (gtk_major_version == 2 && gtk_minor_version < 10)) 1.227 + return NS_ERROR_NOT_AVAILABLE; // I'm so sorry bz 1.228 + 1.229 + mPrintSettings = aPS; 1.230 + mIsPPreview = aIsPrintPreview; 1.231 + 1.232 + // This is only set by embedders 1.233 + bool toFile; 1.234 + aPS->GetPrintToFile(&toFile); 1.235 + 1.236 + mToPrinter = !toFile && !aIsPrintPreview; 1.237 + 1.238 + nsCOMPtr<nsPrintSettingsGTK> printSettingsGTK(do_QueryInterface(aPS)); 1.239 + if (!printSettingsGTK) 1.240 + return NS_ERROR_NO_INTERFACE; 1.241 + 1.242 + mGtkPrinter = printSettingsGTK->GetGtkPrinter(); 1.243 + mGtkPrintSettings = printSettingsGTK->GetGtkPrintSettings(); 1.244 + mGtkPageSetup = printSettingsGTK->GetGtkPageSetup(); 1.245 + 1.246 + // This is a horrible workaround for some printer driver bugs that treat custom page sizes different 1.247 + // to standard ones. If our paper object matches one of a standard one, use a standard paper size 1.248 + // object instead. See bug 414314 for more info. 1.249 + GtkPaperSize* geckosHackishPaperSize = gtk_page_setup_get_paper_size(mGtkPageSetup); 1.250 + GtkPaperSize* standardGtkPaperSize = gtk_paper_size_new(gtk_paper_size_get_name(geckosHackishPaperSize)); 1.251 + 1.252 + mGtkPageSetup = gtk_page_setup_copy(mGtkPageSetup); 1.253 + mGtkPrintSettings = gtk_print_settings_copy(mGtkPrintSettings); 1.254 + 1.255 + GtkPaperSize* properPaperSize; 1.256 + if (gtk_paper_size_is_equal(geckosHackishPaperSize, standardGtkPaperSize)) { 1.257 + properPaperSize = standardGtkPaperSize; 1.258 + } else { 1.259 + properPaperSize = geckosHackishPaperSize; 1.260 + } 1.261 + gtk_print_settings_set_paper_size(mGtkPrintSettings, properPaperSize); 1.262 + gtk_page_setup_set_paper_size_and_default_margins(mGtkPageSetup, properPaperSize); 1.263 + gtk_paper_size_free(standardGtkPaperSize); 1.264 + 1.265 + return NS_OK; 1.266 +} 1.267 + 1.268 +NS_IMETHODIMP nsDeviceContextSpecGTK::GetPath(const char **aPath) 1.269 +{ 1.270 + *aPath = mPath; 1.271 + return NS_OK; 1.272 +} 1.273 + 1.274 +/* static !! */ 1.275 +nsresult nsDeviceContextSpecGTK::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod) 1.276 +{ 1.277 + aMethod = pmPostScript; 1.278 + return NS_OK; 1.279 +} 1.280 + 1.281 +static void 1.282 +#if (MOZ_WIDGET_GTK == 3) 1.283 +print_callback(GtkPrintJob *aJob, gpointer aData, const GError *aError) { 1.284 +#else 1.285 +print_callback(GtkPrintJob *aJob, gpointer aData, GError *aError) { 1.286 +#endif 1.287 + g_object_unref(aJob); 1.288 + ((nsIFile*) aData)->Remove(false); 1.289 +} 1.290 + 1.291 +static void 1.292 +ns_release_macro(gpointer aData) { 1.293 + nsIFile* spoolFile = (nsIFile*) aData; 1.294 + NS_RELEASE(spoolFile); 1.295 +} 1.296 + 1.297 +NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, char16_t * aPrintToFileName, 1.298 + int32_t aStartPage, int32_t aEndPage) 1.299 +{ 1.300 + if (mToPrinter) { 1.301 + if (!GTK_IS_PRINTER(mGtkPrinter)) 1.302 + return NS_ERROR_FAILURE; 1.303 + 1.304 + mPrintJob = gtk_print_job_new(NS_ConvertUTF16toUTF8(aTitle).get(), mGtkPrinter, 1.305 + mGtkPrintSettings, mGtkPageSetup); 1.306 + } 1.307 + 1.308 + return NS_OK; 1.309 +} 1.310 + 1.311 +NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument() 1.312 +{ 1.313 + if (mToPrinter) { 1.314 + if (!mPrintJob) 1.315 + return NS_OK; // The operation was aborted. 1.316 + 1.317 + if (!gtk_print_job_set_source_file(mPrintJob, mSpoolName.get(), nullptr)) 1.318 + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; 1.319 + 1.320 + NS_ADDREF(mSpoolFile.get()); 1.321 + gtk_print_job_send(mPrintJob, print_callback, mSpoolFile, ns_release_macro); 1.322 + } else { 1.323 + // Handle print-to-file ourselves for the benefit of embedders 1.324 + nsXPIDLString targetPath; 1.325 + nsCOMPtr<nsIFile> destFile; 1.326 + mPrintSettings->GetToFileName(getter_Copies(targetPath)); 1.327 + 1.328 + nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), 1.329 + false, getter_AddRefs(destFile)); 1.330 + NS_ENSURE_SUCCESS(rv, rv); 1.331 + 1.332 + nsAutoString destLeafName; 1.333 + rv = destFile->GetLeafName(destLeafName); 1.334 + NS_ENSURE_SUCCESS(rv, rv); 1.335 + 1.336 + nsCOMPtr<nsIFile> destDir; 1.337 + rv = destFile->GetParent(getter_AddRefs(destDir)); 1.338 + NS_ENSURE_SUCCESS(rv, rv); 1.339 + 1.340 + rv = mSpoolFile->MoveTo(destDir, destLeafName); 1.341 + NS_ENSURE_SUCCESS(rv, rv); 1.342 + 1.343 + // This is the standard way to get the UNIX umask. Ugh. 1.344 + mode_t mask = umask(0); 1.345 + umask(mask); 1.346 + // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions 1.347 + // (thats because files and directories have different numbers of bits for their permissions) 1.348 + destFile->SetPermissions(0666 & ~(mask)); 1.349 + } 1.350 + return NS_OK; 1.351 +} 1.352 + 1.353 +/* Get prefs for printer 1.354 + * Search order: 1.355 + * - Get prefs per printer name and module name 1.356 + * - Get prefs per printer name 1.357 + * - Get prefs per module name 1.358 + * - Get prefs 1.359 + */ 1.360 +static 1.361 +nsresult CopyPrinterCharPref(const char *modulename, const char *printername, 1.362 + const char *prefname, nsCString &return_buf) 1.363 +{ 1.364 + DO_PR_DEBUG_LOG(("CopyPrinterCharPref('%s', '%s', '%s')\n", modulename, printername, prefname)); 1.365 + 1.366 + nsresult rv = NS_ERROR_FAILURE; 1.367 + 1.368 + if (printername && modulename) { 1.369 + /* Get prefs per printer name and module name */ 1.370 + nsPrintfCString name("print.%s.printer_%s.%s", modulename, printername, prefname); 1.371 + DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); 1.372 + rv = Preferences::GetCString(name.get(), &return_buf); 1.373 + } 1.374 + 1.375 + if (NS_FAILED(rv)) { 1.376 + if (printername) { 1.377 + /* Get prefs per printer name */ 1.378 + nsPrintfCString name("print.printer_%s.%s", printername, prefname); 1.379 + DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); 1.380 + rv = Preferences::GetCString(name.get(), &return_buf); 1.381 + } 1.382 + 1.383 + if (NS_FAILED(rv)) { 1.384 + if (modulename) { 1.385 + /* Get prefs per module name */ 1.386 + nsPrintfCString name("print.%s.%s", modulename, prefname); 1.387 + DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); 1.388 + rv = Preferences::GetCString(name.get(), &return_buf); 1.389 + } 1.390 + 1.391 + if (NS_FAILED(rv)) { 1.392 + /* Get prefs */ 1.393 + nsPrintfCString name("print.%s", prefname); 1.394 + DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get())); 1.395 + rv = Preferences::GetCString(name.get(), &return_buf); 1.396 + } 1.397 + } 1.398 + } 1.399 + 1.400 +#ifdef PR_LOG 1.401 + if (NS_SUCCEEDED(rv)) { 1.402 + DO_PR_DEBUG_LOG(("CopyPrinterCharPref returning '%s'.\n", return_buf.get())); 1.403 + } 1.404 + else 1.405 + { 1.406 + DO_PR_DEBUG_LOG(("CopyPrinterCharPref failure.\n")); 1.407 + } 1.408 +#endif /* PR_LOG */ 1.409 + 1.410 + return rv; 1.411 +} 1.412 + 1.413 +// Printer Enumerator 1.414 +nsPrinterEnumeratorGTK::nsPrinterEnumeratorGTK() 1.415 +{ 1.416 +} 1.417 + 1.418 +NS_IMPL_ISUPPORTS(nsPrinterEnumeratorGTK, nsIPrinterEnumerator) 1.419 + 1.420 +NS_IMETHODIMP nsPrinterEnumeratorGTK::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList) 1.421 +{ 1.422 + NS_ENSURE_ARG_POINTER(aPrinterNameList); 1.423 + *aPrinterNameList = nullptr; 1.424 + 1.425 + nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); 1.426 + if (NS_FAILED(rv)) { 1.427 + return rv; 1.428 + } 1.429 + 1.430 + uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters(); 1.431 + nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters); 1.432 + if (!printers) { 1.433 + GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.434 + return NS_ERROR_OUT_OF_MEMORY; 1.435 + } 1.436 + 1.437 + uint32_t count = 0; 1.438 + while( count < numPrinters ) 1.439 + { 1.440 + printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++)); 1.441 + } 1.442 + GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.443 + 1.444 + return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); 1.445 +} 1.446 + 1.447 +/* readonly attribute wstring defaultPrinterName; */ 1.448 +NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(char16_t **aDefaultPrinterName) 1.449 +{ 1.450 + DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::GetDefaultPrinterName()\n")); 1.451 + NS_ENSURE_ARG_POINTER(aDefaultPrinterName); 1.452 + 1.453 + GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName); 1.454 + 1.455 + DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get())); 1.456 + return NS_OK; 1.457 +} 1.458 + 1.459 +/* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */ 1.460 +NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings) 1.461 +{ 1.462 + DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter()")); 1.463 + nsresult rv; 1.464 + 1.465 + NS_ENSURE_ARG_POINTER(aPrinterName); 1.466 + NS_ENSURE_ARG_POINTER(aPrintSettings); 1.467 + 1.468 + NS_ENSURE_TRUE(*aPrinterName, NS_ERROR_FAILURE); 1.469 + NS_ENSURE_TRUE(aPrintSettings, NS_ERROR_FAILURE); 1.470 + 1.471 + nsXPIDLCString fullPrinterName, /* Full name of printer incl. driver-specific prefix */ 1.472 + printerName; /* "Stripped" name of printer */ 1.473 + fullPrinterName.Assign(NS_ConvertUTF16toUTF8(aPrinterName)); 1.474 + printerName.Assign(NS_ConvertUTF16toUTF8(aPrinterName)); 1.475 + DO_PR_DEBUG_LOG(("printerName='%s'\n", printerName.get())); 1.476 + 1.477 + PrintMethod type = pmInvalid; 1.478 + rv = nsDeviceContextSpecGTK::GetPrintMethod(printerName, type); 1.479 + if (NS_FAILED(rv)) 1.480 + return rv; 1.481 + 1.482 + /* "Demangle" postscript printer name */ 1.483 + if (type == pmPostScript) { 1.484 + /* Strip the printing method name from the printer, 1.485 + * e.g. turn "PostScript/foobar" to "foobar" */ 1.486 + int32_t slash = printerName.FindChar('/'); 1.487 + if (kNotFound != slash) 1.488 + printerName.Cut(0, slash + 1); 1.489 + } 1.490 + 1.491 + /* Set filename */ 1.492 + nsAutoCString filename; 1.493 + if (NS_FAILED(CopyPrinterCharPref(nullptr, printerName, "filename", filename))) { 1.494 + const char *path; 1.495 + 1.496 + if (!(path = PR_GetEnv("PWD"))) 1.497 + path = PR_GetEnv("HOME"); 1.498 + 1.499 + if (path) 1.500 + filename = nsPrintfCString("%s/mozilla.pdf", path); 1.501 + else 1.502 + filename.AssignLiteral("mozilla.pdf"); 1.503 + } 1.504 + DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", filename.get())); 1.505 + aPrintSettings->SetToFileName(NS_ConvertUTF8toUTF16(filename).get()); 1.506 + 1.507 + aPrintSettings->SetIsInitializedFromPrinter(true); 1.508 + 1.509 + if (type == pmPostScript) { 1.510 + DO_PR_DEBUG_LOG(("InitPrintSettingsFromPrinter() for PostScript printer\n")); 1.511 + 1.512 + nsAutoCString orientation; 1.513 + if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName, 1.514 + "orientation", orientation))) { 1.515 + if (orientation.LowerCaseEqualsLiteral("portrait")) { 1.516 + DO_PR_DEBUG_LOG(("setting default orientation to 'portrait'\n")); 1.517 + aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation); 1.518 + } 1.519 + else if (orientation.LowerCaseEqualsLiteral("landscape")) { 1.520 + DO_PR_DEBUG_LOG(("setting default orientation to 'landscape'\n")); 1.521 + aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); 1.522 + } 1.523 + else { 1.524 + DO_PR_DEBUG_LOG(("Unknown default orientation '%s'\n", orientation.get())); 1.525 + } 1.526 + } 1.527 + 1.528 + /* PostScript module does not support changing the plex mode... */ 1.529 + DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", "default")); 1.530 + aPrintSettings->SetPlexName(MOZ_UTF16("default")); 1.531 + 1.532 + /* PostScript module does not support changing the resolution mode... */ 1.533 + DO_PR_DEBUG_LOG(("setting default resolution to '%s'\n", "default")); 1.534 + aPrintSettings->SetResolutionName(MOZ_UTF16("default")); 1.535 + 1.536 + /* PostScript module does not support changing the colorspace... */ 1.537 + DO_PR_DEBUG_LOG(("setting default colorspace to '%s'\n", "default")); 1.538 + aPrintSettings->SetColorspace(MOZ_UTF16("default")); 1.539 + 1.540 + nsAutoCString papername; 1.541 + if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName, 1.542 + "paper_size", papername))) { 1.543 + nsPaperSizePS paper; 1.544 + 1.545 + if (paper.Find(papername.get())) { 1.546 + DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n", 1.547 + paper.Name(), paper.Width_mm(), paper.Height_mm())); 1.548 + aPrintSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters); 1.549 + aPrintSettings->SetPaperWidth(paper.Width_mm()); 1.550 + aPrintSettings->SetPaperHeight(paper.Height_mm()); 1.551 + aPrintSettings->SetPaperName(NS_ConvertASCIItoUTF16(paper.Name()).get()); 1.552 + } 1.553 + else { 1.554 + DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get())); 1.555 + } 1.556 + } 1.557 + 1.558 + bool hasSpoolerCmd = (nsPSPrinterList::kTypePS == 1.559 + nsPSPrinterList::GetPrinterType(fullPrinterName)); 1.560 + 1.561 + if (hasSpoolerCmd) { 1.562 + nsAutoCString command; 1.563 + if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", 1.564 + printerName, "print_command", command))) { 1.565 + DO_PR_DEBUG_LOG(("setting default print command to '%s'\n", 1.566 + command.get())); 1.567 + aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUTF16(command).get()); 1.568 + } 1.569 + } 1.570 + 1.571 + return NS_OK; 1.572 + } 1.573 + 1.574 + return NS_ERROR_UNEXPECTED; 1.575 +} 1.576 + 1.577 +NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const char16_t *aPrinter, nsIPrintSettings *aPrintSettings) 1.578 +{ 1.579 + return NS_OK; 1.580 +} 1.581 + 1.582 +//---------------------------------------------------------------------- 1.583 +nsresult GlobalPrinters::InitializeGlobalPrinters () 1.584 +{ 1.585 + if (PrintersAreAllocated()) { 1.586 + return NS_OK; 1.587 + } 1.588 + 1.589 + mGlobalPrinterList = new nsTArray<nsString>(); 1.590 + 1.591 + nsPSPrinterList psMgr; 1.592 + if (psMgr.Enabled()) { 1.593 + /* Get the list of PostScript-module printers */ 1.594 + // XXX: this function is the only user of GetPrinterList 1.595 + // So it may be interesting to convert the nsCStrings 1.596 + // in this function, we would save one loop here 1.597 + nsTArray<nsCString> printerList; 1.598 + psMgr.GetPrinterList(printerList); 1.599 + for (uint32_t i = 0; i < printerList.Length(); i++) 1.600 + { 1.601 + mGlobalPrinterList->AppendElement(NS_ConvertUTF8toUTF16(printerList[i])); 1.602 + } 1.603 + } 1.604 + 1.605 + /* If there are no printers available after all checks, return an error */ 1.606 + if (!mGlobalPrinterList->Length()) 1.607 + { 1.608 + /* Make sure we do not cache an empty printer list */ 1.609 + FreeGlobalPrinters(); 1.610 + 1.611 + return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; 1.612 + } 1.613 + 1.614 + return NS_OK; 1.615 +} 1.616 + 1.617 +//---------------------------------------------------------------------- 1.618 +void GlobalPrinters::FreeGlobalPrinters() 1.619 +{ 1.620 + if (mGlobalPrinterList) { 1.621 + delete mGlobalPrinterList; 1.622 + mGlobalPrinterList = nullptr; 1.623 + } 1.624 +} 1.625 + 1.626 +void 1.627 +GlobalPrinters::GetDefaultPrinterName(char16_t **aDefaultPrinterName) 1.628 +{ 1.629 + *aDefaultPrinterName = nullptr; 1.630 + 1.631 + bool allocate = !GlobalPrinters::GetInstance()->PrintersAreAllocated(); 1.632 + 1.633 + if (allocate) { 1.634 + nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); 1.635 + if (NS_FAILED(rv)) { 1.636 + return; 1.637 + } 1.638 + } 1.639 + NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters"); 1.640 + 1.641 + if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0) 1.642 + return; 1.643 + 1.644 + *aDefaultPrinterName = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(0)); 1.645 + 1.646 + if (allocate) { 1.647 + GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.648 + } 1.649 +} 1.650 +