Differentiate between version 0 and version 1 property storages.
[wine] / dlls / commdlg / printdlg.c
1 /*
2  * COMMDLG - Print Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1999 Klaas van Gend
7  * Copyright 2000 Huw D M Davies
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winspool.h"
36 #include "winerror.h"
37
38 #include "wine/debug.h"
39
40 #include "commdlg.h"
41 #include "dlgs.h"
42 #include "cderr.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
45
46 #include "cdlg.h"
47 #include "printdlg.h"
48
49 /* Yes these constants are the same, but we're just copying win98 */
50 #define UPDOWN_ID 0x270f
51 #define MAX_COPIES 9999
52
53 /* Debugging info */
54 static struct pd_flags psd_flags[] = {
55   {PSD_MINMARGINS,"PSD_MINMARGINS"},
56   {PSD_MARGINS,"PSD_MARGINS"},
57   {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
58   {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
59   {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
60   {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
61   {PSD_NOWARNING,"PSD_NOWARNING"},
62   {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
63   {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
64   {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
65   {PSD_SHOWHELP,"PSD_SHOWHELP"},
66   {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
67   {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
68   {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
69   {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
70   {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
71   {-1, NULL}
72 };
73
74 /* address of wndproc for subclassed Static control */
75 static WNDPROC lpfnStaticWndProc;
76 /* the text of the fake document to render for the Page Setup dialog */
77 static WCHAR wszFakeDocumentText[1024];
78
79 /***********************************************************************
80  *    PRINTDLG_OpenDefaultPrinter
81  *
82  * Returns a winspool printer handle to the default printer in *hprn
83  * Caller must call ClosePrinter on the handle
84  *
85  * Returns TRUE on success else FALSE
86  */
87 BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
88 {
89     WCHAR buf[260];
90     DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
91     BOOL res;
92     if(!GetDefaultPrinterW(buf, &dwBufLen))
93         return FALSE;
94     res = OpenPrinterW(buf, hprn, NULL);
95     if (!res)
96         WARN("Could not open printer %s\n", debugstr_w(buf));
97     return res;
98 }
99
100 /***********************************************************************
101  *    PRINTDLG_SetUpPrinterListCombo
102  *
103  * Initializes printer list combox.
104  * hDlg:  HWND of dialog
105  * id:    Control id of combo
106  * name:  Name of printer to select
107  *
108  * Initializes combo with list of available printers.  Selects printer 'name'
109  * If name is NULL or does not exist select the default printer.
110  *
111  * Returns number of printers added to list.
112  */
113 INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
114 {
115     DWORD needed, num;
116     INT i;
117     LPPRINTER_INFO_2A pi;
118     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
119     pi = HeapAlloc(GetProcessHeap(), 0, needed);
120     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
121                   &num);
122
123     for(i = 0; i < num; i++) {
124         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
125                             (LPARAM)pi[i].pPrinterName );
126     }
127     HeapFree(GetProcessHeap(), 0, pi);
128     if(!name ||
129        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
130                                 (LPARAM)name)) == CB_ERR) {
131
132         char buf[260];
133         DWORD dwBufLen = sizeof(buf);
134         FIXME("Can't find '%s' in printer list so trying to find default\n",
135               name);
136         if(!GetDefaultPrinterA(buf, &dwBufLen))
137             return num;
138         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
139         if(i == CB_ERR)
140             FIXME("Can't find default printer in printer list\n");
141     }
142     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
143     return num;
144 }
145
146 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
147 {
148     DWORD needed, num;
149     INT i;
150     LPPRINTER_INFO_2W pi;
151     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
152     pi = HeapAlloc(GetProcessHeap(), 0, needed);
153     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
154                   &num);
155
156     for(i = 0; i < num; i++) {
157         SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
158                             (LPARAM)pi[i].pPrinterName );
159     }
160     HeapFree(GetProcessHeap(), 0, pi);
161     if(!name ||
162        (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
163                                 (LPARAM)name)) == CB_ERR) {
164         WCHAR buf[260];
165         DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
166         TRACE("Can't find '%s' in printer list so trying to find default\n",
167               debugstr_w(name));
168         if(!GetDefaultPrinterW(buf, &dwBufLen))
169             return num;
170         i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
171         if(i == CB_ERR)
172             TRACE("Can't find default printer in printer list\n");
173     }
174     SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
175     return num;
176 }
177
178 /***********************************************************************
179  *             PRINTDLG_CreateDevNames          [internal]
180  *
181  *
182  *   creates a DevNames structure.
183  *
184  *  (NB. when we handle unicode the offsets will be in wchars).
185  */
186 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName,
187                                     char* DeviceName, char* OutputPort)
188 {
189     long size;
190     char*   pDevNamesSpace;
191     char*   pTempPtr;
192     LPDEVNAMES lpDevNames;
193     char buf[260];
194     DWORD dwBufLen = sizeof(buf);
195
196     size = strlen(DeviceDriverName) + 1
197             + strlen(DeviceName) + 1
198             + strlen(OutputPort) + 1
199             + sizeof(DEVNAMES);
200
201     if(*hmem)
202         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
203     else
204         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
205     if (*hmem == 0)
206         return FALSE;
207
208     pDevNamesSpace = GlobalLock(*hmem);
209     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
210
211     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
212     strcpy(pTempPtr, DeviceDriverName);
213     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
214
215     pTempPtr += strlen(DeviceDriverName) + 1;
216     strcpy(pTempPtr, DeviceName);
217     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
218
219     pTempPtr += strlen(DeviceName) + 1;
220     strcpy(pTempPtr, OutputPort);
221     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
222
223     GetDefaultPrinterA(buf, &dwBufLen);
224     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
225     GlobalUnlock(*hmem);
226     return TRUE;
227 }
228
229 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
230                                     LPCWSTR DeviceName, LPCWSTR OutputPort)
231 {
232     long size;
233     LPWSTR   pDevNamesSpace;
234     LPWSTR   pTempPtr;
235     LPDEVNAMES lpDevNames;
236     WCHAR bufW[260];
237     DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
238
239     size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
240             + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
241             + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
242             + sizeof(DEVNAMES);
243
244     if(*hmem)
245         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
246     else
247         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
248     if (*hmem == 0)
249         return FALSE;
250
251     pDevNamesSpace = GlobalLock(*hmem);
252     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
253
254     pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
255     lstrcpyW(pTempPtr, DeviceDriverName);
256     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
257
258     pTempPtr += lstrlenW(DeviceDriverName) + 1;
259     lstrcpyW(pTempPtr, DeviceName);
260     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
261
262     pTempPtr += lstrlenW(DeviceName) + 1;
263     lstrcpyW(pTempPtr, OutputPort);
264     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
265
266     GetDefaultPrinterW(bufW, &dwBufLen);
267     lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
268     GlobalUnlock(*hmem);
269     return TRUE;
270 }
271
272 /***********************************************************************
273  *             PRINTDLG_UpdatePrintDlg          [internal]
274  *
275  *
276  *   updates the PrintDlg structure for return values.
277  *
278  * RETURNS
279  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
280  *   TRUE  if successful.
281  */
282 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
283                                     PRINT_PTRA* PrintStructures)
284 {
285     LPPRINTDLGA       lppd = PrintStructures->lpPrintDlg;
286     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
287     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
288
289
290     if(!lpdm) {
291         FIXME("No lpdm ptr?\n");
292         return FALSE;
293     }
294
295
296     if(!(lppd->Flags & PD_PRINTSETUP)) {
297         /* check whether nFromPage and nToPage are within range defined by
298          * nMinPage and nMaxPage
299          */
300         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
301             WORD nToPage;
302             WORD nFromPage;
303             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
304             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
305             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
306                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
307                 char resourcestr[256];
308                 char resultstr[256];
309                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
310                             resourcestr, 255);
311                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
312                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
313                             resourcestr, 255);
314                 MessageBoxA(hDlg, resultstr, resourcestr,
315                             MB_OK | MB_ICONWARNING);
316                 return FALSE;
317             }
318             lppd->nFromPage = nFromPage;
319             lppd->nToPage   = nToPage;
320             lppd->Flags |= PD_PAGENUMS;
321         }
322         else
323             lppd->Flags &= ~PD_PAGENUMS;
324
325         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
326             lppd->Flags |= PD_PRINTTOFILE;
327             pi->pPortName = "FILE:";
328         }
329
330         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
331             FIXME("Collate lppd not yet implemented as output\n");
332         }
333
334         /* set PD_Collate and nCopies */
335         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
336           /*  The application doesn't support multiple copies or collate...
337            */
338             lppd->Flags &= ~PD_COLLATE;
339             lppd->nCopies = 1;
340           /* if the printer driver supports it... store info there
341            * otherwise no collate & multiple copies !
342            */
343             if (lpdm->dmFields & DM_COLLATE)
344                 lpdm->dmCollate =
345                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
346             if (lpdm->dmFields & DM_COPIES)
347                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
348         } else {
349             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
350                 lppd->Flags |= PD_COLLATE;
351             else
352                lppd->Flags &= ~PD_COLLATE;
353             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
354         }
355     }
356     return TRUE;
357 }
358
359 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
360                                     PRINT_PTRW* PrintStructures)
361 {
362     LPPRINTDLGW       lppd = PrintStructures->lpPrintDlg;
363     PDEVMODEW         lpdm = PrintStructures->lpDevMode;
364     LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
365
366
367     if(!lpdm) {
368         FIXME("No lpdm ptr?\n");
369         return FALSE;
370     }
371
372
373     if(!(lppd->Flags & PD_PRINTSETUP)) {
374         /* check whether nFromPage and nToPage are within range defined by
375          * nMinPage and nMaxPage
376          */
377         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
378             WORD nToPage;
379             WORD nFromPage;
380             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
381             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
382             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
383                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
384                 WCHAR resourcestr[256];
385                 WCHAR resultstr[256];
386                 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
387                             resourcestr, 255);
388                 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
389                 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
390                             resourcestr, 255);
391                 MessageBoxW(hDlg, resultstr, resourcestr,
392                             MB_OK | MB_ICONWARNING);
393                 return FALSE;
394             }
395             lppd->nFromPage = nFromPage;
396             lppd->nToPage   = nToPage;
397         }
398
399         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
400             static WCHAR file[] = {'F','I','L','E',':',0};
401             lppd->Flags |= PD_PRINTTOFILE;
402             pi->pPortName = file;
403         }
404
405         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
406             FIXME("Collate lppd not yet implemented as output\n");
407         }
408
409         /* set PD_Collate and nCopies */
410         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
411           /*  The application doesn't support multiple copies or collate...
412            */
413             lppd->Flags &= ~PD_COLLATE;
414             lppd->nCopies = 1;
415           /* if the printer driver supports it... store info there
416            * otherwise no collate & multiple copies !
417            */
418             if (lpdm->dmFields & DM_COLLATE)
419                 lpdm->dmCollate =
420                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
421             if (lpdm->dmFields & DM_COPIES)
422                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
423         } else {
424             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
425                 lppd->Flags |= PD_COLLATE;
426             else
427                lppd->Flags &= ~PD_COLLATE;
428             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
429         }
430     }
431     return TRUE;
432 }
433
434 static BOOL PRINTDLG_PaperSizeA(
435         PRINTDLGA       *pdlga,const char *PaperSize,LPPOINT size
436 ) {
437     DEVNAMES    *dn;
438     DEVMODEA    *dm;
439     LPSTR       devname,portname;
440     int         i;
441     INT         NrOfEntries,ret;
442     char        *Names = NULL;
443     POINT       *points = NULL;
444     BOOL        retval = FALSE;
445
446     dn = GlobalLock(pdlga->hDevNames);
447     dm = GlobalLock(pdlga->hDevMode);
448     devname     = ((char*)dn)+dn->wDeviceOffset;
449     portname    = ((char*)dn)+dn->wOutputOffset;
450
451
452     NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
453     if (!NrOfEntries) {
454         FIXME("No papernames found for %s/%s\n",devname,portname);
455         goto out;
456     }
457     if (NrOfEntries == -1) {
458         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
459         goto out;
460     }
461
462     Names = HeapAlloc(GetProcessHeap(),0,NrOfEntries*64);
463     if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,Names,dm))) {
464         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
465         goto out;
466     }
467     for (i=0;i<NrOfEntries;i++)
468         if (!strcmp(PaperSize,Names+(64*i)))
469             break;
470     HeapFree(GetProcessHeap(),0,Names);
471     if (i==NrOfEntries) {
472         FIXME("Papersize %s not found in list?\n",PaperSize);
473         goto out;
474     }
475     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
476     if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPBYTE)points,dm))) {
477         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
478         goto out;
479     }
480     /* this is _10ths_ of a millimeter */
481     size->x=points[i].x;
482     size->y=points[i].y;
483     retval = TRUE;
484 out:
485     GlobalUnlock(pdlga->hDevNames);
486     GlobalUnlock(pdlga->hDevMode);
487     HeapFree(GetProcessHeap(),0,Names);
488     HeapFree(GetProcessHeap(),0,points);
489     return retval;
490 }
491
492 static BOOL PRINTDLG_PaperSizeW(
493         PRINTDLGW       *pdlga,const WCHAR *PaperSize,LPPOINT size
494 ) {
495     DEVNAMES    *dn;
496     DEVMODEW    *dm;
497     LPWSTR      devname,portname;
498     int         i;
499     INT         NrOfEntries,ret;
500     WCHAR       *Names = NULL;
501     POINT       *points = NULL;
502     BOOL        retval = FALSE;
503
504     dn = GlobalLock(pdlga->hDevNames);
505     dm = GlobalLock(pdlga->hDevMode);
506     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
507     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
508
509
510     NrOfEntries = DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,NULL,dm);
511     if (!NrOfEntries) {
512         FIXME("No papernames found for %s/%s\n",debugstr_w(devname),debugstr_w(portname));
513         goto out;
514     }
515     if (NrOfEntries == -1) {
516         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
517         goto out;
518     }
519
520     Names = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*NrOfEntries*64);
521     if (NrOfEntries != (ret=DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,Names,dm))) {
522         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
523         goto out;
524     }
525     for (i=0;i<NrOfEntries;i++)
526         if (!lstrcmpW(PaperSize,Names+(64*i)))
527             break;
528     HeapFree(GetProcessHeap(),0,Names);
529     if (i==NrOfEntries) {
530         FIXME("Papersize %s not found in list?\n",debugstr_w(PaperSize));
531         goto out;
532     }
533     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
534     if (NrOfEntries!=(ret=DeviceCapabilitiesW(devname,portname,DC_PAPERSIZE,(LPWSTR)points,dm))) {
535         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
536         goto out;
537     }
538     /* this is _10ths_ of a millimeter */
539     size->x=points[i].x;
540     size->y=points[i].y;
541     retval = TRUE;
542 out:
543     GlobalUnlock(pdlga->hDevNames);
544     GlobalUnlock(pdlga->hDevMode);
545     HeapFree(GetProcessHeap(),0,Names);
546     HeapFree(GetProcessHeap(),0,points);
547     return retval;
548 }
549
550
551 /************************************************************************
552  * PRINTDLG_SetUpPaperComboBox
553  *
554  * Initialize either the papersize or inputslot combos of the Printer Setup
555  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
556  * We also try to re-select the old selection.
557  */
558 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
559                                         int   nIDComboBox,
560                                         char* PrinterName,
561                                         char* PortName,
562                                         LPDEVMODEA dm)
563 {
564     int     i;
565     int     NrOfEntries;
566     char*   Names;
567     WORD*   Words;
568     DWORD   Sel;
569     WORD    oldWord = 0;
570     int     NamesSize;
571     int     fwCapability_Names;
572     int     fwCapability_Words;
573
574     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
575
576     /* query the dialog box for the current selected value */
577     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
578     if(Sel != CB_ERR) {
579         /* we enter here only if a different printer is selected after
580          * the Print Setup dialog is opened. The current settings are
581          * stored into the newly selected printer.
582          */
583         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
584                                       Sel, 0);
585         if (dm) {
586             if (nIDComboBox == cmb2)
587                 dm->u1.s1.dmPaperSize = oldWord;
588             else
589                 dm->dmDefaultSource = oldWord;
590         }
591     }
592     else {
593         /* we enter here only when the Print setup dialog is initially
594          * opened. In this case the settings are restored from when
595          * the dialog was last closed.
596          */
597         if (dm) {
598             if (nIDComboBox == cmb2)
599                 oldWord = dm->u1.s1.dmPaperSize;
600             else
601                 oldWord = dm->dmDefaultSource;
602         }
603     }
604
605     if (nIDComboBox == cmb2) {
606          NamesSize          = 64;
607          fwCapability_Names = DC_PAPERNAMES;
608          fwCapability_Words = DC_PAPERS;
609     } else {
610          nIDComboBox        = cmb3;
611          NamesSize          = 24;
612          fwCapability_Names = DC_BINNAMES;
613          fwCapability_Words = DC_BINS;
614     }
615
616     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
617      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
618      */
619     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
620     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
621                                       fwCapability_Names, NULL, dm);
622     if (NrOfEntries == 0)
623          WARN("no Name Entries found!\n");
624     else if (NrOfEntries < 0)
625          return FALSE;
626
627     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
628        != NrOfEntries) {
629         ERR("Number of caps is different\n");
630         NrOfEntries = 0;
631     }
632
633     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
634     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
635     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
636                                       fwCapability_Names, Names, dm);
637     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
638                                       fwCapability_Words, (LPSTR)Words, dm);
639
640     /* reset any current content in the combobox */
641     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
642
643     /* store new content */
644     for (i = 0; i < NrOfEntries; i++) {
645         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
646                                         (LPARAM)(&Names[i*NamesSize]) );
647         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
648                             Words[i]);
649     }
650
651     /* Look for old selection - can't do this is previous loop since
652        item order will change as more items are added */
653     Sel = 0;
654     for (i = 0; i < NrOfEntries; i++) {
655         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
656            oldWord) {
657             Sel = i;
658             break;
659         }
660     }
661     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
662
663     HeapFree(GetProcessHeap(),0,Words);
664     HeapFree(GetProcessHeap(),0,Names);
665     return TRUE;
666 }
667
668 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
669                                         int   nIDComboBox,
670                                         WCHAR* PrinterName,
671                                         WCHAR* PortName,
672                                         LPDEVMODEW dm)
673 {
674     int     i;
675     int     NrOfEntries;
676     WCHAR*  Names;
677     WORD*   Words;
678     DWORD   Sel;
679     WORD    oldWord = 0;
680     int     NamesSize;
681     int     fwCapability_Names;
682     int     fwCapability_Words;
683
684     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
685
686     /* query the dialog box for the current selected value */
687     Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
688     if(Sel != CB_ERR) {
689         /* we enter here only if a different printer is selected after
690          * the Print Setup dialog is opened. The current settings are
691          * stored into the newly selected printer.
692          */
693         oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
694                                       Sel, 0);
695         if (dm) {
696             if (nIDComboBox == cmb2)
697                 dm->u1.s1.dmPaperSize = oldWord;
698             else
699                 dm->dmDefaultSource = oldWord;
700         }
701     }
702     else {
703         /* we enter here only when the Print setup dialog is initially
704          * opened. In this case the settings are restored from when
705          * the dialog was last closed.
706          */
707         if (dm) {
708             if (nIDComboBox == cmb2)
709                 oldWord = dm->u1.s1.dmPaperSize;
710             else
711                 oldWord = dm->dmDefaultSource;
712         }
713     }
714
715     if (nIDComboBox == cmb2) {
716          NamesSize          = 64;
717          fwCapability_Names = DC_PAPERNAMES;
718          fwCapability_Words = DC_PAPERS;
719     } else {
720          nIDComboBox        = cmb3;
721          NamesSize          = 24;
722          fwCapability_Names = DC_BINNAMES;
723          fwCapability_Words = DC_BINS;
724     }
725
726     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
727      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
728      */
729     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
730     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
731                                       fwCapability_Names, NULL, dm);
732     if (NrOfEntries == 0)
733          WARN("no Name Entries found!\n");
734     else if (NrOfEntries < 0)
735          return FALSE;
736
737     if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
738        != NrOfEntries) {
739         ERR("Number of caps is different\n");
740         NrOfEntries = 0;
741     }
742
743     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
744     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
745     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
746                                       fwCapability_Names, Names, dm);
747     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
748                                       fwCapability_Words, (LPWSTR)Words, dm);
749
750     /* reset any current content in the combobox */
751     SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
752
753     /* store new content */
754     for (i = 0; i < NrOfEntries; i++) {
755         DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
756                                         (LPARAM)(&Names[i*NamesSize]) );
757         SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
758                             Words[i]);
759     }
760
761     /* Look for old selection - can't do this is previous loop since
762        item order will change as more items are added */
763     Sel = 0;
764     for (i = 0; i < NrOfEntries; i++) {
765         if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
766            oldWord) {
767             Sel = i;
768             break;
769         }
770     }
771     SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
772
773     HeapFree(GetProcessHeap(),0,Words);
774     HeapFree(GetProcessHeap(),0,Names);
775     return TRUE;
776 }
777
778
779 /***********************************************************************
780  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
781  */
782 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, LPPRINTER_INFO_2A pi)
783 {
784     char   StatusMsg[256];
785     char   ResourceString[256];
786     int    i;
787
788     /* Status Message */
789     StatusMsg[0]='\0';
790
791     /* add all status messages */
792     for (i = 0; i < 25; i++) {
793         if (pi->Status & (1<<i)) {
794             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
795                         ResourceString, 255);
796             strcat(StatusMsg,ResourceString);
797         }
798     }
799     /* append "ready" */
800     /* FIXME: status==ready must only be appended if really so.
801               but how to detect? */
802     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
803                 ResourceString, 255);
804     strcat(StatusMsg,ResourceString);
805     SetDlgItemTextA(hDlg, stc12, StatusMsg);
806
807     /* set all other printer info texts */
808     SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
809     
810     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
811         SetDlgItemTextA(hDlg, stc14, pi->pLocation);
812     else
813         SetDlgItemTextA(hDlg, stc14, pi->pPortName);
814     SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
815     return;
816 }
817
818 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, LPPRINTER_INFO_2W pi)
819 {
820     WCHAR   StatusMsg[256];
821     WCHAR   ResourceString[256];
822     static const WCHAR emptyW[] = {0};
823     int    i;
824
825     /* Status Message */
826     StatusMsg[0]='\0';
827
828     /* add all status messages */
829     for (i = 0; i < 25; i++) {
830         if (pi->Status & (1<<i)) {
831             LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
832                         ResourceString, 255);
833             lstrcatW(StatusMsg,ResourceString);
834         }
835     }
836     /* append "ready" */
837     /* FIXME: status==ready must only be appended if really so.
838               but how to detect? */
839     LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
840                 ResourceString, 255);
841     lstrcatW(StatusMsg,ResourceString);
842     SetDlgItemTextW(hDlg, stc12, StatusMsg);
843
844     /* set all other printer info texts */
845     SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
846     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
847         SetDlgItemTextW(hDlg, stc14, pi->pLocation);
848     else
849         SetDlgItemTextW(hDlg, stc14, pi->pPortName);
850     SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
851 }
852
853
854 /*******************************************************************
855  *
856  *                 PRINTDLG_ChangePrinter
857  *
858  */
859 BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name,
860                                    PRINT_PTRA *PrintStructures)
861 {
862     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
863     LPDEVMODEA lpdm = NULL;
864     LONG dmSize;
865     DWORD needed;
866     HANDLE hprn;
867
868     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
869     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
870     if(!OpenPrinterA(name, &hprn, NULL)) {
871         ERR("Can't open printer %s\n", name);
872         return FALSE;
873     }
874     GetPrinterA(hprn, 2, NULL, 0, &needed);
875     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
876     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
877                 &needed);
878     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
879     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
880     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
881             needed, &needed)) {
882         ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
883         return FALSE;
884     }
885     ClosePrinter(hprn);
886
887     PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
888
889     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
890     PrintStructures->lpDevMode = NULL;
891
892     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
893     if(dmSize == -1) {
894         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
895         return FALSE;
896     }
897     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
898     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
899                                  DM_OUT_BUFFER);
900     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
901                           !strcmp(lpdm->dmDeviceName,
902                                   PrintStructures->lpDevMode->dmDeviceName)) {
903       /* Supplied devicemode matches current printer so try to use it */
904         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
905                             DM_OUT_BUFFER | DM_IN_BUFFER);
906     }
907     if(lpdm)
908         GlobalUnlock(lppd->hDevMode);
909
910     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
911
912     if(!(lppd->Flags & PD_PRINTSETUP)) {
913       /* Print range (All/Range/Selection) */
914         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
915         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
916         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
917         if (lppd->Flags & PD_NOSELECTION)
918             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
919         else
920             if (lppd->Flags & PD_SELECTION)
921                 CheckRadioButton(hDlg, rad1, rad3, rad2);
922         if (lppd->Flags & PD_NOPAGENUMS) {
923             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
924             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
925             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
926             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
927             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
928         } else {
929             if (lppd->Flags & PD_PAGENUMS)
930                 CheckRadioButton(hDlg, rad1, rad3, rad3);
931         }
932
933         /* Collate pages
934          *
935          * FIXME: The ico3 is not displayed for some reason. I don't know why.
936          */
937         if (lppd->Flags & PD_COLLATE) {
938             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
939                                 (LPARAM)PrintStructures->hCollateIcon);
940             CheckDlgButton(hDlg, chx2, 1);
941         } else {
942             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
943                                 (LPARAM)PrintStructures->hNoCollateIcon);
944             CheckDlgButton(hDlg, chx2, 0);
945         }
946
947         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
948           /* if printer doesn't support it: no Collate */
949             if (!(lpdm->dmFields & DM_COLLATE)) {
950                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
951                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
952             }
953         }
954
955         /* nCopies */
956         {
957           INT copies;
958           if (lppd->hDevMode == 0)
959               copies = lppd->nCopies;
960           else
961               copies = lpdm->dmCopies;
962           if(copies == 0) copies = 1;
963           else if(copies < 0) copies = MAX_COPIES;
964           SetDlgItemInt(hDlg, edt3, copies, FALSE);
965         }
966
967         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
968           /* if printer doesn't support it: no nCopies */
969             if (!(lpdm->dmFields & DM_COPIES)) {
970                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
971                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
972             }
973         }
974
975         /* print to file */
976         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
977         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
978             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
979         if (lppd->Flags & PD_HIDEPRINTTOFILE)
980             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
981
982     } else { /* PD_PRINTSETUP */
983       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
984
985       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
986                                   PrintStructures->lpPrinterInfo->pPrinterName,
987                                   PrintStructures->lpPrinterInfo->pPortName,
988                                   lpdm);
989       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
990                                   PrintStructures->lpPrinterInfo->pPrinterName,
991                                   PrintStructures->lpPrinterInfo->pPortName,
992                                   lpdm);
993       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
994       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
995                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
996                                    PrintStructures->hLandscapeIcon));
997
998     }
999
1000     /* help button */
1001     if ((lppd->Flags & PD_SHOWHELP)==0) {
1002         /* hide if PD_SHOWHELP not specified */
1003         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1004     }
1005     return TRUE;
1006 }
1007
1008 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1009                                    PRINT_PTRW *PrintStructures)
1010 {
1011     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1012     LPDEVMODEW lpdm = NULL;
1013     LONG dmSize;
1014     DWORD needed;
1015     HANDLE hprn;
1016
1017     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1018     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1019     if(!OpenPrinterW(name, &hprn, NULL)) {
1020         ERR("Can't open printer %s\n", debugstr_w(name));
1021         return FALSE;
1022     }
1023     GetPrinterW(hprn, 2, NULL, 0, &needed);
1024     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1025     GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1026                 &needed);
1027     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1028     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1029     if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1030             needed, &needed)) {
1031         ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1032         return FALSE;
1033     }
1034     ClosePrinter(hprn);
1035
1036     PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1037
1038     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1039     PrintStructures->lpDevMode = NULL;
1040
1041     dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1042     if(dmSize == -1) {
1043         ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1044         return FALSE;
1045     }
1046     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1047     dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1048                                  DM_OUT_BUFFER);
1049     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1050                           !lstrcmpW(lpdm->dmDeviceName,
1051                                   PrintStructures->lpDevMode->dmDeviceName)) {
1052       /* Supplied devicemode matches current printer so try to use it */
1053         DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1054                             DM_OUT_BUFFER | DM_IN_BUFFER);
1055     }
1056     if(lpdm)
1057         GlobalUnlock(lppd->hDevMode);
1058
1059     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
1060
1061     if(!(lppd->Flags & PD_PRINTSETUP)) {
1062       /* Print range (All/Range/Selection) */
1063         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1064         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1065         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
1066         if (lppd->Flags & PD_NOSELECTION)
1067             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1068         else
1069             if (lppd->Flags & PD_SELECTION)
1070                 CheckRadioButton(hDlg, rad1, rad3, rad2);
1071         if (lppd->Flags & PD_NOPAGENUMS) {
1072             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1073             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1074             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1075             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1076             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1077         } else {
1078             if (lppd->Flags & PD_PAGENUMS)
1079                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1080         }
1081
1082         /* Collate pages
1083          *
1084          * FIXME: The ico3 is not displayed for some reason. I don't know why.
1085          */
1086         if (lppd->Flags & PD_COLLATE) {
1087             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1088                                 (LPARAM)PrintStructures->hCollateIcon);
1089             CheckDlgButton(hDlg, chx2, 1);
1090         } else {
1091             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1092                                 (LPARAM)PrintStructures->hNoCollateIcon);
1093             CheckDlgButton(hDlg, chx2, 0);
1094         }
1095
1096         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1097           /* if printer doesn't support it: no Collate */
1098             if (!(lpdm->dmFields & DM_COLLATE)) {
1099                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1100                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1101             }
1102         }
1103
1104         /* nCopies */
1105         {
1106           INT copies;
1107           if (lppd->hDevMode == 0)
1108               copies = lppd->nCopies;
1109           else
1110               copies = lpdm->dmCopies;
1111           if(copies == 0) copies = 1;
1112           else if(copies < 0) copies = MAX_COPIES;
1113           SetDlgItemInt(hDlg, edt3, copies, FALSE);
1114         }
1115
1116         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1117           /* if printer doesn't support it: no nCopies */
1118             if (!(lpdm->dmFields & DM_COPIES)) {
1119                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1120                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1121             }
1122         }
1123
1124         /* print to file */
1125         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1126         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1127             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1128         if (lppd->Flags & PD_HIDEPRINTTOFILE)
1129             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1130
1131     } else { /* PD_PRINTSETUP */
1132       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1133
1134       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1135                                   PrintStructures->lpPrinterInfo->pPrinterName,
1136                                   PrintStructures->lpPrinterInfo->pPortName,
1137                                   lpdm);
1138       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1139                                   PrintStructures->lpPrinterInfo->pPrinterName,
1140                                   PrintStructures->lpPrinterInfo->pPortName,
1141                                   lpdm);
1142       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1143       SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1144                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1145                                    PrintStructures->hLandscapeIcon));
1146
1147     }
1148
1149     /* help button */
1150     if ((lppd->Flags & PD_SHOWHELP)==0) {
1151         /* hide if PD_SHOWHELP not specified */
1152         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1153     }
1154     return TRUE;
1155 }
1156
1157 /***********************************************************************
1158  *           PRINTDLG_WMInitDialog                      [internal]
1159  */
1160 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
1161                                      PRINT_PTRA* PrintStructures)
1162 {
1163     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1164     DEVNAMES *pdn;
1165     DEVMODEA *pdm;
1166     char *name = NULL;
1167     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1168
1169     /* load Collate ICONs */
1170     /* We load these with LoadImage because they are not a standard
1171        size and we don't want them rescaled */
1172     PrintStructures->hCollateIcon =
1173       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1174     PrintStructures->hNoCollateIcon =
1175       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1176
1177     /* These can be done with LoadIcon */
1178     PrintStructures->hPortraitIcon =
1179       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1180     PrintStructures->hLandscapeIcon =
1181       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1182
1183     /* display the collate/no_collate icon */
1184     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1185                         (LPARAM)PrintStructures->hNoCollateIcon);
1186
1187     if(PrintStructures->hCollateIcon == 0 ||
1188        PrintStructures->hNoCollateIcon == 0 ||
1189        PrintStructures->hPortraitIcon == 0 ||
1190        PrintStructures->hLandscapeIcon == 0) {
1191         ERR("no icon in resourcefile\n");
1192         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1193         EndDialog(hDlg, FALSE);
1194     }
1195
1196     /*
1197      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1198      * must be registered and the Help button must be shown.
1199      */
1200     if (lppd->Flags & PD_SHOWHELP) {
1201         if((PrintStructures->HelpMessageID =
1202             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1203             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1204             return FALSE;
1205         }
1206     } else
1207         PrintStructures->HelpMessageID = 0;
1208
1209     if(!(lppd->Flags &PD_PRINTSETUP)) {
1210         PrintStructures->hwndUpDown =
1211           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1212                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1213                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1214                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1215                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1216     }
1217
1218     /* FIXME: I allow more freedom than either Win95 or WinNT,
1219      *        which do not agree to what errors should be thrown or not
1220      *        in case nToPage or nFromPage is out-of-range.
1221      */
1222     if (lppd->nMaxPage < lppd->nMinPage)
1223         lppd->nMaxPage = lppd->nMinPage;
1224     if (lppd->nMinPage == lppd->nMaxPage)
1225         lppd->Flags |= PD_NOPAGENUMS;
1226     if (lppd->nToPage < lppd->nMinPage)
1227         lppd->nToPage = lppd->nMinPage;
1228     if (lppd->nToPage > lppd->nMaxPage)
1229         lppd->nToPage = lppd->nMaxPage;
1230     if (lppd->nFromPage < lppd->nMinPage)
1231         lppd->nFromPage = lppd->nMinPage;
1232     if (lppd->nFromPage > lppd->nMaxPage)
1233         lppd->nFromPage = lppd->nMaxPage;
1234
1235     /* if we have the combo box, fill it */
1236     if (GetDlgItem(hDlg,comboID)) {
1237         /* Fill Combobox
1238          */
1239         pdn = GlobalLock(lppd->hDevNames);
1240         pdm = GlobalLock(lppd->hDevMode);
1241         if(pdn)
1242             name = (char*)pdn + pdn->wDeviceOffset;
1243         else if(pdm)
1244             name = pdm->dmDeviceName;
1245         PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1246         if(pdm) GlobalUnlock(lppd->hDevMode);
1247         if(pdn) GlobalUnlock(lppd->hDevNames);
1248
1249         /* Now find selected printer and update rest of dlg */
1250         name = HeapAlloc(GetProcessHeap(),0,256);
1251         if (GetDlgItemTextA(hDlg, comboID, name, 255))
1252             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1253         HeapFree(GetProcessHeap(),0,name);
1254     } else {
1255         /* else use default printer */
1256         char name[200];
1257         DWORD dwBufLen = sizeof(name);
1258         BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1259
1260         if (ret)
1261             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1262         else
1263             FIXME("No default printer found, expect problems!\n");
1264     }
1265     return TRUE;
1266 }
1267
1268 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1269                                      PRINT_PTRW* PrintStructures)
1270 {
1271     const static WCHAR PD32_COLLATE[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1272     const static WCHAR PD32_NOCOLLATE[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1273     const static WCHAR PD32_PORTRAIT[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
1274     const static WCHAR PD32_LANDSCAPE[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
1275     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1276     DEVNAMES *pdn;
1277     DEVMODEW *pdm;
1278     WCHAR *name = NULL;
1279     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1280
1281     /* load Collate ICONs */
1282     /* We load these with LoadImage because they are not a standard
1283        size and we don't want them rescaled */
1284     PrintStructures->hCollateIcon =
1285       LoadImageW(COMDLG32_hInstance, PD32_COLLATE, IMAGE_ICON, 0, 0, 0);
1286     PrintStructures->hNoCollateIcon =
1287       LoadImageW(COMDLG32_hInstance, PD32_NOCOLLATE, IMAGE_ICON, 0, 0, 0);
1288
1289     /* These can be done with LoadIcon */
1290     PrintStructures->hPortraitIcon =
1291       LoadIconW(COMDLG32_hInstance, PD32_PORTRAIT);
1292     PrintStructures->hLandscapeIcon =
1293       LoadIconW(COMDLG32_hInstance, PD32_LANDSCAPE);
1294
1295     /* display the collate/no_collate icon */
1296     SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1297                         (LPARAM)PrintStructures->hNoCollateIcon);
1298
1299     if(PrintStructures->hCollateIcon == 0 ||
1300        PrintStructures->hNoCollateIcon == 0 ||
1301        PrintStructures->hPortraitIcon == 0 ||
1302        PrintStructures->hLandscapeIcon == 0) {
1303         ERR("no icon in resourcefile\n");
1304         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1305         EndDialog(hDlg, FALSE);
1306     }
1307
1308     /*
1309      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1310      * must be registered and the Help button must be shown.
1311      */
1312     if (lppd->Flags & PD_SHOWHELP) {
1313         if((PrintStructures->HelpMessageID =
1314             RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1315             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1316             return FALSE;
1317         }
1318     } else
1319         PrintStructures->HelpMessageID = 0;
1320
1321     if(!(lppd->Flags &PD_PRINTSETUP)) {
1322         PrintStructures->hwndUpDown =
1323           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1324                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1325                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1326                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1327                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1328     }
1329
1330     /* FIXME: I allow more freedom than either Win95 or WinNT,
1331      *        which do not agree to what errors should be thrown or not
1332      *        in case nToPage or nFromPage is out-of-range.
1333      */
1334     if (lppd->nMaxPage < lppd->nMinPage)
1335         lppd->nMaxPage = lppd->nMinPage;
1336     if (lppd->nMinPage == lppd->nMaxPage)
1337         lppd->Flags |= PD_NOPAGENUMS;
1338     if (lppd->nToPage < lppd->nMinPage)
1339         lppd->nToPage = lppd->nMinPage;
1340     if (lppd->nToPage > lppd->nMaxPage)
1341         lppd->nToPage = lppd->nMaxPage;
1342     if (lppd->nFromPage < lppd->nMinPage)
1343         lppd->nFromPage = lppd->nMinPage;
1344     if (lppd->nFromPage > lppd->nMaxPage)
1345         lppd->nFromPage = lppd->nMaxPage;
1346
1347     /* if we have the combo box, fill it */
1348     if (GetDlgItem(hDlg,comboID)) {
1349         /* Fill Combobox
1350          */
1351         pdn = GlobalLock(lppd->hDevNames);
1352         pdm = GlobalLock(lppd->hDevMode);
1353         if(pdn)
1354             name = (WCHAR*)pdn + pdn->wDeviceOffset;
1355         else if(pdm)
1356             name = pdm->dmDeviceName;
1357         PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1358         if(pdm) GlobalUnlock(lppd->hDevMode);
1359         if(pdn) GlobalUnlock(lppd->hDevNames);
1360
1361         /* Now find selected printer and update rest of dlg */
1362         /* ansi is ok here */
1363         name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1364         if (GetDlgItemTextW(hDlg, comboID, name, 255))
1365             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1366         HeapFree(GetProcessHeap(),0,name);
1367     } else {
1368         /* else use default printer */
1369         WCHAR name[200];
1370         DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1371         BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1372
1373         if (ret)
1374             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1375         else
1376             FIXME("No default printer found, expect problems!\n");
1377     }
1378     return TRUE;
1379 }
1380
1381 /***********************************************************************
1382  *                              PRINTDLG_WMCommand               [internal]
1383  */
1384 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1385                         LPARAM lParam, PRINT_PTRA* PrintStructures)
1386 {
1387     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1388     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1389     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1390
1391     switch (LOWORD(wParam))  {
1392     case IDOK:
1393         TRACE(" OK button was hit\n");
1394         if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1395             FIXME("Update printdlg was not successful!\n");
1396             return(FALSE);
1397         }
1398         EndDialog(hDlg, TRUE);
1399         return(TRUE);
1400
1401     case IDCANCEL:
1402         TRACE(" CANCEL button was hit\n");
1403         EndDialog(hDlg, FALSE);
1404         return(FALSE);
1405
1406      case pshHelp:
1407         TRACE(" HELP button was hit\n");
1408         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1409                                 (WPARAM) hDlg, (LPARAM) lppd);
1410         break;
1411
1412      case chx2:                         /* collate pages checkbox */
1413         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1414             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1415                                     (LPARAM)PrintStructures->hCollateIcon);
1416         else
1417             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1418                                     (LPARAM)PrintStructures->hNoCollateIcon);
1419         break;
1420      case edt1:                         /* from page nr editbox */
1421      case edt2:                         /* to page nr editbox */
1422         if (HIWORD(wParam)==EN_CHANGE) {
1423             WORD nToPage;
1424             WORD nFromPage;
1425             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1426             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1427             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1428                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1429         }
1430         break;
1431
1432     case edt3:
1433         if(HIWORD(wParam) == EN_CHANGE) {
1434             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1435             if(copies <= 1)
1436                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1437             else
1438                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1439         }
1440         break;
1441
1442 #if 0
1443      case psh1:                       /* Print Setup */
1444         {
1445             PRINTDLG16  pdlg;
1446
1447             if (!PrintStructures->dlg.lpPrintDlg16) {
1448                 FIXME("The 32bit print dialog does not have this button!?\n");
1449                 break;
1450             }
1451
1452             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1453             pdlg.Flags |= PD_PRINTSETUP;
1454             pdlg.hwndOwner = HWND_16(hDlg);
1455             if (!PrintDlg16(&pdlg))
1456                 break;
1457         }
1458         break;
1459 #endif
1460      case psh2:                       /* Properties button */
1461        {
1462          HANDLE hPrinter;
1463          char   PrinterName[256];
1464
1465          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1466          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1467              FIXME(" Call to OpenPrinter did not succeed!\n");
1468              break;
1469          }
1470          DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1471                              PrintStructures->lpDevMode,
1472                              PrintStructures->lpDevMode,
1473                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1474          ClosePrinter(hPrinter);
1475          break;
1476        }
1477
1478     case rad1: /* Paperorientation */
1479         if (lppd->Flags & PD_PRINTSETUP)
1480         {
1481               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1482               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1483                           (LPARAM)(PrintStructures->hPortraitIcon));
1484         }
1485         break;
1486
1487     case rad2: /* Paperorientation */
1488         if (lppd->Flags & PD_PRINTSETUP)
1489         {
1490               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1491               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1492                           (LPARAM)(PrintStructures->hLandscapeIcon));
1493         }
1494         break;
1495
1496     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1497          if (PrinterComboID != LOWORD(wParam)) {
1498              FIXME("No handling for print quality combo box yet.\n");
1499              break;
1500          }
1501          /* FALLTHROUGH */
1502     case cmb4:                         /* Printer combobox */
1503          if (HIWORD(wParam)==CBN_SELCHANGE) {
1504              char   PrinterName[256];
1505              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1506              PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1507          }
1508          break;
1509
1510     case cmb2: /* Papersize */
1511       {
1512           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1513           if(Sel != CB_ERR)
1514               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1515                                                             CB_GETITEMDATA,
1516                                                             Sel, 0);
1517       }
1518       break;
1519
1520     case cmb3: /* Bin */
1521       {
1522           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1523           if(Sel != CB_ERR)
1524               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1525                                                           CB_GETITEMDATA, Sel,
1526                                                           0);
1527       }
1528       break;
1529     }
1530     if(lppd->Flags & PD_PRINTSETUP) {
1531         switch (LOWORD(wParam)) {
1532         case rad1:                         /* orientation */
1533         case rad2:
1534             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1535                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1536                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1537                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1538                                         (WPARAM)IMAGE_ICON,
1539                                         (LPARAM)PrintStructures->hPortraitIcon);
1540                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1541                                         (WPARAM)IMAGE_ICON,
1542                                         (LPARAM)PrintStructures->hPortraitIcon);
1543                 }
1544             } else {
1545                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1546                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1547                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1548                                         (WPARAM)IMAGE_ICON,
1549                                         (LPARAM)PrintStructures->hLandscapeIcon);
1550                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1551                                         (WPARAM)IMAGE_ICON,
1552                                         (LPARAM)PrintStructures->hLandscapeIcon);
1553                 }
1554             }
1555             break;
1556         }
1557     }
1558     return FALSE;
1559 }
1560
1561 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1562                         LPARAM lParam, PRINT_PTRW* PrintStructures)
1563 {
1564     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1565     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1566     LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1567
1568     switch (LOWORD(wParam))  {
1569     case IDOK:
1570         TRACE(" OK button was hit\n");
1571         if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1572             FIXME("Update printdlg was not successful!\n");
1573             return(FALSE);
1574         }
1575         EndDialog(hDlg, TRUE);
1576         return(TRUE);
1577
1578     case IDCANCEL:
1579         TRACE(" CANCEL button was hit\n");
1580         EndDialog(hDlg, FALSE);
1581         return(FALSE);
1582
1583      case pshHelp:
1584         TRACE(" HELP button was hit\n");
1585         SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1586                                 (WPARAM) hDlg, (LPARAM) lppd);
1587         break;
1588
1589      case chx2:                         /* collate pages checkbox */
1590         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1591             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1592                                     (LPARAM)PrintStructures->hCollateIcon);
1593         else
1594             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1595                                     (LPARAM)PrintStructures->hNoCollateIcon);
1596         break;
1597      case edt1:                         /* from page nr editbox */
1598      case edt2:                         /* to page nr editbox */
1599         if (HIWORD(wParam)==EN_CHANGE) {
1600             WORD nToPage;
1601             WORD nFromPage;
1602             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1603             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1604             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1605                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1606         }
1607         break;
1608
1609     case edt3:
1610         if(HIWORD(wParam) == EN_CHANGE) {
1611             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1612             if(copies <= 1)
1613                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1614             else
1615                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1616         }
1617         break;
1618
1619      case psh1:                       /* Print Setup */
1620         {
1621                 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1622         }
1623         break;
1624      case psh2:                       /* Properties button */
1625        {
1626          HANDLE hPrinter;
1627          WCHAR  PrinterName[256];
1628
1629          if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1630          if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1631              FIXME(" Call to OpenPrinter did not succeed!\n");
1632              break;
1633          }
1634          DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1635                              PrintStructures->lpDevMode,
1636                              PrintStructures->lpDevMode,
1637                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1638          ClosePrinter(hPrinter);
1639          break;
1640        }
1641
1642     case rad1: /* Paperorientation */
1643         if (lppd->Flags & PD_PRINTSETUP)
1644         {
1645               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1646               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1647                           (LPARAM)(PrintStructures->hPortraitIcon));
1648         }
1649         break;
1650
1651     case rad2: /* Paperorientation */
1652         if (lppd->Flags & PD_PRINTSETUP)
1653         {
1654               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1655               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1656                           (LPARAM)(PrintStructures->hLandscapeIcon));
1657         }
1658         break;
1659
1660     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1661          if (PrinterComboID != LOWORD(wParam)) {
1662              FIXME("No handling for print quality combo box yet.\n");
1663              break;
1664          }
1665          /* FALLTHROUGH */
1666     case cmb4:                         /* Printer combobox */
1667          if (HIWORD(wParam)==CBN_SELCHANGE) {
1668              WCHAR   PrinterName[256];
1669              GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1670              PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1671          }
1672          break;
1673
1674     case cmb2: /* Papersize */
1675       {
1676           DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1677           if(Sel != CB_ERR)
1678               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1679                                                             CB_GETITEMDATA,
1680                                                             Sel, 0);
1681       }
1682       break;
1683
1684     case cmb3: /* Bin */
1685       {
1686           DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1687           if(Sel != CB_ERR)
1688               lpdm->dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1689                                                           CB_GETITEMDATA, Sel,
1690                                                           0);
1691       }
1692       break;
1693     }
1694     if(lppd->Flags & PD_PRINTSETUP) {
1695         switch (LOWORD(wParam)) {
1696         case rad1:                         /* orientation */
1697         case rad2:
1698             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1699                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1700                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1701                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1702                                         (WPARAM)IMAGE_ICON,
1703                                         (LPARAM)PrintStructures->hPortraitIcon);
1704                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1705                                         (WPARAM)IMAGE_ICON,
1706                                         (LPARAM)PrintStructures->hPortraitIcon);
1707                 }
1708             } else {
1709                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1710                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1711                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1712                                         (WPARAM)IMAGE_ICON,
1713                                         (LPARAM)PrintStructures->hLandscapeIcon);
1714                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1715                                         (WPARAM)IMAGE_ICON,
1716                                         (LPARAM)PrintStructures->hLandscapeIcon);
1717                 }
1718             }
1719             break;
1720         }
1721     }
1722     return FALSE;
1723 }
1724
1725 /***********************************************************************
1726  *           PrintDlgProcA                      [internal]
1727  */
1728 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1729                                       LPARAM lParam)
1730 {
1731     PRINT_PTRA* PrintStructures;
1732     INT_PTR res = FALSE;
1733
1734     if (uMsg!=WM_INITDIALOG) {
1735         PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
1736         if (!PrintStructures)
1737             return FALSE;
1738     } else {
1739         PrintStructures = (PRINT_PTRA*) lParam;
1740         SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
1741         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1742
1743         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1744             res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1745                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1746             );
1747         return res;
1748     }
1749
1750     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1751         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1752                                                          lParam);
1753         if(res) return res;
1754     }
1755
1756     switch (uMsg) {
1757     case WM_COMMAND:
1758         return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1759
1760     case WM_DESTROY:
1761         DestroyIcon(PrintStructures->hCollateIcon);
1762         DestroyIcon(PrintStructures->hNoCollateIcon);
1763         DestroyIcon(PrintStructures->hPortraitIcon);
1764         DestroyIcon(PrintStructures->hLandscapeIcon);
1765         if(PrintStructures->hwndUpDown)
1766             DestroyWindow(PrintStructures->hwndUpDown);
1767         return FALSE;
1768     }
1769     return res;
1770 }
1771
1772 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1773                                       LPARAM lParam)
1774 {
1775     static const WCHAR propW[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
1776     PRINT_PTRW* PrintStructures;
1777     INT_PTR res = FALSE;
1778
1779     if (uMsg!=WM_INITDIALOG) {
1780         PrintStructures = (PRINT_PTRW*) GetPropW(hDlg, propW);
1781         if (!PrintStructures)
1782             return FALSE;
1783     } else {
1784         PrintStructures = (PRINT_PTRW*) lParam;
1785         SetPropW(hDlg, propW, PrintStructures);
1786         res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1787
1788         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1789             res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1790         return res;
1791     }
1792
1793     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1794         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1795         if(res) return res;
1796     }
1797
1798     switch (uMsg) {
1799     case WM_COMMAND:
1800         return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1801
1802     case WM_DESTROY:
1803         DestroyIcon(PrintStructures->hCollateIcon);
1804         DestroyIcon(PrintStructures->hNoCollateIcon);
1805         DestroyIcon(PrintStructures->hPortraitIcon);
1806         DestroyIcon(PrintStructures->hLandscapeIcon);
1807         if(PrintStructures->hwndUpDown)
1808             DestroyWindow(PrintStructures->hwndUpDown);
1809         return FALSE;
1810     }
1811     return res;
1812 }
1813
1814 /************************************************************
1815  *
1816  *      PRINTDLG_GetDlgTemplate
1817  *
1818  */
1819 static HGLOBAL PRINTDLG_GetDlgTemplateA(PRINTDLGA *lppd)
1820 {
1821     HRSRC hResInfo;
1822     HGLOBAL hDlgTmpl;
1823
1824     if (lppd->Flags & PD_PRINTSETUP) {
1825         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1826             hDlgTmpl = lppd->hSetupTemplate;
1827         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1828             hResInfo = FindResourceA(lppd->hInstance,
1829                                      lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1830             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1831         } else {
1832             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1833                                      (LPSTR)RT_DIALOG);
1834             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1835         }
1836     } else {
1837         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1838             hDlgTmpl = lppd->hPrintTemplate;
1839         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1840             hResInfo = FindResourceA(lppd->hInstance,
1841                                      lppd->lpPrintTemplateName,
1842                                      (LPSTR)RT_DIALOG);
1843             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1844         } else {
1845             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1846                                      (LPSTR)RT_DIALOG);
1847             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1848         }
1849     }
1850     return hDlgTmpl;
1851 }
1852
1853 static HGLOBAL PRINTDLG_GetDlgTemplateW(PRINTDLGW *lppd)
1854 {
1855     HRSRC hResInfo;
1856     HGLOBAL hDlgTmpl;
1857     static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1858     static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1859
1860     if (lppd->Flags & PD_PRINTSETUP) {
1861         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1862             hDlgTmpl = lppd->hSetupTemplate;
1863         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1864             hResInfo = FindResourceW(lppd->hInstance,
1865                                      lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1866             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1867         } else {
1868             hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1869             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1870         }
1871     } else {
1872         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1873             hDlgTmpl = lppd->hPrintTemplate;
1874         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1875             hResInfo = FindResourceW(lppd->hInstance,
1876                                      lppd->lpPrintTemplateName,
1877                                      (LPWSTR)RT_DIALOG);
1878             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1879         } else {
1880             hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1881             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1882         }
1883     }
1884     return hDlgTmpl;
1885 }
1886
1887 /***********************************************************************
1888  *
1889  *      PRINTDLG_CreateDC
1890  *
1891  */
1892 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1893 {
1894     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1895     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1896
1897     if(lppd->Flags & PD_RETURNDC) {
1898         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1899                               (char*)pdn + pdn->wDeviceOffset,
1900                               (char*)pdn + pdn->wOutputOffset,
1901                               pdm );
1902     } else if(lppd->Flags & PD_RETURNIC) {
1903         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1904                               (char*)pdn + pdn->wDeviceOffset,
1905                               (char*)pdn + pdn->wOutputOffset,
1906                               pdm );
1907     }
1908     GlobalUnlock(lppd->hDevNames);
1909     GlobalUnlock(lppd->hDevMode);
1910     return lppd->hDC ? TRUE : FALSE;
1911 }
1912
1913 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1914 {
1915     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1916     DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1917
1918     if(lppd->Flags & PD_RETURNDC) {
1919         lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1920                               (WCHAR*)pdn + pdn->wDeviceOffset,
1921                               (WCHAR*)pdn + pdn->wOutputOffset,
1922                               pdm );
1923     } else if(lppd->Flags & PD_RETURNIC) {
1924         lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1925                               (WCHAR*)pdn + pdn->wDeviceOffset,
1926                               (WCHAR*)pdn + pdn->wOutputOffset,
1927                               pdm );
1928     }
1929     GlobalUnlock(lppd->hDevNames);
1930     GlobalUnlock(lppd->hDevMode);
1931     return lppd->hDC ? TRUE : FALSE;
1932 }
1933
1934 /***********************************************************************
1935  *           PrintDlgA   (COMDLG32.@)
1936  *
1937  *  Displays the the PRINT dialog box, which enables the user to specify
1938  *  specific properties of the print job.
1939  *
1940  * RETURNS
1941  *  nonzero if the user pressed the OK button
1942  *  zero    if the user cancelled the window or an error occurred
1943  *
1944  * BUGS
1945  *  PrintDlg:
1946  *  * The Collate Icons do not display, even though they are in the code.
1947  *  * The Properties Button(s) should call DocumentPropertiesA().
1948  *  PrintSetupDlg:
1949  *  * The Paper Orientation Icons are not implemented yet.
1950  *  * The Properties Button(s) should call DocumentPropertiesA().
1951  *  * Settings are not yet taken from a provided DevMode or
1952  *    default printer settings.
1953  */
1954
1955 BOOL WINAPI PrintDlgA(
1956                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1957                       )
1958 {
1959     BOOL      bRet = FALSE;
1960     LPVOID   ptr;
1961     HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrA( lppd->hwndOwner, GWLP_HINSTANCE );
1962
1963     if(TRACE_ON(commdlg)) {
1964         char flagstr[1000] = "";
1965         struct pd_flags *pflag = pd_flags;
1966         for( ; pflag->name; pflag++) {
1967             if(lppd->Flags & pflag->flag)
1968                 strcat(flagstr, pflag->name);
1969         }
1970         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
1971               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
1972               "flags %08lx (%s)\n",
1973               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1974               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1975               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1976     }
1977
1978     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1979         WARN("structure size failure !!!\n");
1980         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1981         return FALSE;
1982     }
1983
1984     if(lppd->Flags & PD_RETURNDEFAULT) {
1985         PRINTER_INFO_2A *pbuf;
1986         DRIVER_INFO_3A  *dbuf;
1987         HANDLE hprn;
1988         DWORD needed;
1989
1990         if(lppd->hDevMode || lppd->hDevNames) {
1991             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1992             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
1993             return FALSE;
1994         }
1995         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1996             WARN("Can't find default printer\n");
1997             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
1998             return FALSE;
1999         }
2000
2001         GetPrinterA(hprn, 2, NULL, 0, &needed);
2002         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2003         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2004
2005         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2006         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2007         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2008             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
2009             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2010             return FALSE;
2011         }
2012         ClosePrinter(hprn);
2013
2014         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2015                                   dbuf->pDriverPath,
2016                                   pbuf->pPrinterName,
2017                                   pbuf->pPortName);
2018         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2019                                      pbuf->pDevMode->dmDriverExtra);
2020         ptr = GlobalLock(lppd->hDevMode);
2021         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2022                pbuf->pDevMode->dmDriverExtra);
2023         GlobalUnlock(lppd->hDevMode);
2024         HeapFree(GetProcessHeap(), 0, pbuf);
2025         HeapFree(GetProcessHeap(), 0, dbuf);
2026         bRet = TRUE;
2027     } else {
2028         HGLOBAL hDlgTmpl;
2029         PRINT_PTRA *PrintStructures;
2030
2031     /* load Dialog resources,
2032      * depending on Flags indicates Print32 or Print32_setup dialog
2033      */
2034         hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2035         if (!hDlgTmpl) {
2036             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2037             return FALSE;
2038         }
2039         ptr = LockResource( hDlgTmpl );
2040         if (!ptr) {
2041             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2042             return FALSE;
2043         }
2044
2045         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2046                                     sizeof(PRINT_PTRA));
2047         PrintStructures->lpPrintDlg = lppd;
2048
2049         /* and create & process the dialog .
2050          * -1 is failure, 0 is broken hwnd, everything else is ok.
2051          */
2052         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2053                                            PrintDlgProcA,
2054                                            (LPARAM)PrintStructures));
2055
2056         if(bRet) {
2057             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2058             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2059             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2060
2061             if (lppd->hDevMode == 0) {
2062                 TRACE(" No hDevMode yet... Need to create my own\n");
2063                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2064                                         lpdm->dmSize + lpdm->dmDriverExtra);
2065             } else {
2066                 WORD locks;
2067                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2068                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2069                     while(locks--) {
2070                         GlobalUnlock(lppd->hDevMode);
2071                         TRACE("Now got %d locks\n", locks);
2072                     }
2073                 }
2074                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2075                                                lpdm->dmSize + lpdm->dmDriverExtra,
2076                                                GMEM_MOVEABLE);
2077             }
2078             lpdmReturn = GlobalLock(lppd->hDevMode);
2079             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2080
2081             if (lppd->hDevNames != 0) {
2082                 WORD locks;
2083                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2084                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2085                     while(locks--)
2086                         GlobalUnlock(lppd->hDevNames);
2087                 }
2088             }
2089             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2090                     di->pDriverPath,
2091                     pi->pPrinterName,
2092                     pi->pPortName
2093             );
2094             GlobalUnlock(lppd->hDevMode);
2095         }
2096         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2097         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2098         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2099         HeapFree(GetProcessHeap(), 0, PrintStructures);
2100     }
2101     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2102         bRet = PRINTDLG_CreateDCA(lppd);
2103
2104     TRACE("exit! (%d)\n", bRet);
2105     return bRet;
2106 }
2107
2108 /***********************************************************************
2109  *           PrintDlgW   (COMDLG32.@)
2110  */
2111 BOOL WINAPI PrintDlgW(
2112                       LPPRINTDLGW lppd /* [in/out] ptr to PRINTDLG32 struct */
2113                       )
2114 {
2115     BOOL      bRet = FALSE;
2116     LPVOID   ptr;
2117     HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2118
2119     if(TRACE_ON(commdlg)) {
2120         char flagstr[1000] = "";
2121         struct pd_flags *pflag = pd_flags;
2122         for( ; pflag->name; pflag++) {
2123             if(lppd->Flags & pflag->flag)
2124                 strcat(flagstr, pflag->name);
2125         }
2126         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2127               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2128               "flags %08lx (%s)\n",
2129               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2130               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2131               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2132     }
2133
2134     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2135         WARN("structure size failure !!!\n");
2136         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2137         return FALSE;
2138     }
2139
2140     if(lppd->Flags & PD_RETURNDEFAULT) {
2141         PRINTER_INFO_2W *pbuf;
2142         DRIVER_INFO_3W  *dbuf;
2143         HANDLE hprn;
2144         DWORD needed;
2145
2146         if(lppd->hDevMode || lppd->hDevNames) {
2147             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2148             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2149             return FALSE;
2150         }
2151         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2152             WARN("Can't find default printer\n");
2153             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2154             return FALSE;
2155         }
2156
2157         GetPrinterW(hprn, 2, NULL, 0, &needed);
2158         pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2159         GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2160
2161         GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2162         dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2163         if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2164             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),debugstr_w(pbuf->pPrinterName));
2165             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2166             return FALSE;
2167         }
2168         ClosePrinter(hprn);
2169
2170         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2171                                   dbuf->pDriverPath,
2172                                   pbuf->pPrinterName,
2173                                   pbuf->pPortName);
2174         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2175                                      pbuf->pDevMode->dmDriverExtra);
2176         ptr = GlobalLock(lppd->hDevMode);
2177         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2178                pbuf->pDevMode->dmDriverExtra);
2179         GlobalUnlock(lppd->hDevMode);
2180         HeapFree(GetProcessHeap(), 0, pbuf);
2181         HeapFree(GetProcessHeap(), 0, dbuf);
2182         bRet = TRUE;
2183     } else {
2184         HGLOBAL hDlgTmpl;
2185         PRINT_PTRW *PrintStructures;
2186
2187     /* load Dialog resources,
2188      * depending on Flags indicates Print32 or Print32_setup dialog
2189      */
2190         hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2191         if (!hDlgTmpl) {
2192             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2193             return FALSE;
2194         }
2195         ptr = LockResource( hDlgTmpl );
2196         if (!ptr) {
2197             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2198             return FALSE;
2199         }
2200
2201         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2202                                     sizeof(PRINT_PTRW));
2203         PrintStructures->lpPrintDlg = lppd;
2204
2205         /* and create & process the dialog .
2206          * -1 is failure, 0 is broken hwnd, everything else is ok.
2207          */
2208         bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2209                                            PrintDlgProcW,
2210                                            (LPARAM)PrintStructures));
2211
2212         if(bRet) {
2213             DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2214             PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2215             DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2216
2217             if (lppd->hDevMode == 0) {
2218                 TRACE(" No hDevMode yet... Need to create my own\n");
2219                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2220                                         lpdm->dmSize + lpdm->dmDriverExtra);
2221             } else {
2222                 WORD locks;
2223                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2224                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2225                     while(locks--) {
2226                         GlobalUnlock(lppd->hDevMode);
2227                         TRACE("Now got %d locks\n", locks);
2228                     }
2229                 }
2230                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2231                                                lpdm->dmSize + lpdm->dmDriverExtra,
2232                                                GMEM_MOVEABLE);
2233             }
2234             lpdmReturn = GlobalLock(lppd->hDevMode);
2235             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2236
2237             if (lppd->hDevNames != 0) {
2238                 WORD locks;
2239                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2240                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2241                     while(locks--)
2242                         GlobalUnlock(lppd->hDevNames);
2243                 }
2244             }
2245             PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2246                     di->pDriverPath,
2247                     pi->pPrinterName,
2248                     pi->pPortName
2249             );
2250             GlobalUnlock(lppd->hDevMode);
2251         }
2252         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2253         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2254         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2255         HeapFree(GetProcessHeap(), 0, PrintStructures);
2256     }
2257     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2258         bRet = PRINTDLG_CreateDCW(lppd);
2259
2260     TRACE("exit! (%d)\n", bRet);
2261     return bRet;
2262 }
2263
2264 /***********************************************************************
2265  *
2266  *          PageSetupDlg
2267  * rad1 - portrait
2268  * rad2 - landscape
2269  * cmb2 - paper size
2270  * cmb3 - source (tray?)
2271  * edt4 - border left
2272  * edt5 - border top
2273  * edt6 - border right
2274  * edt7 - border bottom
2275  * psh3 - "Printer..."
2276  */
2277
2278 typedef struct {
2279     LPPAGESETUPDLGA     dlga;
2280     PRINTDLGA           pdlg;
2281 } PageSetupDataA;
2282
2283 typedef struct {
2284     LPPAGESETUPDLGW     dlga;
2285     PRINTDLGW           pdlg;
2286 } PageSetupDataW;
2287
2288 static HGLOBAL PRINTDLG_GetPGSTemplateA(PAGESETUPDLGA *lppd)
2289 {
2290     HRSRC hResInfo;
2291     HGLOBAL hDlgTmpl;
2292
2293     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2294         hDlgTmpl = lppd->hPageSetupTemplate;
2295     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2296         hResInfo = FindResourceA(lppd->hInstance,
2297                                  lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2298         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2299     } else {
2300         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2301         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2302     }
2303     return hDlgTmpl;
2304 }
2305
2306 static HGLOBAL PRINTDLG_GetPGSTemplateW(PAGESETUPDLGW *lppd)
2307 {
2308     HRSRC hResInfo;
2309     HGLOBAL hDlgTmpl;
2310
2311     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2312         hDlgTmpl = lppd->hPageSetupTemplate;
2313     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2314         hResInfo = FindResourceW(lppd->hInstance,
2315                                  lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2316         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2317     } else {
2318         hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2319         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2320     }
2321     return hDlgTmpl;
2322 }
2323
2324 static DWORD
2325 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2326     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2327         return 10*size*10/25.4;
2328     /* If we don't have a flag, we can choose one. Use millimeters
2329      * to avoid confusing me
2330      */
2331     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2332     return 10*size;
2333 }
2334
2335
2336 static DWORD
2337 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2338     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2339         return size;
2340     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2341         return (size*254)/10;
2342     /* if we don't have a flag, we can choose one. Use millimeters
2343      * to avoid confusing me
2344      */
2345     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2346     return (size*254)/10;
2347 }
2348
2349 static void
2350 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2351     strcpy(strout,"<undef>");
2352     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2353         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2354         return;
2355     }
2356     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2357         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
2358         return;
2359     }
2360     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2361     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2362     return;
2363 }
2364 static void
2365 _c_size2strW(PageSetupDataW *pda,DWORD size,LPWSTR strout) {
2366     const static WCHAR UNDEF[] = { '<', 'u', 'n', 'd', 'e', 'f', '>', 0 };
2367     const static WCHAR mm_fmt[] = { '%', '.', '2', 'f', 'm', 'm', 0 };
2368     const static WCHAR in_fmt[] = { '%', '.', '2', 'f', 'i', 'n', 0 };
2369     lstrcpyW(strout, UNDEF);
2370     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2371         wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2372         return;
2373     }
2374     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2375         wsprintfW(strout,in_fmt,(size*1.0)/1000.0);
2376         return;
2377     }
2378     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2379     wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2380     return;
2381 }
2382
2383 static DWORD
2384 _c_str2sizeA(PAGESETUPDLGA *dlga,LPCSTR strin) {
2385     float       val;
2386     char        rest[200];
2387
2388     rest[0]='\0';
2389     if (!sscanf(strin,"%f%s",&val,rest))
2390         return 0;
2391
2392     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2393         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2394             return 1000*val;
2395         else
2396             return val*25.4*100;
2397     }
2398     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2399     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2400
2401     if (!strcmp(rest,"mm")) {
2402         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2403             return 100*val;
2404         else
2405             return 1000.0*val/25.4;
2406     }
2407     if (rest[0]=='\0') {
2408         /* use application supplied default */
2409         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2410             /* 100*mm */
2411             return 100.0*val;
2412         }
2413         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2414             /* 1000*inch */
2415             return 1000.0*val;
2416         }
2417     }
2418     ERR("Did not find a conversion for type '%s'!\n",rest);
2419     return 0;
2420 }
2421
2422
2423 static DWORD
2424 _c_str2sizeW(PAGESETUPDLGW *dlga, LPCWSTR strin) {
2425     char        buf[200];
2426
2427     /* this W -> A transition is OK */
2428     /* we need a unicode version of sscanf to avoid it */
2429     WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2430     return _c_str2sizeA((PAGESETUPDLGA *)dlga, buf);
2431 }
2432
2433
2434 /*
2435  * This is called on finish and will update the output fields of the
2436  * struct.
2437  */
2438 static BOOL
2439 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2440     DEVNAMES    *dn;
2441     DEVMODEA    *dm;
2442     LPSTR       devname,portname;
2443     char        papername[64];
2444     char        buf[200];
2445
2446     dn = GlobalLock(pda->pdlg.hDevNames);
2447     dm = GlobalLock(pda->pdlg.hDevMode);
2448     devname     = ((char*)dn)+dn->wDeviceOffset;
2449     portname    = ((char*)dn)+dn->wOutputOffset;
2450     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2451     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2452
2453     if (GetDlgItemTextA(hDlg,cmb2,papername,sizeof(papername))>0) {
2454         PRINTDLG_PaperSizeA(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2455         pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.x);
2456         pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.y);
2457     } else
2458         FIXME("could not get dialog text for papersize cmbbox?\n");
2459 #define GETVAL(id,val) if (GetDlgItemTextA(hDlg,id,buf,sizeof(buf))>0) { val = _c_str2sizeA(pda->dlga,buf); } else { FIXME("could not get dlgitemtexta for %x\n",id); }
2460     GETVAL(edt4,pda->dlga->rtMargin.left);
2461     GETVAL(edt5,pda->dlga->rtMargin.top);
2462     GETVAL(edt6,pda->dlga->rtMargin.right);
2463     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2464 #undef GETVAL
2465
2466     /* If we are in landscape, swap x and y of page size */
2467     if (IsDlgButtonChecked(hDlg, rad2)) {
2468         DWORD tmp;
2469         tmp = pda->dlga->ptPaperSize.x;
2470         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2471         pda->dlga->ptPaperSize.y = tmp;
2472     }
2473     GlobalUnlock(pda->pdlg.hDevNames);
2474     GlobalUnlock(pda->pdlg.hDevMode);
2475     return TRUE;
2476 }
2477
2478 static BOOL
2479 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2480     DEVNAMES    *dn;
2481     DEVMODEW    *dm;
2482     LPWSTR      devname,portname;
2483     WCHAR       papername[64];
2484     WCHAR       buf[200];
2485
2486     dn = GlobalLock(pda->pdlg.hDevNames);
2487     dm = GlobalLock(pda->pdlg.hDevMode);
2488     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2489     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2490     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2491     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2492
2493     if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2494         PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2495         pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2496         pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2497     } else
2498         FIXME("could not get dialog text for papersize cmbbox?\n");
2499 #define GETVAL(id,val) if (GetDlgItemTextW(hDlg,id,buf,sizeof(buf)/sizeof(buf[0]))>0) { val = _c_str2sizeW(pda->dlga,buf); } else { FIXME("could not get dlgitemtextw for %x\n",id); }
2500     GETVAL(edt4,pda->dlga->rtMargin.left);
2501     GETVAL(edt5,pda->dlga->rtMargin.top);
2502     GETVAL(edt6,pda->dlga->rtMargin.right);
2503     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2504 #undef GETVAL
2505
2506     /* If we are in landscape, swap x and y of page size */
2507     if (IsDlgButtonChecked(hDlg, rad2)) {
2508         DWORD tmp;
2509         tmp = pda->dlga->ptPaperSize.x;
2510         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2511         pda->dlga->ptPaperSize.y = tmp;
2512     }
2513     GlobalUnlock(pda->pdlg.hDevNames);
2514     GlobalUnlock(pda->pdlg.hDevMode);
2515     return TRUE;
2516 }
2517
2518 /*
2519  * This is called after returning from PrintDlg().
2520  */
2521 static BOOL
2522 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2523     DEVNAMES    *dn;
2524     DEVMODEA    *dm;
2525     LPSTR       devname,portname;
2526
2527     dn = GlobalLock(pda->pdlg.hDevNames);
2528     dm = GlobalLock(pda->pdlg.hDevMode);
2529     devname     = ((char*)dn)+dn->wDeviceOffset;
2530     portname    = ((char*)dn)+dn->wOutputOffset;
2531     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2532     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2533     GlobalUnlock(pda->pdlg.hDevNames);
2534     GlobalUnlock(pda->pdlg.hDevMode);
2535     return TRUE;
2536 }
2537
2538 static BOOL
2539 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2540     DEVNAMES    *dn;
2541     DEVMODEW    *dm;
2542     LPWSTR      devname,portname;
2543
2544     dn = GlobalLock(pda->pdlg.hDevNames);
2545     dm = GlobalLock(pda->pdlg.hDevMode);
2546     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2547     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2548     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2549     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2550     GlobalUnlock(pda->pdlg.hDevNames);
2551     GlobalUnlock(pda->pdlg.hDevMode);
2552     return TRUE;
2553 }
2554
2555 static BOOL
2556 PRINTDLG_PS_WMCommandA(
2557     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2558 ) {
2559     TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2560             LOWORD(lParam),wParam,lParam);
2561     switch (LOWORD(wParam))  {
2562     case IDOK:
2563         if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2564             return(FALSE);
2565         EndDialog(hDlg, TRUE);
2566         return TRUE ;
2567
2568     case IDCANCEL:
2569         EndDialog(hDlg, FALSE);
2570         return FALSE ;
2571
2572     case psh3: {
2573         pda->pdlg.Flags         = 0;
2574         pda->pdlg.hwndOwner     = hDlg;
2575         if (PrintDlgA(&(pda->pdlg)))
2576             PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2577         return TRUE;
2578     }
2579     }
2580     return FALSE;
2581 }
2582
2583 static BOOL
2584 PRINTDLG_PS_WMCommandW(
2585     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2586 ) {
2587     TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2588             LOWORD(lParam),wParam,lParam);
2589     switch (LOWORD(wParam))  {
2590     case IDOK:
2591         if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2592             return(FALSE);
2593         EndDialog(hDlg, TRUE);
2594         return TRUE ;
2595
2596     case IDCANCEL:
2597         EndDialog(hDlg, FALSE);
2598         return FALSE ;
2599
2600     case psh3: {
2601         pda->pdlg.Flags         = 0;
2602         pda->pdlg.hwndOwner     = hDlg;
2603         if (PrintDlgW(&(pda->pdlg)))
2604             PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2605         return TRUE;
2606     }
2607     }
2608     return FALSE;
2609 }
2610
2611
2612 static LRESULT CALLBACK
2613 PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2614 {
2615     if (uMsg == WM_PAINT)
2616     {
2617         PAINTSTRUCT ps;
2618         RECT rcClient;
2619         HPEN hpen, holdpen;
2620         HDC hdc;
2621         HFONT hfont, holdfont;
2622         LOGFONTW lf;
2623         HBRUSH hbrush, holdbrush;
2624         INT oldbkmode;
2625
2626         hdc = BeginPaint(hWnd, &ps);
2627
2628         GetClientRect(hWnd, &rcClient);
2629
2630         /* fill background */
2631         hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
2632         FillRect(hdc, &rcClient, hbrush);
2633         holdbrush = SelectObject(hdc, hbrush);
2634
2635         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
2636         holdpen = SelectObject(hdc, hpen);
2637
2638         /* paint left edge */
2639         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
2640         LineTo(hdc, rcClient.left, rcClient.bottom-1);
2641
2642         /* paint top edge */
2643         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
2644         LineTo(hdc, rcClient.right, rcClient.top);
2645
2646         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
2647         DeleteObject(SelectObject(hdc, hpen));
2648
2649         /* paint right edge */
2650         MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
2651         LineTo(hdc, rcClient.right-1, rcClient.bottom);
2652
2653         /* paint bottom edge */
2654         MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
2655         LineTo(hdc, rcClient.right, rcClient.bottom-1);
2656
2657         hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
2658         DeleteObject(SelectObject(hdc, hpen));
2659
2660         /* draw dashed rectangle showing margins */
2661
2662         /* FIXME: use real margin values */
2663         rcClient.left += 5;
2664         rcClient.top += 5;
2665         rcClient.right -= 5;
2666         rcClient.bottom -= 5;
2667
2668         /* if the space is too small then we make sure to not draw anything */
2669         rcClient.left = min(rcClient.left,rcClient.right);
2670         rcClient.top = min(rcClient.top,rcClient.bottom);
2671
2672         Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
2673
2674         DeleteObject(SelectObject(hdc, holdpen));
2675
2676         /* draw the fake document */
2677
2678         /* give text a bit of a space from the frame */
2679         rcClient.left += 2;
2680         rcClient.top += 2;
2681         rcClient.right -= 2;
2682         rcClient.bottom -= 2;
2683
2684         /* if the space is too small then we make sure to not draw anything */
2685         rcClient.left = min(rcClient.left,rcClient.right);
2686         rcClient.top = min(rcClient.top,rcClient.bottom);
2687
2688         /* select a nice scalable font, because we want the text really small */
2689         SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2690         lf.lfHeight = 6; /* value chosen based on visual effect */
2691         hfont = CreateFontIndirectW(&lf);
2692         holdfont = SelectObject(hdc, hfont);
2693
2694         /* if text not loaded, then do so now */
2695         if (wszFakeDocumentText[0] == '\0')
2696             LoadStringW(COMDLG32_hInstance,
2697                         IDS_FAKEDOCTEXT,
2698                         wszFakeDocumentText,
2699                         sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
2700
2701         oldbkmode = SetBkMode(hdc, TRANSPARENT);
2702         DrawTextW(hdc, wszFakeDocumentText, -1, &rcClient, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
2703         SetBkMode(hdc, oldbkmode);
2704
2705         DeleteObject(SelectObject(hdc, holdfont));
2706
2707         SelectObject(hdc, holdbrush);
2708
2709         EndPaint(hWnd, &ps);
2710         return 0;
2711     }
2712     else
2713         return CallWindowProcW(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
2714 }
2715
2716 static INT_PTR CALLBACK
2717 PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2718 {
2719     PageSetupDataA      *pda;
2720     INT_PTR             res = FALSE;
2721
2722     if (uMsg==WM_INITDIALOG) {
2723         lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
2724             GetDlgItem(hDlg, rct1),
2725             GWLP_WNDPROC,
2726             (ULONG_PTR)PagePaintProc);
2727         res = TRUE;
2728         pda = (PageSetupDataA*)lParam;
2729         SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",pda);
2730         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2731             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2732             if (!res) {
2733                 FIXME("Setup page hook failed?\n");
2734                 res = TRUE;
2735             }
2736         }
2737         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
2738             FIXME("PagePaintHook not yet implemented!\n");
2739         }
2740         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2741             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2742         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2743             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2744             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2745             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2746             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2747         }
2748         /* width larger as height -> landscape */
2749         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2750             CheckRadioButton(hDlg, rad1, rad2, rad2);
2751         else /* this is default if papersize is not set */
2752             CheckRadioButton(hDlg, rad1, rad2, rad1);
2753         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2754             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2755             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2756         }
2757         /* We fill them out enabled or not */
2758         if (pda->dlga->Flags & PSD_MARGINS) {
2759             char str[100];
2760             _c_size2strA(pda,pda->dlga->rtMargin.left,str);
2761             SetDlgItemTextA(hDlg,edt4,str);
2762             _c_size2strA(pda,pda->dlga->rtMargin.top,str);
2763             SetDlgItemTextA(hDlg,edt5,str);
2764             _c_size2strA(pda,pda->dlga->rtMargin.right,str);
2765             SetDlgItemTextA(hDlg,edt6,str);
2766             _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
2767             SetDlgItemTextA(hDlg,edt7,str);
2768         } else {
2769             /* default is 1 inch */
2770             DWORD size = _c_inch2size(pda->dlga,1000);
2771             char        str[20];
2772             _c_size2strA(pda,size,str);
2773             SetDlgItemTextA(hDlg,edt4,str);
2774             SetDlgItemTextA(hDlg,edt5,str);
2775             SetDlgItemTextA(hDlg,edt6,str);
2776             SetDlgItemTextA(hDlg,edt7,str);
2777         }
2778         PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2779         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2780             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2781             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2782         }
2783         return TRUE;
2784     } else {
2785         pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2786         if (!pda) {
2787             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2788             return FALSE;
2789         }
2790         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2791             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2792             if (res) return res;
2793         }
2794     }
2795     switch (uMsg) {
2796     case WM_COMMAND:
2797         return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
2798     }
2799     return FALSE;
2800 }
2801
2802 static INT_PTR CALLBACK
2803 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2804 {
2805     const static WCHAR __WINE_PAGESETUPDLGDATA[] = 
2806         { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E', 
2807           'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
2808     PageSetupDataW      *pda;
2809     BOOL                res = FALSE;
2810
2811     if (uMsg==WM_INITDIALOG) {
2812         res = TRUE;
2813         pda = (PageSetupDataW*)lParam;
2814         SetPropW(hDlg, __WINE_PAGESETUPDLGDATA, pda);
2815         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2816             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2817             if (!res) {
2818                 FIXME("Setup page hook failed?\n");
2819                 res = TRUE;
2820             }
2821         }
2822         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
2823             FIXME("PagePaintHook not yet implemented!\n");
2824         }
2825         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2826             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2827         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2828             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2829             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2830             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2831             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2832         }
2833         /* width larger as height -> landscape */
2834         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2835             CheckRadioButton(hDlg, rad1, rad2, rad2);
2836         else /* this is default if papersize is not set */
2837             CheckRadioButton(hDlg, rad1, rad2, rad1);
2838         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2839             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2840             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2841         }
2842         /* We fill them out enabled or not */
2843         if (pda->dlga->Flags & PSD_MARGINS) {
2844             WCHAR str[100];
2845             _c_size2strW(pda,pda->dlga->rtMargin.left,str);
2846             SetDlgItemTextW(hDlg,edt4,str);
2847             _c_size2strW(pda,pda->dlga->rtMargin.top,str);
2848             SetDlgItemTextW(hDlg,edt5,str);
2849             _c_size2strW(pda,pda->dlga->rtMargin.right,str);
2850             SetDlgItemTextW(hDlg,edt6,str);
2851             _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
2852             SetDlgItemTextW(hDlg,edt7,str);
2853         } else {
2854             /* default is 1 inch */
2855             DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
2856             WCHAR       str[20];
2857             _c_size2strW(pda,size,str);
2858             SetDlgItemTextW(hDlg,edt4,str);
2859             SetDlgItemTextW(hDlg,edt5,str);
2860             SetDlgItemTextW(hDlg,edt6,str);
2861             SetDlgItemTextW(hDlg,edt7,str);
2862         }
2863         PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2864         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2865             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2866             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2867         }
2868         return TRUE;
2869     } else {
2870         pda = (PageSetupDataW*)GetPropW(hDlg, __WINE_PAGESETUPDLGDATA);
2871         if (!pda) {
2872             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2873             return FALSE;
2874         }
2875         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2876             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2877             if (res) return res;
2878         }
2879     }
2880     switch (uMsg) {
2881     case WM_COMMAND:
2882         return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
2883     }
2884     return FALSE;
2885 }
2886
2887 /***********************************************************************
2888  *            PageSetupDlgA  (COMDLG32.@)
2889  */
2890 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
2891     HGLOBAL             hDlgTmpl;
2892     LPVOID              ptr;
2893     BOOL                bRet;
2894     PageSetupDataA      *pda;
2895     PRINTDLGA           pdlg;
2896
2897     if(TRACE_ON(commdlg)) {
2898         char flagstr[1000] = "";
2899         struct pd_flags *pflag = psd_flags;
2900         for( ; pflag->name; pflag++) {
2901             if(setupdlg->Flags & pflag->flag) {
2902                 strcat(flagstr, pflag->name);
2903                 strcat(flagstr, "|");
2904             }
2905         }
2906         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2907               "hinst %p, flags %08lx (%s)\n",
2908               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2909               setupdlg->hDevNames,
2910               setupdlg->hInstance, setupdlg->Flags, flagstr);
2911     }
2912
2913     /* First get default printer data, we need it right after that. */
2914     memset(&pdlg,0,sizeof(pdlg));
2915     pdlg.lStructSize    = sizeof(pdlg);
2916     pdlg.Flags          = PD_RETURNDEFAULT;
2917     bRet = PrintDlgA(&pdlg);
2918     if (!bRet) return FALSE;
2919
2920     /* short cut exit, just return default values */
2921     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2922         setupdlg->hDevMode      = pdlg.hDevMode;
2923         setupdlg->hDevNames     = pdlg.hDevNames;
2924         /* FIXME: Just return "A4" for now. */
2925         PRINTDLG_PaperSizeA(&pdlg,"A4",&setupdlg->ptPaperSize);
2926         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
2927         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
2928         return TRUE;
2929     }
2930     hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
2931     if (!hDlgTmpl) {
2932         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2933         return FALSE;
2934     }
2935     ptr = LockResource( hDlgTmpl );
2936     if (!ptr) {
2937         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2938         return FALSE;
2939     }
2940     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
2941     pda->dlga = setupdlg;
2942     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
2943
2944     bRet = (0<DialogBoxIndirectParamA(
2945                 setupdlg->hInstance,
2946                 ptr,
2947                 setupdlg->hwndOwner,
2948                 PageDlgProcA,
2949                 (LPARAM)pda)
2950     );
2951     return bRet;
2952 }
2953 /***********************************************************************
2954  *            PageSetupDlgW  (COMDLG32.@)
2955  */
2956 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
2957     HGLOBAL             hDlgTmpl;
2958     LPVOID              ptr;
2959     BOOL                bRet;
2960     PageSetupDataW      *pdw;
2961     PRINTDLGW           pdlg;
2962
2963     if(TRACE_ON(commdlg)) {
2964         char flagstr[1000] = "";
2965         struct pd_flags *pflag = psd_flags;
2966         for( ; pflag->name; pflag++) {
2967             if(setupdlg->Flags & pflag->flag) {
2968                 strcat(flagstr, pflag->name);
2969                 strcat(flagstr, "|");
2970             }
2971         }
2972         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2973               "hinst %p, flags %08lx (%s)\n",
2974               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2975               setupdlg->hDevNames,
2976               setupdlg->hInstance, setupdlg->Flags, flagstr);
2977     }
2978
2979     /* First get default printer data, we need it right after that. */
2980     memset(&pdlg,0,sizeof(pdlg));
2981     pdlg.lStructSize    = sizeof(pdlg);
2982     pdlg.Flags          = PD_RETURNDEFAULT;
2983     bRet = PrintDlgW(&pdlg);
2984     if (!bRet) return FALSE;
2985
2986     /* short cut exit, just return default values */
2987     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2988         static const WCHAR a4[] = {'A','4',0};
2989         setupdlg->hDevMode      = pdlg.hDevMode;
2990         setupdlg->hDevNames     = pdlg.hDevNames;
2991         /* FIXME: Just return "A4" for now. */
2992         PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
2993         setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
2994         setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
2995         return TRUE;
2996     }
2997     hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
2998     if (!hDlgTmpl) {
2999         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3000         return FALSE;
3001     }
3002     ptr = LockResource( hDlgTmpl );
3003     if (!ptr) {
3004         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3005         return FALSE;
3006     }
3007     pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3008     pdw->dlga = setupdlg;
3009     memcpy(&pdw->pdlg,&pdlg,sizeof(pdlg));
3010
3011     bRet = (0<DialogBoxIndirectParamW(
3012                 setupdlg->hInstance,
3013                 ptr,
3014                 setupdlg->hwndOwner,
3015                 PageDlgProcW,
3016                 (LPARAM)pdw)
3017     );
3018     return bRet;
3019 }
3020
3021 /***********************************************************************
3022  *      PrintDlgExA (COMDLG32.@)
3023  */
3024 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lpPrintDlgExA)
3025 {
3026         FIXME("stub\n");
3027         return E_NOTIMPL;
3028 }
3029
3030 /***********************************************************************
3031  *      PrintDlgExW (COMDLG32.@)
3032  */
3033 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lpPrintDlgExW)
3034 {
3035         FIXME("stub\n");
3036         return E_NOTIMPL;
3037 }