widget/windows/nsDeviceContextSpecWin.cpp

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

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

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

     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"
     9 #include "prmem.h"
    11 #include <winspool.h>
    13 #include <tchar.h>
    15 #include "nsAutoPtr.h"
    16 #include "nsIWidget.h"
    18 #include "nsTArray.h"
    19 #include "nsIPrintSettingsWin.h"
    21 #include "nsString.h"
    22 #include "nsCRT.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"
    38 // File Picker
    39 #include "nsIFile.h"
    40 #include "nsIFilePicker.h"
    41 #include "nsIStringBundle.h"
    42 #define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties"
    44 #include "prlog.h"
    45 #ifdef PR_LOGGING 
    46 PRLogModuleInfo * kWidgetPrintingLogMod = PR_NewLogModule("printing-widget");
    47 #define PR_PL(_p1)  PR_LOG(kWidgetPrintingLogMod, PR_LOG_DEBUG, _p1)
    48 #else
    49 #define PR_PL(_p1)
    50 #endif
    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 {
    61 public:
    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; }
    73 protected:
    74   GlobalPrinters() {}
    75   nsresult EnumerateNativePrinters();
    76   void     ReallocatePrinters();
    78   static GlobalPrinters    mGlobalPrinters;
    79   static nsTArray<LPWSTR>* mPrinters;
    80 };
    81 //---------------
    82 // static members
    83 GlobalPrinters    GlobalPrinters::mGlobalPrinters;
    84 nsTArray<LPWSTR>* GlobalPrinters::mPrinters = nullptr;
    87 //******************************************************
    88 // Define native paper sizes
    89 //******************************************************
    90 typedef struct {
    91   short  mPaperSize; // native enum
    92   double mWidth;
    93   double mHeight;
    94   bool mIsInches;
    95 } NativePaperSizes;
    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},  
   140 };
   141 const int32_t kNumPaperSizes = 41;
   143 //----------------------------------------------------------------------------------
   144 nsDeviceContextSpecWin::nsDeviceContextSpecWin()
   145 {
   146   mDriverName    = nullptr;
   147   mDeviceName    = nullptr;
   148   mDevMode       = nullptr;
   150 }
   153 //----------------------------------------------------------------------------------
   155 NS_IMPL_ISUPPORTS(nsDeviceContextSpecWin, nsIDeviceContextSpec)
   157 nsDeviceContextSpecWin::~nsDeviceContextSpecWin()
   158 {
   159   SetDeviceName(nullptr);
   160   SetDriverName(nullptr);
   161   SetDevMode(nullptr);
   163   nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(mPrintSettings));
   164   if (psWin) {
   165     psWin->SetDeviceName(nullptr);
   166     psWin->SetDriverName(nullptr);
   167     psWin->SetDevMode(nullptr);
   168   }
   170   // Free them, we won't need them for a while
   171   GlobalPrinters::GetInstance()->FreeGlobalPrinters();
   172 }
   175 //------------------------------------------------------------------
   176 // helper
   177 static char16_t * GetDefaultPrinterNameFromGlobalPrinters()
   178 {
   179   nsAutoString printerName;
   180   GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName);
   181   return ToNewUnicode(printerName);
   182 }
   184 //----------------------------------------------------------------------------------
   185 NS_IMETHODIMP nsDeviceContextSpecWin::Init(nsIWidget* aWidget,
   186                                            nsIPrintSettings* aPrintSettings,
   187                                            bool aIsPrintPreview)
   188 {
   189   mPrintSettings = aPrintSettings;
   191   nsresult rv = NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE;
   192   if (aPrintSettings) {
   193     nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings));
   194     if (psWin) {
   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)
   200       LPDEVMODEW devMode;
   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;
   208           if (scale != 1.0) {
   209             aPrintSettings->SetScaling(scale);
   210             devMode->dmScale = 100;
   211           }
   212         }
   214         SetDeviceName(deviceName);
   215         SetDriverName(driverName);
   216         SetDevMode(devMode);
   218         // clean up
   219         free(deviceName);
   220         free(driverName);
   222         return NS_OK;
   223       } else {
   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);
   228       }
   229     }
   230   } else {
   231     PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n"));
   232   }
   234   // Get the Print Name to be used
   235   char16_t * printerName = nullptr;
   236   if (mPrintSettings) {
   237     mPrintSettings->GetPrinterName(&printerName);
   238   }
   240   // If there is no name then use the default printer
   241   if (!printerName || (printerName && !*printerName)) {
   242     printerName = GetDefaultPrinterNameFromGlobalPrinters();
   243   }
   245   NS_ASSERTION(printerName, "We have to have a printer name");
   246   if (!printerName || !*printerName) return rv;
   248   return GetDataFromPrinter(printerName, mPrintSettings);
   249 }
   251 //----------------------------------------------------------
   252 // Helper Function - Free and reallocate the string
   253 static void CleanAndCopyString(wchar_t*& aStr, const wchar_t* aNewStr)
   254 {
   255   if (aStr != nullptr) {
   256     if (aNewStr != nullptr && wcslen(aStr) > wcslen(aNewStr)) { // reuse it if we can
   257       wcscpy(aStr, aNewStr);
   258       return;
   259     } else {
   260       PR_Free(aStr);
   261       aStr = nullptr;
   262     }
   263   }
   265   if (nullptr != aNewStr) {
   266     aStr = (wchar_t *)PR_Malloc(sizeof(wchar_t)*(wcslen(aNewStr) + 1));
   267     wcscpy(aStr, aNewStr);
   268   }
   269 }
   271 NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface)
   272 {
   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);
   280   }
   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);
   294     if (NS_FAILED(rv))
   295       return rv;
   297     nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
   298     rv = stream->Init(file, -1, -1, 0);
   299     if (NS_FAILED(rv))
   300       return rv;
   302     newSurface = new gfxPDFSurface(stream, gfxSize(width, height));
   303   } else {
   304     if (mDevMode) {
   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);
   310     }
   311   }
   313   if (newSurface) {
   314     *surface = newSurface;
   315     NS_ADDREF(*surface);
   316     return NS_OK;
   317   }
   319   *surface = nullptr;
   320   return NS_ERROR_FAILURE;
   321 }
   323 //----------------------------------------------------------------------------------
   324 void nsDeviceContextSpecWin::SetDeviceName(char16ptr_t aDeviceName)
   325 {
   326   CleanAndCopyString(mDeviceName, aDeviceName);
   327 }
   329 //----------------------------------------------------------------------------------
   330 void nsDeviceContextSpecWin::SetDriverName(char16ptr_t aDriverName)
   331 {
   332   CleanAndCopyString(mDriverName, aDriverName);
   333 }
   335 //----------------------------------------------------------------------------------
   336 void nsDeviceContextSpecWin::SetDevMode(LPDEVMODEW aDevMode)
   337 {
   338   if (mDevMode) {
   339     ::HeapFree(::GetProcessHeap(), 0, mDevMode);
   340   }
   342   mDevMode = aDevMode;
   343 }
   345 //------------------------------------------------------------------
   346 void 
   347 nsDeviceContextSpecWin::GetDevMode(LPDEVMODEW &aDevMode)
   348 {
   349   aDevMode = mDevMode;
   350 }
   352 //----------------------------------------------------------------------------------
   353 // Map an incoming size to a Windows Native enum in the DevMode
   354 static void 
   355 MapPaperSizeToNativeEnum(LPDEVMODEW aDevMode,
   356                          int16_t   aType, 
   357                          double    aW, 
   358                          double    aH)
   359 {
   361 #ifdef DEBUG_rods
   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;
   366 #endif
   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;
   374       return;
   375     }
   376   }
   378   short width  = 0;
   379   short height = 0;
   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);
   387   } else {
   388     return; // don't set anything
   389   }
   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;
   399 }
   401 //----------------------------------------------------------------------------------
   402 // Setup Paper Size & Orientation options into the DevMode
   403 // 
   404 static void 
   405 SetupDevModeFromSettings(LPDEVMODEW aDevMode, nsIPrintSettings* aPrintSettings)
   406 {
   407   // Setup paper size
   408   if (aPrintSettings) {
   409     int16_t type;
   410     aPrintSettings->GetPaperSizeType(&type);
   411     if (type == nsIPrintSettings::kPaperSizeNativeData) {
   412       int16_t paperEnum;
   413       aPrintSettings->GetPaperData(&paperEnum);
   414       aDevMode->dmPaperSize = paperEnum;
   415       aDevMode->dmFields &= ~DM_PAPERLENGTH;
   416       aDevMode->dmFields &= ~DM_PAPERWIDTH;
   417       aDevMode->dmFields |= DM_PAPERSIZE;
   418     } else {
   419       int16_t unit;
   420       double width, height;
   421       aPrintSettings->GetPaperSizeUnit(&unit);
   422       aPrintSettings->GetPaperWidth(&width);
   423       aPrintSettings->GetPaperHeight(&height);
   424       MapPaperSizeToNativeEnum(aDevMode, unit, width, height);
   425     }
   427     // Setup Orientation
   428     int32_t orientation;
   429     aPrintSettings->GetOrientation(&orientation);
   430     aDevMode->dmOrientation = orientation == nsIPrintSettings::kPortraitOrientation?DMORIENT_PORTRAIT:DMORIENT_LANDSCAPE;
   431     aDevMode->dmFields |= DM_ORIENTATION;
   433     // Setup Number of Copies
   434     int32_t copies;
   435     aPrintSettings->GetNumCopies(&copies);
   436     aDevMode->dmCopies = copies;
   437     aDevMode->dmFields |= DM_COPIES;
   438   }
   440 }
   442 #define DISPLAY_LAST_ERROR 
   444 //----------------------------------------------------------------------------------
   445 // Setup the object's data member with the selected printer's data
   446 nsresult
   447 nsDeviceContextSpecWin::GetDataFromPrinter(char16ptr_t aName, nsIPrintSettings* aPS)
   448 {
   449   nsresult rv = NS_ERROR_FAILURE;
   451   if (!GlobalPrinters::GetInstance()->PrintersAreAllocated()) {
   452     rv = GlobalPrinters::GetInstance()->EnumeratePrinterList();
   453     if (NS_FAILED(rv)) {
   454       PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't enumerate printers!\n"));
   455       DISPLAY_LAST_ERROR
   456     }
   457     NS_ENSURE_SUCCESS(rv, rv);
   458   }
   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);
   464   if (status) {
   466     LPDEVMODEW   pDevMode;
   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,
   483                                    pDevMode, pDevMode,
   484                                    DM_IN_BUFFER | DM_OUT_BUFFER);
   485     }
   487     if (dwRet != IDOK) {
   488       ::HeapFree(::GetProcessHeap(), 0, pDevMode);
   489       ::ClosePrinter(hPrinter);
   490       PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - DocumentProperties call failed code: %d/0x%x\n", dwRet, dwRet));
   491       DISPLAY_LAST_ERROR
   492       return NS_ERROR_FAILURE;
   493     }
   495     SetDevMode(pDevMode); // cache the pointer and takes responsibility for the memory
   497     SetDeviceName(aName);
   499     SetDriverName(L"WINSPOOL");
   501     ::ClosePrinter(hPrinter);
   502     rv = NS_OK;
   503   } else {
   504     rv = NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
   505     PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't open printer: [%s]\n", NS_ConvertUTF16toUTF8(aName).get()));
   506     DISPLAY_LAST_ERROR
   507   }
   508   return rv;
   509 }
   511 //----------------------------------------------------------------------------------
   512 // Setup Paper Size options into the DevMode
   513 // 
   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.
   517 void 
   518 nsDeviceContextSpecWin::SetupPaperInfoFromSettings()
   519 {
   520   LPDEVMODEW devMode;
   522   GetDevMode(devMode);
   523   NS_ASSERTION(devMode, "DevMode can't be NULL here");
   524   if (devMode) {
   525     SetupDevModeFromSettings(devMode, mPrintSettings);
   526   }
   527 }
   529 //----------------------------------------------------------------------------------
   530 // Helper Function - Free and reallocate the string
   531 nsresult 
   532 nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings, 
   533                                                     LPDEVMODEW         aDevMode)
   534 {
   535   if (aPrintSettings == nullptr) {
   536     return NS_ERROR_FAILURE;
   537   }
   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);
   550   }
   552   // Setup Number of Copies
   553   if (doingNumCopies) {
   554     aPrintSettings->SetNumCopies(int32_t(aDevMode->dmCopies));
   555   }
   557   if (aDevMode->dmFields & DM_SCALE) {
   558     double scale = double(aDevMode->dmScale) / 100.0f;
   559     if (scale != 1.0) {
   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);
   564     }
   565   }
   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);
   574         break;
   575       }
   576     }
   578   } else if (doingPaperLength && doingPaperWidth) {
   579     bool found = false;
   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);
   587         found = true;
   588         break;
   589       }
   590     }
   591     if (!found) {
   592       return NS_ERROR_FAILURE;
   593     }
   594   } else {
   595     return NS_ERROR_FAILURE;
   596   }
   597   return NS_OK;
   598 }
   600 //***********************************************************
   601 //  Printer Enumerator
   602 //***********************************************************
   603 nsPrinterEnumeratorWin::nsPrinterEnumeratorWin()
   604 {
   605 }
   607 nsPrinterEnumeratorWin::~nsPrinterEnumeratorWin()
   608 {
   609   // Do not free printers here
   610   // GlobalPrinters::GetInstance()->FreeGlobalPrinters();
   611 }
   613 NS_IMPL_ISUPPORTS(nsPrinterEnumeratorWin, nsIPrinterEnumerator)
   615 //----------------------------------------------------------------------------------
   616 // Return the Default Printer name
   617 /* readonly attribute wstring defaultPrinterName; */
   618 NS_IMETHODIMP 
   619 nsPrinterEnumeratorWin::GetDefaultPrinterName(char16_t * *aDefaultPrinterName)
   620 {
   621   NS_ENSURE_ARG_POINTER(aDefaultPrinterName);
   623   *aDefaultPrinterName = GetDefaultPrinterNameFromGlobalPrinters(); // helper
   625   return NS_OK;
   626 }
   628 /* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */
   629 NS_IMETHODIMP 
   630 nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings)
   631 {
   632   NS_ENSURE_ARG_POINTER(aPrinterName);
   633   NS_ENSURE_ARG_POINTER(aPrintSettings);
   635   if (!*aPrinterName) {
   636     return NS_OK;
   637   }
   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;
   644   }
   646   devSpecWin->GetDataFromPrinter(aPrinterName);
   648   LPDEVMODEW devmode;
   649   devSpecWin->GetDevMode(devmode);
   650   NS_ASSERTION(devmode, "DevMode can't be NULL here");
   651   if (devmode) {
   652     aPrintSettings->SetPrinterName(aPrinterName);
   653     nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(aPrintSettings, devmode);
   654   }
   656   // Free them, we won't need them for a while
   657   GlobalPrinters::GetInstance()->FreeGlobalPrinters();
   658   return NS_OK;
   659 }
   662 //----------------------------------------------------------------------------------
   663 // Enumerate all the Printers from the global array and pass their
   664 // names back (usually to script)
   665 NS_IMETHODIMP 
   666 nsPrinterEnumeratorWin::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList)
   667 {
   668   NS_ENSURE_ARG_POINTER(aPrinterNameList);
   669   *aPrinterNameList = nullptr;
   671   nsresult rv = GlobalPrinters::GetInstance()->EnumeratePrinterList();
   672   if (NS_FAILED(rv)) {
   673     PR_PL(("***** nsDeviceContextSpecWin::GetPrinterNameList - Couldn't enumerate printers!\n"));
   674     return rv;
   675   }
   677   uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
   678   nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters);
   679   if (!printers)
   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));
   686   }
   688   return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers);
   689 }
   691 //----------------------------------------------------------------------------------
   692 // Display the AdvancedDocumentProperties for the selected Printer
   693 NS_IMETHODIMP nsPrinterEnumeratorWin::DisplayPropertiesDlg(const char16_t *aPrinterName, nsIPrintSettings* aPrintSettings)
   694 {
   695   // Implementation removed because it is unused
   696   return NS_OK;
   697 }
   699 //----------------------------------------------------------------------------------
   700 //-- Global Printers
   701 //----------------------------------------------------------------------------------
   703 //----------------------------------------------------------------------------------
   704 // THe array hold the name and port for each printer
   705 void 
   706 GlobalPrinters::ReallocatePrinters()
   707 {
   708   if (PrintersAreAllocated()) {
   709     FreeGlobalPrinters();
   710   }
   711   mPrinters = new nsTArray<LPWSTR>();
   712   NS_ASSERTION(mPrinters, "Printers Array is NULL!");
   713 }
   715 //----------------------------------------------------------------------------------
   716 void 
   717 GlobalPrinters::FreeGlobalPrinters()
   718 {
   719   if (mPrinters != nullptr) {
   720     for (uint32_t i=0;i<mPrinters->Length();i++) {
   721       free(mPrinters->ElementAt(i));
   722     }
   723     delete mPrinters;
   724     mPrinters = nullptr;
   725   }
   726 }
   728 //----------------------------------------------------------------------------------
   729 nsresult 
   730 GlobalPrinters::EnumerateNativePrinters()
   731 {
   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));
   740   if (status > 0) {
   741     DWORD count = 0;
   742     LPWSTR sPtr   = szDefaultPrinterName;
   743     LPWSTR ePtr   = szDefaultPrinterName + status;
   744     LPWSTR prvPtr = sPtr;
   745     while (sPtr < ePtr) {
   746       if (*sPtr == 0) {
   747         LPWSTR name = wcsdup(prvPtr);
   748         mPrinters->AppendElement(name);
   749         PR_PL(("Printer Name:    %s\n", prvPtr));
   750         prvPtr = sPtr+1;
   751         count++;
   752       }
   753       sPtr++;
   754     }
   755     rv = NS_OK;
   756   }
   757   PR_PL(("-----------------------\n"));
   758   return rv;
   759 }
   761 //------------------------------------------------------------------
   762 // Uses the GetProfileString to get the default printer from the registry
   763 void 
   764 GlobalPrinters::GetDefaultPrinterName(nsString& aDefaultPrinterName)
   765 {
   766   aDefaultPrinterName.Truncate();
   767   WCHAR szDefaultPrinterName[1024];    
   768   DWORD status = GetProfileStringW(L"windows", L"device", 0,
   769                                    szDefaultPrinterName,
   770                                    ArrayLength(szDefaultPrinterName));
   771   if (status > 0) {
   772     WCHAR comma = ',';
   773     LPWSTR sPtr = szDefaultPrinterName;
   774     while (*sPtr != comma && *sPtr != 0) 
   775       sPtr++;
   776     if (*sPtr == comma) {
   777       *sPtr = 0;
   778     }
   779     aDefaultPrinterName = szDefaultPrinterName;
   780   } else {
   781     aDefaultPrinterName = EmptyString();
   782   }
   784   PR_PL(("DEFAULT PRINTER [%s]\n", aDefaultPrinterName.get()));
   785 }
   787 //----------------------------------------------------------------------------------
   788 // This goes and gets the list of available printers and puts
   789 // the default printer at the beginning of the list
   790 nsresult 
   791 GlobalPrinters::EnumeratePrinterList()
   792 {
   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)) {
   811         if (i > 0) {
   812           LPWSTR ptr = mPrinters->ElementAt(0);
   813           mPrinters->ElementAt(0) = name;
   814           mPrinters->ElementAt(i) = ptr;
   815         }
   816         break;
   817       }
   818     }
   819   }
   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;
   825   }
   827   return NS_OK;
   828 }

mercurial