embedding/components/printingui/src/win/nsPrintDialogUtil.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 /* -------------------------------------------------------------------
michael@0 7 To Build This:
michael@0 8
michael@0 9 You need to add this to the the makefile.win in mozilla/content/base/src:
michael@0 10
michael@0 11 .\$(OBJDIR)\nsFlyOwnPrintDialog.obj \
michael@0 12
michael@0 13
michael@0 14 And this to the makefile.win in mozilla/content/build:
michael@0 15
michael@0 16 WIN_LIBS= \
michael@0 17 winspool.lib \
michael@0 18 comctl32.lib \
michael@0 19 comdlg32.lib
michael@0 20
michael@0 21 ---------------------------------------------------------------------- */
michael@0 22
michael@0 23 #define NOMINMAX 1
michael@0 24
michael@0 25 #include "plstr.h"
michael@0 26 #include <windows.h>
michael@0 27 #include <tchar.h>
michael@0 28
michael@0 29 #include <unknwn.h>
michael@0 30 #include <commdlg.h>
michael@0 31
michael@0 32 #include "nsIWebBrowserPrint.h"
michael@0 33 #include "nsString.h"
michael@0 34 #include "nsIServiceManager.h"
michael@0 35 #include "nsReadableUtils.h"
michael@0 36 #include "nsIPrintSettings.h"
michael@0 37 #include "nsIPrintSettingsWin.h"
michael@0 38 #include "nsIPrintOptions.h"
michael@0 39
michael@0 40 #include "nsRect.h"
michael@0 41
michael@0 42 #include "nsIPrefService.h"
michael@0 43 #include "nsIPrefBranch.h"
michael@0 44
michael@0 45 #include "nsCRT.h"
michael@0 46 #include "prenv.h" /* for PR_GetEnv */
michael@0 47
michael@0 48 #include <windows.h>
michael@0 49 #include <winspool.h>
michael@0 50
michael@0 51 // For Localization
michael@0 52 #include "nsIStringBundle.h"
michael@0 53
michael@0 54 // For NS_CopyUnicodeToNative
michael@0 55 #include "nsNativeCharsetUtils.h"
michael@0 56
michael@0 57 // This is for extending the dialog
michael@0 58 #include <dlgs.h>
michael@0 59
michael@0 60 // Default labels for the radio buttons
michael@0 61 static const char* kAsLaidOutOnScreenStr = "As &laid out on the screen";
michael@0 62 static const char* kTheSelectedFrameStr = "The selected &frame";
michael@0 63 static const char* kEachFrameSeparately = "&Each frame separately";
michael@0 64
michael@0 65
michael@0 66 //-----------------------------------------------
michael@0 67 // Global Data
michael@0 68 //-----------------------------------------------
michael@0 69 // Identifies which new radio btn was cliked on
michael@0 70 static UINT gFrameSelectedRadioBtn = 0;
michael@0 71
michael@0 72 // Indicates whether the native print dialog was successfully extended
michael@0 73 static bool gDialogWasExtended = false;
michael@0 74
michael@0 75 #define PRINTDLG_PROPERTIES "chrome://global/locale/printdialog.properties"
michael@0 76
michael@0 77 static HWND gParentWnd = nullptr;
michael@0 78
michael@0 79 //******************************************************
michael@0 80 // Define native paper sizes
michael@0 81 //******************************************************
michael@0 82 typedef struct {
michael@0 83 short mPaperSize; // native enum
michael@0 84 double mWidth;
michael@0 85 double mHeight;
michael@0 86 bool mIsInches;
michael@0 87 } NativePaperSizes;
michael@0 88
michael@0 89 // There are around 40 default print sizes defined by Windows
michael@0 90 const NativePaperSizes kPaperSizes[] = {
michael@0 91 {DMPAPER_LETTER, 8.5, 11.0, true},
michael@0 92 {DMPAPER_LEGAL, 8.5, 14.0, true},
michael@0 93 {DMPAPER_A4, 210.0, 297.0, false},
michael@0 94 {DMPAPER_TABLOID, 11.0, 17.0, true},
michael@0 95 {DMPAPER_LEDGER, 17.0, 11.0, true},
michael@0 96 {DMPAPER_STATEMENT, 5.5, 8.5, true},
michael@0 97 {DMPAPER_EXECUTIVE, 7.25, 10.5, true},
michael@0 98 {DMPAPER_A3, 297.0, 420.0, false},
michael@0 99 {DMPAPER_A5, 148.0, 210.0, false},
michael@0 100 {DMPAPER_CSHEET, 17.0, 22.0, true},
michael@0 101 {DMPAPER_DSHEET, 22.0, 34.0, true},
michael@0 102 {DMPAPER_ESHEET, 34.0, 44.0, true},
michael@0 103 {DMPAPER_LETTERSMALL, 8.5, 11.0, true},
michael@0 104 {DMPAPER_A4SMALL, 210.0, 297.0, false},
michael@0 105 {DMPAPER_B4, 250.0, 354.0, false},
michael@0 106 {DMPAPER_B5, 182.0, 257.0, false},
michael@0 107 {DMPAPER_FOLIO, 8.5, 13.0, true},
michael@0 108 {DMPAPER_QUARTO, 215.0, 275.0, false},
michael@0 109 {DMPAPER_10X14, 10.0, 14.0, true},
michael@0 110 {DMPAPER_11X17, 11.0, 17.0, true},
michael@0 111 {DMPAPER_NOTE, 8.5, 11.0, true},
michael@0 112 {DMPAPER_ENV_9, 3.875, 8.875, true},
michael@0 113 {DMPAPER_ENV_10, 40.125, 9.5, true},
michael@0 114 {DMPAPER_ENV_11, 4.5, 10.375, true},
michael@0 115 {DMPAPER_ENV_12, 4.75, 11.0, true},
michael@0 116 {DMPAPER_ENV_14, 5.0, 11.5, true},
michael@0 117 {DMPAPER_ENV_DL, 110.0, 220.0, false},
michael@0 118 {DMPAPER_ENV_C5, 162.0, 229.0, false},
michael@0 119 {DMPAPER_ENV_C3, 324.0, 458.0, false},
michael@0 120 {DMPAPER_ENV_C4, 229.0, 324.0, false},
michael@0 121 {DMPAPER_ENV_C6, 114.0, 162.0, false},
michael@0 122 {DMPAPER_ENV_C65, 114.0, 229.0, false},
michael@0 123 {DMPAPER_ENV_B4, 250.0, 353.0, false},
michael@0 124 {DMPAPER_ENV_B5, 176.0, 250.0, false},
michael@0 125 {DMPAPER_ENV_B6, 176.0, 125.0, false},
michael@0 126 {DMPAPER_ENV_ITALY, 110.0, 230.0, false},
michael@0 127 {DMPAPER_ENV_MONARCH, 3.875, 7.5, true},
michael@0 128 {DMPAPER_ENV_PERSONAL, 3.625, 6.5, true},
michael@0 129 {DMPAPER_FANFOLD_US, 14.875, 11.0, true},
michael@0 130 {DMPAPER_FANFOLD_STD_GERMAN, 8.5, 12.0, true},
michael@0 131 {DMPAPER_FANFOLD_LGL_GERMAN, 8.5, 13.0, true},
michael@0 132 };
michael@0 133 const int32_t kNumPaperSizes = 41;
michael@0 134
michael@0 135 //----------------------------------------------------------------------------------
michael@0 136 // Map an incoming size to a Windows Native enum in the DevMode
michael@0 137 static void
michael@0 138 MapPaperSizeToNativeEnum(LPDEVMODEW aDevMode,
michael@0 139 int16_t aType,
michael@0 140 double aW,
michael@0 141 double aH)
michael@0 142 {
michael@0 143
michael@0 144 #ifdef DEBUG_rods
michael@0 145 BOOL doingOrientation = aDevMode->dmFields & DM_ORIENTATION;
michael@0 146 BOOL doingPaperSize = aDevMode->dmFields & DM_PAPERSIZE;
michael@0 147 BOOL doingPaperLength = aDevMode->dmFields & DM_PAPERLENGTH;
michael@0 148 BOOL doingPaperWidth = aDevMode->dmFields & DM_PAPERWIDTH;
michael@0 149 #endif
michael@0 150
michael@0 151 const double kThreshold = 0.05;
michael@0 152 for (int32_t i=0;i<kNumPaperSizes;i++) {
michael@0 153 double width = kPaperSizes[i].mWidth;
michael@0 154 double height = kPaperSizes[i].mHeight;
michael@0 155 if (aW < width+kThreshold && aW > width-kThreshold &&
michael@0 156 aH < height+kThreshold && aH > height-kThreshold) {
michael@0 157 aDevMode->dmPaperSize = kPaperSizes[i].mPaperSize;
michael@0 158 aDevMode->dmFields &= ~DM_PAPERLENGTH;
michael@0 159 aDevMode->dmFields &= ~DM_PAPERWIDTH;
michael@0 160 aDevMode->dmFields |= DM_PAPERSIZE;
michael@0 161 return;
michael@0 162 }
michael@0 163 }
michael@0 164
michael@0 165 short width = 0;
michael@0 166 short height = 0;
michael@0 167 if (aType == nsIPrintSettings::kPaperSizeInches) {
michael@0 168 width = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aW))) / 10);
michael@0 169 height = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aH))) / 10);
michael@0 170
michael@0 171 } else if (aType == nsIPrintSettings::kPaperSizeMillimeters) {
michael@0 172 width = short(aW / 10.0);
michael@0 173 height = short(aH / 10.0);
michael@0 174 } else {
michael@0 175 return; // don't set anything
michael@0 176 }
michael@0 177
michael@0 178 // width and height is in
michael@0 179 aDevMode->dmPaperSize = 0;
michael@0 180 aDevMode->dmPaperWidth = width;
michael@0 181 aDevMode->dmPaperLength = height;
michael@0 182
michael@0 183 aDevMode->dmFields |= DM_PAPERSIZE;
michael@0 184 aDevMode->dmFields |= DM_PAPERLENGTH;
michael@0 185 aDevMode->dmFields |= DM_PAPERWIDTH;
michael@0 186 }
michael@0 187
michael@0 188 //----------------------------------------------------------------------------------
michael@0 189 // Setup Paper Size & Orientation options into the DevMode
michael@0 190 //
michael@0 191 static void
michael@0 192 SetupDevModeFromSettings(LPDEVMODEW aDevMode, nsIPrintSettings* aPrintSettings)
michael@0 193 {
michael@0 194 // Setup paper size
michael@0 195 if (aPrintSettings) {
michael@0 196 int16_t type;
michael@0 197 aPrintSettings->GetPaperSizeType(&type);
michael@0 198 if (type == nsIPrintSettings::kPaperSizeNativeData) {
michael@0 199 int16_t paperEnum;
michael@0 200 aPrintSettings->GetPaperData(&paperEnum);
michael@0 201 aDevMode->dmPaperSize = paperEnum;
michael@0 202 aDevMode->dmFields &= ~DM_PAPERLENGTH;
michael@0 203 aDevMode->dmFields &= ~DM_PAPERWIDTH;
michael@0 204 aDevMode->dmFields |= DM_PAPERSIZE;
michael@0 205 } else {
michael@0 206 int16_t unit;
michael@0 207 double width, height;
michael@0 208 aPrintSettings->GetPaperSizeUnit(&unit);
michael@0 209 aPrintSettings->GetPaperWidth(&width);
michael@0 210 aPrintSettings->GetPaperHeight(&height);
michael@0 211 MapPaperSizeToNativeEnum(aDevMode, unit, width, height);
michael@0 212 }
michael@0 213
michael@0 214 // Setup Orientation
michael@0 215 int32_t orientation;
michael@0 216 aPrintSettings->GetOrientation(&orientation);
michael@0 217 aDevMode->dmOrientation = orientation == nsIPrintSettings::kPortraitOrientation?DMORIENT_PORTRAIT:DMORIENT_LANDSCAPE;
michael@0 218 aDevMode->dmFields |= DM_ORIENTATION;
michael@0 219
michael@0 220 // Setup Number of Copies
michael@0 221 int32_t copies;
michael@0 222 aPrintSettings->GetNumCopies(&copies);
michael@0 223 aDevMode->dmCopies = copies;
michael@0 224 aDevMode->dmFields |= DM_COPIES;
michael@0 225
michael@0 226 }
michael@0 227
michael@0 228 }
michael@0 229
michael@0 230 //----------------------------------------------------------------------------------
michael@0 231 // Helper Function - Free and reallocate the string
michael@0 232 static nsresult
michael@0 233 SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings,
michael@0 234 LPDEVMODEW aDevMode)
michael@0 235 {
michael@0 236 if (aPrintSettings == nullptr) {
michael@0 237 return NS_ERROR_FAILURE;
michael@0 238 }
michael@0 239
michael@0 240 aPrintSettings->SetIsInitializedFromPrinter(true);
michael@0 241 if (aDevMode->dmFields & DM_ORIENTATION) {
michael@0 242 int32_t orientation = aDevMode->dmOrientation == DMORIENT_PORTRAIT?
michael@0 243 nsIPrintSettings::kPortraitOrientation:nsIPrintSettings::kLandscapeOrientation;
michael@0 244 aPrintSettings->SetOrientation(orientation);
michael@0 245 }
michael@0 246
michael@0 247 // Setup Number of Copies
michael@0 248 if (aDevMode->dmFields & DM_COPIES) {
michael@0 249 aPrintSettings->SetNumCopies(int32_t(aDevMode->dmCopies));
michael@0 250 }
michael@0 251
michael@0 252 // Scaling
michael@0 253 // Since we do the scaling, grab their value and reset back to 100
michael@0 254 if (aDevMode->dmFields & DM_SCALE) {
michael@0 255 double origScale = 1.0;
michael@0 256 aPrintSettings->GetScaling(&origScale);
michael@0 257 double scale = double(aDevMode->dmScale) / 100.0f;
michael@0 258 if (origScale == 1.0 || scale != 1.0) {
michael@0 259 aPrintSettings->SetScaling(scale);
michael@0 260 }
michael@0 261 aDevMode->dmScale = 100;
michael@0 262 // To turn this on you must change where the mPrt->mShrinkToFit is being set in the DocumentViewer
michael@0 263 //aPrintSettings->SetShrinkToFit(false);
michael@0 264 }
michael@0 265
michael@0 266 if (aDevMode->dmFields & DM_PAPERSIZE) {
michael@0 267 aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeNativeData);
michael@0 268 aPrintSettings->SetPaperData(aDevMode->dmPaperSize);
michael@0 269 for (int32_t i=0;i<kNumPaperSizes;i++) {
michael@0 270 if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) {
michael@0 271 aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches?nsIPrintSettings::kPaperSizeInches:nsIPrintSettings::kPaperSizeMillimeters);
michael@0 272 break;
michael@0 273 }
michael@0 274 }
michael@0 275
michael@0 276 } else if (aDevMode->dmFields & DM_PAPERLENGTH && aDevMode->dmFields & DM_PAPERWIDTH) {
michael@0 277 bool found = false;
michael@0 278 for (int32_t i=0;i<kNumPaperSizes;i++) {
michael@0 279 if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) {
michael@0 280 aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined);
michael@0 281 aPrintSettings->SetPaperWidth(kPaperSizes[i].mWidth);
michael@0 282 aPrintSettings->SetPaperHeight(kPaperSizes[i].mHeight);
michael@0 283 aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches?nsIPrintSettings::kPaperSizeInches:nsIPrintSettings::kPaperSizeMillimeters);
michael@0 284 found = true;
michael@0 285 break;
michael@0 286 }
michael@0 287 }
michael@0 288 if (!found) {
michael@0 289 return NS_ERROR_FAILURE;
michael@0 290 }
michael@0 291 } else {
michael@0 292 return NS_ERROR_FAILURE;
michael@0 293 }
michael@0 294 return NS_OK;
michael@0 295 }
michael@0 296
michael@0 297 //----------------------------------------------------------------------------------
michael@0 298 // Return localized bundle for resource strings
michael@0 299 static nsresult
michael@0 300 GetLocalizedBundle(const char * aPropFileName, nsIStringBundle** aStrBundle)
michael@0 301 {
michael@0 302 NS_ENSURE_ARG_POINTER(aPropFileName);
michael@0 303 NS_ENSURE_ARG_POINTER(aStrBundle);
michael@0 304
michael@0 305 nsresult rv;
michael@0 306 nsCOMPtr<nsIStringBundle> bundle;
michael@0 307
michael@0 308
michael@0 309 // Create bundle
michael@0 310 nsCOMPtr<nsIStringBundleService> stringService =
michael@0 311 do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
michael@0 312 if (NS_SUCCEEDED(rv) && stringService) {
michael@0 313 rv = stringService->CreateBundle(aPropFileName, aStrBundle);
michael@0 314 }
michael@0 315
michael@0 316 return rv;
michael@0 317 }
michael@0 318
michael@0 319 //--------------------------------------------------------
michael@0 320 // Return localized string
michael@0 321 static nsresult
michael@0 322 GetLocalizedString(nsIStringBundle* aStrBundle, const char* aKey, nsString& oVal)
michael@0 323 {
michael@0 324 NS_ENSURE_ARG_POINTER(aStrBundle);
michael@0 325 NS_ENSURE_ARG_POINTER(aKey);
michael@0 326
michael@0 327 // Determine default label from string bundle
michael@0 328 nsXPIDLString valUni;
michael@0 329 nsAutoString key;
michael@0 330 key.AssignWithConversion(aKey);
michael@0 331 nsresult rv = aStrBundle->GetStringFromName(key.get(), getter_Copies(valUni));
michael@0 332 if (NS_SUCCEEDED(rv) && valUni) {
michael@0 333 oVal.Assign(valUni);
michael@0 334 } else {
michael@0 335 oVal.Truncate();
michael@0 336 }
michael@0 337 return rv;
michael@0 338 }
michael@0 339
michael@0 340 //--------------------------------------------------------
michael@0 341 // Set a multi-byte string in the control
michael@0 342 static void SetTextOnWnd(HWND aControl, const nsString& aStr)
michael@0 343 {
michael@0 344 nsAutoCString text;
michael@0 345 if (NS_SUCCEEDED(NS_CopyUnicodeToNative(aStr, text))) {
michael@0 346 ::SetWindowText(aControl, text.get());
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 //--------------------------------------------------------
michael@0 351 // Will get the control and localized string by "key"
michael@0 352 static void SetText(HWND aParent,
michael@0 353 UINT aId,
michael@0 354 nsIStringBundle* aStrBundle,
michael@0 355 const char* aKey)
michael@0 356 {
michael@0 357 HWND wnd = GetDlgItem (aParent, aId);
michael@0 358 if (!wnd) {
michael@0 359 return;
michael@0 360 }
michael@0 361 nsAutoString str;
michael@0 362 nsresult rv = GetLocalizedString(aStrBundle, aKey, str);
michael@0 363 if (NS_SUCCEEDED(rv)) {
michael@0 364 SetTextOnWnd(wnd, str);
michael@0 365 }
michael@0 366 }
michael@0 367
michael@0 368 //--------------------------------------------------------
michael@0 369 static void SetRadio(HWND aParent,
michael@0 370 UINT aId,
michael@0 371 bool aIsSet,
michael@0 372 bool isEnabled = true)
michael@0 373 {
michael@0 374 HWND wnd = ::GetDlgItem (aParent, aId);
michael@0 375 if (!wnd) {
michael@0 376 return;
michael@0 377 }
michael@0 378 if (!isEnabled) {
michael@0 379 ::EnableWindow(wnd, FALSE);
michael@0 380 return;
michael@0 381 }
michael@0 382 ::EnableWindow(wnd, TRUE);
michael@0 383 ::SendMessage(wnd, BM_SETCHECK, (WPARAM)aIsSet, (LPARAM)0);
michael@0 384 }
michael@0 385
michael@0 386 //--------------------------------------------------------
michael@0 387 static void SetRadioOfGroup(HWND aDlg, int aRadId)
michael@0 388 {
michael@0 389 int radioIds[] = {rad4, rad5, rad6};
michael@0 390 int numRads = 3;
michael@0 391
michael@0 392 for (int i=0;i<numRads;i++) {
michael@0 393 HWND radWnd = ::GetDlgItem(aDlg, radioIds[i]);
michael@0 394 if (radWnd != nullptr) {
michael@0 395 ::SendMessage(radWnd, BM_SETCHECK, (WPARAM)(radioIds[i] == aRadId), (LPARAM)0);
michael@0 396 }
michael@0 397 }
michael@0 398 }
michael@0 399
michael@0 400 //--------------------------------------------------------
michael@0 401 typedef struct {
michael@0 402 const char * mKeyStr;
michael@0 403 long mKeyId;
michael@0 404 } PropKeyInfo;
michael@0 405
michael@0 406 // These are the control ids used in the dialog and
michael@0 407 // defined by MS-Windows in commdlg.h
michael@0 408 static PropKeyInfo gAllPropKeys[] = {
michael@0 409 {"printFramesTitleWindows", grp3},
michael@0 410 {"asLaidOutWindows", rad4},
michael@0 411 {"selectedFrameWindows", rad5},
michael@0 412 {"separateFramesWindows", rad6},
michael@0 413 {nullptr, 0}};
michael@0 414
michael@0 415 //--------------------------------------------------------
michael@0 416 //--------------------------------------------------------
michael@0 417 //--------------------------------------------------------
michael@0 418 //--------------------------------------------------------
michael@0 419 // Get the absolute coords of the child windows relative
michael@0 420 // to its parent window
michael@0 421 static void GetLocalRect(HWND aWnd, RECT& aRect, HWND aParent)
michael@0 422 {
michael@0 423 ::GetWindowRect(aWnd, &aRect);
michael@0 424
michael@0 425 // MapWindowPoints converts screen coordinates to client coordinates.
michael@0 426 // It works correctly in both left-to-right and right-to-left windows.
michael@0 427 ::MapWindowPoints(nullptr, aParent, (LPPOINT)&aRect, 2);
michael@0 428 }
michael@0 429
michael@0 430 //--------------------------------------------------------
michael@0 431 // Show or Hide the control
michael@0 432 static void Show(HWND aWnd, bool bState)
michael@0 433 {
michael@0 434 if (aWnd) {
michael@0 435 ::ShowWindow(aWnd, bState?SW_SHOW:SW_HIDE);
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 //--------------------------------------------------------
michael@0 440 // Create a child window "control"
michael@0 441 static HWND CreateControl(LPCTSTR aType,
michael@0 442 DWORD aStyle,
michael@0 443 HINSTANCE aHInst,
michael@0 444 HWND aHdlg,
michael@0 445 int aId,
michael@0 446 const nsAString& aStr,
michael@0 447 const nsIntRect& aRect)
michael@0 448 {
michael@0 449 nsAutoCString str;
michael@0 450 if (NS_FAILED(NS_CopyUnicodeToNative(aStr, str)))
michael@0 451 return nullptr;
michael@0 452
michael@0 453 HWND hWnd = ::CreateWindow (aType, str.get(),
michael@0 454 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | aStyle,
michael@0 455 aRect.x, aRect.y, aRect.width, aRect.height,
michael@0 456 (HWND)aHdlg, (HMENU)(intptr_t)aId,
michael@0 457 aHInst, nullptr);
michael@0 458 if (hWnd == nullptr) return nullptr;
michael@0 459
michael@0 460 // get the native font for the dialog and
michael@0 461 // set it into the new control
michael@0 462 HFONT hFont = (HFONT)::SendMessage(aHdlg, WM_GETFONT, (WPARAM)0, (LPARAM)0);
michael@0 463 if (hFont != nullptr) {
michael@0 464 ::SendMessage(hWnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0);
michael@0 465 }
michael@0 466 return hWnd;
michael@0 467 }
michael@0 468
michael@0 469 //--------------------------------------------------------
michael@0 470 // Create a Radio Button
michael@0 471 static HWND CreateRadioBtn(HINSTANCE aHInst,
michael@0 472 HWND aHdlg,
michael@0 473 int aId,
michael@0 474 const char* aStr,
michael@0 475 const nsIntRect& aRect)
michael@0 476 {
michael@0 477 nsString cStr;
michael@0 478 cStr.AssignWithConversion(aStr);
michael@0 479 return CreateControl("BUTTON", BS_RADIOBUTTON, aHInst, aHdlg, aId, cStr, aRect);
michael@0 480 }
michael@0 481
michael@0 482 //--------------------------------------------------------
michael@0 483 // Create a Group Box
michael@0 484 static HWND CreateGroupBox(HINSTANCE aHInst,
michael@0 485 HWND aHdlg,
michael@0 486 int aId,
michael@0 487 const nsAString& aStr,
michael@0 488 const nsIntRect& aRect)
michael@0 489 {
michael@0 490 return CreateControl("BUTTON", BS_GROUPBOX, aHInst, aHdlg, aId, aStr, aRect);
michael@0 491 }
michael@0 492
michael@0 493 //--------------------------------------------------------
michael@0 494 // Localizes and initializes the radio buttons and group
michael@0 495 static void InitializeExtendedDialog(HWND hdlg, int16_t aHowToEnableFrameUI)
michael@0 496 {
michael@0 497 NS_ABORT_IF_FALSE(aHowToEnableFrameUI != nsIPrintSettings::kFrameEnableNone,
michael@0 498 "should not be called");
michael@0 499
michael@0 500 // Localize the new controls in the print dialog
michael@0 501 nsCOMPtr<nsIStringBundle> strBundle;
michael@0 502 if (NS_SUCCEEDED(GetLocalizedBundle(PRINTDLG_PROPERTIES, getter_AddRefs(strBundle)))) {
michael@0 503 int32_t i = 0;
michael@0 504 while (gAllPropKeys[i].mKeyStr != nullptr) {
michael@0 505 SetText(hdlg, gAllPropKeys[i].mKeyId, strBundle, gAllPropKeys[i].mKeyStr);
michael@0 506 i++;
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 // Set up radio buttons
michael@0 511 if (aHowToEnableFrameUI == nsIPrintSettings::kFrameEnableAll) {
michael@0 512 SetRadio(hdlg, rad4, false);
michael@0 513 SetRadio(hdlg, rad5, true);
michael@0 514 SetRadio(hdlg, rad6, false);
michael@0 515 // set default so user doesn't have to actually press on it
michael@0 516 gFrameSelectedRadioBtn = rad5;
michael@0 517
michael@0 518 } else { // nsIPrintSettings::kFrameEnableAsIsAndEach
michael@0 519 SetRadio(hdlg, rad4, false);
michael@0 520 SetRadio(hdlg, rad5, false, false);
michael@0 521 SetRadio(hdlg, rad6, true);
michael@0 522 // set default so user doesn't have to actually press on it
michael@0 523 gFrameSelectedRadioBtn = rad6;
michael@0 524 }
michael@0 525 }
michael@0 526
michael@0 527
michael@0 528 //--------------------------------------------------------
michael@0 529 // Special Hook Procedure for handling the print dialog messages
michael@0 530 static UINT CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
michael@0 531 {
michael@0 532
michael@0 533 if (uiMsg == WM_COMMAND) {
michael@0 534 UINT id = LOWORD(wParam);
michael@0 535 if (id == rad4 || id == rad5 || id == rad6) {
michael@0 536 gFrameSelectedRadioBtn = id;
michael@0 537 SetRadioOfGroup(hdlg, id);
michael@0 538 }
michael@0 539
michael@0 540 } else if (uiMsg == WM_INITDIALOG) {
michael@0 541 PRINTDLG * printDlg = (PRINTDLG *)lParam;
michael@0 542 if (printDlg == nullptr) return 0L;
michael@0 543
michael@0 544 int16_t howToEnableFrameUI = (int16_t)printDlg->lCustData;
michael@0 545 // don't add frame options if they would be disabled anyway
michael@0 546 // because there are no frames
michael@0 547 if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableNone)
michael@0 548 return TRUE;
michael@0 549
michael@0 550 HINSTANCE hInst = (HINSTANCE)::GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
michael@0 551 if (hInst == nullptr) return 0L;
michael@0 552
michael@0 553 // Start by getting the local rects of several of the controls
michael@0 554 // so we can calculate where the new controls are
michael@0 555 HWND wnd = ::GetDlgItem(hdlg, grp1);
michael@0 556 if (wnd == nullptr) return 0L;
michael@0 557 RECT dlgRect;
michael@0 558 GetLocalRect(wnd, dlgRect, hdlg);
michael@0 559
michael@0 560 wnd = ::GetDlgItem(hdlg, rad1); // this is the top control "All"
michael@0 561 if (wnd == nullptr) return 0L;
michael@0 562 RECT rad1Rect;
michael@0 563 GetLocalRect(wnd, rad1Rect, hdlg);
michael@0 564
michael@0 565 wnd = ::GetDlgItem(hdlg, rad2); // this is the bottom control "Selection"
michael@0 566 if (wnd == nullptr) return 0L;
michael@0 567 RECT rad2Rect;
michael@0 568 GetLocalRect(wnd, rad2Rect, hdlg);
michael@0 569
michael@0 570 wnd = ::GetDlgItem(hdlg, rad3); // this is the middle control "Pages"
michael@0 571 if (wnd == nullptr) return 0L;
michael@0 572 RECT rad3Rect;
michael@0 573 GetLocalRect(wnd, rad3Rect, hdlg);
michael@0 574
michael@0 575 HWND okWnd = ::GetDlgItem(hdlg, IDOK);
michael@0 576 if (okWnd == nullptr) return 0L;
michael@0 577 RECT okRect;
michael@0 578 GetLocalRect(okWnd, okRect, hdlg);
michael@0 579
michael@0 580 wnd = ::GetDlgItem(hdlg, grp4); // this is the "Print range" groupbox
michael@0 581 if (wnd == nullptr) return 0L;
michael@0 582 RECT prtRect;
michael@0 583 GetLocalRect(wnd, prtRect, hdlg);
michael@0 584
michael@0 585
michael@0 586 // calculate various different "gaps" for layout purposes
michael@0 587
michael@0 588 int rbGap = rad3Rect.top - rad1Rect.bottom; // gap between radiobtns
michael@0 589 int grpBotGap = dlgRect.bottom - rad2Rect.bottom; // gap from bottom rb to bottom of grpbox
michael@0 590 int grpGap = dlgRect.top - prtRect.bottom ; // gap between group boxes
michael@0 591 int top = dlgRect.bottom + grpGap;
michael@0 592 int radHgt = rad1Rect.bottom - rad1Rect.top + 1; // top of new group box
michael@0 593 int y = top+(rad1Rect.top-dlgRect.top); // starting pos of first radio
michael@0 594 int rbWidth = dlgRect.right - rad1Rect.left - 5; // measure from rb left to the edge of the groupbox
michael@0 595 // (5 is arbitrary)
michael@0 596 nsIntRect rect;
michael@0 597
michael@0 598 // Create and position the radio buttons
michael@0 599 //
michael@0 600 // If any one control cannot be created then
michael@0 601 // hide the others and bail out
michael@0 602 //
michael@0 603 rect.SetRect(rad1Rect.left, y, rbWidth,radHgt);
michael@0 604 HWND rad4Wnd = CreateRadioBtn(hInst, hdlg, rad4, kAsLaidOutOnScreenStr, rect);
michael@0 605 if (rad4Wnd == nullptr) return 0L;
michael@0 606 y += radHgt + rbGap;
michael@0 607
michael@0 608 rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
michael@0 609 HWND rad5Wnd = CreateRadioBtn(hInst, hdlg, rad5, kTheSelectedFrameStr, rect);
michael@0 610 if (rad5Wnd == nullptr) {
michael@0 611 Show(rad4Wnd, FALSE); // hide
michael@0 612 return 0L;
michael@0 613 }
michael@0 614 y += radHgt + rbGap;
michael@0 615
michael@0 616 rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
michael@0 617 HWND rad6Wnd = CreateRadioBtn(hInst, hdlg, rad6, kEachFrameSeparately, rect);
michael@0 618 if (rad6Wnd == nullptr) {
michael@0 619 Show(rad4Wnd, FALSE); // hide
michael@0 620 Show(rad5Wnd, FALSE); // hide
michael@0 621 return 0L;
michael@0 622 }
michael@0 623 y += radHgt + grpBotGap;
michael@0 624
michael@0 625 // Create and position the group box
michael@0 626 rect.SetRect (dlgRect.left, top, dlgRect.right-dlgRect.left+1, y-top+1);
michael@0 627 HWND grpBoxWnd = CreateGroupBox(hInst, hdlg, grp3, NS_LITERAL_STRING("Print Frame"), rect);
michael@0 628 if (grpBoxWnd == nullptr) {
michael@0 629 Show(rad4Wnd, FALSE); // hide
michael@0 630 Show(rad5Wnd, FALSE); // hide
michael@0 631 Show(rad6Wnd, FALSE); // hide
michael@0 632 return 0L;
michael@0 633 }
michael@0 634
michael@0 635 // Here we figure out the old height of the dlg
michael@0 636 // then figure its gap from the old grpbx to the bottom
michael@0 637 // then size the dlg
michael@0 638 RECT pr, cr;
michael@0 639 ::GetWindowRect(hdlg, &pr);
michael@0 640 ::GetClientRect(hdlg, &cr);
michael@0 641
michael@0 642 int dlgHgt = (cr.bottom - cr.top) + 1;
michael@0 643 int bottomGap = dlgHgt - okRect.bottom;
michael@0 644 pr.bottom += (dlgRect.bottom-dlgRect.top) + grpGap + 1 - (dlgHgt-dlgRect.bottom) + bottomGap;
michael@0 645
michael@0 646 ::SetWindowPos(hdlg, nullptr, pr.left, pr.top, pr.right-pr.left+1, pr.bottom-pr.top+1,
michael@0 647 SWP_NOMOVE|SWP_NOREDRAW|SWP_NOZORDER);
michael@0 648
michael@0 649 // figure out the new height of the dialog
michael@0 650 ::GetClientRect(hdlg, &cr);
michael@0 651 dlgHgt = (cr.bottom - cr.top) + 1;
michael@0 652
michael@0 653 // Reposition the OK and Cancel btns
michael@0 654 int okHgt = okRect.bottom - okRect.top + 1;
michael@0 655 ::SetWindowPos(okWnd, nullptr, okRect.left, dlgHgt-bottomGap-okHgt, 0, 0,
michael@0 656 SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
michael@0 657
michael@0 658 HWND cancelWnd = ::GetDlgItem(hdlg, IDCANCEL);
michael@0 659 if (cancelWnd == nullptr) return 0L;
michael@0 660
michael@0 661 RECT cancelRect;
michael@0 662 GetLocalRect(cancelWnd, cancelRect, hdlg);
michael@0 663 int cancelHgt = cancelRect.bottom - cancelRect.top + 1;
michael@0 664 ::SetWindowPos(cancelWnd, nullptr, cancelRect.left, dlgHgt-bottomGap-cancelHgt, 0, 0,
michael@0 665 SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
michael@0 666
michael@0 667 // localize and initialize the groupbox and radiobuttons
michael@0 668 InitializeExtendedDialog(hdlg, howToEnableFrameUI);
michael@0 669
michael@0 670 // Looks like we were able to extend the dialog
michael@0 671 gDialogWasExtended = true;
michael@0 672 return TRUE;
michael@0 673 }
michael@0 674 return 0L;
michael@0 675 }
michael@0 676
michael@0 677 //----------------------------------------------------------------------------------
michael@0 678 // Returns a Global Moveable Memory Handle to a DevMode
michael@0 679 // from the Printer by the name of aPrintName
michael@0 680 //
michael@0 681 // NOTE:
michael@0 682 // This function assumes that aPrintName has already been converted from
michael@0 683 // unicode
michael@0 684 //
michael@0 685 static HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS)
michael@0 686 {
michael@0 687 HGLOBAL hGlobalDevMode = nullptr;
michael@0 688
michael@0 689 HANDLE hPrinter = nullptr;
michael@0 690 // const cast kludge for silly Win32 api's
michael@0 691 LPWSTR printName = const_cast<wchar_t*>(static_cast<const wchar_t*>(aPrintName.get()));
michael@0 692 BOOL status = ::OpenPrinterW(printName, &hPrinter, nullptr);
michael@0 693 if (status) {
michael@0 694
michael@0 695 LPDEVMODEW pNewDevMode;
michael@0 696 DWORD dwNeeded, dwRet;
michael@0 697
michael@0 698 // Get the buffer size
michael@0 699 dwNeeded = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr, nullptr, 0);
michael@0 700 if (dwNeeded == 0) {
michael@0 701 return nullptr;
michael@0 702 }
michael@0 703
michael@0 704 // Allocate a buffer of the correct size.
michael@0 705 pNewDevMode = (LPDEVMODEW)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
michael@0 706 if (!pNewDevMode) return nullptr;
michael@0 707
michael@0 708 hGlobalDevMode = (HGLOBAL)::GlobalAlloc(GHND, dwNeeded);
michael@0 709 if (!hGlobalDevMode) {
michael@0 710 ::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
michael@0 711 return nullptr;
michael@0 712 }
michael@0 713
michael@0 714 dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, pNewDevMode, nullptr, DM_OUT_BUFFER);
michael@0 715
michael@0 716 if (dwRet != IDOK) {
michael@0 717 ::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
michael@0 718 ::GlobalFree(hGlobalDevMode);
michael@0 719 ::ClosePrinter(hPrinter);
michael@0 720 return nullptr;
michael@0 721 }
michael@0 722
michael@0 723 // Lock memory and copy contents from DEVMODE (current printer)
michael@0 724 // to Global Memory DEVMODE
michael@0 725 LPDEVMODEW devMode = (DEVMODEW *)::GlobalLock(hGlobalDevMode);
michael@0 726 if (devMode) {
michael@0 727 memcpy(devMode, pNewDevMode, dwNeeded);
michael@0 728 // Initialize values from the PrintSettings
michael@0 729 SetupDevModeFromSettings(devMode, aPS);
michael@0 730
michael@0 731 // Sets back the changes we made to the DevMode into the Printer Driver
michael@0 732 dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER);
michael@0 733 if (dwRet != IDOK) {
michael@0 734 ::GlobalUnlock(hGlobalDevMode);
michael@0 735 ::GlobalFree(hGlobalDevMode);
michael@0 736 ::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
michael@0 737 ::ClosePrinter(hPrinter);
michael@0 738 return nullptr;
michael@0 739 }
michael@0 740
michael@0 741 ::GlobalUnlock(hGlobalDevMode);
michael@0 742 } else {
michael@0 743 ::GlobalFree(hGlobalDevMode);
michael@0 744 hGlobalDevMode = nullptr;
michael@0 745 }
michael@0 746
michael@0 747 ::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
michael@0 748
michael@0 749 ::ClosePrinter(hPrinter);
michael@0 750
michael@0 751 } else {
michael@0 752 return nullptr;
michael@0 753 }
michael@0 754
michael@0 755 return hGlobalDevMode;
michael@0 756 }
michael@0 757
michael@0 758 //------------------------------------------------------------------
michael@0 759 // helper
michael@0 760 static void GetDefaultPrinterNameFromGlobalPrinters(nsXPIDLString &printerName)
michael@0 761 {
michael@0 762 nsCOMPtr<nsIPrinterEnumerator> prtEnum = do_GetService("@mozilla.org/gfx/printerenumerator;1");
michael@0 763 if (prtEnum) {
michael@0 764 prtEnum->GetDefaultPrinterName(getter_Copies(printerName));
michael@0 765 }
michael@0 766 }
michael@0 767
michael@0 768 // Determine whether we have a completely native dialog
michael@0 769 // or whether we cshould extend it
michael@0 770 static bool ShouldExtendPrintDialog()
michael@0 771 {
michael@0 772 nsresult rv;
michael@0 773 nsCOMPtr<nsIPrefService> prefs =
michael@0 774 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
michael@0 775 NS_ENSURE_SUCCESS(rv, true);
michael@0 776 nsCOMPtr<nsIPrefBranch> prefBranch;
michael@0 777 rv = prefs->GetBranch(nullptr, getter_AddRefs(prefBranch));
michael@0 778 NS_ENSURE_SUCCESS(rv, true);
michael@0 779
michael@0 780 bool result;
michael@0 781 rv = prefBranch->GetBoolPref("print.extend_native_print_dialog", &result);
michael@0 782 NS_ENSURE_SUCCESS(rv, true);
michael@0 783 return result;
michael@0 784 }
michael@0 785
michael@0 786 //------------------------------------------------------------------
michael@0 787 // Displays the native Print Dialog
michael@0 788 static nsresult
michael@0 789 ShowNativePrintDialog(HWND aHWnd,
michael@0 790 nsIPrintSettings* aPrintSettings)
michael@0 791 {
michael@0 792 //NS_ENSURE_ARG_POINTER(aHWnd);
michael@0 793 NS_ENSURE_ARG_POINTER(aPrintSettings);
michael@0 794
michael@0 795 gDialogWasExtended = false;
michael@0 796
michael@0 797 HGLOBAL hGlobalDevMode = nullptr;
michael@0 798 HGLOBAL hDevNames = nullptr;
michael@0 799
michael@0 800 // Get the Print Name to be used
michael@0 801 nsXPIDLString printerName;
michael@0 802 aPrintSettings->GetPrinterName(getter_Copies(printerName));
michael@0 803
michael@0 804 // If there is no name then use the default printer
michael@0 805 if (printerName.IsEmpty()) {
michael@0 806 GetDefaultPrinterNameFromGlobalPrinters(printerName);
michael@0 807 } else {
michael@0 808 HANDLE hPrinter = nullptr;
michael@0 809 if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())), &hPrinter, nullptr)) {
michael@0 810 // If the last used printer is not found, we should use default printer.
michael@0 811 GetDefaultPrinterNameFromGlobalPrinters(printerName);
michael@0 812 } else {
michael@0 813 ::ClosePrinter(hPrinter);
michael@0 814 }
michael@0 815 }
michael@0 816
michael@0 817 // Now create a DEVNAMES struct so the the dialog is initialized correctly.
michael@0 818
michael@0 819 uint32_t len = printerName.Length();
michael@0 820 hDevNames = (HGLOBAL)::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1) +
michael@0 821 sizeof(DEVNAMES));
michael@0 822 if (!hDevNames) {
michael@0 823 return NS_ERROR_OUT_OF_MEMORY;
michael@0 824 }
michael@0 825
michael@0 826 DEVNAMES* pDevNames = (DEVNAMES*)::GlobalLock(hDevNames);
michael@0 827 if (!pDevNames) {
michael@0 828 ::GlobalFree(hDevNames);
michael@0 829 return NS_ERROR_FAILURE;
michael@0 830 }
michael@0 831 pDevNames->wDriverOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
michael@0 832 pDevNames->wDeviceOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
michael@0 833 pDevNames->wOutputOffset = sizeof(DEVNAMES)/sizeof(wchar_t)+len;
michael@0 834 pDevNames->wDefault = 0;
michael@0 835
michael@0 836 memcpy(pDevNames+1, printerName, (len + 1) * sizeof(wchar_t));
michael@0 837 ::GlobalUnlock(hDevNames);
michael@0 838
michael@0 839 // Create a Moveable Memory Object that holds a new DevMode
michael@0 840 // from the Printer Name
michael@0 841 // The PRINTDLG.hDevMode requires that it be a moveable memory object
michael@0 842 // NOTE: We only need to free hGlobalDevMode when the dialog is cancelled
michael@0 843 // When the user prints, it comes back in the printdlg struct and
michael@0 844 // is used and cleaned up later
michael@0 845 hGlobalDevMode = CreateGlobalDevModeAndInit(printerName, aPrintSettings);
michael@0 846
michael@0 847 // Prepare to Display the Print Dialog
michael@0 848 PRINTDLGW prntdlg;
michael@0 849 memset(&prntdlg, 0, sizeof(PRINTDLGW));
michael@0 850
michael@0 851 prntdlg.lStructSize = sizeof(prntdlg);
michael@0 852 prntdlg.hwndOwner = aHWnd;
michael@0 853 prntdlg.hDevMode = hGlobalDevMode;
michael@0 854 prntdlg.hDevNames = hDevNames;
michael@0 855 prntdlg.hDC = nullptr;
michael@0 856 prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC |
michael@0 857 PD_USEDEVMODECOPIESANDCOLLATE | PD_COLLATE;
michael@0 858
michael@0 859 // if there is a current selection then enable the "Selection" radio button
michael@0 860 int16_t howToEnableFrameUI = nsIPrintSettings::kFrameEnableNone;
michael@0 861 bool isOn;
michael@0 862 aPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &isOn);
michael@0 863 if (!isOn) {
michael@0 864 prntdlg.Flags |= PD_NOSELECTION;
michael@0 865 }
michael@0 866 aPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
michael@0 867
michael@0 868 int32_t pg = 1;
michael@0 869 aPrintSettings->GetStartPageRange(&pg);
michael@0 870 prntdlg.nFromPage = pg;
michael@0 871
michael@0 872 aPrintSettings->GetEndPageRange(&pg);
michael@0 873 prntdlg.nToPage = pg;
michael@0 874
michael@0 875 prntdlg.nMinPage = 1;
michael@0 876 prntdlg.nMaxPage = 0xFFFF;
michael@0 877 prntdlg.nCopies = 1;
michael@0 878 prntdlg.lpfnSetupHook = nullptr;
michael@0 879 prntdlg.lpSetupTemplateName = nullptr;
michael@0 880 prntdlg.hPrintTemplate = nullptr;
michael@0 881 prntdlg.hSetupTemplate = nullptr;
michael@0 882
michael@0 883 prntdlg.hInstance = nullptr;
michael@0 884 prntdlg.lpPrintTemplateName = nullptr;
michael@0 885
michael@0 886 if (!ShouldExtendPrintDialog()) {
michael@0 887 prntdlg.lCustData = 0;
michael@0 888 prntdlg.lpfnPrintHook = nullptr;
michael@0 889 } else {
michael@0 890 // Set up print dialog "hook" procedure for extending the dialog
michael@0 891 prntdlg.lCustData = (DWORD)howToEnableFrameUI;
michael@0 892 prntdlg.lpfnPrintHook = (LPPRINTHOOKPROC)PrintHookProc;
michael@0 893 prntdlg.Flags |= PD_ENABLEPRINTHOOK;
michael@0 894 }
michael@0 895
michael@0 896 BOOL result = ::PrintDlgW(&prntdlg);
michael@0 897
michael@0 898 if (TRUE == result) {
michael@0 899 // check to make sure we don't have any nullptr pointers
michael@0 900 NS_ENSURE_TRUE(aPrintSettings && prntdlg.hDevMode, NS_ERROR_FAILURE);
michael@0 901
michael@0 902 if (prntdlg.hDevNames == nullptr) {
michael@0 903 ::GlobalFree(hGlobalDevMode);
michael@0 904 return NS_ERROR_FAILURE;
michael@0 905 }
michael@0 906 // Lock the deviceNames and check for nullptr
michael@0 907 DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(prntdlg.hDevNames);
michael@0 908 if (devnames == nullptr) {
michael@0 909 ::GlobalFree(hGlobalDevMode);
michael@0 910 return NS_ERROR_FAILURE;
michael@0 911 }
michael@0 912
michael@0 913 char16_t* device = &(((char16_t *)devnames)[devnames->wDeviceOffset]);
michael@0 914 char16_t* driver = &(((char16_t *)devnames)[devnames->wDriverOffset]);
michael@0 915
michael@0 916 // Check to see if the "Print To File" control is checked
michael@0 917 // then take the name from devNames and set it in the PrintSettings
michael@0 918 //
michael@0 919 // NOTE:
michael@0 920 // As per Microsoft SDK documentation the returned value offset from
michael@0 921 // devnames->wOutputOffset is either "FILE:" or nullptr
michael@0 922 // if the "Print To File" checkbox is checked it MUST be "FILE:"
michael@0 923 // We assert as an extra safety check.
michael@0 924 if (prntdlg.Flags & PD_PRINTTOFILE) {
michael@0 925 char16ptr_t fileName = &(((wchar_t *)devnames)[devnames->wOutputOffset]);
michael@0 926 NS_ASSERTION(wcscmp(fileName, L"FILE:") == 0, "FileName must be `FILE:`");
michael@0 927 aPrintSettings->SetToFileName(fileName);
michael@0 928 aPrintSettings->SetPrintToFile(true);
michael@0 929 } else {
michael@0 930 // clear "print to file" info
michael@0 931 aPrintSettings->SetPrintToFile(false);
michael@0 932 aPrintSettings->SetToFileName(nullptr);
michael@0 933 }
michael@0 934
michael@0 935 nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings));
michael@0 936 if (!psWin) {
michael@0 937 ::GlobalFree(hGlobalDevMode);
michael@0 938 return NS_ERROR_FAILURE;
michael@0 939 }
michael@0 940
michael@0 941 // Setup local Data members
michael@0 942 psWin->SetDeviceName(device);
michael@0 943 psWin->SetDriverName(driver);
michael@0 944
michael@0 945 #if defined(DEBUG_rods) || defined(DEBUG_dcone)
michael@0 946 wprintf(L"printer: driver %s, device %s flags: %d\n", driver, device, prntdlg.Flags);
michael@0 947 #endif
michael@0 948 // fill the print options with the info from the dialog
michael@0 949
michael@0 950 aPrintSettings->SetPrinterName(device);
michael@0 951
michael@0 952 if (prntdlg.Flags & PD_SELECTION) {
michael@0 953 aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection);
michael@0 954
michael@0 955 } else if (prntdlg.Flags & PD_PAGENUMS) {
michael@0 956 aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange);
michael@0 957 aPrintSettings->SetStartPageRange(prntdlg.nFromPage);
michael@0 958 aPrintSettings->SetEndPageRange(prntdlg.nToPage);
michael@0 959
michael@0 960 } else { // (prntdlg.Flags & PD_ALLPAGES)
michael@0 961 aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
michael@0 962 }
michael@0 963
michael@0 964 if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) {
michael@0 965 // make sure the dialog got extended
michael@0 966 if (gDialogWasExtended) {
michael@0 967 // check to see about the frame radio buttons
michael@0 968 switch (gFrameSelectedRadioBtn) {
michael@0 969 case rad4:
michael@0 970 aPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
michael@0 971 break;
michael@0 972 case rad5:
michael@0 973 aPrintSettings->SetPrintFrameType(nsIPrintSettings::kSelectedFrame);
michael@0 974 break;
michael@0 975 case rad6:
michael@0 976 aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
michael@0 977 break;
michael@0 978 } // switch
michael@0 979 } else {
michael@0 980 // if it didn't get extended then have it default to printing
michael@0 981 // each frame separately
michael@0 982 aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
michael@0 983 }
michael@0 984 } else {
michael@0 985 aPrintSettings->SetPrintFrameType(nsIPrintSettings::kNoFrames);
michael@0 986 }
michael@0 987 // Unlock DeviceNames
michael@0 988 ::GlobalUnlock(prntdlg.hDevNames);
michael@0 989
michael@0 990 // Transfer the settings from the native data to the PrintSettings
michael@0 991 LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
michael@0 992 if (devMode == nullptr) {
michael@0 993 ::GlobalFree(hGlobalDevMode);
michael@0 994 return NS_ERROR_FAILURE;
michael@0 995 }
michael@0 996 psWin->SetDevMode(devMode); // copies DevMode
michael@0 997 SetPrintSettingsFromDevMode(aPrintSettings, devMode);
michael@0 998 ::GlobalUnlock(prntdlg.hDevMode);
michael@0 999
michael@0 1000 #if defined(DEBUG_rods) || defined(DEBUG_dcone)
michael@0 1001 bool printSelection = prntdlg.Flags & PD_SELECTION;
michael@0 1002 bool printAllPages = prntdlg.Flags & PD_ALLPAGES;
michael@0 1003 bool printNumPages = prntdlg.Flags & PD_PAGENUMS;
michael@0 1004 int32_t fromPageNum = 0;
michael@0 1005 int32_t toPageNum = 0;
michael@0 1006
michael@0 1007 if (printNumPages) {
michael@0 1008 fromPageNum = prntdlg.nFromPage;
michael@0 1009 toPageNum = prntdlg.nToPage;
michael@0 1010 }
michael@0 1011 if (printSelection) {
michael@0 1012 printf("Printing the selection\n");
michael@0 1013
michael@0 1014 } else if (printAllPages) {
michael@0 1015 printf("Printing all the pages\n");
michael@0 1016
michael@0 1017 } else {
michael@0 1018 printf("Printing from page no. %d to %d\n", fromPageNum, toPageNum);
michael@0 1019 }
michael@0 1020 #endif
michael@0 1021
michael@0 1022 } else {
michael@0 1023 ::SetFocus(aHWnd);
michael@0 1024 aPrintSettings->SetIsCancelled(true);
michael@0 1025 if (hGlobalDevMode) ::GlobalFree(hGlobalDevMode);
michael@0 1026 return NS_ERROR_ABORT;
michael@0 1027 }
michael@0 1028
michael@0 1029 return NS_OK;
michael@0 1030 }
michael@0 1031
michael@0 1032 //------------------------------------------------------------------
michael@0 1033 static void
michael@0 1034 PrepareForPrintDialog(nsIWebBrowserPrint* aWebBrowserPrint, nsIPrintSettings* aPS)
michael@0 1035 {
michael@0 1036 NS_ASSERTION(aWebBrowserPrint, "Can't be null");
michael@0 1037 NS_ASSERTION(aPS, "Can't be null");
michael@0 1038
michael@0 1039 bool isFramesetDocument;
michael@0 1040 bool isFramesetFrameSelected;
michael@0 1041 bool isIFrameSelected;
michael@0 1042 bool isRangeSelection;
michael@0 1043
michael@0 1044 aWebBrowserPrint->GetIsFramesetDocument(&isFramesetDocument);
michael@0 1045 aWebBrowserPrint->GetIsFramesetFrameSelected(&isFramesetFrameSelected);
michael@0 1046 aWebBrowserPrint->GetIsIFrameSelected(&isIFrameSelected);
michael@0 1047 aWebBrowserPrint->GetIsRangeSelection(&isRangeSelection);
michael@0 1048
michael@0 1049 // Setup print options for UI
michael@0 1050 if (isFramesetDocument) {
michael@0 1051 if (isFramesetFrameSelected) {
michael@0 1052 aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll);
michael@0 1053 } else {
michael@0 1054 aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach);
michael@0 1055 }
michael@0 1056 } else {
michael@0 1057 aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone);
michael@0 1058 }
michael@0 1059
michael@0 1060 // Now determine how to set up the Frame print UI
michael@0 1061 aPS->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isRangeSelection || isIFrameSelected);
michael@0 1062
michael@0 1063 }
michael@0 1064
michael@0 1065 //----------------------------------------------------------------------------------
michael@0 1066 //-- Show Print Dialog
michael@0 1067 //----------------------------------------------------------------------------------
michael@0 1068 nsresult NativeShowPrintDialog(HWND aHWnd,
michael@0 1069 nsIWebBrowserPrint* aWebBrowserPrint,
michael@0 1070 nsIPrintSettings* aPrintSettings)
michael@0 1071 {
michael@0 1072 PrepareForPrintDialog(aWebBrowserPrint, aPrintSettings);
michael@0 1073
michael@0 1074 nsresult rv = ShowNativePrintDialog(aHWnd, aPrintSettings);
michael@0 1075 if (aHWnd) {
michael@0 1076 ::DestroyWindow(aHWnd);
michael@0 1077 }
michael@0 1078
michael@0 1079 return rv;
michael@0 1080 }
michael@0 1081

mercurial