1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include "nsDeviceContextSpecWin.h"
15 #include "nsAutoPtr.h"
16 #include "nsIWidget.h"
19 #include "nsIPrintSettingsWin.h"
23 #include "nsIServiceManager.h"
24 #include "nsReadableUtils.h"
25 #include "nsStringEnumerator.h"
27 #include "gfxPDFSurface.h"
28 #include "gfxWindowsSurface.h"
30 #include "nsIFileStreams.h"
31 #include "nsIWindowWatcher.h"
32 #include "nsIDOMWindow.h"
33 #include "mozilla/Services.h"
35 // For NS_CopyNativeToUnicode
36 #include "nsNativeCharsetUtils.h"
40 #include "nsIFilePicker.h"
41 #include "nsIStringBundle.h"
42 #define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties"
46 PRLogModuleInfo
* kWidgetPrintingLogMod
= PR_NewLogModule("printing-widget");
47 #define PR_PL(_p1) PR_LOG(kWidgetPrintingLogMod, PR_LOG_DEBUG, _p1)
52 using namespace mozilla
;
54 //----------------------------------------------------------------------------------
55 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecWin
56 // The PrinterEnumerator creates the printer info
57 // but the nsDeviceContextSpecWin cleans it up
58 // If it gets created (via the Page Setup Dialog) but the user never prints anything
59 // then it will never be delete, so this class takes care of that.
60 class GlobalPrinters
{
62 static GlobalPrinters
* GetInstance() { return &mGlobalPrinters
; }
63 ~GlobalPrinters() { FreeGlobalPrinters(); }
65 void FreeGlobalPrinters();
67 bool PrintersAreAllocated() { return mPrinters
!= nullptr; }
68 LPWSTR
GetItemFromList(int32_t aInx
) { return mPrinters
?mPrinters
->ElementAt(aInx
):nullptr; }
69 nsresult
EnumeratePrinterList();
70 void GetDefaultPrinterName(nsString
& aDefaultPrinterName
);
71 uint32_t GetNumPrinters() { return mPrinters
?mPrinters
->Length():0; }
75 nsresult
EnumerateNativePrinters();
76 void ReallocatePrinters();
78 static GlobalPrinters mGlobalPrinters
;
79 static nsTArray
<LPWSTR
>* mPrinters
;
83 GlobalPrinters
GlobalPrinters::mGlobalPrinters
;
84 nsTArray
<LPWSTR
>* GlobalPrinters::mPrinters
= nullptr;
87 //******************************************************
88 // Define native paper sizes
89 //******************************************************
91 short mPaperSize
; // native enum
97 // There are around 40 default print sizes defined by Windows
98 const NativePaperSizes kPaperSizes
[] = {
99 {DMPAPER_LETTER
, 8.5, 11.0, true},
100 {DMPAPER_LEGAL
, 8.5, 14.0, true},
101 {DMPAPER_A4
, 210.0, 297.0, false},
102 {DMPAPER_B4
, 250.0, 354.0, false},
103 {DMPAPER_B5
, 182.0, 257.0, false},
104 {DMPAPER_TABLOID
, 11.0, 17.0, true},
105 {DMPAPER_LEDGER
, 17.0, 11.0, true},
106 {DMPAPER_STATEMENT
, 5.5, 8.5, true},
107 {DMPAPER_EXECUTIVE
, 7.25, 10.5, true},
108 {DMPAPER_A3
, 297.0, 420.0, false},
109 {DMPAPER_A5
, 148.0, 210.0, false},
110 {DMPAPER_CSHEET
, 17.0, 22.0, true},
111 {DMPAPER_DSHEET
, 22.0, 34.0, true},
112 {DMPAPER_ESHEET
, 34.0, 44.0, true},
113 {DMPAPER_LETTERSMALL
, 8.5, 11.0, true},
114 {DMPAPER_A4SMALL
, 210.0, 297.0, false},
115 {DMPAPER_FOLIO
, 8.5, 13.0, true},
116 {DMPAPER_QUARTO
, 215.0, 275.0, false},
117 {DMPAPER_10X14
, 10.0, 14.0, true},
118 {DMPAPER_11X17
, 11.0, 17.0, true},
119 {DMPAPER_NOTE
, 8.5, 11.0, true},
120 {DMPAPER_ENV_9
, 3.875, 8.875, true},
121 {DMPAPER_ENV_10
, 40.125, 9.5, true},
122 {DMPAPER_ENV_11
, 4.5, 10.375, true},
123 {DMPAPER_ENV_12
, 4.75, 11.0, true},
124 {DMPAPER_ENV_14
, 5.0, 11.5, true},
125 {DMPAPER_ENV_DL
, 110.0, 220.0, false},
126 {DMPAPER_ENV_C5
, 162.0, 229.0, false},
127 {DMPAPER_ENV_C3
, 324.0, 458.0, false},
128 {DMPAPER_ENV_C4
, 229.0, 324.0, false},
129 {DMPAPER_ENV_C6
, 114.0, 162.0, false},
130 {DMPAPER_ENV_C65
, 114.0, 229.0, false},
131 {DMPAPER_ENV_B4
, 250.0, 353.0, false},
132 {DMPAPER_ENV_B5
, 176.0, 250.0, false},
133 {DMPAPER_ENV_B6
, 176.0, 125.0, false},
134 {DMPAPER_ENV_ITALY
, 110.0, 230.0, false},
135 {DMPAPER_ENV_MONARCH
, 3.875, 7.5, true},
136 {DMPAPER_ENV_PERSONAL
, 3.625, 6.5, true},
137 {DMPAPER_FANFOLD_US
, 14.875, 11.0, true},
138 {DMPAPER_FANFOLD_STD_GERMAN
, 8.5, 12.0, true},
139 {DMPAPER_FANFOLD_LGL_GERMAN
, 8.5, 13.0, true},
141 const int32_t kNumPaperSizes
= 41;
143 //----------------------------------------------------------------------------------
144 nsDeviceContextSpecWin::nsDeviceContextSpecWin()
146 mDriverName
= nullptr;
147 mDeviceName
= nullptr;
153 //----------------------------------------------------------------------------------
155 NS_IMPL_ISUPPORTS(nsDeviceContextSpecWin
, nsIDeviceContextSpec
)
157 nsDeviceContextSpecWin::~nsDeviceContextSpecWin()
159 SetDeviceName(nullptr);
160 SetDriverName(nullptr);
163 nsCOMPtr
<nsIPrintSettingsWin
> psWin(do_QueryInterface(mPrintSettings
));
165 psWin
->SetDeviceName(nullptr);
166 psWin
->SetDriverName(nullptr);
167 psWin
->SetDevMode(nullptr);
170 // Free them, we won't need them for a while
171 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
175 //------------------------------------------------------------------
177 static char16_t
* GetDefaultPrinterNameFromGlobalPrinters()
179 nsAutoString printerName
;
180 GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName
);
181 return ToNewUnicode(printerName
);
184 //----------------------------------------------------------------------------------
185 NS_IMETHODIMP
nsDeviceContextSpecWin::Init(nsIWidget
* aWidget
,
186 nsIPrintSettings
* aPrintSettings
,
187 bool aIsPrintPreview
)
189 mPrintSettings
= aPrintSettings
;
191 nsresult rv
= NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE
;
192 if (aPrintSettings
) {
193 nsCOMPtr
<nsIPrintSettingsWin
> psWin(do_QueryInterface(aPrintSettings
));
195 char16_t
* deviceName
;
196 char16_t
* driverName
;
197 psWin
->GetDeviceName(&deviceName
); // creates new memory (makes a copy)
198 psWin
->GetDriverName(&driverName
); // creates new memory (makes a copy)
201 psWin
->GetDevMode(&devMode
); // creates new memory (makes a copy)
203 if (deviceName
&& driverName
&& devMode
) {
204 // Scaling is special, it is one of the few
205 // devMode items that we control in layout
206 if (devMode
->dmFields
& DM_SCALE
) {
207 double scale
= double(devMode
->dmScale
) / 100.0f
;
209 aPrintSettings
->SetScaling(scale
);
210 devMode
->dmScale
= 100;
214 SetDeviceName(deviceName
);
215 SetDriverName(driverName
);
224 PR_PL(("***** nsDeviceContextSpecWin::Init - deviceName/driverName/devMode was NULL!\n"));
225 if (deviceName
) free(deviceName
);
226 if (driverName
) free(driverName
);
227 if (devMode
) ::HeapFree(::GetProcessHeap(), 0, devMode
);
231 PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n"));
234 // Get the Print Name to be used
235 char16_t
* printerName
= nullptr;
236 if (mPrintSettings
) {
237 mPrintSettings
->GetPrinterName(&printerName
);
240 // If there is no name then use the default printer
241 if (!printerName
|| (printerName
&& !*printerName
)) {
242 printerName
= GetDefaultPrinterNameFromGlobalPrinters();
245 NS_ASSERTION(printerName
, "We have to have a printer name");
246 if (!printerName
|| !*printerName
) return rv
;
248 return GetDataFromPrinter(printerName
, mPrintSettings
);
251 //----------------------------------------------------------
252 // Helper Function - Free and reallocate the string
253 static void CleanAndCopyString(wchar_t*& aStr
, const wchar_t* aNewStr
)
255 if (aStr
!= nullptr) {
256 if (aNewStr
!= nullptr && wcslen(aStr
) > wcslen(aNewStr
)) { // reuse it if we can
257 wcscpy(aStr
, aNewStr
);
265 if (nullptr != aNewStr
) {
266 aStr
= (wchar_t *)PR_Malloc(sizeof(wchar_t)*(wcslen(aNewStr
) + 1));
267 wcscpy(aStr
, aNewStr
);
271 NS_IMETHODIMP
nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface
**surface
)
273 NS_ASSERTION(mDevMode
, "DevMode can't be NULL here");
275 nsRefPtr
<gfxASurface
> newSurface
;
277 int16_t outputFormat
= 0;
278 if (mPrintSettings
) {
279 mPrintSettings
->GetOutputFormat(&outputFormat
);
282 if (outputFormat
== nsIPrintSettings::kOutputFormatPDF
) {
283 nsXPIDLString filename
;
284 mPrintSettings
->GetToFileName(getter_Copies(filename
));
286 double width
, height
;
287 mPrintSettings
->GetEffectivePageSize(&width
, &height
);
288 // convert twips to points
289 width
/= TWIPS_PER_POINT_FLOAT
;
290 height
/= TWIPS_PER_POINT_FLOAT
;
292 nsCOMPtr
<nsIFile
> file
= do_CreateInstance("@mozilla.org/file/local;1");
293 nsresult rv
= file
->InitWithPath(filename
);
297 nsCOMPtr
<nsIFileOutputStream
> stream
= do_CreateInstance("@mozilla.org/network/file-output-stream;1");
298 rv
= stream
->Init(file
, -1, -1, 0);
302 newSurface
= new gfxPDFSurface(stream
, gfxSize(width
, height
));
305 NS_WARN_IF_FALSE(mDriverName
, "No driver!");
306 HDC dc
= ::CreateDCW(mDriverName
, mDeviceName
, nullptr, mDevMode
);
308 // have this surface take over ownership of this DC
309 newSurface
= new gfxWindowsSurface(dc
, gfxWindowsSurface::FLAG_TAKE_DC
| gfxWindowsSurface::FLAG_FOR_PRINTING
);
314 *surface
= newSurface
;
320 return NS_ERROR_FAILURE
;
323 //----------------------------------------------------------------------------------
324 void nsDeviceContextSpecWin::SetDeviceName(char16ptr_t aDeviceName
)
326 CleanAndCopyString(mDeviceName
, aDeviceName
);
329 //----------------------------------------------------------------------------------
330 void nsDeviceContextSpecWin::SetDriverName(char16ptr_t aDriverName
)
332 CleanAndCopyString(mDriverName
, aDriverName
);
335 //----------------------------------------------------------------------------------
336 void nsDeviceContextSpecWin::SetDevMode(LPDEVMODEW aDevMode
)
339 ::HeapFree(::GetProcessHeap(), 0, mDevMode
);
345 //------------------------------------------------------------------
347 nsDeviceContextSpecWin::GetDevMode(LPDEVMODEW
&aDevMode
)
352 //----------------------------------------------------------------------------------
353 // Map an incoming size to a Windows Native enum in the DevMode
355 MapPaperSizeToNativeEnum(LPDEVMODEW aDevMode
,
362 BOOL doingOrientation
= aDevMode
->dmFields
& DM_ORIENTATION
;
363 BOOL doingPaperSize
= aDevMode
->dmFields
& DM_PAPERSIZE
;
364 BOOL doingPaperLength
= aDevMode
->dmFields
& DM_PAPERLENGTH
;
365 BOOL doingPaperWidth
= aDevMode
->dmFields
& DM_PAPERWIDTH
;
368 for (int32_t i
=0;i
<kNumPaperSizes
;i
++) {
369 if (kPaperSizes
[i
].mWidth
== aW
&& kPaperSizes
[i
].mHeight
== aH
) {
370 aDevMode
->dmPaperSize
= kPaperSizes
[i
].mPaperSize
;
371 aDevMode
->dmFields
&= ~DM_PAPERLENGTH
;
372 aDevMode
->dmFields
&= ~DM_PAPERWIDTH
;
373 aDevMode
->dmFields
|= DM_PAPERSIZE
;
380 if (aType
== nsIPrintSettings::kPaperSizeInches
) {
381 width
= short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aW
))) / 10);
382 height
= short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aH
))) / 10);
384 } else if (aType
== nsIPrintSettings::kPaperSizeMillimeters
) {
385 width
= short(aW
/ 10.0);
386 height
= short(aH
/ 10.0);
388 return; // don't set anything
391 // width and height is in
392 aDevMode
->dmPaperSize
= 0;
393 aDevMode
->dmPaperWidth
= width
;
394 aDevMode
->dmPaperLength
= height
;
396 aDevMode
->dmFields
|= DM_PAPERSIZE
;
397 aDevMode
->dmFields
|= DM_PAPERLENGTH
;
398 aDevMode
->dmFields
|= DM_PAPERWIDTH
;
401 //----------------------------------------------------------------------------------
402 // Setup Paper Size & Orientation options into the DevMode
405 SetupDevModeFromSettings(LPDEVMODEW aDevMode
, nsIPrintSettings
* aPrintSettings
)
408 if (aPrintSettings
) {
410 aPrintSettings
->GetPaperSizeType(&type
);
411 if (type
== nsIPrintSettings::kPaperSizeNativeData
) {
413 aPrintSettings
->GetPaperData(&paperEnum
);
414 aDevMode
->dmPaperSize
= paperEnum
;
415 aDevMode
->dmFields
&= ~DM_PAPERLENGTH
;
416 aDevMode
->dmFields
&= ~DM_PAPERWIDTH
;
417 aDevMode
->dmFields
|= DM_PAPERSIZE
;
420 double width
, height
;
421 aPrintSettings
->GetPaperSizeUnit(&unit
);
422 aPrintSettings
->GetPaperWidth(&width
);
423 aPrintSettings
->GetPaperHeight(&height
);
424 MapPaperSizeToNativeEnum(aDevMode
, unit
, width
, height
);
429 aPrintSettings
->GetOrientation(&orientation
);
430 aDevMode
->dmOrientation
= orientation
== nsIPrintSettings::kPortraitOrientation
?DMORIENT_PORTRAIT
:DMORIENT_LANDSCAPE
;
431 aDevMode
->dmFields
|= DM_ORIENTATION
;
433 // Setup Number of Copies
435 aPrintSettings
->GetNumCopies(&copies
);
436 aDevMode
->dmCopies
= copies
;
437 aDevMode
->dmFields
|= DM_COPIES
;
442 #define DISPLAY_LAST_ERROR
444 //----------------------------------------------------------------------------------
445 // Setup the object's data member with the selected printer's data
447 nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName
, nsIPrintSettings
* aPS
)
449 nsresult rv
= NS_ERROR_FAILURE
;
451 if (!GlobalPrinters::GetInstance()->PrintersAreAllocated()) {
452 rv
= GlobalPrinters::GetInstance()->EnumeratePrinterList();
454 PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't enumerate printers!\n"));
457 NS_ENSURE_SUCCESS(rv
, rv
);
460 HANDLE hPrinter
= nullptr;
461 wchar_t *name
= (wchar_t*)aName
; // Windows APIs use non-const name argument
463 BOOL status
= ::OpenPrinterW(name
, &hPrinter
, nullptr);
467 DWORD dwNeeded
, dwRet
;
469 // Allocate a buffer of the correct size.
470 dwNeeded
= ::DocumentPropertiesW(nullptr, hPrinter
, name
, nullptr, nullptr, 0);
472 pDevMode
= (LPDEVMODEW
)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY
, dwNeeded
);
473 if (!pDevMode
) return NS_ERROR_FAILURE
;
475 // Get the default DevMode for the printer and modify it for our needs.
476 dwRet
= DocumentPropertiesW(nullptr, hPrinter
, name
,
477 pDevMode
, nullptr, DM_OUT_BUFFER
);
479 if (dwRet
== IDOK
&& aPS
) {
480 SetupDevModeFromSettings(pDevMode
, aPS
);
481 // Sets back the changes we made to the DevMode into the Printer Driver
482 dwRet
= ::DocumentPropertiesW(nullptr, hPrinter
, name
,
484 DM_IN_BUFFER
| DM_OUT_BUFFER
);
488 ::HeapFree(::GetProcessHeap(), 0, pDevMode
);
489 ::ClosePrinter(hPrinter
);
490 PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - DocumentProperties call failed code: %d/0x%x\n", dwRet
, dwRet
));
492 return NS_ERROR_FAILURE
;
495 SetDevMode(pDevMode
); // cache the pointer and takes responsibility for the memory
497 SetDeviceName(aName
);
499 SetDriverName(L
"WINSPOOL");
501 ::ClosePrinter(hPrinter
);
504 rv
= NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND
;
505 PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't open printer: [%s]\n", NS_ConvertUTF16toUTF8(aName
).get()));
511 //----------------------------------------------------------------------------------
512 // Setup Paper Size options into the DevMode
514 // When using a data member it may be a HGLOCAL or LPDEVMODE
515 // if it is a HGLOBAL then we need to "lock" it to get the LPDEVMODE
516 // and unlock it when we are done.
518 nsDeviceContextSpecWin::SetupPaperInfoFromSettings()
523 NS_ASSERTION(devMode
, "DevMode can't be NULL here");
525 SetupDevModeFromSettings(devMode
, mPrintSettings
);
529 //----------------------------------------------------------------------------------
530 // Helper Function - Free and reallocate the string
532 nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(nsIPrintSettings
* aPrintSettings
,
535 if (aPrintSettings
== nullptr) {
536 return NS_ERROR_FAILURE
;
538 aPrintSettings
->SetIsInitializedFromPrinter(true);
540 BOOL doingNumCopies
= aDevMode
->dmFields
& DM_COPIES
;
541 BOOL doingOrientation
= aDevMode
->dmFields
& DM_ORIENTATION
;
542 BOOL doingPaperSize
= aDevMode
->dmFields
& DM_PAPERSIZE
;
543 BOOL doingPaperLength
= aDevMode
->dmFields
& DM_PAPERLENGTH
;
544 BOOL doingPaperWidth
= aDevMode
->dmFields
& DM_PAPERWIDTH
;
546 if (doingOrientation
) {
547 int32_t orientation
= aDevMode
->dmOrientation
== DMORIENT_PORTRAIT
?
548 int32_t(nsIPrintSettings::kPortraitOrientation
):nsIPrintSettings::kLandscapeOrientation
;
549 aPrintSettings
->SetOrientation(orientation
);
552 // Setup Number of Copies
553 if (doingNumCopies
) {
554 aPrintSettings
->SetNumCopies(int32_t(aDevMode
->dmCopies
));
557 if (aDevMode
->dmFields
& DM_SCALE
) {
558 double scale
= double(aDevMode
->dmScale
) / 100.0f
;
560 aPrintSettings
->SetScaling(scale
);
561 aDevMode
->dmScale
= 100;
562 // To turn this on you must change where the mPrt->mShrinkToFit is being set in the DocumentViewer
563 //aPrintSettings->SetShrinkToFit(false);
567 if (doingPaperSize
) {
568 aPrintSettings
->SetPaperSizeType(nsIPrintSettings::kPaperSizeNativeData
);
569 aPrintSettings
->SetPaperData(aDevMode
->dmPaperSize
);
570 for (int32_t i
=0;i
<kNumPaperSizes
;i
++) {
571 if (kPaperSizes
[i
].mPaperSize
== aDevMode
->dmPaperSize
) {
572 aPrintSettings
->SetPaperSizeUnit(kPaperSizes
[i
].mIsInches
573 ?int16_t(nsIPrintSettings::kPaperSizeInches
):nsIPrintSettings::kPaperSizeMillimeters
);
578 } else if (doingPaperLength
&& doingPaperWidth
) {
580 for (int32_t i
=0;i
<kNumPaperSizes
;i
++) {
581 if (kPaperSizes
[i
].mPaperSize
== aDevMode
->dmPaperSize
) {
582 aPrintSettings
->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined
);
583 aPrintSettings
->SetPaperWidth(kPaperSizes
[i
].mWidth
);
584 aPrintSettings
->SetPaperHeight(kPaperSizes
[i
].mHeight
);
585 aPrintSettings
->SetPaperSizeUnit(kPaperSizes
[i
].mIsInches
586 ?int16_t(nsIPrintSettings::kPaperSizeInches
):nsIPrintSettings::kPaperSizeMillimeters
);
592 return NS_ERROR_FAILURE
;
595 return NS_ERROR_FAILURE
;
600 //***********************************************************
601 // Printer Enumerator
602 //***********************************************************
603 nsPrinterEnumeratorWin::nsPrinterEnumeratorWin()
607 nsPrinterEnumeratorWin::~nsPrinterEnumeratorWin()
609 // Do not free printers here
610 // GlobalPrinters::GetInstance()->FreeGlobalPrinters();
613 NS_IMPL_ISUPPORTS(nsPrinterEnumeratorWin
, nsIPrinterEnumerator
)
615 //----------------------------------------------------------------------------------
616 // Return the Default Printer name
617 /* readonly attribute wstring defaultPrinterName; */
619 nsPrinterEnumeratorWin::GetDefaultPrinterName(char16_t
* *aDefaultPrinterName
)
621 NS_ENSURE_ARG_POINTER(aDefaultPrinterName
);
623 *aDefaultPrinterName
= GetDefaultPrinterNameFromGlobalPrinters(); // helper
628 /* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */
630 nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const char16_t
*aPrinterName
, nsIPrintSettings
*aPrintSettings
)
632 NS_ENSURE_ARG_POINTER(aPrinterName
);
633 NS_ENSURE_ARG_POINTER(aPrintSettings
);
635 if (!*aPrinterName
) {
639 nsRefPtr
<nsDeviceContextSpecWin
> devSpecWin
= new nsDeviceContextSpecWin();
640 if (!devSpecWin
) return NS_ERROR_OUT_OF_MEMORY
;
642 if (NS_FAILED(GlobalPrinters::GetInstance()->EnumeratePrinterList())) {
643 return NS_ERROR_FAILURE
;
646 devSpecWin
->GetDataFromPrinter(aPrinterName
);
649 devSpecWin
->GetDevMode(devmode
);
650 NS_ASSERTION(devmode
, "DevMode can't be NULL here");
652 aPrintSettings
->SetPrinterName(aPrinterName
);
653 nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(aPrintSettings
, devmode
);
656 // Free them, we won't need them for a while
657 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
662 //----------------------------------------------------------------------------------
663 // Enumerate all the Printers from the global array and pass their
664 // names back (usually to script)
666 nsPrinterEnumeratorWin::GetPrinterNameList(nsIStringEnumerator
**aPrinterNameList
)
668 NS_ENSURE_ARG_POINTER(aPrinterNameList
);
669 *aPrinterNameList
= nullptr;
671 nsresult rv
= GlobalPrinters::GetInstance()->EnumeratePrinterList();
673 PR_PL(("***** nsDeviceContextSpecWin::GetPrinterNameList - Couldn't enumerate printers!\n"));
677 uint32_t numPrinters
= GlobalPrinters::GetInstance()->GetNumPrinters();
678 nsTArray
<nsString
> *printers
= new nsTArray
<nsString
>(numPrinters
);
680 return NS_ERROR_OUT_OF_MEMORY
;
682 uint32_t printerInx
= 0;
683 while( printerInx
< numPrinters
) {
684 LPWSTR name
= GlobalPrinters::GetInstance()->GetItemFromList(printerInx
++);
685 printers
->AppendElement(nsDependentString(name
));
688 return NS_NewAdoptingStringEnumerator(aPrinterNameList
, printers
);
691 //----------------------------------------------------------------------------------
692 // Display the AdvancedDocumentProperties for the selected Printer
693 NS_IMETHODIMP
nsPrinterEnumeratorWin::DisplayPropertiesDlg(const char16_t
*aPrinterName
, nsIPrintSettings
* aPrintSettings
)
695 // Implementation removed because it is unused
699 //----------------------------------------------------------------------------------
701 //----------------------------------------------------------------------------------
703 //----------------------------------------------------------------------------------
704 // THe array hold the name and port for each printer
706 GlobalPrinters::ReallocatePrinters()
708 if (PrintersAreAllocated()) {
709 FreeGlobalPrinters();
711 mPrinters
= new nsTArray
<LPWSTR
>();
712 NS_ASSERTION(mPrinters
, "Printers Array is NULL!");
715 //----------------------------------------------------------------------------------
717 GlobalPrinters::FreeGlobalPrinters()
719 if (mPrinters
!= nullptr) {
720 for (uint32_t i
=0;i
<mPrinters
->Length();i
++) {
721 free(mPrinters
->ElementAt(i
));
728 //----------------------------------------------------------------------------------
730 GlobalPrinters::EnumerateNativePrinters()
732 nsresult rv
= NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE
;
733 PR_PL(("-----------------------\n"));
734 PR_PL(("EnumerateNativePrinters\n"));
736 WCHAR szDefaultPrinterName
[1024];
737 DWORD status
= GetProfileStringW(L
"devices", 0, L
",",
738 szDefaultPrinterName
,
739 ArrayLength(szDefaultPrinterName
));
742 LPWSTR sPtr
= szDefaultPrinterName
;
743 LPWSTR ePtr
= szDefaultPrinterName
+ status
;
744 LPWSTR prvPtr
= sPtr
;
745 while (sPtr
< ePtr
) {
747 LPWSTR name
= wcsdup(prvPtr
);
748 mPrinters
->AppendElement(name
);
749 PR_PL(("Printer Name: %s\n", prvPtr
));
757 PR_PL(("-----------------------\n"));
761 //------------------------------------------------------------------
762 // Uses the GetProfileString to get the default printer from the registry
764 GlobalPrinters::GetDefaultPrinterName(nsString
& aDefaultPrinterName
)
766 aDefaultPrinterName
.Truncate();
767 WCHAR szDefaultPrinterName
[1024];
768 DWORD status
= GetProfileStringW(L
"windows", L
"device", 0,
769 szDefaultPrinterName
,
770 ArrayLength(szDefaultPrinterName
));
773 LPWSTR sPtr
= szDefaultPrinterName
;
774 while (*sPtr
!= comma
&& *sPtr
!= 0)
776 if (*sPtr
== comma
) {
779 aDefaultPrinterName
= szDefaultPrinterName
;
781 aDefaultPrinterName
= EmptyString();
784 PR_PL(("DEFAULT PRINTER [%s]\n", aDefaultPrinterName
.get()));
787 //----------------------------------------------------------------------------------
788 // This goes and gets the list of available printers and puts
789 // the default printer at the beginning of the list
791 GlobalPrinters::EnumeratePrinterList()
793 // reallocate and get a new list each time it is asked for
794 // this deletes the list and re-allocates them
795 ReallocatePrinters();
797 // any of these could only fail with an OUT_MEMORY_ERROR
798 // PRINTER_ENUM_LOCAL should get the network printers on Win95
799 nsresult rv
= EnumerateNativePrinters();
800 if (NS_FAILED(rv
)) return rv
;
802 // get the name of the default printer
803 nsAutoString defPrinterName
;
804 GetDefaultPrinterName(defPrinterName
);
806 // put the default printer at the beginning of list
807 if (!defPrinterName
.IsEmpty()) {
808 for (uint32_t i
=0;i
<mPrinters
->Length();i
++) {
809 LPWSTR name
= mPrinters
->ElementAt(i
);
810 if (defPrinterName
.Equals(name
)) {
812 LPWSTR ptr
= mPrinters
->ElementAt(0);
813 mPrinters
->ElementAt(0) = name
;
814 mPrinters
->ElementAt(i
) = ptr
;
821 // make sure we at least tried to get the printers
822 if (!PrintersAreAllocated()) {
823 PR_PL(("***** nsDeviceContextSpecWin::EnumeratePrinterList - Printers aren`t allocated\n"));
824 return NS_ERROR_FAILURE
;