CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / src / os2 / nsDeviceContextSpecOS2.cpp
blob856ac94a5066c979e335caf9e5379c37cab8ce95
1 /* vim: set sw=2 sts=2 et cin: */
2 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is the Mozilla OS/2 libraries.
18 * The Initial Developer of the Original Code is
19 * John Fairhurst, <john_fairhurst@iname.com>.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Peter Weilbacher <mozilla@weilbacher.org>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include <stdlib.h>
42 #include "nsDeviceContextSpecOS2.h"
44 #include "nsReadableUtils.h"
45 #include "nsTArray.h"
47 #include "nsIPrefService.h"
48 #include "nsIPrefBranch.h"
49 #include "prenv.h" /* for PR_GetEnv */
50 #include "prtime.h"
52 #include "nsPrintfCString.h"
53 #include "nsIServiceManager.h"
54 #include "nsUnicharUtils.h"
55 #include "nsStringFwd.h"
56 #include "nsStringEnumerator.h"
58 #include "nsOS2Uni.h"
60 #include "nsILocalFile.h"
61 #include "nsDirectoryServiceDefs.h"
62 #include "nsIFileStreams.h"
63 #include "gfxPDFSurface.h"
64 #include "gfxOS2Surface.h"
65 #include "nsIPrintSettingsService.h"
67 PRINTDLG nsDeviceContextSpecOS2::PrnDlg;
69 //----------------------------------------------------------------------------------
70 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecOS2
71 // The PrinterEnumerator creates the printer info
72 // but the nsDeviceContextSpecOS2 cleans it up
73 // If it gets created (via the Page Setup Dialog) but the user never prints anything
74 // then it will never be delete, so this class takes care of that.
75 class GlobalPrinters {
76 public:
77 static GlobalPrinters* GetInstance() { return &mGlobalPrinters; }
78 ~GlobalPrinters() { FreeGlobalPrinters(); }
80 void FreeGlobalPrinters();
81 nsresult InitializeGlobalPrinters();
83 PRBool PrintersAreAllocated() { return mGlobalPrinterList != nsnull; }
84 PRUint32 GetNumPrinters() { return mGlobalNumPrinters; }
85 nsString* GetStringAt(PRInt32 aInx) { return &mGlobalPrinterList->ElementAt(aInx); }
86 void GetDefaultPrinterName(PRUnichar*& aDefaultPrinterName);
88 protected:
89 GlobalPrinters() {}
91 static GlobalPrinters mGlobalPrinters;
92 static nsTArray<nsString>* mGlobalPrinterList;
93 static ULONG mGlobalNumPrinters;
96 //---------------
97 // static members
98 GlobalPrinters GlobalPrinters::mGlobalPrinters;
99 nsTArray<nsString>* GlobalPrinters::mGlobalPrinterList = nsnull;
100 ULONG GlobalPrinters::mGlobalNumPrinters = 0;
101 //---------------
103 nsDeviceContextSpecOS2::nsDeviceContextSpecOS2()
104 : mQueue(nsnull), mPrintDC(nsnull), mPrintingStarted(PR_FALSE)
108 nsDeviceContextSpecOS2::~nsDeviceContextSpecOS2()
110 if (mQueue)
111 PrnClosePrinter(mQueue);
114 NS_IMPL_ISUPPORTS1(nsDeviceContextSpecOS2, nsIDeviceContextSpec)
116 void SetupDevModeFromSettings(ULONG printer, nsIPrintSettings* aPrintSettings)
118 if (aPrintSettings) {
119 int bufferSize = 3 * sizeof(DJP_ITEM);
120 PBYTE pDJP_Buffer = new BYTE[bufferSize];
121 memset(pDJP_Buffer, 0, bufferSize);
122 PDJP_ITEM pDJP = (PDJP_ITEM) pDJP_Buffer;
124 HDC hdc = nsDeviceContextSpecOS2::PrnDlg.GetDCHandle(printer);
125 char* driver = nsDeviceContextSpecOS2::PrnDlg.GetDriverType(printer);
127 // Setup Orientation
128 PRInt32 orientation;
129 aPrintSettings->GetOrientation(&orientation);
130 if (!strcmp(driver, "LASERJET"))
131 pDJP->lType = DJP_ALL;
132 else
133 pDJP->lType = DJP_CURRENT;
134 pDJP->cb = sizeof(DJP_ITEM);
135 pDJP->ulNumReturned = 1;
136 pDJP->ulProperty = DJP_SJ_ORIENTATION;
137 pDJP->ulValue = orientation == nsIPrintSettings::kPortraitOrientation?DJP_ORI_PORTRAIT:DJP_ORI_LANDSCAPE;
138 pDJP++;
140 // Setup Number of Copies
141 PRInt32 copies;
142 aPrintSettings->GetNumCopies(&copies);
143 pDJP->cb = sizeof(DJP_ITEM);
144 pDJP->lType = DJP_CURRENT;
145 pDJP->ulNumReturned = 1;
146 pDJP->ulProperty = DJP_SJ_COPIES;
147 pDJP->ulValue = copies;
148 pDJP++;
150 pDJP->cb = sizeof(DJP_ITEM);
151 pDJP->lType = DJP_NONE;
152 pDJP->ulNumReturned = 1;
153 pDJP->ulProperty = 0;
154 pDJP->ulValue = 0;
156 LONG driverSize = nsDeviceContextSpecOS2::PrnDlg.GetPrintDriverSize(printer);
157 GreEscape (hdc, DEVESC_SETJOBPROPERTIES, bufferSize, pDJP_Buffer,
158 &driverSize, PBYTE(nsDeviceContextSpecOS2::PrnDlg.GetPrintDriver(printer)));
160 delete [] pDJP_Buffer;
161 DevCloseDC(hdc);
165 nsresult nsDeviceContextSpecOS2::SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings, ULONG printer)
167 if (aPrintSettings == nsnull)
168 return NS_ERROR_FAILURE;
170 int bufferSize = 3 * sizeof(DJP_ITEM);
171 PBYTE pDJP_Buffer = new BYTE[bufferSize];
172 memset(pDJP_Buffer, 0, bufferSize);
173 PDJP_ITEM pDJP = (PDJP_ITEM) pDJP_Buffer;
175 HDC hdc = nsDeviceContextSpecOS2::PrnDlg.GetDCHandle(printer);
177 //Get Number of Copies from Job Properties
178 pDJP->lType = DJP_CURRENT;
179 pDJP->cb = sizeof(DJP_ITEM);
180 pDJP->ulNumReturned = 1;
181 pDJP->ulProperty = DJP_SJ_COPIES;
182 pDJP->ulValue = 1;
183 pDJP++;
185 //Get Orientation from Job Properties
186 pDJP->lType = DJP_CURRENT;
187 pDJP->cb = sizeof(DJP_ITEM);
188 pDJP->ulNumReturned = 1;
189 pDJP->ulProperty = DJP_SJ_ORIENTATION;
190 pDJP->ulValue = 1;
191 pDJP++;
193 pDJP->lType = DJP_NONE;
194 pDJP->cb = sizeof(DJP_ITEM);
195 pDJP->ulNumReturned = 1;
196 pDJP->ulProperty = 0;
197 pDJP->ulValue = 0;
199 LONG driverSize = nsDeviceContextSpecOS2::PrnDlg.GetPrintDriverSize(printer);
200 LONG rc = GreEscape(hdc, DEVESC_QUERYJOBPROPERTIES, bufferSize, pDJP_Buffer,
201 &driverSize, PBYTE(nsDeviceContextSpecOS2::PrnDlg.GetPrintDriver(printer)));
203 pDJP = (PDJP_ITEM) pDJP_Buffer;
204 if ((rc == DEV_OK) || (rc == DEV_WARNING)) {
205 while (pDJP->lType != DJP_NONE) {
206 if ((pDJP->ulProperty == DJP_SJ_ORIENTATION) && (pDJP->lType > 0)){
207 if ((pDJP->ulValue == DJP_ORI_PORTRAIT) || (pDJP->ulValue == DJP_ORI_REV_PORTRAIT))
208 aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
209 else
210 aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
212 if ((pDJP->ulProperty == DJP_SJ_COPIES) && (pDJP->lType > 0)){
213 aPrintSettings->SetNumCopies(PRInt32(pDJP->ulValue));
215 pDJP = DJP_NEXT_STRUCTP(pDJP);
219 delete [] pDJP_Buffer;
220 DevCloseDC(hdc);
221 return NS_OK;
224 NS_IMETHODIMP nsDeviceContextSpecOS2::Init(nsIWidget *aWidget,
225 nsIPrintSettings* aPS,
226 PRBool aIsPrintPreview)
228 nsresult rv = NS_ERROR_FAILURE;
230 mPrintSettings = aPS;
231 NS_ASSERTION(aPS, "Must have a PrintSettings!");
233 rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
234 if (NS_FAILED(rv)) {
235 return rv;
238 if (aPS) {
239 PRBool tofile = PR_FALSE;
240 PRInt32 copies = 1;
241 PRUnichar *printer = nsnull;
242 PRUnichar *printfile = nsnull;
244 mPrintSettings->GetPrinterName(&printer);
245 mPrintSettings->GetToFileName(&printfile);
246 mPrintSettings->GetPrintToFile(&tofile);
247 mPrintSettings->GetNumCopies(&copies);
249 if ((copies == 0) || (copies > 999)) {
250 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
251 return NS_ERROR_FAILURE;
254 if (printfile != nsnull) {
255 // ToDo: Use LocalEncoding instead of UTF-8 (see bug 73446)
256 strcpy(mPrData.path, NS_ConvertUTF16toUTF8(printfile).get());
258 if (printer != nsnull)
259 strcpy(mPrData.printer, NS_ConvertUTF16toUTF8(printer).get());
261 if (aIsPrintPreview)
262 mPrData.destination = printPreview;
263 else if (tofile)
264 mPrData.destination = printToFile;
265 else
266 mPrData.destination = printToPrinter;
267 mPrData.copies = copies;
269 rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
270 if (NS_FAILED(rv))
271 return rv;
273 const nsAFlatString& printerUCS2 = NS_ConvertUTF8toUTF16(mPrData.printer);
274 ULONG numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
275 if (numPrinters) {
276 for(ULONG i = 0; (i < numPrinters) && !mQueue; i++) {
277 if ((GlobalPrinters::GetInstance()->GetStringAt(i)->Equals(printerUCS2, nsCaseInsensitiveStringComparator()))) {
278 SetupDevModeFromSettings(i, aPS);
279 mQueue = PrnDlg.SetPrinterQueue(i);
284 if (printfile != nsnull)
285 nsMemory::Free(printfile);
287 if (printer != nsnull)
288 nsMemory::Free(printer);
291 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
292 return rv;
296 NS_IMETHODIMP nsDeviceContextSpecOS2 :: GetDestination( int &aDestination )
298 aDestination = mPrData.destination;
299 return NS_OK;
302 NS_IMETHODIMP nsDeviceContextSpecOS2 :: GetPrinterName ( char **aPrinter )
304 *aPrinter = &mPrData.printer[0];
305 return NS_OK;
308 NS_IMETHODIMP nsDeviceContextSpecOS2 :: GetCopies ( int &aCopies )
310 aCopies = mPrData.copies;
311 return NS_OK;
314 NS_IMETHODIMP nsDeviceContextSpecOS2 :: GetPath ( char **aPath )
316 *aPath = &mPrData.path[0];
317 return NS_OK;
320 NS_IMETHODIMP nsDeviceContextSpecOS2 :: GetUserCancelled( PRBool &aCancel )
322 aCancel = mPrData.cancel;
323 return NS_OK;
326 /** -------------------------------------------------------
327 * Closes the printmanager if it is open.
328 * @update dc 2/15/98
330 NS_IMETHODIMP nsDeviceContextSpecOS2 :: ClosePrintManager()
332 return NS_OK;
335 nsresult nsDeviceContextSpecOS2::GetPRTQUEUE( PRTQUEUE *&p)
337 p = mQueue;
338 return NS_OK;
341 NS_IMETHODIMP nsDeviceContextSpecOS2::GetSurfaceForPrinter(gfxASurface **surface)
343 NS_ASSERTION(mQueue, "Queue can't be NULL here");
345 nsRefPtr<gfxASurface> newSurface;
347 PRInt16 outputFormat;
348 mPrintSettings->GetOutputFormat(&outputFormat);
349 int printerDest;
350 GetDestination(printerDest);
351 if (printerDest != printPreview) {
352 // for now always set the output format to PDF, see bug 415522
353 outputFormat = nsIPrintSettings::kOutputFormatPDF;
354 mPrintSettings->SetOutputFormat(outputFormat); // save PDF format in settings
357 if (outputFormat == nsIPrintSettings::kOutputFormatPDF) {
358 nsXPIDLString filename;
359 mPrintSettings->GetToFileName(getter_Copies(filename));
360 nsresult rv;
361 if (filename.IsEmpty()) {
362 // print to a file that is visible, like one on the Desktop
363 nsCOMPtr<nsIFile> pdfLocation;
364 rv = NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(pdfLocation));
365 NS_ENSURE_SUCCESS(rv, rv);
367 // construct a print output name using the current time, to make it
368 // unique and not overwrite existing files
369 char printName[CCHMAXPATH];
370 PRExplodedTime time;
371 PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &time);
372 snprintf(printName, CCHMAXPATH-1, "%s_%04d%02d%02d_%02d%02d%02d.pdf",
373 MOZ_APP_DISPLAYNAME, time.tm_year, time.tm_month+1, time.tm_mday,
374 time.tm_hour, time.tm_min, time.tm_sec);
375 printName[CCHMAXPATH-1] = '\0';
377 nsCAutoString printString(printName);
378 rv = pdfLocation->AppendNative(printString);
379 NS_ENSURE_SUCCESS(rv, rv);
380 rv = pdfLocation->GetPath(filename);
381 NS_ENSURE_SUCCESS(rv, rv);
383 #ifdef debug_thebes_print
384 printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): print to filename=%s\n",
385 NS_LossyConvertUTF16toASCII(filename).get());
386 #endif
388 double width, height;
389 mPrintSettings->GetEffectivePageSize(&width, &height);
390 // convert twips to points
391 width /= TWIPS_PER_POINT_FLOAT;
392 height /= TWIPS_PER_POINT_FLOAT;
394 nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
395 rv = file->InitWithPath(filename);
396 if (NS_FAILED(rv))
397 return rv;
399 nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
400 rv = stream->Init(file, -1, -1, 0);
401 if (NS_FAILED(rv))
402 return rv;
404 newSurface = new(std::nothrow) gfxPDFSurface(stream, gfxSize(width, height));
405 } else {
406 int numCopies = 0;
407 GetCopies(numCopies);
408 char *filename = nsnull;
409 if (printerDest == printToFile) {
410 GetPath(&filename);
412 mPrintingStarted = PR_TRUE;
413 mPrintDC = PrnOpenDC(mQueue, "Mozilla", numCopies, printerDest, filename);
415 double width, height;
416 mPrintSettings->GetEffectivePageSize(&width, &height);
417 #ifdef debug_thebes_print
418 printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%ftwips, copies=%d\n",
419 width, height, numCopies);
420 #endif
422 // we need pixels, so scale from twips to the printer resolution
423 // and take into account that CAPS_*_RESOLUTION are in px/m, default
424 // to approx. 100dpi
425 double hDPI = 3937., vDPI = 3937.;
426 LONG value;
427 if (DevQueryCaps(mPrintDC, CAPS_HORIZONTAL_RESOLUTION, 1, &value))
428 hDPI = value * 0.0254;
429 if (DevQueryCaps(mPrintDC, CAPS_VERTICAL_RESOLUTION, 1, &value))
430 vDPI = value * 0.0254;
431 width = width * hDPI / 1440;
432 height = height * vDPI / 1440;
433 #ifdef debug_thebes_print
434 printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%fpx (res=%fx%f)\n"
435 " expected size: %7.2f MiB\n",
436 width, height, hDPI, vDPI, width*height*4./1024./1024.);
437 #endif
439 // perhaps restrict to usable area
440 // (this or scaling down won't help, we will just get more pages and still crash!)
441 if (DevQueryCaps(mPrintDC, CAPS_WIDTH, 1, &value) && width > (double)value)
442 width = (double)value;
443 if (DevQueryCaps(mPrintDC, CAPS_HEIGHT, 1, &value) && height > (double)value)
444 height = (double)value;
446 #ifdef debug_thebes_print
447 printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): capped? %fx%fpx (res=%fx%f)\n"
448 " expected size: %7.2f MiB per page\n",
449 width, height, hDPI, vDPI, width*height*4./1024./1024.);
450 #endif
452 // Now pass the created DC into the thebes surface for printing.
453 // It gets destroyed there.
454 newSurface = new(std::nothrow)
455 gfxOS2Surface(mPrintDC, gfxIntSize(int(ceil(width)), int(ceil(height))));
457 if (!newSurface) {
458 *surface = nsnull;
459 return NS_ERROR_FAILURE;
461 *surface = newSurface;
462 NS_ADDREF(*surface);
463 return NS_OK;
466 // Helper function to convert the string to the native codepage,
467 // similar to UnicodeToCodepage() in nsDragService.cpp.
468 char *GetACPString(const PRUnichar* aStr)
470 nsString str(aStr);
471 if (str.Length() == 0) {
472 return nsnull;
475 nsAutoCharBuffer buffer;
476 PRInt32 bufLength;
477 WideCharToMultiByte(0, PromiseFlatString(str).get(), str.Length(),
478 buffer, bufLength);
479 return ToNewCString(nsDependentCString(buffer.Elements()));
482 NS_IMETHODIMP nsDeviceContextSpecOS2::BeginDocument(PRUnichar* aTitle,
483 PRUnichar* aPrintToFileName,
484 PRInt32 aStartPage,
485 PRInt32 aEndPage)
487 #ifdef debug_thebes_print
488 printf("nsDeviceContextSpecOS2[%#x]::BeginPrinting(%s, %s)\n", (unsigned)this,
489 NS_LossyConvertUTF16toASCII(nsString(aTitle)).get(),
490 NS_LossyConvertUTF16toASCII(nsString(aPrintToFileName)).get());
491 #endif
492 // don't try to send device escapes for non-native output (like PDF)
493 PRInt16 outputFormat;
494 mPrintSettings->GetOutputFormat(&outputFormat);
495 if (outputFormat != nsIPrintSettings::kOutputFormatNative) {
496 return NS_OK;
499 char *title = GetACPString(aTitle);
500 PCSZ pszGenericDocName = "Mozilla Document";
501 PCSZ pszDocName = title ? title : pszGenericDocName;
502 LONG lResult = DevEscape(mPrintDC, DEVESC_STARTDOC,
503 strlen(pszDocName) + 1, const_cast<BYTE*>(pszDocName),
504 (PLONG)NULL, (PBYTE)NULL);
505 mPrintingStarted = PR_TRUE;
506 if (title) {
507 nsMemory::Free(title);
510 return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTDOC;
513 NS_IMETHODIMP nsDeviceContextSpecOS2::EndDocument()
515 // don't try to send device escapes for non-native output (like PDF)
516 // but clear the filename to make sure that we don't overwrite it next time
517 PRInt16 outputFormat;
518 mPrintSettings->GetOutputFormat(&outputFormat);
519 if (outputFormat != nsIPrintSettings::kOutputFormatNative) {
520 mPrintSettings->SetToFileName(NULL);
521 nsCOMPtr<nsIPrintSettingsService> pss = do_GetService("@mozilla.org/gfx/printsettings-service;1");
522 if (pss)
523 pss->SavePrintSettingsToPrefs(mPrintSettings, PR_TRUE, nsIPrintSettings::kInitSaveToFileName);
524 return NS_OK;
527 LONG lOutCount = 2;
528 USHORT usJobID = 0;
529 LONG lResult = DevEscape(mPrintDC, DEVESC_ENDDOC, 0L, (PBYTE)NULL,
530 &lOutCount, (PBYTE)&usJobID);
531 return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_ENDDOC;
534 NS_IMETHODIMP nsDeviceContextSpecOS2::BeginPage()
536 PRInt16 outputFormat;
537 mPrintSettings->GetOutputFormat(&outputFormat);
538 if (outputFormat != nsIPrintSettings::kOutputFormatNative) {
539 return NS_OK;
542 if (mPrintingStarted) {
543 // we don't want an extra page break at the start of the document
544 mPrintingStarted = PR_FALSE;
545 return NS_OK;
547 LONG lResult = DevEscape(mPrintDC, DEVESC_NEWFRAME, 0L, (PBYTE)NULL,
548 (PLONG)NULL, (PBYTE)NULL);
549 return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTPAGE;
552 NS_IMETHODIMP nsDeviceContextSpecOS2::EndPage()
554 return NS_OK;
557 // Printer Enumerator
558 nsPrinterEnumeratorOS2::nsPrinterEnumeratorOS2()
562 NS_IMPL_ISUPPORTS1(nsPrinterEnumeratorOS2, nsIPrinterEnumerator)
564 NS_IMETHODIMP nsPrinterEnumeratorOS2::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList)
566 NS_ENSURE_ARG_POINTER(aPrinterNameList);
567 *aPrinterNameList = nsnull;
569 nsDeviceContextSpecOS2::PrnDlg.RefreshPrintQueue();
571 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
572 if (NS_FAILED(rv)) {
573 return rv;
576 ULONG numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
577 nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters);
578 if (!printers) {
579 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
580 return NS_ERROR_OUT_OF_MEMORY;
583 ULONG count = 0;
584 while( count < numPrinters )
586 printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++));
588 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
590 return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers);
593 NS_IMETHODIMP nsPrinterEnumeratorOS2::GetDefaultPrinterName(PRUnichar * *aDefaultPrinterName)
595 NS_ENSURE_ARG_POINTER(aDefaultPrinterName);
596 GlobalPrinters::GetInstance()->GetDefaultPrinterName(*aDefaultPrinterName);
597 return NS_OK;
600 /* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */
601 NS_IMETHODIMP nsPrinterEnumeratorOS2::InitPrintSettingsFromPrinter(const PRUnichar *aPrinterName, nsIPrintSettings *aPrintSettings)
603 NS_ENSURE_ARG_POINTER(aPrinterName);
604 NS_ENSURE_ARG_POINTER(aPrintSettings);
606 if (!*aPrinterName)
607 return NS_OK;
609 if (NS_FAILED(GlobalPrinters::GetInstance()->InitializeGlobalPrinters()))
610 return NS_ERROR_FAILURE;
612 ULONG numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
613 for(ULONG i = 0; i < numPrinters; i++) {
614 if ((GlobalPrinters::GetInstance()->GetStringAt(i)->Equals(aPrinterName, nsCaseInsensitiveStringComparator())))
615 nsDeviceContextSpecOS2::SetPrintSettingsFromDevMode(aPrintSettings, i);
618 // Free them, we won't need them for a while
619 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
620 aPrintSettings->SetIsInitializedFromPrinter(PR_TRUE);
621 return NS_OK;
624 NS_IMETHODIMP nsPrinterEnumeratorOS2::DisplayPropertiesDlg(const PRUnichar *aPrinter, nsIPrintSettings *aPrintSettings)
626 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
627 if (NS_FAILED(rv)) {
628 return rv;
631 ULONG numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
632 for(ULONG i = 0; i < numPrinters; i++) {
633 if ((GlobalPrinters::GetInstance()->GetStringAt(i)->Equals(aPrinter, nsCaseInsensitiveStringComparator()))) {
634 SetupDevModeFromSettings(i, aPrintSettings);
635 if ( nsDeviceContextSpecOS2::PrnDlg.ShowProperties(i) ) {
636 nsDeviceContextSpecOS2::SetPrintSettingsFromDevMode(aPrintSettings, i);
637 return NS_OK;
638 } else {
639 return NS_ERROR_FAILURE;
643 return NS_ERROR_FAILURE;
646 nsresult GlobalPrinters::InitializeGlobalPrinters ()
648 if (PrintersAreAllocated())
649 return NS_OK;
651 mGlobalNumPrinters = 0;
652 mGlobalNumPrinters = nsDeviceContextSpecOS2::PrnDlg.GetNumPrinters();
653 if (!mGlobalNumPrinters)
654 return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE;
656 mGlobalPrinterList = new nsTArray<nsString>();
657 if (!mGlobalPrinterList)
658 return NS_ERROR_OUT_OF_MEMORY;
660 nsresult rv;
661 nsCOMPtr<nsIPrefBranch> pPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
662 BOOL prefFailed = NS_FAILED(rv); // don't return on failure, optional feature
664 for (ULONG i = 0; i < mGlobalNumPrinters; i++) {
665 nsXPIDLCString printer;
666 nsDeviceContextSpecOS2::PrnDlg.GetPrinter(i, getter_Copies(printer));
668 nsAutoChar16Buffer printerName;
669 PRInt32 printerNameLength;
670 rv = MultiByteToWideChar(0, printer, strlen(printer),
671 printerName, printerNameLength);
672 mGlobalPrinterList->AppendElement(nsDependentString(printerName.Elements()));
674 // store printer description in prefs for the print dialog
675 if (!prefFailed) {
676 nsCAutoString printerDescription;
677 printerDescription = nsCAutoString(nsDeviceContextSpecOS2::PrnDlg.GetPrintDriver(i)->szDeviceName);
678 printerDescription += " (";
679 printerDescription += nsCAutoString(nsDeviceContextSpecOS2::PrnDlg.GetDriverType(i));
680 printerDescription += ")";
681 pPrefs->SetCharPref(nsPrintfCString(256,
682 "print.printer_%s.printer_description",
683 printer.get()).get(),
684 printerDescription.get());
687 return NS_OK;
690 void GlobalPrinters::GetDefaultPrinterName(PRUnichar*& aDefaultPrinterName)
692 aDefaultPrinterName = nsnull;
694 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
695 if (NS_FAILED(rv))
696 return;
698 if (GetNumPrinters() == 0)
699 return;
701 // the default printer is always index 0
702 nsXPIDLCString printer;
703 nsDeviceContextSpecOS2::PrnDlg.GetPrinter(0, getter_Copies(printer));
705 nsAutoChar16Buffer printerName;
706 PRInt32 printerNameLength;
707 MultiByteToWideChar(0, printer, strlen(printer), printerName,
708 printerNameLength);
709 aDefaultPrinterName = ToNewUnicode(nsDependentString(printerName.Elements()));
711 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
714 void GlobalPrinters::FreeGlobalPrinters()
716 delete mGlobalPrinterList;
717 mGlobalPrinterList = nsnull;
718 mGlobalNumPrinters = 0;