ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

printdlg.c
Go to the documentation of this file.
00001 /*
00002  * COMMDLG - Print Dialog
00003  *
00004  * Copyright 1994 Martin Ayotte
00005  * Copyright 1996 Albrecht Kleine
00006  * Copyright 1999 Klaas van Gend
00007  * Copyright 2000 Huw D M Davies
00008  * Copyright 2010 Vitaly Perov
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 #include <ctype.h>
00025 #include <stdlib.h>
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <assert.h>
00030 
00031 #define NONAMELESSUNION
00032 #define NONAMELESSSTRUCT
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "wingdi.h"
00036 #include "winuser.h"
00037 #include "winspool.h"
00038 #include "winerror.h"
00039 
00040 #include "wine/unicode.h"
00041 #include "wine/debug.h"
00042 
00043 #include "commdlg.h"
00044 #include "dlgs.h"
00045 #include "cderr.h"
00046 #include "cdlg.h"
00047 
00048 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
00049 
00050 /* Yes these constants are the same, but we're just copying win98 */
00051 #define UPDOWN_ID 0x270f
00052 #define MAX_COPIES 9999
00053 
00054 /* This PRINTDLGA internal structure stores
00055  * pointers to several throughout useful structures.
00056  */
00057 
00058 typedef struct
00059 {
00060   LPDEVMODEA        lpDevMode;
00061   LPPRINTDLGA       lpPrintDlg;
00062   LPPRINTER_INFO_2A lpPrinterInfo;
00063   LPDRIVER_INFO_3A  lpDriverInfo;
00064   UINT              HelpMessageID;
00065   HICON             hCollateIcon;    /* PrintDlg only */
00066   HICON             hNoCollateIcon;  /* PrintDlg only */
00067   HICON             hPortraitIcon;   /* PrintSetupDlg only */
00068   HICON             hLandscapeIcon;  /* PrintSetupDlg only */
00069   HWND              hwndUpDown;
00070 } PRINT_PTRA;
00071 
00072 typedef struct
00073 {
00074   LPDEVMODEW        lpDevMode;
00075   LPPRINTDLGW       lpPrintDlg;
00076   LPPRINTER_INFO_2W lpPrinterInfo;
00077   LPDRIVER_INFO_3W  lpDriverInfo;
00078   UINT              HelpMessageID;
00079   HICON             hCollateIcon;    /* PrintDlg only */
00080   HICON             hNoCollateIcon;  /* PrintDlg only */
00081   HICON             hPortraitIcon;   /* PrintSetupDlg only */
00082   HICON             hLandscapeIcon;  /* PrintSetupDlg only */
00083   HWND              hwndUpDown;
00084 } PRINT_PTRW;
00085 
00086 /* Debugging info */
00087 struct pd_flags
00088 {
00089   DWORD  flag;
00090   LPCSTR name;
00091 };
00092 
00093 static const struct pd_flags psd_flags[] = {
00094   {PSD_MINMARGINS,"PSD_MINMARGINS"},
00095   {PSD_MARGINS,"PSD_MARGINS"},
00096   {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
00097   {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
00098   {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
00099   {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
00100   {PSD_NOWARNING,"PSD_NOWARNING"},
00101   {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
00102   {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
00103   {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
00104   {PSD_SHOWHELP,"PSD_SHOWHELP"},
00105   {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
00106   {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
00107   {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
00108   {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
00109   {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
00110   {-1, NULL}
00111 };
00112 
00113 static const struct pd_flags pd_flags[] = {
00114   {PD_SELECTION, "PD_SELECTION "},
00115   {PD_PAGENUMS, "PD_PAGENUMS "},
00116   {PD_NOSELECTION, "PD_NOSELECTION "},
00117   {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
00118   {PD_COLLATE, "PD_COLLATE "},
00119   {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
00120   {PD_PRINTSETUP, "PD_PRINTSETUP "},
00121   {PD_NOWARNING, "PD_NOWARNING "},
00122   {PD_RETURNDC, "PD_RETURNDC "},
00123   {PD_RETURNIC, "PD_RETURNIC "},
00124   {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
00125   {PD_SHOWHELP, "PD_SHOWHELP "},
00126   {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
00127   {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
00128   {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
00129   {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
00130   {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
00131   {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
00132   {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
00133   {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
00134   {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
00135   {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
00136   {-1, NULL}
00137 };
00138 /* address of wndproc for subclassed Static control */
00139 static WNDPROC lpfnStaticWndProc;
00140 static WNDPROC edit_wndproc;
00141 /* the text of the fake document to render for the Page Setup dialog */
00142 static WCHAR wszFakeDocumentText[1024];
00143 static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
00144 static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
00145 static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
00146 static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
00147 static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
00148 static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
00149                                            'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
00150 
00151 
00152 static LPWSTR strdupW(LPCWSTR p)
00153 {
00154     LPWSTR ret;
00155     DWORD len;
00156 
00157     if(!p) return NULL;
00158     len = (strlenW(p) + 1) * sizeof(WCHAR);
00159     ret = HeapAlloc(GetProcessHeap(), 0, len);
00160     memcpy(ret, p, len);
00161     return ret;
00162 }
00163 
00164 /***********************************************************
00165  * convert_to_devmodeA
00166  *
00167  * Creates an ansi copy of supplied devmode
00168  */
00169 static DEVMODEA *convert_to_devmodeA(const DEVMODEW *dmW)
00170 {
00171     DEVMODEA *dmA;
00172     DWORD size;
00173 
00174     if (!dmW) return NULL;
00175     size = dmW->dmSize - CCHDEVICENAME -
00176                         ((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
00177 
00178     dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra);
00179     if (!dmA) return NULL;
00180 
00181     WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1,
00182                         (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
00183 
00184     if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
00185     {
00186         memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
00187                dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
00188     }
00189     else
00190     {
00191         memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
00192                FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
00193         WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1,
00194                             (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
00195 
00196         memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
00197     }
00198 
00199     dmA->dmSize = size;
00200     memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
00201     return dmA;
00202 }
00203 
00204 /***********************************************************************
00205  *    PRINTDLG_OpenDefaultPrinter
00206  *
00207  * Returns a winspool printer handle to the default printer in *hprn
00208  * Caller must call ClosePrinter on the handle
00209  *
00210  * Returns TRUE on success else FALSE
00211  */
00212 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
00213 {
00214     WCHAR buf[260];
00215     DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
00216     BOOL res;
00217     if(!GetDefaultPrinterW(buf, &dwBufLen))
00218         return FALSE;
00219     res = OpenPrinterW(buf, hprn, NULL);
00220     if (!res)
00221         WARN("Could not open printer %s\n", debugstr_w(buf));
00222     return res;
00223 }
00224 
00225 /***********************************************************************
00226  *    PRINTDLG_SetUpPrinterListCombo
00227  *
00228  * Initializes printer list combox.
00229  * hDlg:  HWND of dialog
00230  * id:    Control id of combo
00231  * name:  Name of printer to select
00232  *
00233  * Initializes combo with list of available printers.  Selects printer 'name'
00234  * If name is NULL or does not exist select the default printer.
00235  *
00236  * Returns number of printers added to list.
00237  */
00238 static INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
00239 {
00240     DWORD needed, num;
00241     INT i;
00242     LPPRINTER_INFO_2A pi;
00243     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
00244     pi = HeapAlloc(GetProcessHeap(), 0, needed);
00245     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
00246           &num);
00247 
00248     SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
00249     
00250     for(i = 0; i < num; i++) {
00251         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
00252                 (LPARAM)pi[i].pPrinterName );
00253     }
00254     HeapFree(GetProcessHeap(), 0, pi);
00255     if(!name ||
00256        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
00257                 (LPARAM)name)) == CB_ERR) {
00258 
00259         char buf[260];
00260         DWORD dwBufLen = sizeof(buf);
00261         if (name != NULL)
00262             WARN("Can't find %s in printer list so trying to find default\n",
00263             debugstr_a(name));
00264     if(!GetDefaultPrinterA(buf, &dwBufLen))
00265         return num;
00266     i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
00267     if(i == CB_ERR)
00268         FIXME("Can't find default printer in printer list\n");
00269     }
00270     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
00271     return num;
00272 }
00273 
00274 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
00275 {
00276     DWORD needed, num;
00277     INT i;
00278     LPPRINTER_INFO_2W pi;
00279     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
00280     pi = HeapAlloc(GetProcessHeap(), 0, needed);
00281     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
00282           &num);
00283 
00284     for(i = 0; i < num; i++) {
00285         SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
00286                 (LPARAM)pi[i].pPrinterName );
00287     }
00288     HeapFree(GetProcessHeap(), 0, pi);
00289     if(!name ||
00290        (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
00291                 (LPARAM)name)) == CB_ERR) {
00292         WCHAR buf[260];
00293         DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
00294         if (name != NULL)
00295             WARN("Can't find %s in printer list so trying to find default\n",
00296             debugstr_w(name));
00297     if(!GetDefaultPrinterW(buf, &dwBufLen))
00298         return num;
00299     i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
00300     if(i == CB_ERR)
00301         TRACE("Can't find default printer in printer list\n");
00302     }
00303     SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
00304     return num;
00305 }
00306 
00307 /***********************************************************************
00308  *             PRINTDLG_CreateDevNames          [internal]
00309  *
00310  *
00311  *   creates a DevNames structure.
00312  *
00313  *  (NB. when we handle unicode the offsets will be in wchars).
00314  */
00315 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
00316                     const char* DeviceName, const char* OutputPort)
00317 {
00318     long size;
00319     char*   pDevNamesSpace;
00320     char*   pTempPtr;
00321     LPDEVNAMES lpDevNames;
00322     char buf[260];
00323     DWORD dwBufLen = sizeof(buf);
00324 
00325     size = strlen(DeviceDriverName) + 1
00326             + strlen(DeviceName) + 1
00327             + strlen(OutputPort) + 1
00328             + sizeof(DEVNAMES);
00329 
00330     if(*hmem)
00331         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
00332     else
00333         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
00334     if (*hmem == 0)
00335         return FALSE;
00336 
00337     pDevNamesSpace = GlobalLock(*hmem);
00338     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
00339 
00340     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
00341     strcpy(pTempPtr, DeviceDriverName);
00342     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
00343 
00344     pTempPtr += strlen(DeviceDriverName) + 1;
00345     strcpy(pTempPtr, DeviceName);
00346     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
00347 
00348     pTempPtr += strlen(DeviceName) + 1;
00349     strcpy(pTempPtr, OutputPort);
00350     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
00351 
00352     GetDefaultPrinterA(buf, &dwBufLen);
00353     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
00354     GlobalUnlock(*hmem);
00355     return TRUE;
00356 }
00357 
00358 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
00359                     LPCWSTR DeviceName, LPCWSTR OutputPort)
00360 {
00361     long size;
00362     LPWSTR   pDevNamesSpace;
00363     LPWSTR   pTempPtr;
00364     LPDEVNAMES lpDevNames;
00365     WCHAR bufW[260];
00366     DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
00367 
00368     size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
00369             + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
00370             + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
00371             + sizeof(DEVNAMES);
00372 
00373     if(*hmem)
00374         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
00375     else
00376         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
00377     if (*hmem == 0)
00378         return FALSE;
00379 
00380     pDevNamesSpace = GlobalLock(*hmem);
00381     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
00382 
00383     pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
00384     lstrcpyW(pTempPtr, DeviceDriverName);
00385     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
00386 
00387     pTempPtr += lstrlenW(DeviceDriverName) + 1;
00388     lstrcpyW(pTempPtr, DeviceName);
00389     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
00390 
00391     pTempPtr += lstrlenW(DeviceName) + 1;
00392     lstrcpyW(pTempPtr, OutputPort);
00393     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
00394 
00395     GetDefaultPrinterW(bufW, &dwBufLen);
00396     lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
00397     GlobalUnlock(*hmem);
00398     return TRUE;
00399 }
00400 
00401 /***********************************************************************
00402  *             PRINTDLG_UpdatePrintDlg          [internal]
00403  *
00404  *
00405  *   updates the PrintDlg structure for return values.
00406  *
00407  * RETURNS
00408  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
00409  *   TRUE  if successful.
00410  */
00411 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
00412                     PRINT_PTRA* PrintStructures)
00413 {
00414     LPPRINTDLGA       lppd = PrintStructures->lpPrintDlg;
00415     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
00416     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
00417 
00418 
00419     if(!lpdm) {
00420     FIXME("No lpdm ptr?\n");
00421     return FALSE;
00422     }
00423 
00424 
00425     if(!(lppd->Flags & PD_PRINTSETUP)) {
00426         /* check whether nFromPage and nToPage are within range defined by
00427      * nMinPage and nMaxPage
00428      */
00429         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
00430         WORD nToPage;
00431         WORD nFromPage;
00432             BOOL translated;
00433         nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
00434         nToPage   = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
00435 
00436         /* if no ToPage value is entered, use the FromPage value */
00437         if(!translated) nToPage = nFromPage;
00438 
00439         if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
00440         nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
00441             WCHAR resourcestr[256];
00442         WCHAR resultstr[256];
00443         LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, resourcestr, 255);
00444         wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
00445         LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
00446         MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
00447         return FALSE;
00448         }
00449         lppd->nFromPage = nFromPage;
00450         lppd->nToPage   = nToPage;
00451         lppd->Flags |= PD_PAGENUMS;
00452     }
00453     else
00454         lppd->Flags &= ~PD_PAGENUMS;
00455 
00456         if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
00457             lppd->Flags |= PD_SELECTION;
00458         else
00459             lppd->Flags &= ~PD_SELECTION;
00460 
00461     if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
00462         static char file[] = "FILE:";
00463         lppd->Flags |= PD_PRINTTOFILE;
00464         pi->pPortName = file;
00465     }
00466 
00467     if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
00468         FIXME("Collate lppd not yet implemented as output\n");
00469     }
00470 
00471     /* set PD_Collate and nCopies */
00472     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
00473       /*  The application doesn't support multiple copies or collate...
00474        */
00475         lppd->Flags &= ~PD_COLLATE;
00476         lppd->nCopies = 1;
00477       /* if the printer driver supports it... store info there
00478        * otherwise no collate & multiple copies !
00479        */
00480         if (lpdm->dmFields & DM_COLLATE)
00481             lpdm->dmCollate =
00482           (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
00483         if (lpdm->dmFields & DM_COPIES)
00484             lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
00485     } else {
00486             /* Application is responsible for multiple copies */
00487         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
00488             lppd->Flags |= PD_COLLATE;
00489             else
00490                lppd->Flags &= ~PD_COLLATE;
00491             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
00492             /* multiple copies already included in the document. Driver must print only one copy */
00493             lpdm->u1.s1.dmCopies = 1;
00494     }
00495 
00496     /* Print quality, PrintDlg16 */
00497     if(GetDlgItem(hDlg, cmb1))
00498     {
00499         HWND hQuality = GetDlgItem(hDlg, cmb1);
00500         int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
00501 
00502         if(Sel != CB_ERR)
00503         {
00504         LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
00505         lpdm->dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
00506         lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
00507         lpdm->dmYResolution = HIWORD(dpi);
00508         }
00509     }
00510     }
00511     return TRUE;
00512 }
00513 
00514 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
00515                     PRINT_PTRW* PrintStructures)
00516 {
00517     LPPRINTDLGW       lppd = PrintStructures->lpPrintDlg;
00518     PDEVMODEW         lpdm = PrintStructures->lpDevMode;
00519     LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
00520 
00521 
00522     if(!lpdm) {
00523     FIXME("No lpdm ptr?\n");
00524     return FALSE;
00525     }
00526 
00527 
00528     if(!(lppd->Flags & PD_PRINTSETUP)) {
00529         /* check whether nFromPage and nToPage are within range defined by
00530      * nMinPage and nMaxPage
00531      */
00532         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
00533         WORD nToPage;
00534         WORD nFromPage;
00535             BOOL translated;
00536         nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
00537         nToPage   = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
00538 
00539         /* if no ToPage value is entered, use the FromPage value */
00540         if(!translated) nToPage = nFromPage;
00541 
00542         if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
00543         nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
00544             WCHAR resourcestr[256];
00545         WCHAR resultstr[256];
00546                 DWORD_PTR args[2];
00547         LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
00548                 resourcestr, 255);
00549                 args[0] = lppd->nMinPage;
00550                 args[1] = lppd->nMaxPage;
00551                 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
00552                                resourcestr, 0, 0, resultstr,
00553                                sizeof(resultstr)/sizeof(*resultstr),
00554                                (__ms_va_list*)args);
00555         LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
00556                 resourcestr, 255);
00557         MessageBoxW(hDlg, resultstr, resourcestr,
00558                 MB_OK | MB_ICONWARNING);
00559         return FALSE;
00560         }
00561         lppd->nFromPage = nFromPage;
00562         lppd->nToPage   = nToPage;
00563         lppd->Flags |= PD_PAGENUMS;
00564     }
00565     else
00566         lppd->Flags &= ~PD_PAGENUMS;
00567 
00568         if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
00569             lppd->Flags |= PD_SELECTION;
00570         else
00571             lppd->Flags &= ~PD_SELECTION;
00572 
00573     if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
00574         static WCHAR file[] = {'F','I','L','E',':',0};
00575         lppd->Flags |= PD_PRINTTOFILE;
00576         pi->pPortName = file;
00577     }
00578 
00579     if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
00580         FIXME("Collate lppd not yet implemented as output\n");
00581     }
00582 
00583     /* set PD_Collate and nCopies */
00584     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
00585       /*  The application doesn't support multiple copies or collate...
00586        */
00587         lppd->Flags &= ~PD_COLLATE;
00588         lppd->nCopies = 1;
00589       /* if the printer driver supports it... store info there
00590        * otherwise no collate & multiple copies !
00591        */
00592         if (lpdm->dmFields & DM_COLLATE)
00593             lpdm->dmCollate =
00594           (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
00595         if (lpdm->dmFields & DM_COPIES)
00596             lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
00597     } else {
00598         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
00599             lppd->Flags |= PD_COLLATE;
00600             else
00601                lppd->Flags &= ~PD_COLLATE;
00602             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
00603     }
00604     }
00605     return TRUE;
00606 }
00607 
00608 /************************************************************************
00609  * PRINTDLG_SetUpPaperComboBox
00610  *
00611  * Initialize either the papersize or inputslot combos of the Printer Setup
00612  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
00613  * We also try to re-select the old selection.
00614  */
00615 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
00616                     int   nIDComboBox,
00617                     char* PrinterName,
00618                     char* PortName,
00619                     LPDEVMODEA dm)
00620 {
00621     int     i;
00622     int     NrOfEntries;
00623     char*   Names;
00624     WORD*   Words;
00625     DWORD   Sel, old_Sel;
00626     WORD    oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
00627     int     NamesSize;
00628     int     fwCapability_Names;
00629     int     fwCapability_Words;
00630 
00631     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
00632 
00633     /* query the dialog box for the current selected value */
00634     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
00635     if(Sel != CB_ERR) {
00636         /* we enter here only if a different printer is selected after
00637          * the Print Setup dialog is opened. The current settings are
00638          * stored into the newly selected printer.
00639          */
00640         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
00641                                       Sel, 0);
00642         if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
00643             oldWord = 0; /* There's no point in trying to keep custom
00644                             paper / bin sizes across printers */
00645     }
00646 
00647     if (dm)
00648         newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
00649 
00650     if (nIDComboBox == cmb2) {
00651          NamesSize          = 64;
00652          fwCapability_Names = DC_PAPERNAMES;
00653          fwCapability_Words = DC_PAPERS;
00654     } else {
00655          nIDComboBox        = cmb3;
00656          NamesSize          = 24;
00657          fwCapability_Names = DC_BINNAMES;
00658          fwCapability_Words = DC_BINS;
00659     }
00660 
00661     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
00662                                       fwCapability_Names, NULL, dm);
00663     if (NrOfEntries == 0)
00664          WARN("no Name Entries found!\n");
00665     else if (NrOfEntries < 0)
00666          return FALSE;
00667 
00668     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
00669        != NrOfEntries) {
00670         ERR("Number of caps is different\n");
00671     NrOfEntries = 0;
00672     }
00673 
00674     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
00675     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
00676     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
00677                                       fwCapability_Names, Names, dm);
00678     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
00679                       fwCapability_Words, (LPSTR)Words, dm);
00680 
00681     /* reset any current content in the combobox */
00682     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
00683 
00684     /* store new content */
00685     for (i = 0; i < NrOfEntries; i++) {
00686         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
00687                     (LPARAM)(&Names[i*NamesSize]) );
00688     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
00689                 Words[i]);
00690     }
00691 
00692     /* Look for old selection or the new default.
00693        Can't do this is previous loop since item order will change as more items are added */
00694     Sel = 0;
00695     old_Sel = NrOfEntries;
00696     for (i = 0; i < NrOfEntries; i++) {
00697         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
00698        oldWord) {
00699         old_Sel = i;
00700         break;
00701     }
00702         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
00703         Sel = i;
00704     }
00705 
00706     if(old_Sel < NrOfEntries)
00707     {
00708         if (dm)
00709         {
00710             if(nIDComboBox == cmb2)
00711                 dm->u1.s1.dmPaperSize = oldWord;
00712             else
00713                 dm->u1.s1.dmDefaultSource = oldWord;
00714         }
00715         Sel = old_Sel;
00716     }
00717 
00718     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
00719 
00720     HeapFree(GetProcessHeap(),0,Words);
00721     HeapFree(GetProcessHeap(),0,Names);
00722     return TRUE;
00723 }
00724 
00725 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
00726                     int   nIDComboBox,
00727                     const WCHAR* PrinterName,
00728                     const WCHAR* PortName,
00729                     LPDEVMODEW dm)
00730 {
00731     int     i;
00732     int     NrOfEntries;
00733     WCHAR*  Names;
00734     WORD*   Words;
00735     DWORD   Sel, old_Sel;
00736     WORD    oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
00737     int     NamesSize;
00738     int     fwCapability_Names;
00739     int     fwCapability_Words;
00740 
00741     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
00742 
00743     /* query the dialog box for the current selected value */
00744     Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
00745     if(Sel != CB_ERR) {
00746         /* we enter here only if a different printer is selected after
00747          * the Print Setup dialog is opened. The current settings are
00748          * stored into the newly selected printer.
00749          */
00750         oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
00751                                       Sel, 0);
00752 
00753         if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
00754             oldWord = 0; /* There's no point in trying to keep custom
00755                             paper / bin sizes across printers */
00756     }
00757 
00758     if (dm)
00759         newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
00760 
00761     if (nIDComboBox == cmb2) {
00762          NamesSize          = 64;
00763          fwCapability_Names = DC_PAPERNAMES;
00764          fwCapability_Words = DC_PAPERS;
00765     } else {
00766          nIDComboBox        = cmb3;
00767          NamesSize          = 24;
00768          fwCapability_Names = DC_BINNAMES;
00769          fwCapability_Words = DC_BINS;
00770     }
00771 
00772     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
00773                                       fwCapability_Names, NULL, dm);
00774     if (NrOfEntries == 0)
00775          WARN("no Name Entries found!\n");
00776     else if (NrOfEntries < 0)
00777          return FALSE;
00778 
00779     if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
00780        != NrOfEntries) {
00781         ERR("Number of caps is different\n");
00782     NrOfEntries = 0;
00783     }
00784 
00785     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
00786     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
00787     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
00788                                       fwCapability_Names, Names, dm);
00789     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
00790                                       fwCapability_Words, Words, dm);
00791 
00792     /* reset any current content in the combobox */
00793     SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
00794 
00795     /* store new content */
00796     for (i = 0; i < NrOfEntries; i++) {
00797         DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
00798                     (LPARAM)(&Names[i*NamesSize]) );
00799     SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
00800                 Words[i]);
00801     }
00802 
00803     /* Look for old selection or the new default.
00804        Can't do this is previous loop since item order will change as more items are added */
00805     Sel = 0;
00806     old_Sel = NrOfEntries;
00807     for (i = 0; i < NrOfEntries; i++) {
00808         if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
00809        oldWord) {
00810         old_Sel = i;
00811         break;
00812     }
00813         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
00814             Sel = i;
00815     }
00816 
00817     if(old_Sel < NrOfEntries)
00818     {
00819         if (dm)
00820         {
00821             if(nIDComboBox == cmb2)
00822                 dm->u1.s1.dmPaperSize = oldWord;
00823             else
00824                 dm->u1.s1.dmDefaultSource = oldWord;
00825         }
00826         Sel = old_Sel;
00827     }
00828 
00829     SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
00830 
00831     HeapFree(GetProcessHeap(),0,Words);
00832     HeapFree(GetProcessHeap(),0,Names);
00833     return TRUE;
00834 }
00835 
00836 
00837 /***********************************************************************
00838  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
00839  */
00840 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, const PRINTER_INFO_2A *pi)
00841 {
00842     char   StatusMsg[256];
00843     char   ResourceString[256];
00844     int    i;
00845 
00846     /* Status Message */
00847     StatusMsg[0]='\0';
00848 
00849     /* add all status messages */
00850     for (i = 0; i < 25; i++) {
00851         if (pi->Status & (1<<i)) {
00852         LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
00853             ResourceString, 255);
00854         strcat(StatusMsg,ResourceString);
00855         }
00856     }
00857     /* append "ready" */
00858     /* FIXME: status==ready must only be appended if really so.
00859               but how to detect? */
00860     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
00861         ResourceString, 255);
00862     strcat(StatusMsg,ResourceString);
00863     SetDlgItemTextA(hDlg, stc12, StatusMsg);
00864 
00865     /* set all other printer info texts */
00866     SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
00867     
00868     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
00869         SetDlgItemTextA(hDlg, stc14, pi->pLocation);
00870     else
00871         SetDlgItemTextA(hDlg, stc14, pi->pPortName);
00872     SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
00873     return;
00874 }
00875 
00876 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, const PRINTER_INFO_2W *pi)
00877 {
00878     WCHAR   StatusMsg[256];
00879     WCHAR   ResourceString[256];
00880     static const WCHAR emptyW[] = {0};
00881     int    i;
00882 
00883     /* Status Message */
00884     StatusMsg[0]='\0';
00885 
00886     /* add all status messages */
00887     for (i = 0; i < 25; i++) {
00888         if (pi->Status & (1<<i)) {
00889         LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
00890             ResourceString, 255);
00891         lstrcatW(StatusMsg,ResourceString);
00892         }
00893     }
00894     /* append "ready" */
00895     /* FIXME: status==ready must only be appended if really so.
00896               but how to detect? */
00897     LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
00898         ResourceString, 255);
00899     lstrcatW(StatusMsg,ResourceString);
00900     SetDlgItemTextW(hDlg, stc12, StatusMsg);
00901 
00902     /* set all other printer info texts */
00903     SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
00904     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
00905         SetDlgItemTextW(hDlg, stc14, pi->pLocation);
00906     else
00907         SetDlgItemTextW(hDlg, stc14, pi->pPortName);
00908     SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
00909 }
00910 
00911 
00912 /*******************************************************************
00913  *
00914  *                 PRINTDLG_ChangePrinter
00915  *
00916  */
00917 static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
00918 {
00919     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
00920     LPDEVMODEA lpdm = NULL;
00921     LONG dmSize;
00922     DWORD needed;
00923     HANDLE hprn;
00924 
00925     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
00926     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
00927     if(!OpenPrinterA(name, &hprn, NULL)) {
00928         ERR("Can't open printer %s\n", name);
00929     return FALSE;
00930     }
00931     GetPrinterA(hprn, 2, NULL, 0, &needed);
00932     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
00933     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
00934         &needed);
00935     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
00936     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
00937     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
00938         needed, &needed)) {
00939     ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
00940     return FALSE;
00941     }
00942     ClosePrinter(hprn);
00943 
00944     PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
00945 
00946     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
00947     PrintStructures->lpDevMode = NULL;
00948 
00949     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
00950     if(dmSize == -1) {
00951         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
00952     return FALSE;
00953     }
00954     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
00955     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
00956                  DM_OUT_BUFFER);
00957     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
00958               !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
00959                      (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
00960       /* Supplied devicemode matches current printer so try to use it */
00961         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
00962                 DM_OUT_BUFFER | DM_IN_BUFFER);
00963     }
00964     if(lpdm)
00965         GlobalUnlock(lppd->hDevMode);
00966 
00967     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
00968 
00969     if(!(lppd->Flags & PD_PRINTSETUP)) {
00970     /* Print range (All/Range/Selection) */
00971     if(lppd->nFromPage != 0xffff)
00972         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
00973     if(lppd->nToPage != 0xffff)
00974         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
00975 
00976     CheckRadioButton(hDlg, rad1, rad3, rad1);       /* default */
00977     if (lppd->Flags & PD_NOSELECTION)
00978         EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
00979     else
00980         if (lppd->Flags & PD_SELECTION)
00981             CheckRadioButton(hDlg, rad1, rad3, rad2);
00982     if (lppd->Flags & PD_NOPAGENUMS) {
00983         EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
00984         EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
00985         EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
00986         EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
00987         EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
00988     } else {
00989         if (lppd->Flags & PD_PAGENUMS)
00990             CheckRadioButton(hDlg, rad1, rad3, rad3);
00991     }
00992 
00993     /* Collate pages
00994      *
00995      * FIXME: The ico3 is not displayed for some reason. I don't know why.
00996      */
00997     if (lppd->Flags & PD_COLLATE) {
00998             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
00999                 (LPARAM)PrintStructures->hCollateIcon);
01000         CheckDlgButton(hDlg, chx2, 1);
01001     } else {
01002             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01003                 (LPARAM)PrintStructures->hNoCollateIcon);
01004         CheckDlgButton(hDlg, chx2, 0);
01005     }
01006 
01007     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
01008       /* if printer doesn't support it: no Collate */
01009         if (!(lpdm->dmFields & DM_COLLATE)) {
01010             EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
01011         EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
01012         }
01013     }
01014 
01015     /* nCopies */
01016     {
01017       INT copies;
01018       if (lppd->hDevMode == 0)
01019           copies = lppd->nCopies;
01020       else
01021           copies = lpdm->u1.s1.dmCopies;
01022       if(copies == 0) copies = 1;
01023       else if(copies < 0) copies = MAX_COPIES;
01024       SetDlgItemInt(hDlg, edt3, copies, FALSE);
01025     }
01026 
01027     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
01028       /* if printer doesn't support it: no nCopies */
01029         if (!(lpdm->dmFields & DM_COPIES)) {
01030             EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
01031         EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
01032         }
01033     }
01034 
01035     /* print to file */
01036     CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
01037     if (lppd->Flags & PD_DISABLEPRINTTOFILE)
01038             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
01039     if (lppd->Flags & PD_HIDEPRINTTOFILE)
01040             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
01041 
01042     /* Fill print quality combo, PrintDlg16 */
01043     if(GetDlgItem(hDlg, cmb1))
01044     {
01045         DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
01046                                PrintStructures->lpPrinterInfo->pPortName,
01047                                DC_ENUMRESOLUTIONS, NULL, lpdm);
01048 
01049         if(numResolutions != -1)
01050         {
01051         HWND hQuality = GetDlgItem(hDlg, cmb1);
01052         LONG* Resolutions;
01053         char buf[255];
01054         DWORD i;
01055         int dpiX, dpiY;
01056         HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
01057                        PrintStructures->lpPrinterInfo->pPrinterName,
01058                        0, lpdm);
01059 
01060         Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
01061         DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
01062                     PrintStructures->lpPrinterInfo->pPortName,
01063                     DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
01064 
01065         dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
01066         dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
01067         DeleteDC(hPrinterDC);
01068 
01069         SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
01070         for(i = 0; i < (numResolutions * 2); i += 2)
01071         {
01072             BOOL IsDefault = FALSE;
01073             LRESULT Index;
01074 
01075             if(Resolutions[i] == Resolutions[i+1])
01076             {
01077             if(dpiX == Resolutions[i])
01078                 IsDefault = TRUE;
01079             sprintf(buf, "%d dpi", Resolutions[i]);
01080             } else
01081             {
01082             if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
01083                 IsDefault = TRUE;
01084             sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
01085             }
01086 
01087             Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
01088 
01089             if(IsDefault)
01090             SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
01091 
01092             SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
01093         }
01094         HeapFree(GetProcessHeap(), 0, Resolutions);
01095         }
01096     }
01097     } else { /* PD_PRINTSETUP */
01098       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
01099 
01100       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
01101                   PrintStructures->lpPrinterInfo->pPrinterName,
01102                   PrintStructures->lpPrinterInfo->pPortName,
01103                   lpdm);
01104       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
01105                   PrintStructures->lpPrinterInfo->pPrinterName,
01106                   PrintStructures->lpPrinterInfo->pPortName,
01107                   lpdm);
01108       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
01109       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01110                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
01111                                    PrintStructures->hLandscapeIcon));
01112 
01113     }
01114 
01115     /* help button */
01116     if ((lppd->Flags & PD_SHOWHELP)==0) {
01117         /* hide if PD_SHOWHELP not specified */
01118         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
01119     }
01120     return TRUE;
01121 }
01122 
01123 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
01124                    PRINT_PTRW *PrintStructures)
01125 {
01126     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
01127     LPDEVMODEW lpdm = NULL;
01128     LONG dmSize;
01129     DWORD needed;
01130     HANDLE hprn;
01131 
01132     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
01133     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
01134     if(!OpenPrinterW(name, &hprn, NULL)) {
01135         ERR("Can't open printer %s\n", debugstr_w(name));
01136     return FALSE;
01137     }
01138     GetPrinterW(hprn, 2, NULL, 0, &needed);
01139     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
01140     GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
01141         &needed);
01142     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
01143     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
01144     if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
01145         needed, &needed)) {
01146     ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
01147     return FALSE;
01148     }
01149     ClosePrinter(hprn);
01150 
01151     PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
01152 
01153     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
01154     PrintStructures->lpDevMode = NULL;
01155 
01156     dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
01157     if(dmSize == -1) {
01158         ERR("DocumentProperties fails on %s\n", debugstr_w(name));
01159     return FALSE;
01160     }
01161     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
01162     dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
01163                  DM_OUT_BUFFER);
01164     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
01165               !lstrcmpW(lpdm->dmDeviceName,
01166                   PrintStructures->lpDevMode->dmDeviceName)) {
01167       /* Supplied devicemode matches current printer so try to use it */
01168         DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
01169                 DM_OUT_BUFFER | DM_IN_BUFFER);
01170     }
01171     if(lpdm)
01172         GlobalUnlock(lppd->hDevMode);
01173 
01174     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
01175 
01176     if(!(lppd->Flags & PD_PRINTSETUP)) {
01177     /* Print range (All/Range/Selection) */
01178     if(lppd->nFromPage != 0xffff)
01179         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
01180     if(lppd->nToPage != 0xffff)
01181         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
01182 
01183     CheckRadioButton(hDlg, rad1, rad3, rad1);       /* default */
01184     if (lppd->Flags & PD_NOSELECTION)
01185         EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
01186     else
01187         if (lppd->Flags & PD_SELECTION)
01188             CheckRadioButton(hDlg, rad1, rad3, rad2);
01189     if (lppd->Flags & PD_NOPAGENUMS) {
01190         EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
01191         EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
01192         EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
01193         EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
01194         EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
01195     } else {
01196         if (lppd->Flags & PD_PAGENUMS)
01197             CheckRadioButton(hDlg, rad1, rad3, rad3);
01198     }
01199 
01200     /* Collate pages
01201      *
01202      * FIXME: The ico3 is not displayed for some reason. I don't know why.
01203      */
01204     if (lppd->Flags & PD_COLLATE) {
01205             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01206                 (LPARAM)PrintStructures->hCollateIcon);
01207         CheckDlgButton(hDlg, chx2, 1);
01208     } else {
01209             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01210                 (LPARAM)PrintStructures->hNoCollateIcon);
01211         CheckDlgButton(hDlg, chx2, 0);
01212     }
01213 
01214     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
01215       /* if printer doesn't support it: no Collate */
01216         if (!(lpdm->dmFields & DM_COLLATE)) {
01217             EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
01218         EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
01219         }
01220     }
01221 
01222     /* nCopies */
01223     {
01224       INT copies;
01225       if (lppd->hDevMode == 0)
01226           copies = lppd->nCopies;
01227       else
01228           copies = lpdm->u1.s1.dmCopies;
01229       if(copies == 0) copies = 1;
01230       else if(copies < 0) copies = MAX_COPIES;
01231       SetDlgItemInt(hDlg, edt3, copies, FALSE);
01232     }
01233 
01234     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
01235       /* if printer doesn't support it: no nCopies */
01236         if (!(lpdm->dmFields & DM_COPIES)) {
01237             EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
01238         EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
01239         }
01240     }
01241 
01242     /* print to file */
01243     CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
01244     if (lppd->Flags & PD_DISABLEPRINTTOFILE)
01245             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
01246     if (lppd->Flags & PD_HIDEPRINTTOFILE)
01247             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
01248 
01249     } else { /* PD_PRINTSETUP */
01250       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
01251 
01252       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
01253                   PrintStructures->lpPrinterInfo->pPrinterName,
01254                   PrintStructures->lpPrinterInfo->pPortName,
01255                   lpdm);
01256       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
01257                   PrintStructures->lpPrinterInfo->pPrinterName,
01258                   PrintStructures->lpPrinterInfo->pPortName,
01259                   lpdm);
01260       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
01261       SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01262                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
01263                                    PrintStructures->hLandscapeIcon));
01264 
01265     }
01266 
01267     /* help button */
01268     if ((lppd->Flags & PD_SHOWHELP)==0) {
01269         /* hide if PD_SHOWHELP not specified */
01270         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
01271     }
01272     return TRUE;
01273 }
01274 
01275  /***********************************************************************
01276  *           check_printer_setup            [internal]
01277  */
01278 static LRESULT check_printer_setup(HWND hDlg)
01279 {
01280     DWORD needed,num;
01281     WCHAR resourcestr[256],resultstr[256];
01282 
01283     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
01284     if(needed == 0)
01285     {
01286           EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
01287     }
01288     if(needed > 0)
01289           return TRUE;
01290     else
01291     {
01292           LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
01293           LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
01294           MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
01295           return FALSE;
01296     }
01297 }
01298 
01299 /***********************************************************************
01300  *           PRINTDLG_WMInitDialog                      [internal]
01301  */
01302 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg,
01303                      PRINT_PTRA* PrintStructures)
01304 {
01305     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
01306     DEVNAMES *pdn;
01307     DEVMODEA *pdm;
01308     char *name = NULL;
01309     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
01310 
01311     /* load Collate ICONs */
01312     /* We load these with LoadImage because they are not a standard
01313        size and we don't want them rescaled */
01314     PrintStructures->hCollateIcon =
01315       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
01316     PrintStructures->hNoCollateIcon =
01317       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
01318 
01319     /* These can be done with LoadIcon */
01320     PrintStructures->hPortraitIcon =
01321       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
01322     PrintStructures->hLandscapeIcon =
01323       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
01324 
01325     /* display the collate/no_collate icon */
01326     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01327                         (LPARAM)PrintStructures->hNoCollateIcon);
01328 
01329     if(PrintStructures->hCollateIcon == 0 ||
01330        PrintStructures->hNoCollateIcon == 0 ||
01331        PrintStructures->hPortraitIcon == 0 ||
01332        PrintStructures->hLandscapeIcon == 0) {
01333         ERR("no icon in resourcefile\n");
01334     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
01335     EndDialog(hDlg, FALSE);
01336     }
01337 
01338     /*
01339      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
01340      * must be registered and the Help button must be shown.
01341      */
01342     if (lppd->Flags & PD_SHOWHELP) {
01343         if((PrintStructures->HelpMessageID =
01344         RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
01345         COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
01346         return FALSE;
01347     }
01348     } else
01349         PrintStructures->HelpMessageID = 0;
01350 
01351     if(!(lppd->Flags &PD_PRINTSETUP)) {
01352         PrintStructures->hwndUpDown =
01353       CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
01354                   UDS_NOTHOUSANDS | UDS_ARROWKEYS |
01355                   UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
01356                   hDlg, UPDOWN_ID, COMDLG32_hInstance,
01357                   GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
01358     }
01359 
01360     /* FIXME: I allow more freedom than either Win95 or WinNT,
01361      *        which do not agree to what errors should be thrown or not
01362      *        in case nToPage or nFromPage is out-of-range.
01363      */
01364     if (lppd->nMaxPage < lppd->nMinPage)
01365         lppd->nMaxPage = lppd->nMinPage;
01366     if (lppd->nMinPage == lppd->nMaxPage)
01367         lppd->Flags |= PD_NOPAGENUMS;
01368     if (lppd->nToPage < lppd->nMinPage)
01369         lppd->nToPage = lppd->nMinPage;
01370     if (lppd->nToPage > lppd->nMaxPage)
01371         lppd->nToPage = lppd->nMaxPage;
01372     if (lppd->nFromPage < lppd->nMinPage)
01373         lppd->nFromPage = lppd->nMinPage;
01374     if (lppd->nFromPage > lppd->nMaxPage)
01375         lppd->nFromPage = lppd->nMaxPage;
01376 
01377     /* if we have the combo box, fill it */
01378     if (GetDlgItem(hDlg,comboID)) {
01379     /* Fill Combobox
01380      */
01381     pdn = GlobalLock(lppd->hDevNames);
01382     pdm = GlobalLock(lppd->hDevMode);
01383     if(pdn)
01384         name = (char*)pdn + pdn->wDeviceOffset;
01385     else if(pdm)
01386         name = (char*)pdm->dmDeviceName;
01387     PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
01388     if(pdm) GlobalUnlock(lppd->hDevMode);
01389     if(pdn) GlobalUnlock(lppd->hDevNames);
01390 
01391     /* Now find selected printer and update rest of dlg */
01392     name = HeapAlloc(GetProcessHeap(),0,256);
01393     if (GetDlgItemTextA(hDlg, comboID, name, 255))
01394         PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
01395     HeapFree(GetProcessHeap(),0,name);
01396     } else {
01397     /* else use default printer */
01398     char name[200];
01399         DWORD dwBufLen = sizeof(name);
01400     BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
01401 
01402     if (ret)
01403         PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
01404     else
01405         FIXME("No default printer found, expect problems!\n");
01406     }
01407     return TRUE;
01408 }
01409 
01410 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg,
01411                      PRINT_PTRW* PrintStructures)
01412 {
01413     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
01414     DEVNAMES *pdn;
01415     DEVMODEW *pdm;
01416     WCHAR *name = NULL;
01417     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
01418 
01419     /* load Collate ICONs */
01420     /* We load these with LoadImage because they are not a standard
01421        size and we don't want them rescaled */
01422     PrintStructures->hCollateIcon =
01423       LoadImageW(COMDLG32_hInstance, pd32_collateW, IMAGE_ICON, 0, 0, 0);
01424     PrintStructures->hNoCollateIcon =
01425       LoadImageW(COMDLG32_hInstance, pd32_nocollateW, IMAGE_ICON, 0, 0, 0);
01426 
01427     /* These can be done with LoadIcon */
01428     PrintStructures->hPortraitIcon =
01429       LoadIconW(COMDLG32_hInstance, pd32_portraitW);
01430     PrintStructures->hLandscapeIcon =
01431       LoadIconW(COMDLG32_hInstance, pd32_landscapeW);
01432 
01433     /* display the collate/no_collate icon */
01434     SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01435                         (LPARAM)PrintStructures->hNoCollateIcon);
01436 
01437     if(PrintStructures->hCollateIcon == 0 ||
01438        PrintStructures->hNoCollateIcon == 0 ||
01439        PrintStructures->hPortraitIcon == 0 ||
01440        PrintStructures->hLandscapeIcon == 0) {
01441         ERR("no icon in resourcefile\n");
01442     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
01443     EndDialog(hDlg, FALSE);
01444     }
01445 
01446     /*
01447      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
01448      * must be registered and the Help button must be shown.
01449      */
01450     if (lppd->Flags & PD_SHOWHELP) {
01451         if((PrintStructures->HelpMessageID =
01452         RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
01453         COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
01454         return FALSE;
01455     }
01456     } else
01457         PrintStructures->HelpMessageID = 0;
01458 
01459     if(!(lppd->Flags &PD_PRINTSETUP)) {
01460         PrintStructures->hwndUpDown =
01461       CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
01462                   UDS_NOTHOUSANDS | UDS_ARROWKEYS |
01463                   UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
01464                   hDlg, UPDOWN_ID, COMDLG32_hInstance,
01465                   GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
01466     }
01467 
01468     /* FIXME: I allow more freedom than either Win95 or WinNT,
01469      *        which do not agree to what errors should be thrown or not
01470      *        in case nToPage or nFromPage is out-of-range.
01471      */
01472     if (lppd->nMaxPage < lppd->nMinPage)
01473         lppd->nMaxPage = lppd->nMinPage;
01474     if (lppd->nMinPage == lppd->nMaxPage)
01475         lppd->Flags |= PD_NOPAGENUMS;
01476     if (lppd->nToPage < lppd->nMinPage)
01477         lppd->nToPage = lppd->nMinPage;
01478     if (lppd->nToPage > lppd->nMaxPage)
01479         lppd->nToPage = lppd->nMaxPage;
01480     if (lppd->nFromPage < lppd->nMinPage)
01481         lppd->nFromPage = lppd->nMinPage;
01482     if (lppd->nFromPage > lppd->nMaxPage)
01483         lppd->nFromPage = lppd->nMaxPage;
01484 
01485     /* if we have the combo box, fill it */
01486     if (GetDlgItem(hDlg,comboID)) {
01487     /* Fill Combobox
01488      */
01489     pdn = GlobalLock(lppd->hDevNames);
01490     pdm = GlobalLock(lppd->hDevMode);
01491     if(pdn)
01492         name = (WCHAR*)pdn + pdn->wDeviceOffset;
01493     else if(pdm)
01494         name = pdm->dmDeviceName;
01495     PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
01496     if(pdm) GlobalUnlock(lppd->hDevMode);
01497     if(pdn) GlobalUnlock(lppd->hDevNames);
01498 
01499     /* Now find selected printer and update rest of dlg */
01500     /* ansi is ok here */
01501     name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
01502     if (GetDlgItemTextW(hDlg, comboID, name, 255))
01503         PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
01504     HeapFree(GetProcessHeap(),0,name);
01505     } else {
01506     /* else use default printer */
01507     WCHAR name[200];
01508         DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
01509     BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
01510 
01511     if (ret)
01512         PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
01513     else
01514         FIXME("No default printer found, expect problems!\n");
01515     }
01516     return TRUE;
01517 }
01518 
01519 /***********************************************************************
01520  *                              PRINTDLG_WMCommand               [internal]
01521  */
01522 static LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
01523                                    PRINT_PTRA* PrintStructures)
01524 {
01525     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
01526     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
01527     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
01528 
01529     switch (LOWORD(wParam))  {
01530     case IDOK:
01531         TRACE(" OK button was hit\n");
01532         if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
01533         FIXME("Update printdlg was not successful!\n");
01534         return(FALSE);
01535     }
01536     EndDialog(hDlg, TRUE);
01537     return(TRUE);
01538 
01539     case IDCANCEL:
01540         TRACE(" CANCEL button was hit\n");
01541         EndDialog(hDlg, FALSE);
01542     return(FALSE);
01543 
01544      case pshHelp:
01545         TRACE(" HELP button was hit\n");
01546         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
01547                     (WPARAM) hDlg, (LPARAM) lppd);
01548         break;
01549 
01550      case chx2:                         /* collate pages checkbox */
01551         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
01552             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01553                                     (LPARAM)PrintStructures->hCollateIcon);
01554         else
01555             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01556                                     (LPARAM)PrintStructures->hNoCollateIcon);
01557         break;
01558      case edt1:                         /* from page nr editbox */
01559      case edt2:                         /* to page nr editbox */
01560         if (HIWORD(wParam)==EN_CHANGE) {
01561         WORD nToPage;
01562         WORD nFromPage;
01563         nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
01564         nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
01565             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
01566             CheckRadioButton(hDlg, rad1, rad3, rad3);
01567     }
01568         break;
01569 
01570     case edt3:
01571         if(HIWORD(wParam) == EN_CHANGE) {
01572         INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
01573         if(copies <= 1)
01574             EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
01575         else
01576             EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
01577     }
01578     break;
01579 
01580      case psh2:                       /* Properties button */
01581        {
01582          HANDLE hPrinter;
01583          char   PrinterName[256];
01584 
01585          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
01586          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
01587          FIXME(" Call to OpenPrinter did not succeed!\n");
01588          break;
01589      }
01590      DocumentPropertiesA(hDlg, hPrinter, PrinterName,
01591                  PrintStructures->lpDevMode,
01592                  PrintStructures->lpDevMode,
01593                  DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
01594      ClosePrinter(hPrinter);
01595          break;
01596        }
01597 
01598     case rad1: /* Paperorientation */
01599         if (lppd->Flags & PD_PRINTSETUP)
01600         {
01601               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
01602               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01603                           (LPARAM)(PrintStructures->hPortraitIcon));
01604         }
01605         break;
01606 
01607     case rad2: /* Paperorientation */
01608         if (lppd->Flags & PD_PRINTSETUP)
01609         {
01610               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
01611               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01612                           (LPARAM)(PrintStructures->hLandscapeIcon));
01613         }
01614         break;
01615 
01616     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
01617      if (PrinterComboID != LOWORD(wParam)) {
01618          break;
01619      }
01620      /* FALLTHROUGH */
01621     case cmb4:                         /* Printer combobox */
01622          if (HIWORD(wParam)==CBN_SELCHANGE) {
01623          char   PrinterName[256];
01624          GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
01625          PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
01626      }
01627      break;
01628 
01629     case cmb2: /* Papersize */
01630       {
01631       DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
01632       if(Sel != CB_ERR)
01633           lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
01634                                 CB_GETITEMDATA,
01635                                 Sel, 0);
01636       }
01637       break;
01638 
01639     case cmb3: /* Bin */
01640       {
01641       DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
01642       if(Sel != CB_ERR)
01643           lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
01644                               CB_GETITEMDATA, Sel,
01645                               0);
01646       }
01647       break;
01648     }
01649     if(lppd->Flags & PD_PRINTSETUP) {
01650         switch (LOWORD(wParam)) {
01651     case rad1:                         /* orientation */
01652     case rad2:
01653         if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
01654             if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
01655             lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
01656                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
01657                     (LPARAM)PrintStructures->hPortraitIcon);
01658                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01659                     (LPARAM)PrintStructures->hPortraitIcon);
01660         }
01661         } else {
01662             if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
01663                 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
01664                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
01665                     (LPARAM)PrintStructures->hLandscapeIcon);
01666                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01667                     (LPARAM)PrintStructures->hLandscapeIcon);
01668         }
01669         }
01670         break;
01671     }
01672     }
01673     return FALSE;
01674 }
01675 
01676 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
01677                        PRINT_PTRW* PrintStructures)
01678 {
01679     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
01680     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
01681     LPDEVMODEW lpdm = PrintStructures->lpDevMode;
01682 
01683     switch (LOWORD(wParam))  {
01684     case IDOK:
01685         TRACE(" OK button was hit\n");
01686         if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
01687         FIXME("Update printdlg was not successful!\n");
01688         return(FALSE);
01689     }
01690     EndDialog(hDlg, TRUE);
01691     return(TRUE);
01692 
01693     case IDCANCEL:
01694         TRACE(" CANCEL button was hit\n");
01695         EndDialog(hDlg, FALSE);
01696     return(FALSE);
01697 
01698      case pshHelp:
01699         TRACE(" HELP button was hit\n");
01700         SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
01701                     (WPARAM) hDlg, (LPARAM) lppd);
01702         break;
01703 
01704      case chx2:                         /* collate pages checkbox */
01705         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
01706             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01707                                     (LPARAM)PrintStructures->hCollateIcon);
01708         else
01709             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
01710                                     (LPARAM)PrintStructures->hNoCollateIcon);
01711         break;
01712      case edt1:                         /* from page nr editbox */
01713      case edt2:                         /* to page nr editbox */
01714         if (HIWORD(wParam)==EN_CHANGE) {
01715         WORD nToPage;
01716         WORD nFromPage;
01717         nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
01718         nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
01719             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
01720             CheckRadioButton(hDlg, rad1, rad3, rad3);
01721     }
01722         break;
01723 
01724     case edt3:
01725         if(HIWORD(wParam) == EN_CHANGE) {
01726         INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
01727         if(copies <= 1)
01728             EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
01729         else
01730                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
01731         }
01732         break;
01733 
01734      case psh2:                       /* Properties button */
01735        {
01736          HANDLE hPrinter;
01737          WCHAR  PrinterName[256];
01738 
01739          if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
01740          if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
01741          FIXME(" Call to OpenPrinter did not succeed!\n");
01742          break;
01743      }
01744      DocumentPropertiesW(hDlg, hPrinter, PrinterName,
01745                  PrintStructures->lpDevMode,
01746                  PrintStructures->lpDevMode,
01747                  DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
01748      ClosePrinter(hPrinter);
01749          break;
01750        }
01751 
01752     case rad1: /* Paperorientation */
01753         if (lppd->Flags & PD_PRINTSETUP)
01754         {
01755               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
01756               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01757                           (LPARAM)(PrintStructures->hPortraitIcon));
01758         }
01759         break;
01760 
01761     case rad2: /* Paperorientation */
01762         if (lppd->Flags & PD_PRINTSETUP)
01763         {
01764               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
01765               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01766                           (LPARAM)(PrintStructures->hLandscapeIcon));
01767         }
01768         break;
01769 
01770     case cmb1: /* Printer Combobox in PRINT SETUP */
01771      /* FALLTHROUGH */
01772     case cmb4:                         /* Printer combobox */
01773          if (HIWORD(wParam)==CBN_SELCHANGE) {
01774          WCHAR   PrinterName[256];
01775          GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
01776          PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
01777      }
01778      break;
01779 
01780     case cmb2: /* Papersize */
01781       {
01782       DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
01783       if(Sel != CB_ERR)
01784           lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
01785                                 CB_GETITEMDATA,
01786                                 Sel, 0);
01787       }
01788       break;
01789 
01790     case cmb3: /* Bin */
01791       {
01792       DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
01793       if(Sel != CB_ERR)
01794           lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
01795                               CB_GETITEMDATA, Sel,
01796                               0);
01797       }
01798       break;
01799     }
01800     if(lppd->Flags & PD_PRINTSETUP) {
01801         switch (LOWORD(wParam)) {
01802     case rad1:                         /* orientation */
01803     case rad2:
01804         if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
01805             if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
01806             lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
01807                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
01808                     (LPARAM)PrintStructures->hPortraitIcon);
01809                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01810                     (LPARAM)PrintStructures->hPortraitIcon);
01811         }
01812         } else {
01813             if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
01814                 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
01815                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
01816                     (LPARAM)PrintStructures->hLandscapeIcon);
01817                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
01818                     (LPARAM)PrintStructures->hLandscapeIcon);
01819         }
01820         }
01821         break;
01822     }
01823     }
01824     return FALSE;
01825 }
01826 
01827 /***********************************************************************
01828  *           PrintDlgProcA          [internal]
01829  */
01830 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
01831                                       LPARAM lParam)
01832 {
01833     PRINT_PTRA* PrintStructures;
01834     INT_PTR res = FALSE;
01835 
01836     if (uMsg!=WM_INITDIALOG) {
01837         PrintStructures = GetPropW(hDlg, printdlg_prop);
01838     if (!PrintStructures)
01839         return FALSE;
01840     } else {
01841         PrintStructures = (PRINT_PTRA*) lParam;
01842         SetPropW(hDlg, printdlg_prop, PrintStructures);
01843         if(!check_printer_setup(hDlg))
01844         {
01845             EndDialog(hDlg,FALSE);
01846             return FALSE;
01847         }
01848     res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
01849 
01850     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
01851         res = PrintStructures->lpPrintDlg->lpfnPrintHook(
01852         hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
01853         );
01854     return res;
01855     }
01856 
01857     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
01858         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
01859                              lParam);
01860     if(res) return res;
01861     }
01862 
01863     switch (uMsg) {
01864     case WM_COMMAND:
01865         return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
01866 
01867     case WM_DESTROY:
01868     DestroyIcon(PrintStructures->hCollateIcon);
01869     DestroyIcon(PrintStructures->hNoCollateIcon);
01870         DestroyIcon(PrintStructures->hPortraitIcon);
01871         DestroyIcon(PrintStructures->hLandscapeIcon);
01872     if(PrintStructures->hwndUpDown)
01873         DestroyWindow(PrintStructures->hwndUpDown);
01874         return FALSE;
01875     }
01876     return res;
01877 }
01878 
01879 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
01880                                       LPARAM lParam)
01881 {
01882     PRINT_PTRW* PrintStructures;
01883     INT_PTR res = FALSE;
01884 
01885     if (uMsg!=WM_INITDIALOG) {
01886         PrintStructures = GetPropW(hDlg, printdlg_prop);
01887     if (!PrintStructures)
01888         return FALSE;
01889     } else {
01890         PrintStructures = (PRINT_PTRW*) lParam;
01891         SetPropW(hDlg, printdlg_prop, PrintStructures);
01892         if(!check_printer_setup(hDlg))
01893         {
01894             EndDialog(hDlg,FALSE);
01895             return FALSE;
01896         }
01897     res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
01898 
01899     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
01900         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
01901     return res;
01902     }
01903 
01904     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
01905         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
01906     if(res) return res;
01907     }
01908 
01909     switch (uMsg) {
01910     case WM_COMMAND:
01911         return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
01912 
01913     case WM_DESTROY:
01914     DestroyIcon(PrintStructures->hCollateIcon);
01915     DestroyIcon(PrintStructures->hNoCollateIcon);
01916         DestroyIcon(PrintStructures->hPortraitIcon);
01917         DestroyIcon(PrintStructures->hLandscapeIcon);
01918     if(PrintStructures->hwndUpDown)
01919         DestroyWindow(PrintStructures->hwndUpDown);
01920         return FALSE;
01921     }
01922     return res;
01923 }
01924 
01925 /************************************************************
01926  *
01927  *      PRINTDLG_GetDlgTemplate
01928  *
01929  */
01930 static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
01931 {
01932     HRSRC hResInfo;
01933     HGLOBAL hDlgTmpl;
01934 
01935     if (lppd->Flags & PD_PRINTSETUP) {
01936     if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
01937         hDlgTmpl = lppd->hSetupTemplate;
01938     } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
01939         hResInfo = FindResourceA(lppd->hInstance,
01940                      lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
01941         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
01942     } else {
01943         hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
01944                      (LPSTR)RT_DIALOG);
01945         hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
01946     }
01947     } else {
01948     if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
01949         hDlgTmpl = lppd->hPrintTemplate;
01950     } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
01951         hResInfo = FindResourceA(lppd->hInstance,
01952                      lppd->lpPrintTemplateName,
01953                      (LPSTR)RT_DIALOG);
01954         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
01955     } else {
01956         hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
01957                      (LPSTR)RT_DIALOG);
01958         hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
01959     }
01960     }
01961     return hDlgTmpl;
01962 }
01963 
01964 static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
01965 {
01966     HRSRC hResInfo;
01967     HGLOBAL hDlgTmpl;
01968     static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
01969     static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
01970 
01971     if (lppd->Flags & PD_PRINTSETUP) {
01972     if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
01973         hDlgTmpl = lppd->hSetupTemplate;
01974     } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
01975         hResInfo = FindResourceW(lppd->hInstance,
01976                      lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
01977         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
01978     } else {
01979         hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
01980         hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
01981     }
01982     } else {
01983     if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
01984         hDlgTmpl = lppd->hPrintTemplate;
01985     } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
01986         hResInfo = FindResourceW(lppd->hInstance,
01987                      lppd->lpPrintTemplateName,
01988                      (LPWSTR)RT_DIALOG);
01989         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
01990     } else {
01991         hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
01992         hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
01993     }
01994     }
01995     return hDlgTmpl;
01996 }
01997 
01998 /***********************************************************************
01999  *
02000  *      PRINTDLG_CreateDC
02001  *
02002  */
02003 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
02004 {
02005     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
02006     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
02007 
02008     if(lppd->Flags & PD_RETURNDC) {
02009         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
02010                   (char*)pdn + pdn->wDeviceOffset,
02011                   (char*)pdn + pdn->wOutputOffset,
02012                   pdm );
02013     } else if(lppd->Flags & PD_RETURNIC) {
02014         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
02015                   (char*)pdn + pdn->wDeviceOffset,
02016                   (char*)pdn + pdn->wOutputOffset,
02017                   pdm );
02018     }
02019     GlobalUnlock(lppd->hDevNames);
02020     GlobalUnlock(lppd->hDevMode);
02021     return lppd->hDC ? TRUE : FALSE;
02022 }
02023 
02024 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
02025 {
02026     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
02027     DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
02028 
02029     if(lppd->Flags & PD_RETURNDC) {
02030         lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
02031                   (WCHAR*)pdn + pdn->wDeviceOffset,
02032                   (WCHAR*)pdn + pdn->wOutputOffset,
02033                   pdm );
02034     } else if(lppd->Flags & PD_RETURNIC) {
02035         lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
02036                   (WCHAR*)pdn + pdn->wDeviceOffset,
02037                   (WCHAR*)pdn + pdn->wOutputOffset,
02038                   pdm );
02039     }
02040     GlobalUnlock(lppd->hDevNames);
02041     GlobalUnlock(lppd->hDevMode);
02042     return lppd->hDC ? TRUE : FALSE;
02043 }
02044 
02045 /***********************************************************************
02046  *           PrintDlgA   (COMDLG32.@)
02047  *
02048  *  Displays the PRINT dialog box, which enables the user to specify
02049  *  specific properties of the print job.
02050  *  
02051  * PARAMS
02052  *  lppd  [IO] ptr to PRINTDLG32 struct
02053  * 
02054  * RETURNS
02055  *  nonzero if the user pressed the OK button
02056  *  zero    if the user cancelled the window or an error occurred
02057  *  
02058  * BUGS
02059  *  PrintDlg:
02060  *  * The Collate Icons do not display, even though they are in the code.
02061  *  * The Properties Button(s) should call DocumentPropertiesA().
02062  */
02063 
02064 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
02065 {
02066     BOOL      bRet = FALSE;
02067     LPVOID    ptr;
02068     HINSTANCE hInst;
02069 
02070     if (!lppd)
02071     {
02072         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
02073         return FALSE;
02074     }
02075 
02076     if(TRACE_ON(commdlg)) {
02077         char flagstr[1000] = "";
02078     const struct pd_flags *pflag = pd_flags;
02079     for( ; pflag->name; pflag++) {
02080         if(lppd->Flags & pflag->flag)
02081             strcat(flagstr, pflag->name);
02082     }
02083     TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
02084               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
02085               "flags %08x (%s)\n",
02086           lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
02087           lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
02088           lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
02089     }
02090 
02091     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
02092         WARN("structure size failure !!!\n");
02093     COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
02094     return FALSE;
02095     }
02096 
02097     if(lppd->Flags & PD_RETURNDEFAULT) {
02098         PRINTER_INFO_2A *pbuf;
02099     DRIVER_INFO_3A  *dbuf;
02100     HANDLE hprn;
02101     DWORD needed;
02102 
02103     if(lppd->hDevMode || lppd->hDevNames) {
02104         WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
02105         COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
02106         return FALSE;
02107     }
02108         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
02109         WARN("Can't find default printer\n");
02110         COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
02111         return FALSE;
02112     }
02113 
02114     GetPrinterA(hprn, 2, NULL, 0, &needed);
02115     pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
02116     GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
02117 
02118     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
02119     dbuf = HeapAlloc(GetProcessHeap(),0,needed);
02120     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
02121         ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
02122             GetLastError(),pbuf->pPrinterName);
02123         HeapFree(GetProcessHeap(), 0, dbuf);
02124         HeapFree(GetProcessHeap(), 0, pbuf);
02125         COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
02126         return FALSE;
02127     }
02128     ClosePrinter(hprn);
02129 
02130     PRINTDLG_CreateDevNames(&(lppd->hDevNames),
02131                   dbuf->pDriverPath,
02132                   pbuf->pPrinterName,
02133                   pbuf->pPortName);
02134     lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
02135                      pbuf->pDevMode->dmDriverExtra);
02136     ptr = GlobalLock(lppd->hDevMode);
02137     memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
02138            pbuf->pDevMode->dmDriverExtra);
02139     GlobalUnlock(lppd->hDevMode);
02140     HeapFree(GetProcessHeap(), 0, pbuf);
02141     HeapFree(GetProcessHeap(), 0, dbuf);
02142     bRet = TRUE;
02143     } else {
02144     HGLOBAL hDlgTmpl;
02145     PRINT_PTRA *PrintStructures;
02146 
02147     /* load Dialog resources,
02148      * depending on Flags indicates Print32 or Print32_setup dialog
02149      */
02150     hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
02151     if (!hDlgTmpl) {
02152         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
02153         return FALSE;
02154     }
02155     ptr = LockResource( hDlgTmpl );
02156     if (!ptr) {
02157         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
02158         return FALSE;
02159     }
02160 
02161         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
02162                     sizeof(PRINT_PTRA));
02163     PrintStructures->lpPrintDlg = lppd;
02164 
02165     /* and create & process the dialog .
02166      * -1 is failure, 0 is broken hwnd, everything else is ok.
02167      */
02168         hInst = COMDLG32_hInstance;
02169     if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
02170     bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
02171                        PrintDlgProcA,
02172                        (LPARAM)PrintStructures));
02173 
02174     if(bRet) {
02175         DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
02176         PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
02177         DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
02178 
02179         if (lppd->hDevMode == 0) {
02180             TRACE(" No hDevMode yet... Need to create my own\n");
02181         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
02182                     lpdm->dmSize + lpdm->dmDriverExtra);
02183         } else {
02184         lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
02185                            lpdm->dmSize + lpdm->dmDriverExtra,
02186                            GMEM_MOVEABLE);
02187         }
02188         lpdmReturn = GlobalLock(lppd->hDevMode);
02189         memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
02190 
02191         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
02192             di->pDriverPath,
02193             pi->pPrinterName,
02194             pi->pPortName
02195         );
02196         GlobalUnlock(lppd->hDevMode);
02197     }
02198     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
02199     HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
02200     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
02201     HeapFree(GetProcessHeap(), 0, PrintStructures);
02202     }
02203     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
02204         bRet = PRINTDLG_CreateDCA(lppd);
02205 
02206     TRACE("exit! (%d)\n", bRet);
02207     return bRet;
02208 }
02209 
02210 /***********************************************************************
02211  *           PrintDlgW   (COMDLG32.@)
02212  *
02213  * See PrintDlgA.
02214  */
02215 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
02216 {
02217     BOOL      bRet = FALSE;
02218     LPVOID    ptr;
02219     HINSTANCE hInst;
02220 
02221     if (!lppd)
02222     {
02223         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
02224         return FALSE;
02225     }
02226 
02227     if(TRACE_ON(commdlg)) {
02228         char flagstr[1000] = "";
02229     const struct pd_flags *pflag = pd_flags;
02230     for( ; pflag->name; pflag++) {
02231         if(lppd->Flags & pflag->flag)
02232             strcat(flagstr, pflag->name);
02233     }
02234     TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
02235               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
02236               "flags %08x (%s)\n",
02237           lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
02238           lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
02239           lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
02240     }
02241 
02242     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
02243         WARN("structure size failure !!!\n");
02244     COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
02245     return FALSE;
02246     }
02247 
02248     if(lppd->Flags & PD_RETURNDEFAULT) {
02249         PRINTER_INFO_2W *pbuf;
02250     DRIVER_INFO_3W  *dbuf;
02251     HANDLE hprn;
02252     DWORD needed;
02253 
02254     if(lppd->hDevMode || lppd->hDevNames) {
02255         WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
02256         COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
02257         return FALSE;
02258     }
02259         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
02260         WARN("Can't find default printer\n");
02261         COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
02262         return FALSE;
02263     }
02264 
02265     GetPrinterW(hprn, 2, NULL, 0, &needed);
02266     pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
02267     GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
02268 
02269     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
02270     dbuf = HeapAlloc(GetProcessHeap(),0,needed);
02271     if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
02272         ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
02273             GetLastError(),debugstr_w(pbuf->pPrinterName));
02274         HeapFree(GetProcessHeap(), 0, dbuf);
02275         HeapFree(GetProcessHeap(), 0, pbuf);
02276         COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
02277         return FALSE;
02278     }
02279     ClosePrinter(hprn);
02280 
02281     PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
02282                   dbuf->pDriverPath,
02283                   pbuf->pPrinterName,
02284                   pbuf->pPortName);
02285     lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
02286                      pbuf->pDevMode->dmDriverExtra);
02287     ptr = GlobalLock(lppd->hDevMode);
02288     memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
02289            pbuf->pDevMode->dmDriverExtra);
02290     GlobalUnlock(lppd->hDevMode);
02291     HeapFree(GetProcessHeap(), 0, pbuf);
02292     HeapFree(GetProcessHeap(), 0, dbuf);
02293     bRet = TRUE;
02294     } else {
02295     HGLOBAL hDlgTmpl;
02296     PRINT_PTRW *PrintStructures;
02297 
02298     /* load Dialog resources,
02299      * depending on Flags indicates Print32 or Print32_setup dialog
02300      */
02301     hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
02302     if (!hDlgTmpl) {
02303         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
02304         return FALSE;
02305     }
02306     ptr = LockResource( hDlgTmpl );
02307     if (!ptr) {
02308         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
02309         return FALSE;
02310     }
02311 
02312         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
02313                     sizeof(PRINT_PTRW));
02314     PrintStructures->lpPrintDlg = lppd;
02315 
02316     /* and create & process the dialog .
02317      * -1 is failure, 0 is broken hwnd, everything else is ok.
02318      */
02319         hInst = COMDLG32_hInstance;
02320     if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
02321     bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
02322                        PrintDlgProcW,
02323                        (LPARAM)PrintStructures));
02324 
02325     if(bRet) {
02326         DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
02327         PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
02328         DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
02329 
02330         if (lppd->hDevMode == 0) {
02331             TRACE(" No hDevMode yet... Need to create my own\n");
02332         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
02333                     lpdm->dmSize + lpdm->dmDriverExtra);
02334         } else {
02335             WORD locks;
02336         if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
02337             WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
02338             while(locks--) {
02339                 GlobalUnlock(lppd->hDevMode);
02340             TRACE("Now got %d locks\n", locks);
02341             }
02342         }
02343         lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
02344                            lpdm->dmSize + lpdm->dmDriverExtra,
02345                            GMEM_MOVEABLE);
02346         }
02347         lpdmReturn = GlobalLock(lppd->hDevMode);
02348         memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
02349 
02350         if (lppd->hDevNames != 0) {
02351             WORD locks;
02352         if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
02353             WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
02354             while(locks--)
02355                 GlobalUnlock(lppd->hDevNames);
02356         }
02357         }
02358         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
02359             di->pDriverPath,
02360             pi->pPrinterName,
02361             pi->pPortName
02362         );
02363         GlobalUnlock(lppd->hDevMode);
02364     }
02365     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
02366     HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
02367     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
02368     HeapFree(GetProcessHeap(), 0, PrintStructures);
02369     }
02370     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
02371         bRet = PRINTDLG_CreateDCW(lppd);
02372 
02373     TRACE("exit! (%d)\n", bRet);
02374     return bRet;
02375 }
02376 
02377 /***********************************************************************
02378  *
02379  *          PageSetupDlg
02380  * rad1 - portrait
02381  * rad2 - landscape
02382  * cmb1 - printer select (not in standard dialog template)
02383  * cmb2 - paper size
02384  * cmb3 - source (tray?)
02385  * edt4 - border left
02386  * edt5 - border top
02387  * edt6 - border right
02388  * edt7 - border bottom
02389  * psh3 - "Printer..."
02390  */
02391 
02392 typedef struct
02393 {
02394     BOOL unicode;
02395     union
02396     {
02397         LPPAGESETUPDLGA dlga;
02398         LPPAGESETUPDLGW dlgw;
02399     } u;
02400     HWND hDlg;                /* Page Setup dialog handle */
02401     RECT rtDrawRect;          /* Drawing rect for page */
02402 } pagesetup_data;
02403 
02404 static inline DWORD pagesetup_get_flags(const pagesetup_data *data)
02405 {
02406     return data->u.dlgw->Flags;
02407 }
02408 
02409 static inline BOOL is_metric(const pagesetup_data *data)
02410 {
02411     return pagesetup_get_flags(data) & PSD_INHUNDREDTHSOFMILLIMETERS;
02412 }
02413 
02414 static inline LONG tenths_mm_to_size(const pagesetup_data *data, LONG size)
02415 {
02416     if (is_metric(data))
02417         return 10 * size;
02418     else
02419         return 10 * size * 100 / 254;
02420 }
02421 
02422 static inline LONG thousandths_inch_to_size(const pagesetup_data *data, LONG size)
02423 {
02424     if (is_metric(data))
02425         return size * 254 / 100;
02426     else
02427         return size;
02428 }
02429 
02430 static WCHAR get_decimal_sep(void)
02431 {
02432     static WCHAR sep;
02433 
02434     if(!sep)
02435     {
02436         WCHAR buf[] = {'.', 0};
02437         GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, sizeof(buf) / sizeof(buf[0]));
02438         sep = buf[0];
02439     }
02440     return sep;
02441 }
02442 
02443 static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
02444 {
02445     WCHAR integer_fmt[] = {'%','d',0};
02446     WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
02447     WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
02448 
02449     /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
02450 
02451     if (is_metric(data))
02452     {
02453         if(size % 100)
02454             wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
02455         else
02456             wsprintfW(strout, integer_fmt, size / 100);
02457     }
02458     else
02459     {
02460         if(size % 1000)
02461             wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
02462         else
02463             wsprintfW(strout, integer_fmt, size / 1000);
02464 
02465     }
02466 }
02467 
02468 static inline BOOL is_default_metric(void)
02469 {
02470     DWORD system;
02471     GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
02472                    (LPWSTR)&system, sizeof(system));
02473     return system == 0;
02474 }
02475 
02476 /**********************************************
02477  *           rotate_rect
02478  * Cyclically permute the four members of rc
02479  * If sense is TRUE l -> t -> r -> b
02480  * otherwise        l <- t <- r <- b
02481  */
02482 static inline void rotate_rect(RECT *rc, BOOL sense)
02483 {
02484     INT tmp;
02485     if(sense)
02486     {
02487         tmp        = rc->bottom;
02488         rc->bottom = rc->right;
02489         rc->right  = rc->top;
02490         rc->top    = rc->left;
02491         rc->left   = tmp;
02492     }
02493     else
02494     {
02495         tmp        = rc->left;
02496         rc->left   = rc->top;
02497         rc->top    = rc->right;
02498         rc->right  = rc->bottom;
02499         rc->bottom = tmp;
02500     }
02501 }
02502 
02503 static void pagesetup_set_orientation(pagesetup_data *data, WORD orient)
02504 {
02505     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02506 
02507     assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
02508 
02509     if(data->unicode)
02510         dm->u1.s1.dmOrientation = orient;
02511     else
02512     {
02513         DEVMODEA *dmA = (DEVMODEA *)dm;
02514         dmA->u1.s1.dmOrientation = orient;
02515     }
02516     GlobalUnlock(data->u.dlgw->hDevMode);
02517 }
02518 
02519 static WORD pagesetup_get_orientation(const pagesetup_data *data)
02520 {
02521     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02522     WORD orient;
02523 
02524     if(data->unicode)
02525         orient = dm->u1.s1.dmOrientation;
02526     else
02527     {
02528         DEVMODEA *dmA = (DEVMODEA *)dm;
02529         orient = dmA->u1.s1.dmOrientation;
02530     }
02531     GlobalUnlock(data->u.dlgw->hDevMode);
02532     return orient;
02533 }
02534 
02535 static void pagesetup_set_papersize(pagesetup_data *data, WORD paper)
02536 {
02537     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02538 
02539     if(data->unicode)
02540         dm->u1.s1.dmPaperSize = paper;
02541     else
02542     {
02543         DEVMODEA *dmA = (DEVMODEA *)dm;
02544         dmA->u1.s1.dmPaperSize = paper;
02545     }
02546     GlobalUnlock(data->u.dlgw->hDevMode);
02547 }
02548 
02549 static WORD pagesetup_get_papersize(const pagesetup_data *data)
02550 {
02551     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02552     WORD paper;
02553 
02554     if(data->unicode)
02555         paper = dm->u1.s1.dmPaperSize;
02556     else
02557     {
02558         DEVMODEA *dmA = (DEVMODEA *)dm;
02559         paper = dmA->u1.s1.dmPaperSize;
02560     }
02561     GlobalUnlock(data->u.dlgw->hDevMode);
02562     return paper;
02563 }
02564 
02565 static void pagesetup_set_defaultsource(pagesetup_data *data, WORD source)
02566 {
02567     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02568 
02569     if(data->unicode)
02570         dm->u1.s1.dmDefaultSource = source;
02571     else
02572     {
02573         DEVMODEA *dmA = (DEVMODEA *)dm;
02574         dmA->u1.s1.dmDefaultSource = source;
02575     }
02576     GlobalUnlock(data->u.dlgw->hDevMode);
02577 }
02578 
02579 typedef enum
02580 {
02581     devnames_driver_name,
02582     devnames_device_name,
02583     devnames_output_name
02584 } devnames_name;
02585 
02586 
02587 static inline WORD get_devname_offset(const DEVNAMES *dn, devnames_name which)
02588 {
02589     switch(which)
02590     {
02591     case devnames_driver_name: return dn->wDriverOffset;
02592     case devnames_device_name: return dn->wDeviceOffset;
02593     case devnames_output_name: return dn->wOutputOffset;
02594     }
02595     ERR("Shouldn't be here\n");
02596     return 0;
02597 }
02598 
02599 static WCHAR *pagesetup_get_a_devname(const pagesetup_data *data, devnames_name which)
02600 {
02601     DEVNAMES *dn;
02602     WCHAR *name;
02603 
02604     dn = GlobalLock(data->u.dlgw->hDevNames);
02605     if(data->unicode)
02606         name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
02607     else
02608     {
02609         int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
02610         name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
02611         MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
02612     }
02613     GlobalUnlock(data->u.dlgw->hDevNames);
02614     return name;
02615 }
02616 
02617 static WCHAR *pagesetup_get_drvname(const pagesetup_data *data)
02618 {
02619     return pagesetup_get_a_devname(data, devnames_driver_name);
02620 }
02621 
02622 static WCHAR *pagesetup_get_devname(const pagesetup_data *data)
02623 {
02624     return pagesetup_get_a_devname(data, devnames_device_name);
02625 }
02626 
02627 static WCHAR *pagesetup_get_portname(const pagesetup_data *data)
02628 {
02629     return pagesetup_get_a_devname(data, devnames_output_name);
02630 }
02631 
02632 static void pagesetup_release_a_devname(const pagesetup_data *data, WCHAR *name)
02633 {
02634     HeapFree(GetProcessHeap(), 0, name);
02635 }
02636 
02637 static void pagesetup_set_devnames(pagesetup_data *data, LPCWSTR drv, LPCWSTR devname, LPCWSTR port)
02638 {
02639     DEVNAMES *dn;
02640     WCHAR def[256];
02641     DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
02642 
02643     if(data->unicode)
02644     {
02645         drv_len  = (strlenW(drv) + 1) * sizeof(WCHAR);
02646         dev_len  = (strlenW(devname) + 1) * sizeof(WCHAR);
02647         port_len = (strlenW(port) + 1) * sizeof(WCHAR);
02648     }
02649     else
02650     {
02651         drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
02652         dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
02653         port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
02654     }
02655     len += drv_len + dev_len + port_len;
02656 
02657     if(data->u.dlgw->hDevNames)
02658         data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
02659     else
02660         data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
02661 
02662     dn = GlobalLock(data->u.dlgw->hDevNames);
02663 
02664     if(data->unicode)
02665     {
02666         WCHAR *ptr = (WCHAR *)(dn + 1);
02667         len = sizeof(DEVNAMES) / sizeof(WCHAR);
02668         dn->wDriverOffset = len;
02669         strcpyW(ptr, drv);
02670         ptr += drv_len / sizeof(WCHAR);
02671         len += drv_len / sizeof(WCHAR);
02672         dn->wDeviceOffset = len;
02673         strcpyW(ptr, devname);
02674         ptr += dev_len / sizeof(WCHAR);
02675         len += dev_len / sizeof(WCHAR);
02676         dn->wOutputOffset = len;
02677         strcpyW(ptr, port);
02678     }
02679     else
02680     {
02681         char *ptr = (char *)(dn + 1);
02682         len = sizeof(DEVNAMES);
02683         dn->wDriverOffset = len;
02684         WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
02685         ptr += drv_len;
02686         len += drv_len;
02687         dn->wDeviceOffset = len;
02688         WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
02689         ptr += dev_len;
02690         len += dev_len;
02691         dn->wOutputOffset = len;
02692         WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
02693     }
02694 
02695     dn->wDefault = 0;
02696     len = sizeof(def) / sizeof(def[0]);
02697     GetDefaultPrinterW(def, &len);
02698     if(!lstrcmpW(def, devname))
02699         dn->wDefault = 1;
02700 
02701     GlobalUnlock(data->u.dlgw->hDevNames);
02702 }
02703 
02704 static DEVMODEW *pagesetup_get_devmode(const pagesetup_data *data)
02705 {
02706     DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
02707     DEVMODEW *ret;
02708 
02709     if(data->unicode)
02710     {
02711         /* We make a copy even in the unicode case because the ptr
02712            may get passed back to us in pagesetup_set_devmode. */
02713         ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
02714         memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
02715     }
02716     else
02717         ret = GdiConvertToDevmodeW((DEVMODEA *)dm);
02718 
02719     GlobalUnlock(data->u.dlgw->hDevMode);
02720     return ret;
02721 }
02722 
02723 static void pagesetup_release_devmode(const pagesetup_data *data, DEVMODEW *dm)
02724 {
02725     HeapFree(GetProcessHeap(), 0, dm);
02726 }
02727 
02728 static void pagesetup_set_devmode(pagesetup_data *data, DEVMODEW *dm)
02729 {
02730     DEVMODEA *dmA = NULL;
02731     void *src, *dst;
02732     DWORD size;
02733 
02734     if(data->unicode)
02735     {
02736         size = dm->dmSize + dm->dmDriverExtra;
02737         src = dm;
02738     }
02739     else
02740     {
02741         dmA = convert_to_devmodeA(dm);
02742         size = dmA->dmSize + dmA->dmDriverExtra;
02743         src = dmA;
02744     }
02745 
02746     if(data->u.dlgw->hDevMode)
02747         data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
02748                                                GMEM_MOVEABLE);
02749     else
02750         data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
02751 
02752     dst = GlobalLock(data->u.dlgw->hDevMode);
02753     memcpy(dst, src, size);
02754     GlobalUnlock(data->u.dlgw->hDevMode);
02755     HeapFree(GetProcessHeap(), 0, dmA);
02756 }
02757 
02758 static inline POINT *pagesetup_get_papersize_pt(const pagesetup_data *data)
02759 {
02760     return &data->u.dlgw->ptPaperSize;
02761 }
02762 
02763 static inline RECT *pagesetup_get_margin_rect(const pagesetup_data *data)
02764 {
02765     return &data->u.dlgw->rtMargin;
02766 }
02767 
02768 typedef enum
02769 {
02770     page_setup_hook,
02771     page_paint_hook
02772 } hook_type;
02773 
02774 static inline LPPAGESETUPHOOK pagesetup_get_hook(const pagesetup_data *data, hook_type which)
02775 {
02776     switch(which)
02777     {
02778     case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
02779     case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
02780     }
02781     return NULL;
02782 }
02783 
02784 /* This should only be used in calls to hook procs so we return the ptr
02785    already cast to LPARAM */
02786 static inline LPARAM pagesetup_get_dlg_struct(const pagesetup_data *data)
02787 {
02788     return (LPARAM)data->u.dlgw;
02789 }
02790 
02791 static inline void swap_point(POINT *pt)
02792 {
02793     LONG tmp = pt->x;
02794     pt->x = pt->y;
02795     pt->y = tmp;
02796 }
02797 
02798 static BOOL pagesetup_update_papersize(pagesetup_data *data)
02799 {
02800     DEVMODEW *dm;
02801     LPWSTR devname, portname;
02802     int i, num;
02803     WORD *words = NULL, paperword;
02804     POINT *points = NULL;
02805     BOOL retval = FALSE;
02806 
02807     dm       = pagesetup_get_devmode(data);
02808     devname  = pagesetup_get_devname(data);
02809     portname = pagesetup_get_portname(data);
02810 
02811     num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
02812     if (num <= 0)
02813     {
02814         FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
02815         goto end;
02816     }
02817 
02818     words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
02819     points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
02820 
02821     if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
02822     {
02823         FIXME("Number of returned words is not %d\n", num);
02824         goto end;
02825     }
02826 
02827     if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
02828     {
02829         FIXME("Number of returned sizes is not %d\n", num);
02830         goto end;
02831     }
02832 
02833     paperword = pagesetup_get_papersize(data);
02834 
02835     for (i = 0; i < num; i++)
02836         if (words[i] == paperword)
02837             break;
02838 
02839     if (i == num)
02840     {
02841         FIXME("Papersize %d not found in list?\n", paperword);
02842         goto end;
02843     }
02844 
02845     /* this is _10ths_ of a millimeter */
02846     pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x);
02847     pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y);
02848 
02849     if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
02850         swap_point(pagesetup_get_papersize_pt(data));
02851 
02852     retval = TRUE;
02853 
02854 end:
02855     HeapFree(GetProcessHeap(), 0, words);
02856     HeapFree(GetProcessHeap(), 0, points);
02857     pagesetup_release_a_devname(data, portname);
02858     pagesetup_release_a_devname(data, devname);
02859     pagesetup_release_devmode(data, dm);
02860 
02861     return retval;
02862 }
02863 
02864 /**********************************************************************************************
02865  * pagesetup_change_printer
02866  *
02867  * Redefines hDevMode and hDevNames HANDLES and initialises it.
02868  * 
02869  */
02870 static BOOL pagesetup_change_printer(LPWSTR name, pagesetup_data *data)
02871 {
02872     HANDLE hprn;
02873     DWORD needed;
02874     PRINTER_INFO_2W *prn_info = NULL;
02875     DRIVER_INFO_3W *drv_info = NULL;
02876     DEVMODEW *dm = NULL;
02877     BOOL retval = FALSE;
02878 
02879     if(!OpenPrinterW(name, &hprn, NULL))
02880     {
02881         ERR("Can't open printer %s\n", debugstr_w(name));
02882         goto end;
02883     }
02884 
02885     GetPrinterW(hprn, 2, NULL, 0, &needed);
02886     prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
02887     GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
02888     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
02889     drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
02890     if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
02891     {
02892         ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
02893         goto end;
02894     }
02895     ClosePrinter(hprn);
02896 
02897     needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
02898     if(needed == -1)
02899     {
02900         ERR("DocumentProperties fails on %s\n", debugstr_w(name));
02901         goto end;
02902     }
02903 
02904     dm = HeapAlloc(GetProcessHeap(), 0, needed);
02905     DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER);
02906 
02907     pagesetup_set_devmode(data, dm);
02908     pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
02909                            prn_info->pPortName);
02910 
02911     retval = TRUE;
02912 end:
02913     HeapFree(GetProcessHeap(), 0, dm);
02914     HeapFree(GetProcessHeap(), 0, prn_info);
02915     HeapFree(GetProcessHeap(), 0, drv_info);
02916     return retval;
02917 }
02918 
02919 /****************************************************************************************
02920  *  pagesetup_init_combos
02921  *
02922  *  Fills Printers, Paper and Source combos
02923  *
02924  */
02925 static void pagesetup_init_combos(HWND hDlg, pagesetup_data *data)
02926 {
02927     DEVMODEW *dm;
02928     LPWSTR devname, portname;
02929 
02930     dm       = pagesetup_get_devmode(data);
02931     devname  = pagesetup_get_devname(data);
02932     portname = pagesetup_get_portname(data);
02933 
02934     PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
02935     PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
02936     PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
02937 
02938     pagesetup_release_a_devname(data, portname);
02939     pagesetup_release_a_devname(data, devname);
02940     pagesetup_release_devmode(data, dm);
02941 }
02942 
02943 
02944 /****************************************************************************************
02945  *  pagesetup_change_printer_dialog
02946  *
02947  *  Pops up another dialog that lets the user pick another printer.
02948  *
02949  *  For now we display the PrintDlg, this should display a striped down version of it.
02950  */
02951 static void pagesetup_change_printer_dialog(HWND hDlg, pagesetup_data *data)
02952 {
02953     PRINTDLGW prnt;
02954     LPWSTR drvname, devname, portname;
02955     DEVMODEW *tmp_dm, *dm;
02956 
02957     memset(&prnt, 0, sizeof(prnt));
02958     prnt.lStructSize = sizeof(prnt);
02959     prnt.Flags     = 0;
02960     prnt.hwndOwner = hDlg;
02961 
02962     drvname = pagesetup_get_drvname(data);
02963     devname = pagesetup_get_devname(data);
02964     portname = pagesetup_get_portname(data);
02965     prnt.hDevNames = 0;
02966     PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
02967     pagesetup_release_a_devname(data, portname);
02968     pagesetup_release_a_devname(data, devname);
02969     pagesetup_release_a_devname(data, drvname);
02970 
02971     tmp_dm = pagesetup_get_devmode(data);
02972     prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
02973     dm = GlobalLock(prnt.hDevMode);
02974     memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
02975     GlobalUnlock(prnt.hDevMode);
02976     pagesetup_release_devmode(data, tmp_dm);
02977 
02978     if (PrintDlgW(&prnt))
02979     {
02980         DEVMODEW *dm = GlobalLock(prnt.hDevMode);
02981         DEVNAMES *dn = GlobalLock(prnt.hDevNames);
02982 
02983         pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset,
02984                                (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
02985         pagesetup_set_devmode(data, dm);
02986         GlobalUnlock(prnt.hDevNames);
02987         GlobalUnlock(prnt.hDevMode);
02988         pagesetup_init_combos(hDlg, data);
02989     }
02990 
02991     GlobalFree(prnt.hDevMode);
02992     GlobalFree(prnt.hDevNames);
02993 
02994 }
02995 
02996 /******************************************************************************************
02997  * pagesetup_change_preview
02998  *
02999  * Changes paper preview size / position
03000  *
03001  */
03002 static void pagesetup_change_preview(const pagesetup_data *data)
03003 {
03004     LONG width, height, x, y;
03005     RECT tmp;
03006     const int shadow = 4;
03007 
03008     if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
03009     {
03010         width  = data->rtDrawRect.right - data->rtDrawRect.left;
03011         height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x;
03012     }
03013     else
03014     {
03015         height = data->rtDrawRect.bottom - data->rtDrawRect.top;
03016         width  = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y;
03017     }
03018     x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
03019     y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
03020     TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
03021           wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
03022 
03023     MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
03024     MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
03025     MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
03026 
03027     tmp = data->rtDrawRect;
03028     tmp.right  += shadow;
03029     tmp.bottom += shadow;
03030     InvalidateRect(data->hDlg, &tmp, TRUE);
03031 }
03032 
03033 static inline LONG *element_from_margin_id(RECT *rc, WORD id)
03034 {
03035     switch(id)
03036     {
03037     case edt4: return &rc->left;
03038     case edt5: return &rc->top;
03039     case edt6: return &rc->right;
03040     case edt7: return &rc->bottom;
03041     }
03042     return NULL;
03043 }
03044 
03045 static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
03046 {
03047     WCHAR str[100];
03048     WORD idx;
03049 
03050     for(idx = edt4; idx <= edt7; idx++)
03051     {
03052         if(id == 0 || id == idx)
03053         {
03054             size2str(data, *element_from_margin_id(pagesetup_get_margin_rect(data), idx), str);
03055             SetDlgItemTextW(hDlg, idx, str);
03056         }
03057     }
03058 }
03059 
03060 static void margin_edit_notification(HWND hDlg, const pagesetup_data *data, WORD msg, WORD id)
03061 {
03062     switch (msg)
03063     {
03064     case EN_CHANGE:
03065       {
03066         WCHAR buf[10];
03067         LONG val = 0;
03068         LONG *value = element_from_margin_id(pagesetup_get_margin_rect(data), id);
03069 
03070         if (GetDlgItemTextW(hDlg, id, buf, sizeof(buf) / sizeof(buf[0])) != 0)
03071         {
03072             WCHAR *end;
03073             WCHAR decimal = get_decimal_sep();
03074 
03075             val = strtolW(buf, &end, 10);
03076             if(end != buf || *end == decimal)
03077             {
03078                 int mult = is_metric(data) ? 100 : 1000;
03079                 val *= mult;
03080                 if(*end == decimal)
03081                 {
03082                     while(mult > 1)
03083                     {
03084                         end++;
03085                         mult /= 10;
03086                         if(isdigitW(*end))
03087                             val += (*end - '0') * mult;
03088                         else
03089                             break;
03090                     }
03091                 }
03092             }
03093         }
03094         *value = val;
03095         return;
03096       }
03097 
03098     case EN_KILLFOCUS:
03099         update_margin_edits(hDlg, data, id);
03100         return;
03101     }
03102 }
03103 
03104 static void set_margin_groupbox_title(HWND hDlg, const pagesetup_data *data)
03105 {
03106     WCHAR title[256];
03107 
03108     if(LoadStringW(COMDLG32_hInstance, is_metric(data) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES,
03109                    title, sizeof(title)/sizeof(title[0])))
03110         SetDlgItemTextW(hDlg, grp4, title);
03111 }
03112 
03113 static void pagesetup_update_orientation_buttons(HWND hDlg, const pagesetup_data *data)
03114 {
03115     if (pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
03116         CheckRadioButton(hDlg, rad1, rad2, rad2);
03117     else
03118         CheckRadioButton(hDlg, rad1, rad2, rad1);
03119 }
03120 
03121 /****************************************************************************************
03122  *  pagesetup_printer_properties
03123  *
03124  *  Handle invocation of the 'Properties' button (not present in the default template).
03125  */
03126 static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data)
03127 {
03128     HANDLE hprn;
03129     LPWSTR devname;
03130     DEVMODEW *dm;
03131     LRESULT count;
03132     int i;
03133 
03134     devname = pagesetup_get_devname(data);
03135 
03136     if (!OpenPrinterW(devname, &hprn, NULL))
03137     {
03138         FIXME("Call to OpenPrinter did not succeed!\n");
03139         pagesetup_release_a_devname(data, devname);
03140         return;
03141     }
03142 
03143     dm = pagesetup_get_devmode(data);
03144     DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
03145     pagesetup_set_devmode(data, dm);
03146     pagesetup_release_devmode(data, dm);
03147     pagesetup_release_a_devname(data, devname);
03148     ClosePrinter(hprn);
03149 
03150     /* Changing paper */
03151     pagesetup_update_papersize(data);
03152     pagesetup_update_orientation_buttons(hDlg, data);
03153 
03154     /* Changing paper preview */
03155     pagesetup_change_preview(data);
03156 
03157     /* Selecting paper in combo */
03158     count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
03159     if(count != CB_ERR)
03160     {
03161         WORD paperword = pagesetup_get_papersize(data);
03162         for(i = 0; i < count; i++)
03163         {
03164             if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
03165                 SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
03166                 break;
03167             }
03168         }
03169     }
03170 }
03171 
03172 /********************************************************************************
03173  * pagesetup_wm_command
03174  * process WM_COMMAND message for PageSetupDlg
03175  *
03176  * PARAMS
03177  *  hDlg    [in]    Main dialog HANDLE 
03178  *  wParam  [in]    WM_COMMAND wParam
03179  *  lParam  [in]    WM_COMMAND lParam
03180  *  pda     [in/out] ptr to PageSetupDataA
03181  */
03182 
03183 static BOOL pagesetup_wm_command(HWND hDlg, WPARAM wParam, LPARAM lParam, pagesetup_data *data)
03184 {
03185     WORD msg = HIWORD(wParam);
03186     WORD id  = LOWORD(wParam);
03187 
03188     TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
03189         LOWORD(lParam),wParam,lParam);
03190     switch (id)  {
03191     case IDOK:
03192     EndDialog(hDlg, TRUE);
03193     return TRUE ;
03194 
03195     case IDCANCEL:
03196         EndDialog(hDlg, FALSE);
03197     return FALSE ;
03198 
03199     case psh3: /* Printer... */
03200         pagesetup_change_printer_dialog(hDlg, data);
03201         return TRUE;
03202 
03203     case rad1: /* Portrait */
03204     case rad2: /* Landscape */
03205         if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) ||
03206            (id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT))
03207     {
03208             pagesetup_set_orientation(data, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
03209             pagesetup_update_papersize(data);
03210             rotate_rect(pagesetup_get_margin_rect(data), (id == rad2));
03211             update_margin_edits(hDlg, data, 0);
03212             pagesetup_change_preview(data);
03213     }
03214     break;
03215     case cmb1: /* Printer combo */
03216         if(msg == CBN_SELCHANGE)
03217         {
03218             WCHAR name[256];
03219             GetDlgItemTextW(hDlg, id, name, sizeof(name) / sizeof(name[0]));
03220             pagesetup_change_printer(name, data);
03221             pagesetup_init_combos(hDlg, data);
03222         }
03223         break;
03224     case cmb2: /* Paper combo */
03225         if(msg == CBN_SELCHANGE)
03226         {
03227             DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
03228                                                   SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
03229             if (paperword != CB_ERR)
03230             {
03231                 pagesetup_set_papersize(data, paperword);
03232                 pagesetup_update_papersize(data);
03233                 pagesetup_change_preview(data);
03234         } else
03235                 FIXME("could not get dialog text for papersize cmbbox?\n");
03236         }
03237         break;
03238     case cmb3: /* Paper Source */
03239         if(msg == CBN_SELCHANGE)
03240         {
03241             WORD source = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA,
03242                                               SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
03243             pagesetup_set_defaultsource(data, source);
03244         }
03245         break;
03246     case psh2: /* Printer Properties button */
03247         pagesetup_printer_properties(hDlg, data);
03248         break;
03249     case edt4:
03250     case edt5:
03251     case edt6:
03252     case edt7:
03253         margin_edit_notification(hDlg, data, msg, id);
03254         break;
03255     }
03256     InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
03257     return FALSE;
03258 }
03259 
03260 /***********************************************************************
03261  *           default_page_paint_hook
03262  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box 
03263  * whenever the sample page is redrawn.
03264  */
03265 static UINT_PTR default_page_paint_hook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
03266                                         const pagesetup_data *data)
03267 {
03268     LPRECT lprc = (LPRECT) lParam;
03269     HDC hdc = (HDC) wParam;
03270     HPEN hpen, holdpen;
03271     LOGFONTW lf;
03272     HFONT hfont, holdfont;
03273     INT oldbkmode;
03274     TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
03275     /* Call user paint hook if enable */
03276     if (pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK)
03277         if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
03278             return TRUE;
03279 
03280     switch (uMsg) {
03281        /* LPPAGESETUPDLG in lParam */
03282        case WM_PSD_PAGESETUPDLG:
03283        /* Inform about the sample page rectangle */
03284        case WM_PSD_FULLPAGERECT:
03285        /* Inform about the margin rectangle */
03286        case WM_PSD_MINMARGINRECT:
03287             return FALSE;
03288 
03289         /* Draw dashed rectangle showing margins */
03290         case WM_PSD_MARGINRECT:
03291             hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
03292             holdpen = SelectObject(hdc, hpen);
03293             Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
03294             DeleteObject(SelectObject(hdc, holdpen));
03295             return TRUE;
03296         /* Draw the fake document */
03297         case WM_PSD_GREEKTEXTRECT:
03298             /* select a nice scalable font, because we want the text really small */
03299             SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
03300             lf.lfHeight = 6; /* value chosen based on visual effect */
03301             hfont = CreateFontIndirectW(&lf);
03302             holdfont = SelectObject(hdc, hfont);
03303 
03304             /* if text not loaded, then do so now */
03305             if (wszFakeDocumentText[0] == '\0')
03306                  LoadStringW(COMDLG32_hInstance,
03307                         IDS_FAKEDOCTEXT,
03308                         wszFakeDocumentText,
03309                         sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
03310 
03311             oldbkmode = SetBkMode(hdc, TRANSPARENT);
03312             DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
03313             SetBkMode(hdc, oldbkmode);
03314 
03315             DeleteObject(SelectObject(hdc, holdfont));
03316             return TRUE;
03317 
03318         /* Envelope stamp */
03319         case WM_PSD_ENVSTAMPRECT:
03320         /* Return address */
03321         case WM_PSD_YAFULLPAGERECT:
03322             FIXME("envelope/stamp is not implemented\n");
03323             return FALSE;
03324         default:
03325             FIXME("Unknown message %x\n",uMsg);
03326             return FALSE;
03327     }
03328     return TRUE;
03329 }
03330 
03331 /***********************************************************************
03332  *           PagePaintProc
03333  * The main paint procedure for the PageSetupDlg function.
03334  * The Page Setup dialog box includes an image of a sample page that shows how
03335  * the user's selections affect the appearance of the printed output.
03336  * The image consists of a rectangle that represents the selected paper
03337  * or envelope type, with a dotted-line rectangle representing
03338  * the current margins, and partial (Greek text) characters
03339  * to show how text looks on the printed page. 
03340  *
03341  * The following messages in the order sends to user hook procedure:
03342  *   WM_PSD_PAGESETUPDLG    Draw the contents of the sample page
03343  *   WM_PSD_FULLPAGERECT    Inform about the bounding rectangle
03344  *   WM_PSD_MINMARGINRECT   Inform about the margin rectangle (min margin?)
03345  *   WM_PSD_MARGINRECT      Draw the margin rectangle
03346  *   WM_PSD_GREEKTEXTRECT   Draw the Greek text inside the margin rectangle
03347  * If any of first three messages returns TRUE, painting done.
03348  *
03349  * PARAMS:
03350  *   hWnd   [in] Handle to the Page Setup dialog box
03351  *   uMsg   [in] Received message
03352  *
03353  * TODO:
03354  *   WM_PSD_ENVSTAMPRECT    Draw in the envelope-stamp rectangle (for envelopes only)
03355  *   WM_PSD_YAFULLPAGERECT  Draw the return address portion (for envelopes and other paper sizes)
03356  *
03357  * RETURNS:
03358  *   FALSE if all done correctly
03359  *
03360  */
03361 
03362 
03363 static LRESULT CALLBACK
03364 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
03365 {
03366     PAINTSTRUCT ps;
03367     RECT rcClient, rcMargin;
03368     HPEN hpen, holdpen;
03369     HDC hdc;
03370     HBRUSH hbrush, holdbrush;
03371     pagesetup_data *data;
03372     int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
03373     double scalx, scaly;
03374 
03375     if (uMsg != WM_PAINT)
03376         return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
03377 
03378     /* Processing WM_PAINT message */
03379     data = GetPropW(hWnd, pagesetupdlg_prop);
03380     if (!data) {
03381         WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
03382         return FALSE;
03383     }
03384     if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
03385                                 pagesetup_get_dlg_struct(data), data))
03386         return FALSE;
03387 
03388     hdc = BeginPaint(hWnd, &ps);
03389     GetClientRect(hWnd, &rcClient);
03390     
03391     scalx = rcClient.right  / (double)pagesetup_get_papersize_pt(data)->x;
03392     scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
03393     rcMargin = rcClient;
03394 
03395     rcMargin.left   += pagesetup_get_margin_rect(data)->left   * scalx;
03396     rcMargin.top    += pagesetup_get_margin_rect(data)->top    * scaly;
03397     rcMargin.right  -= pagesetup_get_margin_rect(data)->right  * scalx;
03398     rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
03399 
03400     /* if the space is too small then we make sure to not draw anything */
03401     rcMargin.left = min(rcMargin.left, rcMargin.right);
03402     rcMargin.top = min(rcMargin.top, rcMargin.bottom);
03403 
03404     if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) &&
03405         !default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) )
03406     {
03407         /* fill background */
03408         hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
03409         FillRect(hdc, &rcClient, hbrush);
03410         holdbrush = SelectObject(hdc, hbrush);
03411 
03412         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
03413         holdpen = SelectObject(hdc, hpen);
03414         
03415         /* paint left edge */
03416         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
03417         LineTo(hdc, rcClient.left, rcClient.bottom-1);
03418 
03419         /* paint top edge */
03420         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
03421         LineTo(hdc, rcClient.right, rcClient.top);
03422 
03423         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
03424         DeleteObject(SelectObject(hdc, hpen));
03425 
03426         /* paint right edge */
03427         MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
03428         LineTo(hdc, rcClient.right-1, rcClient.bottom);
03429 
03430         /* paint bottom edge */
03431         MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
03432         LineTo(hdc, rcClient.right, rcClient.bottom-1);
03433 
03434         DeleteObject(SelectObject(hdc, holdpen));
03435         DeleteObject(SelectObject(hdc, holdbrush));
03436 
03437         default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
03438 
03439         /* give text a bit of a space from the frame */
03440         rcMargin.left += 2;
03441         rcMargin.top += 2;
03442         rcMargin.right -= 2;
03443         rcMargin.bottom -= 2;
03444         
03445         /* if the space is too small then we make sure to not draw anything */
03446         rcMargin.left = min(rcMargin.left, rcMargin.right);
03447         rcMargin.top = min(rcMargin.top, rcMargin.bottom);
03448 
03449         default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
03450     }
03451 
03452     EndPaint(hWnd, &ps);
03453     return FALSE;
03454 }
03455 
03456 /*******************************************************
03457  * The margin edit controls are subclassed to filter
03458  * anything other than numbers and the decimal separator.
03459  */
03460 static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
03461 {
03462     if (msg == WM_CHAR)
03463     {
03464         WCHAR decimal = get_decimal_sep();
03465         WCHAR wc = (WCHAR)wparam;
03466         if(!isdigitW(wc) && wc != decimal && wc != VK_BACK) return 0;
03467     }
03468     return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
03469 }
03470 
03471 static void subclass_margin_edits(HWND hDlg)
03472 {
03473     int id;
03474     WNDPROC old_proc;
03475 
03476     for(id = edt4; id <= edt7; id++)
03477     {
03478         old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
03479                                               GWLP_WNDPROC,
03480                                               (ULONG_PTR)pagesetup_margin_editproc);
03481         InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL);
03482     }
03483 }
03484 
03485 /***********************************************************************
03486  *           pagesetup_dlg_proc
03487  *
03488  * Message handler for PageSetupDlg
03489  */
03490 static INT_PTR CALLBACK pagesetup_dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
03491 {
03492     pagesetup_data *data;
03493     INT_PTR     res = FALSE;
03494     HWND        hDrawWnd;
03495 
03496     if (uMsg == WM_INITDIALOG) { /*Init dialog*/
03497         data = (pagesetup_data *)lParam;
03498         data->hDlg = hDlg;
03499 
03500     hDrawWnd = GetDlgItem(hDlg, rct1); 
03501         TRACE("set property to %p\n", data);
03502         SetPropW(hDlg, pagesetupdlg_prop, data);
03503         SetPropW(hDrawWnd, pagesetupdlg_prop, data);
03504         GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
03505         MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
03506         lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
03507             hDrawWnd,
03508             GWLP_WNDPROC,
03509             (ULONG_PTR)PRINTDLG_PagePaintProc);
03510     
03511     /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
03512     res = TRUE;
03513         if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
03514         {
03515             if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
03516                                                            pagesetup_get_dlg_struct(data)))
03517         FIXME("Setup page hook failed?\n");
03518     }
03519 
03520     /* if printer button disabled */
03521         if (pagesetup_get_flags(data) & PSD_DISABLEPRINTER)
03522             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
03523     /* if margin edit boxes disabled */
03524         if (pagesetup_get_flags(data) & PSD_DISABLEMARGINS)
03525         {
03526             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
03527             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
03528             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
03529             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
03530     }
03531 
03532         /* Set orientation radiobuttons properly */
03533         pagesetup_update_orientation_buttons(hDlg, data);
03534 
03535     /* if orientation disabled */
03536         if (pagesetup_get_flags(data) & PSD_DISABLEORIENTATION)
03537         {
03538         EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
03539         EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
03540     }
03541 
03542     /* We fill them out enabled or not */
03543         if (!(pagesetup_get_flags(data) & PSD_MARGINS))
03544         {
03545             /* default is 1 inch */
03546             LONG size = thousandths_inch_to_size(data, 1000);
03547             SetRect(pagesetup_get_margin_rect(data), size, size, size, size);
03548         }
03549         update_margin_edits(hDlg, data, 0);
03550         subclass_margin_edits(hDlg);
03551         set_margin_groupbox_title(hDlg, data);
03552 
03553     /* if paper disabled */
03554         if (pagesetup_get_flags(data) & PSD_DISABLEPAPER)
03555         {
03556         EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
03557         EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
03558     }
03559 
03560     /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
03561         pagesetup_init_combos(hDlg, data);
03562         pagesetup_update_papersize(data);
03563         pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
03564 
03565     /* Drawing paper prev */
03566         pagesetup_change_preview(data);
03567     return TRUE;
03568     } else {
03569         data = GetPropW(hDlg, pagesetupdlg_prop);
03570         if (!data)
03571         {
03572         WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
03573         return FALSE;
03574     }
03575         if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
03576         {
03577             res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam);
03578         if (res) return res;
03579     }
03580     }
03581     switch (uMsg) {
03582     case WM_COMMAND:
03583         return pagesetup_wm_command(hDlg, wParam, lParam, data);
03584     }
03585     return FALSE;
03586 }
03587 
03588 static WCHAR *get_default_printer(void)
03589 {
03590     WCHAR *name = NULL;
03591     DWORD len = 0;
03592 
03593     GetDefaultPrinterW(NULL, &len);
03594     if(len)
03595     {
03596         name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
03597         GetDefaultPrinterW(name, &len);
03598     }
03599     return name;
03600 }
03601 
03602 static void pagesetup_dump_dlg_struct(const pagesetup_data *data)
03603 {
03604     if(TRACE_ON(commdlg))
03605     {
03606         char flagstr[1000] = "";
03607     const struct pd_flags *pflag = psd_flags;
03608         for( ; pflag->name; pflag++)
03609         {
03610             if(pagesetup_get_flags(data) & pflag->flag)
03611             {
03612                 strcat(flagstr, pflag->name);
03613                 strcat(flagstr, "|");
03614             }
03615         }
03616         TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
03617               "hinst %p, flags %08x (%s)\n",
03618               data->unicode ? "unicode" : "ansi",
03619               data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
03620               data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
03621               pagesetup_get_flags(data), flagstr);
03622     }
03623 }
03624 
03625 static void *pagesetup_get_template(pagesetup_data *data)
03626 {
03627     HRSRC res;
03628     HGLOBAL tmpl_handle;
03629 
03630     if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE)
03631     {
03632     tmpl_handle = data->u.dlgw->hPageSetupTemplate;
03633     }
03634     else if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATE)
03635     {
03636         if(data->unicode)
03637             res = FindResourceW(data->u.dlgw->hInstance,
03638                                 data->u.dlgw->lpPageSetupTemplateName, MAKEINTRESOURCEW(RT_DIALOG));
03639         else
03640             res = FindResourceA(data->u.dlga->hInstance,
03641                                 data->u.dlga->lpPageSetupTemplateName, MAKEINTRESOURCEA(RT_DIALOG));
03642         tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
03643     }
03644     else
03645     {
03646         res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD),
03647                             MAKEINTRESOURCEW(RT_DIALOG));
03648         tmpl_handle = LoadResource(COMDLG32_hInstance, res);
03649     }
03650     return LockResource(tmpl_handle);
03651 }
03652 
03653 static BOOL pagesetup_common(pagesetup_data *data)
03654 {
03655     BOOL ret;
03656     void *tmpl;
03657 
03658     if(!pagesetup_get_dlg_struct(data))
03659     {
03660         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
03661         return FALSE;
03662     }
03663 
03664     pagesetup_dump_dlg_struct(data);
03665 
03666     if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
03667     {
03668         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
03669         return FALSE;
03670     }
03671 
03672     if ((pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) &&
03673         (pagesetup_get_hook(data, page_paint_hook) == NULL))
03674     {
03675         COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
03676         return FALSE;
03677     }
03678 
03679     if(!(pagesetup_get_flags(data) & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
03680         data->u.dlgw->Flags |= is_default_metric() ?
03681             PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES;
03682 
03683     if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
03684     {
03685         WCHAR *def = get_default_printer();
03686         if(!def)
03687         {
03688             if (!(pagesetup_get_flags(data) & PSD_NOWARNING))
03689             {
03690                 WCHAR errstr[256];
03691                 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
03692                 MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
03693             }
03694             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
03695             return FALSE;
03696         }
03697         pagesetup_change_printer(def, data);
03698         HeapFree(GetProcessHeap(), 0, def);
03699     }
03700 
03701     if (pagesetup_get_flags(data) & PSD_RETURNDEFAULT)
03702     {
03703         pagesetup_update_papersize(data);
03704         return TRUE;
03705     }
03706 
03707     tmpl = pagesetup_get_template(data);
03708 
03709     ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
03710                                   data->u.dlgw->hwndOwner,
03711                                   pagesetup_dlg_proc, (LPARAM)data) > 0;
03712     return ret;
03713 }
03714 
03715 /***********************************************************************
03716  *            PageSetupDlgA  (COMDLG32.@)
03717  *
03718  *  Displays the PAGE SETUP dialog box, which enables the user to specify
03719  *  specific properties of a printed page such as
03720  *  size, source, orientation and the width of the page margins.
03721  *
03722  * PARAMS
03723  *  setupdlg [IO] PAGESETUPDLGA struct
03724  *
03725  * RETURNS
03726  *  TRUE    if the user pressed the OK button
03727  *  FALSE   if the user cancelled the window or an error occurred
03728  *
03729  * NOTES
03730  *    The values of hDevMode and hDevNames are filled on output and can be
03731  *    changed in PAGESETUPDLG when they are passed in PageSetupDlg.
03732  *
03733  */
03734 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg)
03735 {
03736     pagesetup_data data;
03737 
03738     data.unicode = FALSE;
03739     data.u.dlga  = setupdlg;
03740 
03741     return pagesetup_common(&data);
03742 }
03743 
03744 /***********************************************************************
03745  *            PageSetupDlgW  (COMDLG32.@)
03746  *
03747  * See PageSetupDlgA.
03748  */
03749 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg)
03750 {
03751     pagesetup_data data;
03752 
03753     data.unicode = TRUE;
03754     data.u.dlgw  = setupdlg;
03755 
03756     return pagesetup_common(&data);
03757 }
03758 
03759 /***********************************************************************
03760  * PrintDlgExA (COMDLG32.@)
03761  *
03762  * See PrintDlgExW.
03763  *
03764  * BUGS
03765  *   Only a Stub
03766  *
03767  */
03768 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
03769 {
03770     DWORD     ret = E_FAIL;
03771     LPVOID    ptr;
03772 
03773     FIXME("(%p) not fully implemented\n", lppd);
03774     if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
03775         return E_INVALIDARG;
03776 
03777     if (!IsWindow(lppd->hwndOwner))
03778         return E_HANDLE;
03779 
03780     if (lppd->Flags & PD_RETURNDEFAULT)
03781     {
03782         PRINTER_INFO_2A *pbuf;
03783         DRIVER_INFO_2A  *dbuf;
03784         HANDLE hprn;
03785         DWORD needed = 1024;
03786         BOOL bRet;
03787 
03788         if (lppd->hDevMode || lppd->hDevNames)
03789         {
03790             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
03791             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
03792             return E_INVALIDARG;
03793         }
03794         if (!PRINTDLG_OpenDefaultPrinter(&hprn))
03795         {
03796             WARN("Can't find default printer\n");
03797             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
03798             return E_FAIL;
03799         }
03800 
03801         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03802         bRet = GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
03803         if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
03804         {
03805             HeapFree(GetProcessHeap(), 0, pbuf);
03806             pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03807             bRet = GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
03808         }
03809         if (!bRet)
03810         {
03811             HeapFree(GetProcessHeap(), 0, pbuf);
03812             ClosePrinter(hprn);
03813             return E_FAIL;
03814         }
03815 
03816         needed = 1024;
03817         dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03818         bRet = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
03819         if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
03820         {
03821             HeapFree(GetProcessHeap(), 0, dbuf);
03822             dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03823             bRet = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
03824         }
03825         if (!bRet)
03826         {
03827             ERR("GetPrinterDriverА failed, last error %d, fix your config for printer %s!\n",
03828                 GetLastError(), pbuf->pPrinterName);
03829             HeapFree(GetProcessHeap(), 0, dbuf);
03830             HeapFree(GetProcessHeap(), 0, pbuf);
03831             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
03832             ClosePrinter(hprn);
03833             return E_FAIL;
03834         }
03835         ClosePrinter(hprn);
03836 
03837         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
03838                       dbuf->pDriverPath,
03839                       pbuf->pPrinterName,
03840                       pbuf->pPortName);
03841         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
03842                                      pbuf->pDevMode->dmDriverExtra);
03843         if (lppd->hDevMode)
03844         {
03845             ptr = GlobalLock(lppd->hDevMode);
03846             if (ptr)
03847             {
03848                 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
03849                        pbuf->pDevMode->dmDriverExtra);
03850                 GlobalUnlock(lppd->hDevMode);
03851                 ret = S_OK;
03852             }
03853         }
03854         HeapFree(GetProcessHeap(), 0, pbuf);
03855         HeapFree(GetProcessHeap(), 0, dbuf);
03856 
03857         return ret;
03858     }
03859 
03860     return E_NOTIMPL;
03861 }
03862 
03863 /***********************************************************************
03864  * PrintDlgExW (COMDLG32.@)
03865  *
03866  * Display the property sheet style PRINT dialog box
03867  *  
03868  * PARAMS
03869  *  lppd  [IO] ptr to PRINTDLGEX struct
03870  * 
03871  * RETURNS
03872  *  Success: S_OK
03873  *  Failure: One of the following COM error codes:
03874  *    E_OUTOFMEMORY Insufficient memory.
03875  *    E_INVALIDARG  One or more arguments are invalid.
03876  *    E_POINTER     Invalid pointer.
03877  *    E_HANDLE      Invalid handle.
03878  *    E_FAIL        Unspecified error.
03879  *  
03880  * NOTES
03881  * This Dialog enables the user to specify specific properties of the print job.
03882  * The property sheet can also have additional application-specific and
03883  * driver-specific property pages.
03884  *
03885  * BUGS
03886  *   Not fully implemented
03887  *
03888  */
03889 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
03890 {
03891     DWORD     ret = E_FAIL;
03892     LPVOID    ptr;
03893 
03894     FIXME("(%p) not fully implemented\n", lppd);
03895 
03896     if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
03897         return E_INVALIDARG;
03898     }
03899 
03900     if (!IsWindow(lppd->hwndOwner)) {
03901         return E_HANDLE;
03902     }
03903 
03904     if (lppd->Flags & PD_RETURNDEFAULT) {
03905         PRINTER_INFO_2W *pbuf;
03906         DRIVER_INFO_2W  *dbuf;
03907         HANDLE hprn;
03908         DWORD needed = 1024;
03909         BOOL bRet;
03910 
03911         if (lppd->hDevMode || lppd->hDevNames) {
03912             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
03913             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
03914             return E_INVALIDARG;
03915         }
03916         if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
03917             WARN("Can't find default printer\n");
03918             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
03919             return E_FAIL;
03920         }
03921 
03922         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03923         bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
03924         if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
03925             HeapFree(GetProcessHeap(), 0, pbuf);
03926             pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03927             bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
03928         }
03929         if (!bRet) {
03930             HeapFree(GetProcessHeap(), 0, pbuf);
03931             ClosePrinter(hprn);
03932             return E_FAIL;
03933         }
03934 
03935         needed = 1024;
03936         dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03937         bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
03938         if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
03939             HeapFree(GetProcessHeap(), 0, dbuf);
03940             dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
03941             bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
03942         }
03943         if (!bRet) {
03944             ERR("GetPrinterDriverW failed, last error %d, fix your config for printer %s!\n",
03945                 GetLastError(), debugstr_w(pbuf->pPrinterName));
03946             HeapFree(GetProcessHeap(), 0, dbuf);
03947             HeapFree(GetProcessHeap(), 0, pbuf);
03948             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
03949             ClosePrinter(hprn);
03950             return E_FAIL;
03951         }
03952         ClosePrinter(hprn);
03953 
03954         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
03955                       dbuf->pDriverPath,
03956                       pbuf->pPrinterName,
03957                       pbuf->pPortName);
03958         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
03959                          pbuf->pDevMode->dmDriverExtra);
03960         if (lppd->hDevMode) {
03961             ptr = GlobalLock(lppd->hDevMode);
03962             if (ptr) {
03963                 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
03964                     pbuf->pDevMode->dmDriverExtra);
03965                 GlobalUnlock(lppd->hDevMode);
03966                 ret = S_OK;
03967             }
03968         }
03969         HeapFree(GetProcessHeap(), 0, pbuf);
03970         HeapFree(GetProcessHeap(), 0, dbuf);
03971 
03972         return ret;
03973     }
03974 
03975     return E_NOTIMPL;
03976 }

Generated on Mon May 28 2012 04:22:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.