widget/gtk/nsDeviceContextSpecG.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial