1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/nsDeviceContextSpecWin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,829 @@ 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 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "nsDeviceContextSpecWin.h" 1.12 +#include "prmem.h" 1.13 + 1.14 +#include <winspool.h> 1.15 + 1.16 +#include <tchar.h> 1.17 + 1.18 +#include "nsAutoPtr.h" 1.19 +#include "nsIWidget.h" 1.20 + 1.21 +#include "nsTArray.h" 1.22 +#include "nsIPrintSettingsWin.h" 1.23 + 1.24 +#include "nsString.h" 1.25 +#include "nsCRT.h" 1.26 +#include "nsIServiceManager.h" 1.27 +#include "nsReadableUtils.h" 1.28 +#include "nsStringEnumerator.h" 1.29 + 1.30 +#include "gfxPDFSurface.h" 1.31 +#include "gfxWindowsSurface.h" 1.32 + 1.33 +#include "nsIFileStreams.h" 1.34 +#include "nsIWindowWatcher.h" 1.35 +#include "nsIDOMWindow.h" 1.36 +#include "mozilla/Services.h" 1.37 + 1.38 +// For NS_CopyNativeToUnicode 1.39 +#include "nsNativeCharsetUtils.h" 1.40 + 1.41 +// File Picker 1.42 +#include "nsIFile.h" 1.43 +#include "nsIFilePicker.h" 1.44 +#include "nsIStringBundle.h" 1.45 +#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties" 1.46 + 1.47 +#include "prlog.h" 1.48 +#ifdef PR_LOGGING 1.49 +PRLogModuleInfo * kWidgetPrintingLogMod = PR_NewLogModule("printing-widget"); 1.50 +#define PR_PL(_p1) PR_LOG(kWidgetPrintingLogMod, PR_LOG_DEBUG, _p1) 1.51 +#else 1.52 +#define PR_PL(_p1) 1.53 +#endif 1.54 + 1.55 +using namespace mozilla; 1.56 + 1.57 +//---------------------------------------------------------------------------------- 1.58 +// The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecWin 1.59 +// The PrinterEnumerator creates the printer info 1.60 +// but the nsDeviceContextSpecWin cleans it up 1.61 +// If it gets created (via the Page Setup Dialog) but the user never prints anything 1.62 +// then it will never be delete, so this class takes care of that. 1.63 +class GlobalPrinters { 1.64 +public: 1.65 + static GlobalPrinters* GetInstance() { return &mGlobalPrinters; } 1.66 + ~GlobalPrinters() { FreeGlobalPrinters(); } 1.67 + 1.68 + void FreeGlobalPrinters(); 1.69 + 1.70 + bool PrintersAreAllocated() { return mPrinters != nullptr; } 1.71 + LPWSTR GetItemFromList(int32_t aInx) { return mPrinters?mPrinters->ElementAt(aInx):nullptr; } 1.72 + nsresult EnumeratePrinterList(); 1.73 + void GetDefaultPrinterName(nsString& aDefaultPrinterName); 1.74 + uint32_t GetNumPrinters() { return mPrinters?mPrinters->Length():0; } 1.75 + 1.76 +protected: 1.77 + GlobalPrinters() {} 1.78 + nsresult EnumerateNativePrinters(); 1.79 + void ReallocatePrinters(); 1.80 + 1.81 + static GlobalPrinters mGlobalPrinters; 1.82 + static nsTArray<LPWSTR>* mPrinters; 1.83 +}; 1.84 +//--------------- 1.85 +// static members 1.86 +GlobalPrinters GlobalPrinters::mGlobalPrinters; 1.87 +nsTArray<LPWSTR>* GlobalPrinters::mPrinters = nullptr; 1.88 + 1.89 + 1.90 +//****************************************************** 1.91 +// Define native paper sizes 1.92 +//****************************************************** 1.93 +typedef struct { 1.94 + short mPaperSize; // native enum 1.95 + double mWidth; 1.96 + double mHeight; 1.97 + bool mIsInches; 1.98 +} NativePaperSizes; 1.99 + 1.100 +// There are around 40 default print sizes defined by Windows 1.101 +const NativePaperSizes kPaperSizes[] = { 1.102 + {DMPAPER_LETTER, 8.5, 11.0, true}, 1.103 + {DMPAPER_LEGAL, 8.5, 14.0, true}, 1.104 + {DMPAPER_A4, 210.0, 297.0, false}, 1.105 + {DMPAPER_B4, 250.0, 354.0, false}, 1.106 + {DMPAPER_B5, 182.0, 257.0, false}, 1.107 + {DMPAPER_TABLOID, 11.0, 17.0, true}, 1.108 + {DMPAPER_LEDGER, 17.0, 11.0, true}, 1.109 + {DMPAPER_STATEMENT, 5.5, 8.5, true}, 1.110 + {DMPAPER_EXECUTIVE, 7.25, 10.5, true}, 1.111 + {DMPAPER_A3, 297.0, 420.0, false}, 1.112 + {DMPAPER_A5, 148.0, 210.0, false}, 1.113 + {DMPAPER_CSHEET, 17.0, 22.0, true}, 1.114 + {DMPAPER_DSHEET, 22.0, 34.0, true}, 1.115 + {DMPAPER_ESHEET, 34.0, 44.0, true}, 1.116 + {DMPAPER_LETTERSMALL, 8.5, 11.0, true}, 1.117 + {DMPAPER_A4SMALL, 210.0, 297.0, false}, 1.118 + {DMPAPER_FOLIO, 8.5, 13.0, true}, 1.119 + {DMPAPER_QUARTO, 215.0, 275.0, false}, 1.120 + {DMPAPER_10X14, 10.0, 14.0, true}, 1.121 + {DMPAPER_11X17, 11.0, 17.0, true}, 1.122 + {DMPAPER_NOTE, 8.5, 11.0, true}, 1.123 + {DMPAPER_ENV_9, 3.875, 8.875, true}, 1.124 + {DMPAPER_ENV_10, 40.125, 9.5, true}, 1.125 + {DMPAPER_ENV_11, 4.5, 10.375, true}, 1.126 + {DMPAPER_ENV_12, 4.75, 11.0, true}, 1.127 + {DMPAPER_ENV_14, 5.0, 11.5, true}, 1.128 + {DMPAPER_ENV_DL, 110.0, 220.0, false}, 1.129 + {DMPAPER_ENV_C5, 162.0, 229.0, false}, 1.130 + {DMPAPER_ENV_C3, 324.0, 458.0, false}, 1.131 + {DMPAPER_ENV_C4, 229.0, 324.0, false}, 1.132 + {DMPAPER_ENV_C6, 114.0, 162.0, false}, 1.133 + {DMPAPER_ENV_C65, 114.0, 229.0, false}, 1.134 + {DMPAPER_ENV_B4, 250.0, 353.0, false}, 1.135 + {DMPAPER_ENV_B5, 176.0, 250.0, false}, 1.136 + {DMPAPER_ENV_B6, 176.0, 125.0, false}, 1.137 + {DMPAPER_ENV_ITALY, 110.0, 230.0, false}, 1.138 + {DMPAPER_ENV_MONARCH, 3.875, 7.5, true}, 1.139 + {DMPAPER_ENV_PERSONAL, 3.625, 6.5, true}, 1.140 + {DMPAPER_FANFOLD_US, 14.875, 11.0, true}, 1.141 + {DMPAPER_FANFOLD_STD_GERMAN, 8.5, 12.0, true}, 1.142 + {DMPAPER_FANFOLD_LGL_GERMAN, 8.5, 13.0, true}, 1.143 +}; 1.144 +const int32_t kNumPaperSizes = 41; 1.145 + 1.146 +//---------------------------------------------------------------------------------- 1.147 +nsDeviceContextSpecWin::nsDeviceContextSpecWin() 1.148 +{ 1.149 + mDriverName = nullptr; 1.150 + mDeviceName = nullptr; 1.151 + mDevMode = nullptr; 1.152 + 1.153 +} 1.154 + 1.155 + 1.156 +//---------------------------------------------------------------------------------- 1.157 + 1.158 +NS_IMPL_ISUPPORTS(nsDeviceContextSpecWin, nsIDeviceContextSpec) 1.159 + 1.160 +nsDeviceContextSpecWin::~nsDeviceContextSpecWin() 1.161 +{ 1.162 + SetDeviceName(nullptr); 1.163 + SetDriverName(nullptr); 1.164 + SetDevMode(nullptr); 1.165 + 1.166 + nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(mPrintSettings)); 1.167 + if (psWin) { 1.168 + psWin->SetDeviceName(nullptr); 1.169 + psWin->SetDriverName(nullptr); 1.170 + psWin->SetDevMode(nullptr); 1.171 + } 1.172 + 1.173 + // Free them, we won't need them for a while 1.174 + GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.175 +} 1.176 + 1.177 + 1.178 +//------------------------------------------------------------------ 1.179 +// helper 1.180 +static char16_t * GetDefaultPrinterNameFromGlobalPrinters() 1.181 +{ 1.182 + nsAutoString printerName; 1.183 + GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName); 1.184 + return ToNewUnicode(printerName); 1.185 +} 1.186 + 1.187 +//---------------------------------------------------------------------------------- 1.188 +NS_IMETHODIMP nsDeviceContextSpecWin::Init(nsIWidget* aWidget, 1.189 + nsIPrintSettings* aPrintSettings, 1.190 + bool aIsPrintPreview) 1.191 +{ 1.192 + mPrintSettings = aPrintSettings; 1.193 + 1.194 + nsresult rv = NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; 1.195 + if (aPrintSettings) { 1.196 + nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings)); 1.197 + if (psWin) { 1.198 + char16_t* deviceName; 1.199 + char16_t* driverName; 1.200 + psWin->GetDeviceName(&deviceName); // creates new memory (makes a copy) 1.201 + psWin->GetDriverName(&driverName); // creates new memory (makes a copy) 1.202 + 1.203 + LPDEVMODEW devMode; 1.204 + psWin->GetDevMode(&devMode); // creates new memory (makes a copy) 1.205 + 1.206 + if (deviceName && driverName && devMode) { 1.207 + // Scaling is special, it is one of the few 1.208 + // devMode items that we control in layout 1.209 + if (devMode->dmFields & DM_SCALE) { 1.210 + double scale = double(devMode->dmScale) / 100.0f; 1.211 + if (scale != 1.0) { 1.212 + aPrintSettings->SetScaling(scale); 1.213 + devMode->dmScale = 100; 1.214 + } 1.215 + } 1.216 + 1.217 + SetDeviceName(deviceName); 1.218 + SetDriverName(driverName); 1.219 + SetDevMode(devMode); 1.220 + 1.221 + // clean up 1.222 + free(deviceName); 1.223 + free(driverName); 1.224 + 1.225 + return NS_OK; 1.226 + } else { 1.227 + PR_PL(("***** nsDeviceContextSpecWin::Init - deviceName/driverName/devMode was NULL!\n")); 1.228 + if (deviceName) free(deviceName); 1.229 + if (driverName) free(driverName); 1.230 + if (devMode) ::HeapFree(::GetProcessHeap(), 0, devMode); 1.231 + } 1.232 + } 1.233 + } else { 1.234 + PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n")); 1.235 + } 1.236 + 1.237 + // Get the Print Name to be used 1.238 + char16_t * printerName = nullptr; 1.239 + if (mPrintSettings) { 1.240 + mPrintSettings->GetPrinterName(&printerName); 1.241 + } 1.242 + 1.243 + // If there is no name then use the default printer 1.244 + if (!printerName || (printerName && !*printerName)) { 1.245 + printerName = GetDefaultPrinterNameFromGlobalPrinters(); 1.246 + } 1.247 + 1.248 + NS_ASSERTION(printerName, "We have to have a printer name"); 1.249 + if (!printerName || !*printerName) return rv; 1.250 + 1.251 + return GetDataFromPrinter(printerName, mPrintSettings); 1.252 +} 1.253 + 1.254 +//---------------------------------------------------------- 1.255 +// Helper Function - Free and reallocate the string 1.256 +static void CleanAndCopyString(wchar_t*& aStr, const wchar_t* aNewStr) 1.257 +{ 1.258 + if (aStr != nullptr) { 1.259 + if (aNewStr != nullptr && wcslen(aStr) > wcslen(aNewStr)) { // reuse it if we can 1.260 + wcscpy(aStr, aNewStr); 1.261 + return; 1.262 + } else { 1.263 + PR_Free(aStr); 1.264 + aStr = nullptr; 1.265 + } 1.266 + } 1.267 + 1.268 + if (nullptr != aNewStr) { 1.269 + aStr = (wchar_t *)PR_Malloc(sizeof(wchar_t)*(wcslen(aNewStr) + 1)); 1.270 + wcscpy(aStr, aNewStr); 1.271 + } 1.272 +} 1.273 + 1.274 +NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface) 1.275 +{ 1.276 + NS_ASSERTION(mDevMode, "DevMode can't be NULL here"); 1.277 + 1.278 + nsRefPtr<gfxASurface> newSurface; 1.279 + 1.280 + int16_t outputFormat = 0; 1.281 + if (mPrintSettings) { 1.282 + mPrintSettings->GetOutputFormat(&outputFormat); 1.283 + } 1.284 + 1.285 + if (outputFormat == nsIPrintSettings::kOutputFormatPDF) { 1.286 + nsXPIDLString filename; 1.287 + mPrintSettings->GetToFileName(getter_Copies(filename)); 1.288 + 1.289 + double width, height; 1.290 + mPrintSettings->GetEffectivePageSize(&width, &height); 1.291 + // convert twips to points 1.292 + width /= TWIPS_PER_POINT_FLOAT; 1.293 + height /= TWIPS_PER_POINT_FLOAT; 1.294 + 1.295 + nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1"); 1.296 + nsresult rv = file->InitWithPath(filename); 1.297 + if (NS_FAILED(rv)) 1.298 + return rv; 1.299 + 1.300 + nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); 1.301 + rv = stream->Init(file, -1, -1, 0); 1.302 + if (NS_FAILED(rv)) 1.303 + return rv; 1.304 + 1.305 + newSurface = new gfxPDFSurface(stream, gfxSize(width, height)); 1.306 + } else { 1.307 + if (mDevMode) { 1.308 + NS_WARN_IF_FALSE(mDriverName, "No driver!"); 1.309 + HDC dc = ::CreateDCW(mDriverName, mDeviceName, nullptr, mDevMode); 1.310 + 1.311 + // have this surface take over ownership of this DC 1.312 + newSurface = new gfxWindowsSurface(dc, gfxWindowsSurface::FLAG_TAKE_DC | gfxWindowsSurface::FLAG_FOR_PRINTING); 1.313 + } 1.314 + } 1.315 + 1.316 + if (newSurface) { 1.317 + *surface = newSurface; 1.318 + NS_ADDREF(*surface); 1.319 + return NS_OK; 1.320 + } 1.321 + 1.322 + *surface = nullptr; 1.323 + return NS_ERROR_FAILURE; 1.324 +} 1.325 + 1.326 +//---------------------------------------------------------------------------------- 1.327 +void nsDeviceContextSpecWin::SetDeviceName(char16ptr_t aDeviceName) 1.328 +{ 1.329 + CleanAndCopyString(mDeviceName, aDeviceName); 1.330 +} 1.331 + 1.332 +//---------------------------------------------------------------------------------- 1.333 +void nsDeviceContextSpecWin::SetDriverName(char16ptr_t aDriverName) 1.334 +{ 1.335 + CleanAndCopyString(mDriverName, aDriverName); 1.336 +} 1.337 + 1.338 +//---------------------------------------------------------------------------------- 1.339 +void nsDeviceContextSpecWin::SetDevMode(LPDEVMODEW aDevMode) 1.340 +{ 1.341 + if (mDevMode) { 1.342 + ::HeapFree(::GetProcessHeap(), 0, mDevMode); 1.343 + } 1.344 + 1.345 + mDevMode = aDevMode; 1.346 +} 1.347 + 1.348 +//------------------------------------------------------------------ 1.349 +void 1.350 +nsDeviceContextSpecWin::GetDevMode(LPDEVMODEW &aDevMode) 1.351 +{ 1.352 + aDevMode = mDevMode; 1.353 +} 1.354 + 1.355 +//---------------------------------------------------------------------------------- 1.356 +// Map an incoming size to a Windows Native enum in the DevMode 1.357 +static void 1.358 +MapPaperSizeToNativeEnum(LPDEVMODEW aDevMode, 1.359 + int16_t aType, 1.360 + double aW, 1.361 + double aH) 1.362 +{ 1.363 + 1.364 +#ifdef DEBUG_rods 1.365 + BOOL doingOrientation = aDevMode->dmFields & DM_ORIENTATION; 1.366 + BOOL doingPaperSize = aDevMode->dmFields & DM_PAPERSIZE; 1.367 + BOOL doingPaperLength = aDevMode->dmFields & DM_PAPERLENGTH; 1.368 + BOOL doingPaperWidth = aDevMode->dmFields & DM_PAPERWIDTH; 1.369 +#endif 1.370 + 1.371 + for (int32_t i=0;i<kNumPaperSizes;i++) { 1.372 + if (kPaperSizes[i].mWidth == aW && kPaperSizes[i].mHeight == aH) { 1.373 + aDevMode->dmPaperSize = kPaperSizes[i].mPaperSize; 1.374 + aDevMode->dmFields &= ~DM_PAPERLENGTH; 1.375 + aDevMode->dmFields &= ~DM_PAPERWIDTH; 1.376 + aDevMode->dmFields |= DM_PAPERSIZE; 1.377 + return; 1.378 + } 1.379 + } 1.380 + 1.381 + short width = 0; 1.382 + short height = 0; 1.383 + if (aType == nsIPrintSettings::kPaperSizeInches) { 1.384 + width = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aW))) / 10); 1.385 + height = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aH))) / 10); 1.386 + 1.387 + } else if (aType == nsIPrintSettings::kPaperSizeMillimeters) { 1.388 + width = short(aW / 10.0); 1.389 + height = short(aH / 10.0); 1.390 + } else { 1.391 + return; // don't set anything 1.392 + } 1.393 + 1.394 + // width and height is in 1.395 + aDevMode->dmPaperSize = 0; 1.396 + aDevMode->dmPaperWidth = width; 1.397 + aDevMode->dmPaperLength = height; 1.398 + 1.399 + aDevMode->dmFields |= DM_PAPERSIZE; 1.400 + aDevMode->dmFields |= DM_PAPERLENGTH; 1.401 + aDevMode->dmFields |= DM_PAPERWIDTH; 1.402 +} 1.403 + 1.404 +//---------------------------------------------------------------------------------- 1.405 +// Setup Paper Size & Orientation options into the DevMode 1.406 +// 1.407 +static void 1.408 +SetupDevModeFromSettings(LPDEVMODEW aDevMode, nsIPrintSettings* aPrintSettings) 1.409 +{ 1.410 + // Setup paper size 1.411 + if (aPrintSettings) { 1.412 + int16_t type; 1.413 + aPrintSettings->GetPaperSizeType(&type); 1.414 + if (type == nsIPrintSettings::kPaperSizeNativeData) { 1.415 + int16_t paperEnum; 1.416 + aPrintSettings->GetPaperData(&paperEnum); 1.417 + aDevMode->dmPaperSize = paperEnum; 1.418 + aDevMode->dmFields &= ~DM_PAPERLENGTH; 1.419 + aDevMode->dmFields &= ~DM_PAPERWIDTH; 1.420 + aDevMode->dmFields |= DM_PAPERSIZE; 1.421 + } else { 1.422 + int16_t unit; 1.423 + double width, height; 1.424 + aPrintSettings->GetPaperSizeUnit(&unit); 1.425 + aPrintSettings->GetPaperWidth(&width); 1.426 + aPrintSettings->GetPaperHeight(&height); 1.427 + MapPaperSizeToNativeEnum(aDevMode, unit, width, height); 1.428 + } 1.429 + 1.430 + // Setup Orientation 1.431 + int32_t orientation; 1.432 + aPrintSettings->GetOrientation(&orientation); 1.433 + aDevMode->dmOrientation = orientation == nsIPrintSettings::kPortraitOrientation?DMORIENT_PORTRAIT:DMORIENT_LANDSCAPE; 1.434 + aDevMode->dmFields |= DM_ORIENTATION; 1.435 + 1.436 + // Setup Number of Copies 1.437 + int32_t copies; 1.438 + aPrintSettings->GetNumCopies(&copies); 1.439 + aDevMode->dmCopies = copies; 1.440 + aDevMode->dmFields |= DM_COPIES; 1.441 + } 1.442 + 1.443 +} 1.444 + 1.445 +#define DISPLAY_LAST_ERROR 1.446 + 1.447 +//---------------------------------------------------------------------------------- 1.448 +// Setup the object's data member with the selected printer's data 1.449 +nsresult 1.450 +nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings* aPS) 1.451 +{ 1.452 + nsresult rv = NS_ERROR_FAILURE; 1.453 + 1.454 + if (!GlobalPrinters::GetInstance()->PrintersAreAllocated()) { 1.455 + rv = GlobalPrinters::GetInstance()->EnumeratePrinterList(); 1.456 + if (NS_FAILED(rv)) { 1.457 + PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't enumerate printers!\n")); 1.458 + DISPLAY_LAST_ERROR 1.459 + } 1.460 + NS_ENSURE_SUCCESS(rv, rv); 1.461 + } 1.462 + 1.463 + HANDLE hPrinter = nullptr; 1.464 + wchar_t *name = (wchar_t*)aName; // Windows APIs use non-const name argument 1.465 + 1.466 + BOOL status = ::OpenPrinterW(name, &hPrinter, nullptr); 1.467 + if (status) { 1.468 + 1.469 + LPDEVMODEW pDevMode; 1.470 + DWORD dwNeeded, dwRet; 1.471 + 1.472 + // Allocate a buffer of the correct size. 1.473 + dwNeeded = ::DocumentPropertiesW(nullptr, hPrinter, name, nullptr, nullptr, 0); 1.474 + 1.475 + pDevMode = (LPDEVMODEW)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded); 1.476 + if (!pDevMode) return NS_ERROR_FAILURE; 1.477 + 1.478 + // Get the default DevMode for the printer and modify it for our needs. 1.479 + dwRet = DocumentPropertiesW(nullptr, hPrinter, name, 1.480 + pDevMode, nullptr, DM_OUT_BUFFER); 1.481 + 1.482 + if (dwRet == IDOK && aPS) { 1.483 + SetupDevModeFromSettings(pDevMode, aPS); 1.484 + // Sets back the changes we made to the DevMode into the Printer Driver 1.485 + dwRet = ::DocumentPropertiesW(nullptr, hPrinter, name, 1.486 + pDevMode, pDevMode, 1.487 + DM_IN_BUFFER | DM_OUT_BUFFER); 1.488 + } 1.489 + 1.490 + if (dwRet != IDOK) { 1.491 + ::HeapFree(::GetProcessHeap(), 0, pDevMode); 1.492 + ::ClosePrinter(hPrinter); 1.493 + PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - DocumentProperties call failed code: %d/0x%x\n", dwRet, dwRet)); 1.494 + DISPLAY_LAST_ERROR 1.495 + return NS_ERROR_FAILURE; 1.496 + } 1.497 + 1.498 + SetDevMode(pDevMode); // cache the pointer and takes responsibility for the memory 1.499 + 1.500 + SetDeviceName(aName); 1.501 + 1.502 + SetDriverName(L"WINSPOOL"); 1.503 + 1.504 + ::ClosePrinter(hPrinter); 1.505 + rv = NS_OK; 1.506 + } else { 1.507 + rv = NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND; 1.508 + PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't open printer: [%s]\n", NS_ConvertUTF16toUTF8(aName).get())); 1.509 + DISPLAY_LAST_ERROR 1.510 + } 1.511 + return rv; 1.512 +} 1.513 + 1.514 +//---------------------------------------------------------------------------------- 1.515 +// Setup Paper Size options into the DevMode 1.516 +// 1.517 +// When using a data member it may be a HGLOCAL or LPDEVMODE 1.518 +// if it is a HGLOBAL then we need to "lock" it to get the LPDEVMODE 1.519 +// and unlock it when we are done. 1.520 +void 1.521 +nsDeviceContextSpecWin::SetupPaperInfoFromSettings() 1.522 +{ 1.523 + LPDEVMODEW devMode; 1.524 + 1.525 + GetDevMode(devMode); 1.526 + NS_ASSERTION(devMode, "DevMode can't be NULL here"); 1.527 + if (devMode) { 1.528 + SetupDevModeFromSettings(devMode, mPrintSettings); 1.529 + } 1.530 +} 1.531 + 1.532 +//---------------------------------------------------------------------------------- 1.533 +// Helper Function - Free and reallocate the string 1.534 +nsresult 1.535 +nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings, 1.536 + LPDEVMODEW aDevMode) 1.537 +{ 1.538 + if (aPrintSettings == nullptr) { 1.539 + return NS_ERROR_FAILURE; 1.540 + } 1.541 + aPrintSettings->SetIsInitializedFromPrinter(true); 1.542 + 1.543 + BOOL doingNumCopies = aDevMode->dmFields & DM_COPIES; 1.544 + BOOL doingOrientation = aDevMode->dmFields & DM_ORIENTATION; 1.545 + BOOL doingPaperSize = aDevMode->dmFields & DM_PAPERSIZE; 1.546 + BOOL doingPaperLength = aDevMode->dmFields & DM_PAPERLENGTH; 1.547 + BOOL doingPaperWidth = aDevMode->dmFields & DM_PAPERWIDTH; 1.548 + 1.549 + if (doingOrientation) { 1.550 + int32_t orientation = aDevMode->dmOrientation == DMORIENT_PORTRAIT? 1.551 + int32_t(nsIPrintSettings::kPortraitOrientation):nsIPrintSettings::kLandscapeOrientation; 1.552 + aPrintSettings->SetOrientation(orientation); 1.553 + } 1.554 + 1.555 + // Setup Number of Copies 1.556 + if (doingNumCopies) { 1.557 + aPrintSettings->SetNumCopies(int32_t(aDevMode->dmCopies)); 1.558 + } 1.559 + 1.560 + if (aDevMode->dmFields & DM_SCALE) { 1.561 + double scale = double(aDevMode->dmScale) / 100.0f; 1.562 + if (scale != 1.0) { 1.563 + aPrintSettings->SetScaling(scale); 1.564 + aDevMode->dmScale = 100; 1.565 + // To turn this on you must change where the mPrt->mShrinkToFit is being set in the DocumentViewer 1.566 + //aPrintSettings->SetShrinkToFit(false); 1.567 + } 1.568 + } 1.569 + 1.570 + if (doingPaperSize) { 1.571 + aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeNativeData); 1.572 + aPrintSettings->SetPaperData(aDevMode->dmPaperSize); 1.573 + for (int32_t i=0;i<kNumPaperSizes;i++) { 1.574 + if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) { 1.575 + aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches 1.576 + ?int16_t(nsIPrintSettings::kPaperSizeInches):nsIPrintSettings::kPaperSizeMillimeters); 1.577 + break; 1.578 + } 1.579 + } 1.580 + 1.581 + } else if (doingPaperLength && doingPaperWidth) { 1.582 + bool found = false; 1.583 + for (int32_t i=0;i<kNumPaperSizes;i++) { 1.584 + if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) { 1.585 + aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined); 1.586 + aPrintSettings->SetPaperWidth(kPaperSizes[i].mWidth); 1.587 + aPrintSettings->SetPaperHeight(kPaperSizes[i].mHeight); 1.588 + aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches 1.589 + ?int16_t(nsIPrintSettings::kPaperSizeInches):nsIPrintSettings::kPaperSizeMillimeters); 1.590 + found = true; 1.591 + break; 1.592 + } 1.593 + } 1.594 + if (!found) { 1.595 + return NS_ERROR_FAILURE; 1.596 + } 1.597 + } else { 1.598 + return NS_ERROR_FAILURE; 1.599 + } 1.600 + return NS_OK; 1.601 +} 1.602 + 1.603 +//*********************************************************** 1.604 +// Printer Enumerator 1.605 +//*********************************************************** 1.606 +nsPrinterEnumeratorWin::nsPrinterEnumeratorWin() 1.607 +{ 1.608 +} 1.609 + 1.610 +nsPrinterEnumeratorWin::~nsPrinterEnumeratorWin() 1.611 +{ 1.612 + // Do not free printers here 1.613 + // GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.614 +} 1.615 + 1.616 +NS_IMPL_ISUPPORTS(nsPrinterEnumeratorWin, nsIPrinterEnumerator) 1.617 + 1.618 +//---------------------------------------------------------------------------------- 1.619 +// Return the Default Printer name 1.620 +/* readonly attribute wstring defaultPrinterName; */ 1.621 +NS_IMETHODIMP 1.622 +nsPrinterEnumeratorWin::GetDefaultPrinterName(char16_t * *aDefaultPrinterName) 1.623 +{ 1.624 + NS_ENSURE_ARG_POINTER(aDefaultPrinterName); 1.625 + 1.626 + *aDefaultPrinterName = GetDefaultPrinterNameFromGlobalPrinters(); // helper 1.627 + 1.628 + return NS_OK; 1.629 +} 1.630 + 1.631 +/* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */ 1.632 +NS_IMETHODIMP 1.633 +nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings) 1.634 +{ 1.635 + NS_ENSURE_ARG_POINTER(aPrinterName); 1.636 + NS_ENSURE_ARG_POINTER(aPrintSettings); 1.637 + 1.638 + if (!*aPrinterName) { 1.639 + return NS_OK; 1.640 + } 1.641 + 1.642 + nsRefPtr<nsDeviceContextSpecWin> devSpecWin = new nsDeviceContextSpecWin(); 1.643 + if (!devSpecWin) return NS_ERROR_OUT_OF_MEMORY; 1.644 + 1.645 + if (NS_FAILED(GlobalPrinters::GetInstance()->EnumeratePrinterList())) { 1.646 + return NS_ERROR_FAILURE; 1.647 + } 1.648 + 1.649 + devSpecWin->GetDataFromPrinter(aPrinterName); 1.650 + 1.651 + LPDEVMODEW devmode; 1.652 + devSpecWin->GetDevMode(devmode); 1.653 + NS_ASSERTION(devmode, "DevMode can't be NULL here"); 1.654 + if (devmode) { 1.655 + aPrintSettings->SetPrinterName(aPrinterName); 1.656 + nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(aPrintSettings, devmode); 1.657 + } 1.658 + 1.659 + // Free them, we won't need them for a while 1.660 + GlobalPrinters::GetInstance()->FreeGlobalPrinters(); 1.661 + return NS_OK; 1.662 +} 1.663 + 1.664 + 1.665 +//---------------------------------------------------------------------------------- 1.666 +// Enumerate all the Printers from the global array and pass their 1.667 +// names back (usually to script) 1.668 +NS_IMETHODIMP 1.669 +nsPrinterEnumeratorWin::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList) 1.670 +{ 1.671 + NS_ENSURE_ARG_POINTER(aPrinterNameList); 1.672 + *aPrinterNameList = nullptr; 1.673 + 1.674 + nsresult rv = GlobalPrinters::GetInstance()->EnumeratePrinterList(); 1.675 + if (NS_FAILED(rv)) { 1.676 + PR_PL(("***** nsDeviceContextSpecWin::GetPrinterNameList - Couldn't enumerate printers!\n")); 1.677 + return rv; 1.678 + } 1.679 + 1.680 + uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters(); 1.681 + nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters); 1.682 + if (!printers) 1.683 + return NS_ERROR_OUT_OF_MEMORY; 1.684 + 1.685 + uint32_t printerInx = 0; 1.686 + while( printerInx < numPrinters ) { 1.687 + LPWSTR name = GlobalPrinters::GetInstance()->GetItemFromList(printerInx++); 1.688 + printers->AppendElement(nsDependentString(name)); 1.689 + } 1.690 + 1.691 + return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); 1.692 +} 1.693 + 1.694 +//---------------------------------------------------------------------------------- 1.695 +// Display the AdvancedDocumentProperties for the selected Printer 1.696 +NS_IMETHODIMP nsPrinterEnumeratorWin::DisplayPropertiesDlg(const char16_t *aPrinterName, nsIPrintSettings* aPrintSettings) 1.697 +{ 1.698 + // Implementation removed because it is unused 1.699 + return NS_OK; 1.700 +} 1.701 + 1.702 +//---------------------------------------------------------------------------------- 1.703 +//-- Global Printers 1.704 +//---------------------------------------------------------------------------------- 1.705 + 1.706 +//---------------------------------------------------------------------------------- 1.707 +// THe array hold the name and port for each printer 1.708 +void 1.709 +GlobalPrinters::ReallocatePrinters() 1.710 +{ 1.711 + if (PrintersAreAllocated()) { 1.712 + FreeGlobalPrinters(); 1.713 + } 1.714 + mPrinters = new nsTArray<LPWSTR>(); 1.715 + NS_ASSERTION(mPrinters, "Printers Array is NULL!"); 1.716 +} 1.717 + 1.718 +//---------------------------------------------------------------------------------- 1.719 +void 1.720 +GlobalPrinters::FreeGlobalPrinters() 1.721 +{ 1.722 + if (mPrinters != nullptr) { 1.723 + for (uint32_t i=0;i<mPrinters->Length();i++) { 1.724 + free(mPrinters->ElementAt(i)); 1.725 + } 1.726 + delete mPrinters; 1.727 + mPrinters = nullptr; 1.728 + } 1.729 +} 1.730 + 1.731 +//---------------------------------------------------------------------------------- 1.732 +nsresult 1.733 +GlobalPrinters::EnumerateNativePrinters() 1.734 +{ 1.735 + nsresult rv = NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; 1.736 + PR_PL(("-----------------------\n")); 1.737 + PR_PL(("EnumerateNativePrinters\n")); 1.738 + 1.739 + WCHAR szDefaultPrinterName[1024]; 1.740 + DWORD status = GetProfileStringW(L"devices", 0, L",", 1.741 + szDefaultPrinterName, 1.742 + ArrayLength(szDefaultPrinterName)); 1.743 + if (status > 0) { 1.744 + DWORD count = 0; 1.745 + LPWSTR sPtr = szDefaultPrinterName; 1.746 + LPWSTR ePtr = szDefaultPrinterName + status; 1.747 + LPWSTR prvPtr = sPtr; 1.748 + while (sPtr < ePtr) { 1.749 + if (*sPtr == 0) { 1.750 + LPWSTR name = wcsdup(prvPtr); 1.751 + mPrinters->AppendElement(name); 1.752 + PR_PL(("Printer Name: %s\n", prvPtr)); 1.753 + prvPtr = sPtr+1; 1.754 + count++; 1.755 + } 1.756 + sPtr++; 1.757 + } 1.758 + rv = NS_OK; 1.759 + } 1.760 + PR_PL(("-----------------------\n")); 1.761 + return rv; 1.762 +} 1.763 + 1.764 +//------------------------------------------------------------------ 1.765 +// Uses the GetProfileString to get the default printer from the registry 1.766 +void 1.767 +GlobalPrinters::GetDefaultPrinterName(nsString& aDefaultPrinterName) 1.768 +{ 1.769 + aDefaultPrinterName.Truncate(); 1.770 + WCHAR szDefaultPrinterName[1024]; 1.771 + DWORD status = GetProfileStringW(L"windows", L"device", 0, 1.772 + szDefaultPrinterName, 1.773 + ArrayLength(szDefaultPrinterName)); 1.774 + if (status > 0) { 1.775 + WCHAR comma = ','; 1.776 + LPWSTR sPtr = szDefaultPrinterName; 1.777 + while (*sPtr != comma && *sPtr != 0) 1.778 + sPtr++; 1.779 + if (*sPtr == comma) { 1.780 + *sPtr = 0; 1.781 + } 1.782 + aDefaultPrinterName = szDefaultPrinterName; 1.783 + } else { 1.784 + aDefaultPrinterName = EmptyString(); 1.785 + } 1.786 + 1.787 + PR_PL(("DEFAULT PRINTER [%s]\n", aDefaultPrinterName.get())); 1.788 +} 1.789 + 1.790 +//---------------------------------------------------------------------------------- 1.791 +// This goes and gets the list of available printers and puts 1.792 +// the default printer at the beginning of the list 1.793 +nsresult 1.794 +GlobalPrinters::EnumeratePrinterList() 1.795 +{ 1.796 + // reallocate and get a new list each time it is asked for 1.797 + // this deletes the list and re-allocates them 1.798 + ReallocatePrinters(); 1.799 + 1.800 + // any of these could only fail with an OUT_MEMORY_ERROR 1.801 + // PRINTER_ENUM_LOCAL should get the network printers on Win95 1.802 + nsresult rv = EnumerateNativePrinters(); 1.803 + if (NS_FAILED(rv)) return rv; 1.804 + 1.805 + // get the name of the default printer 1.806 + nsAutoString defPrinterName; 1.807 + GetDefaultPrinterName(defPrinterName); 1.808 + 1.809 + // put the default printer at the beginning of list 1.810 + if (!defPrinterName.IsEmpty()) { 1.811 + for (uint32_t i=0;i<mPrinters->Length();i++) { 1.812 + LPWSTR name = mPrinters->ElementAt(i); 1.813 + if (defPrinterName.Equals(name)) { 1.814 + if (i > 0) { 1.815 + LPWSTR ptr = mPrinters->ElementAt(0); 1.816 + mPrinters->ElementAt(0) = name; 1.817 + mPrinters->ElementAt(i) = ptr; 1.818 + } 1.819 + break; 1.820 + } 1.821 + } 1.822 + } 1.823 + 1.824 + // make sure we at least tried to get the printers 1.825 + if (!PrintersAreAllocated()) { 1.826 + PR_PL(("***** nsDeviceContextSpecWin::EnumeratePrinterList - Printers aren`t allocated\n")); 1.827 + return NS_ERROR_FAILURE; 1.828 + } 1.829 + 1.830 + return NS_OK; 1.831 +} 1.832 +