comdlg32: Assign to structs instead of using memcpy.
[wine] / dlls / comdlg32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 const 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     SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
124     
125     for(i = 0; i < num; i++) {
126         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
127                             (LPARAM)pi[i].pPrinterName );
128     }
129     HeapFree(GetProcessHeap(), 0, pi);
130     if(!name ||
131        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
132                                 (LPARAM)name)) == CB_ERR) {
133
134         char buf[260];
135         DWORD dwBufLen = sizeof(buf);
136         if (name != NULL)
137             WARN("Can't find %s in printer list so trying to find default\n",
138                 debugstr_a(name));
139         if(!GetDefaultPrinterA(buf, &dwBufLen))
140             return num;
141         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
142         if(i == CB_ERR)
143             FIXME("Can't find default printer in printer list\n");
144     }
145     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
146     return num;
147 }
148
149 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
150 {
151     DWORD needed, num;
152     INT i;
153     LPPRINTER_INFO_2W pi;
154     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
155     pi = HeapAlloc(GetProcessHeap(), 0, needed);
156     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
157                   &num);
158
159     for(i = 0; i < num; i++) {
160         SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
161                             (LPARAM)pi[i].pPrinterName );
162     }
163     HeapFree(GetProcessHeap(), 0, pi);
164     if(!name ||
165        (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
166                                 (LPARAM)name)) == CB_ERR) {
167         WCHAR buf[260];
168         DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
169         if (name != NULL)
170             WARN("Can't find %s in printer list so trying to find default\n",
171                 debugstr_w(name));
172         if(!GetDefaultPrinterW(buf, &dwBufLen))
173             return num;
174         i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
175         if(i == CB_ERR)
176             TRACE("Can't find default printer in printer list\n");
177     }
178     SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
179     return num;
180 }
181
182 /***********************************************************************
183  *             PRINTDLG_CreateDevNames          [internal]
184  *
185  *
186  *   creates a DevNames structure.
187  *
188  *  (NB. when we handle unicode the offsets will be in wchars).
189  */
190 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
191                                     const char* DeviceName, const char* OutputPort)
192 {
193     long size;
194     char*   pDevNamesSpace;
195     char*   pTempPtr;
196     LPDEVNAMES lpDevNames;
197     char buf[260];
198     DWORD dwBufLen = sizeof(buf);
199
200     size = strlen(DeviceDriverName) + 1
201             + strlen(DeviceName) + 1
202             + strlen(OutputPort) + 1
203             + sizeof(DEVNAMES);
204
205     if(*hmem)
206         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
207     else
208         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
209     if (*hmem == 0)
210         return FALSE;
211
212     pDevNamesSpace = GlobalLock(*hmem);
213     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
214
215     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
216     strcpy(pTempPtr, DeviceDriverName);
217     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
218
219     pTempPtr += strlen(DeviceDriverName) + 1;
220     strcpy(pTempPtr, DeviceName);
221     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
222
223     pTempPtr += strlen(DeviceName) + 1;
224     strcpy(pTempPtr, OutputPort);
225     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
226
227     GetDefaultPrinterA(buf, &dwBufLen);
228     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
229     GlobalUnlock(*hmem);
230     return TRUE;
231 }
232
233 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
234                                     LPCWSTR DeviceName, LPCWSTR OutputPort)
235 {
236     long size;
237     LPWSTR   pDevNamesSpace;
238     LPWSTR   pTempPtr;
239     LPDEVNAMES lpDevNames;
240     WCHAR bufW[260];
241     DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
242
243     size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
244             + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
245             + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
246             + sizeof(DEVNAMES);
247
248     if(*hmem)
249         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
250     else
251         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
252     if (*hmem == 0)
253         return FALSE;
254
255     pDevNamesSpace = GlobalLock(*hmem);
256     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
257
258     pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
259     lstrcpyW(pTempPtr, DeviceDriverName);
260     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
261
262     pTempPtr += lstrlenW(DeviceDriverName) + 1;
263     lstrcpyW(pTempPtr, DeviceName);
264     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
265
266     pTempPtr += lstrlenW(DeviceName) + 1;
267     lstrcpyW(pTempPtr, OutputPort);
268     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
269
270     GetDefaultPrinterW(bufW, &dwBufLen);
271     lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
272     GlobalUnlock(*hmem);
273     return TRUE;
274 }
275
276 /***********************************************************************
277  *             PRINTDLG_UpdatePrintDlg          [internal]
278  *
279  *
280  *   updates the PrintDlg structure for return values.
281  *
282  * RETURNS
283  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
284  *   TRUE  if successful.
285  */
286 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
287                                     PRINT_PTRA* PrintStructures)
288 {
289     LPPRINTDLGA       lppd = PrintStructures->lpPrintDlg;
290     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
291     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
292
293
294     if(!lpdm) {
295         FIXME("No lpdm ptr?\n");
296         return FALSE;
297     }
298
299
300     if(!(lppd->Flags & PD_PRINTSETUP)) {
301         /* check whether nFromPage and nToPage are within range defined by
302          * nMinPage and nMaxPage
303          */
304         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
305             WORD nToPage;
306             WORD nFromPage;
307             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
308             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
309             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
310                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
311                 char resourcestr[256];
312                 char resultstr[256];
313                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
314                             resourcestr, 255);
315                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
316                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
317                             resourcestr, 255);
318                 MessageBoxA(hDlg, resultstr, resourcestr,
319                             MB_OK | MB_ICONWARNING);
320                 return FALSE;
321             }
322             lppd->nFromPage = nFromPage;
323             lppd->nToPage   = nToPage;
324             lppd->Flags |= PD_PAGENUMS;
325         }
326         else
327             lppd->Flags &= ~PD_PAGENUMS;
328
329         if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
330             lppd->Flags |= PD_SELECTION;
331         else
332             lppd->Flags &= ~PD_SELECTION;
333
334         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
335             static char file[] = "FILE:";
336             lppd->Flags |= PD_PRINTTOFILE;
337             pi->pPortName = file;
338         }
339
340         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
341             FIXME("Collate lppd not yet implemented as output\n");
342         }
343
344         /* set PD_Collate and nCopies */
345         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
346           /*  The application doesn't support multiple copies or collate...
347            */
348             lppd->Flags &= ~PD_COLLATE;
349             lppd->nCopies = 1;
350           /* if the printer driver supports it... store info there
351            * otherwise no collate & multiple copies !
352            */
353             if (lpdm->dmFields & DM_COLLATE)
354                 lpdm->dmCollate =
355                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
356             if (lpdm->dmFields & DM_COPIES)
357                 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
358         } else {
359             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
360                 lppd->Flags |= PD_COLLATE;
361             else
362                lppd->Flags &= ~PD_COLLATE;
363             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
364         }
365     }
366     return TRUE;
367 }
368
369 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
370                                     PRINT_PTRW* PrintStructures)
371 {
372     LPPRINTDLGW       lppd = PrintStructures->lpPrintDlg;
373     PDEVMODEW         lpdm = PrintStructures->lpDevMode;
374     LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
375
376
377     if(!lpdm) {
378         FIXME("No lpdm ptr?\n");
379         return FALSE;
380     }
381
382
383     if(!(lppd->Flags & PD_PRINTSETUP)) {
384         /* check whether nFromPage and nToPage are within range defined by
385          * nMinPage and nMaxPage
386          */
387         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
388             WORD nToPage;
389             WORD nFromPage;
390             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
391             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
392             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
393                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
394                 WCHAR resourcestr[256];
395                 WCHAR resultstr[256];
396                 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
397                             resourcestr, 255);
398                 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
399                 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
400                             resourcestr, 255);
401                 MessageBoxW(hDlg, resultstr, resourcestr,
402                             MB_OK | MB_ICONWARNING);
403                 return FALSE;
404             }
405             lppd->nFromPage = nFromPage;
406             lppd->nToPage   = nToPage;
407             lppd->Flags |= PD_PAGENUMS;
408         }
409         else
410             lppd->Flags &= ~PD_PAGENUMS;
411
412         if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
413             lppd->Flags |= PD_SELECTION;
414         else
415             lppd->Flags &= ~PD_SELECTION;
416
417         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
418             static WCHAR file[] = {'F','I','L','E',':',0};
419             lppd->Flags |= PD_PRINTTOFILE;
420             pi->pPortName = file;
421         }
422
423         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
424             FIXME("Collate lppd not yet implemented as output\n");
425         }
426
427         /* set PD_Collate and nCopies */
428         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
429           /*  The application doesn't support multiple copies or collate...
430            */
431             lppd->Flags &= ~PD_COLLATE;
432             lppd->nCopies = 1;
433           /* if the printer driver supports it... store info there
434            * otherwise no collate & multiple copies !
435            */
436             if (lpdm->dmFields & DM_COLLATE)
437                 lpdm->dmCollate =
438                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
439             if (lpdm->dmFields & DM_COPIES)
440                 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
441         } else {
442             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
443                 lppd->Flags |= PD_COLLATE;
444             else
445                lppd->Flags &= ~PD_COLLATE;
446             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
447         }
448     }
449     return TRUE;
450 }
451
452 static BOOL PRINTDLG_PaperSizeA(
453         PRINTDLGA       *pdlga,const WORD PaperSize,LPPOINT size
454 ) {
455     DEVNAMES    *dn;
456     DEVMODEA    *dm;
457     LPSTR       devname,portname;
458     int         i;
459     INT         NrOfEntries,ret;
460     WORD        *Words = NULL;
461     POINT       *points = NULL;
462     BOOL        retval = FALSE;
463
464     dn = GlobalLock(pdlga->hDevNames);
465     dm = GlobalLock(pdlga->hDevMode);
466     devname     = ((char*)dn)+dn->wDeviceOffset;
467     portname    = ((char*)dn)+dn->wOutputOffset;
468
469
470     NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
471     if (!NrOfEntries) {
472         FIXME("No papernames found for %s/%s\n",devname,portname);
473         goto out;
474     }
475     if (NrOfEntries == -1) {
476         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
477         goto out;
478     }
479
480     Words = HeapAlloc(GetProcessHeap(),0,NrOfEntries*sizeof(WORD));
481     if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERS,(LPSTR)Words,dm))) {
482         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
483         goto out;
484     }
485     for (i=0;i<NrOfEntries;i++)
486         if (Words[i] == PaperSize)
487             break;
488     HeapFree(GetProcessHeap(),0,Words);
489     if (i == NrOfEntries) {
490         FIXME("Papersize %d not found in list?\n",PaperSize);
491         goto out;
492     }
493     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
494     if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPSTR)points,dm))) {
495         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
496         goto out;
497     }
498     /* this is _10ths_ of a millimeter */
499     size->x=points[i].x;
500     size->y=points[i].y;
501     retval = TRUE;
502 out:
503     GlobalUnlock(pdlga->hDevNames);
504     GlobalUnlock(pdlga->hDevMode);
505     HeapFree(GetProcessHeap(),0,Words);
506     HeapFree(GetProcessHeap(),0,points);
507     return retval;
508 }
509
510 static BOOL PRINTDLG_PaperSizeW(
511         PRINTDLGW       *pdlga,const WCHAR *PaperSize,LPPOINT size
512 ) {
513     DEVNAMES    *dn;
514     DEVMODEW    *dm;
515     LPWSTR      devname,portname;
516     int         i;
517     INT         NrOfEntries,ret;
518     WCHAR       *Names = NULL;
519     POINT       *points = NULL;
520     BOOL        retval = FALSE;
521
522     dn = GlobalLock(pdlga->hDevNames);
523     dm = GlobalLock(pdlga->hDevMode);
524     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
525     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
526
527
528     NrOfEntries = DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,NULL,dm);
529     if (!NrOfEntries) {
530         FIXME("No papernames found for %s/%s\n",debugstr_w(devname),debugstr_w(portname));
531         goto out;
532     }
533     if (NrOfEntries == -1) {
534         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
535         goto out;
536     }
537
538     Names = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*NrOfEntries*64);
539     if (NrOfEntries != (ret=DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,Names,dm))) {
540         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
541         goto out;
542     }
543     for (i=0;i<NrOfEntries;i++)
544         if (!lstrcmpW(PaperSize,Names+(64*i)))
545             break;
546     HeapFree(GetProcessHeap(),0,Names);
547     if (i==NrOfEntries) {
548         FIXME("Papersize %s not found in list?\n",debugstr_w(PaperSize));
549         goto out;
550     }
551     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
552     if (NrOfEntries!=(ret=DeviceCapabilitiesW(devname,portname,DC_PAPERSIZE,(LPWSTR)points,dm))) {
553         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
554         goto out;
555     }
556     /* this is _10ths_ of a millimeter */
557     size->x=points[i].x;
558     size->y=points[i].y;
559     retval = TRUE;
560 out:
561     GlobalUnlock(pdlga->hDevNames);
562     GlobalUnlock(pdlga->hDevMode);
563     HeapFree(GetProcessHeap(),0,Names);
564     HeapFree(GetProcessHeap(),0,points);
565     return retval;
566 }
567
568
569 /************************************************************************
570  * PRINTDLG_SetUpPaperComboBox
571  *
572  * Initialize either the papersize or inputslot combos of the Printer Setup
573  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
574  * We also try to re-select the old selection.
575  */
576 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
577                                         int   nIDComboBox,
578                                         char* PrinterName,
579                                         char* PortName,
580                                         LPDEVMODEA dm)
581 {
582     int     i;
583     int     NrOfEntries;
584     char*   Names;
585     WORD*   Words;
586     DWORD   Sel;
587     WORD    oldWord = 0;
588     int     NamesSize;
589     int     fwCapability_Names;
590     int     fwCapability_Words;
591
592     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
593
594     /* query the dialog box for the current selected value */
595     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
596     if(Sel != CB_ERR) {
597         /* we enter here only if a different printer is selected after
598          * the Print Setup dialog is opened. The current settings are
599          * stored into the newly selected printer.
600          */
601         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
602                                       Sel, 0);
603         if (dm) {
604             if (nIDComboBox == cmb2)
605                 dm->u1.s1.dmPaperSize = oldWord;
606             else
607                 dm->u1.s1.dmDefaultSource = oldWord;
608         }
609     }
610     else {
611         /* we enter here only when the Print setup dialog is initially
612          * opened. In this case the settings are restored from when
613          * the dialog was last closed.
614          */
615         if (dm) {
616             if (nIDComboBox == cmb2)
617                 oldWord = dm->u1.s1.dmPaperSize;
618             else
619                 oldWord = dm->u1.s1.dmDefaultSource;
620         }
621     }
622
623     if (nIDComboBox == cmb2) {
624          NamesSize          = 64;
625          fwCapability_Names = DC_PAPERNAMES;
626          fwCapability_Words = DC_PAPERS;
627     } else {
628          nIDComboBox        = cmb3;
629          NamesSize          = 24;
630          fwCapability_Names = DC_BINNAMES;
631          fwCapability_Words = DC_BINS;
632     }
633
634     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
635      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
636      */
637     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
638     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
639                                       fwCapability_Names, NULL, dm);
640     if (NrOfEntries == 0)
641          WARN("no Name Entries found!\n");
642     else if (NrOfEntries < 0)
643          return FALSE;
644
645     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
646        != NrOfEntries) {
647         ERR("Number of caps is different\n");
648         NrOfEntries = 0;
649     }
650
651     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
652     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
653     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
654                                       fwCapability_Names, Names, dm);
655     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
656                                       fwCapability_Words, (LPSTR)Words, dm);
657
658     /* reset any current content in the combobox */
659     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
660
661     /* store new content */
662     for (i = 0; i < NrOfEntries; i++) {
663         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
664                                         (LPARAM)(&Names[i*NamesSize]) );
665         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
666                             Words[i]);
667     }
668
669     /* Look for old selection - can't do this is previous loop since
670        item order will change as more items are added */
671     Sel = 0;
672     for (i = 0; i < NrOfEntries; i++) {
673         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
674            oldWord) {
675             Sel = i;
676             break;
677         }
678     }
679     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
680
681     HeapFree(GetProcessHeap(),0,Words);
682     HeapFree(GetProcessHeap(),0,Names);
683     return TRUE;
684 }
685
686 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
687                                         int   nIDComboBox,
688                                         const WCHAR* PrinterName,
689                                         const WCHAR* PortName,
690                                         LPDEVMODEW dm)
691 {
692     int     i;
693     int     NrOfEntries;
694     WCHAR*  Names;
695     WORD*   Words;
696     DWORD   Sel;
697     WORD    oldWord = 0;
698     int     NamesSize;
699     int     fwCapability_Names;
700     int     fwCapability_Words;
701
702     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
703
704     /* query the dialog box for the current selected value */
705     Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
706     if(Sel != CB_ERR) {
707         /* we enter here only if a different printer is selected after
708          * the Print Setup dialog is opened. The current settings are
709          * stored into the newly selected printer.
710          */
711         oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
712                                       Sel, 0);
713         if (dm) {
714             if (nIDComboBox == cmb2)
715                 dm->u1.s1.dmPaperSize = oldWord;
716             else
717                 dm->u1.s1.dmDefaultSource = oldWord;
718         }
719     }
720     else {
721         /* we enter here only when the Print setup dialog is initially
722          * opened. In this case the settings are restored from when
723          * the dialog was last closed.
724          */
725         if (dm) {
726             if (nIDComboBox == cmb2)
727                 oldWord = dm->u1.s1.dmPaperSize;
728             else
729                 oldWord = dm->u1.s1.dmDefaultSource;
730         }
731     }
732
733     if (nIDComboBox == cmb2) {
734          NamesSize          = 64;
735          fwCapability_Names = DC_PAPERNAMES;
736          fwCapability_Words = DC_PAPERS;
737     } else {
738          nIDComboBox        = cmb3;
739          NamesSize          = 24;
740          fwCapability_Names = DC_BINNAMES;
741          fwCapability_Words = DC_BINS;
742     }
743
744     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
745      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
746      */
747     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
748     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
749                                       fwCapability_Names, NULL, dm);
750     if (NrOfEntries == 0)
751          WARN("no Name Entries found!\n");
752     else if (NrOfEntries < 0)
753          return FALSE;
754
755     if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
756        != NrOfEntries) {
757         ERR("Number of caps is different\n");
758         NrOfEntries = 0;
759     }
760
761     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
762     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
763     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
764                                       fwCapability_Names, Names, dm);
765     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
766                                       fwCapability_Words, (LPWSTR)Words, dm);
767
768     /* reset any current content in the combobox */
769     SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
770
771     /* store new content */
772     for (i = 0; i < NrOfEntries; i++) {
773         DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
774                                         (LPARAM)(&Names[i*NamesSize]) );
775         SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
776                             Words[i]);
777     }
778
779     /* Look for old selection - can't do this is previous loop since
780        item order will change as more items are added */
781     Sel = 0;
782     for (i = 0; i < NrOfEntries; i++) {
783         if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
784            oldWord) {
785             Sel = i;
786             break;
787         }
788     }
789     SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
790
791     HeapFree(GetProcessHeap(),0,Words);
792     HeapFree(GetProcessHeap(),0,Names);
793     return TRUE;
794 }
795
796
797 /***********************************************************************
798  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
799  */
800 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, const PRINTER_INFO_2A *pi)
801 {
802     char   StatusMsg[256];
803     char   ResourceString[256];
804     int    i;
805
806     /* Status Message */
807     StatusMsg[0]='\0';
808
809     /* add all status messages */
810     for (i = 0; i < 25; i++) {
811         if (pi->Status & (1<<i)) {
812             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
813                         ResourceString, 255);
814             strcat(StatusMsg,ResourceString);
815         }
816     }
817     /* append "ready" */
818     /* FIXME: status==ready must only be appended if really so.
819               but how to detect? */
820     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
821                 ResourceString, 255);
822     strcat(StatusMsg,ResourceString);
823     SetDlgItemTextA(hDlg, stc12, StatusMsg);
824
825     /* set all other printer info texts */
826     SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
827     
828     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
829         SetDlgItemTextA(hDlg, stc14, pi->pLocation);
830     else
831         SetDlgItemTextA(hDlg, stc14, pi->pPortName);
832     SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
833     return;
834 }
835
836 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, const PRINTER_INFO_2W *pi)
837 {
838     WCHAR   StatusMsg[256];
839     WCHAR   ResourceString[256];
840     static const WCHAR emptyW[] = {0};
841     int    i;
842
843     /* Status Message */
844     StatusMsg[0]='\0';
845
846     /* add all status messages */
847     for (i = 0; i < 25; i++) {
848         if (pi->Status & (1<<i)) {
849             LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
850                         ResourceString, 255);
851             lstrcatW(StatusMsg,ResourceString);
852         }
853     }
854     /* append "ready" */
855     /* FIXME: status==ready must only be appended if really so.
856               but how to detect? */
857     LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
858                 ResourceString, 255);
859     lstrcatW(StatusMsg,ResourceString);
860     SetDlgItemTextW(hDlg, stc12, StatusMsg);
861
862     /* set all other printer info texts */
863     SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
864     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
865         SetDlgItemTextW(hDlg, stc14, pi->pLocation);
866     else
867         SetDlgItemTextW(hDlg, stc14, pi->pPortName);
868     SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
869 }
870
871
872 /*******************************************************************
873  *
874  *                 PRINTDLG_ChangePrinter
875  *
876  */
877 BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name,
878                                    PRINT_PTRA *PrintStructures)
879 {
880     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
881     LPDEVMODEA lpdm = NULL;
882     LONG dmSize;
883     DWORD needed;
884     HANDLE hprn;
885
886     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
887     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
888     if(!OpenPrinterA(name, &hprn, NULL)) {
889         ERR("Can't open printer %s\n", name);
890         return FALSE;
891     }
892     GetPrinterA(hprn, 2, NULL, 0, &needed);
893     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
894     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
895                 &needed);
896     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
897     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
898     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
899             needed, &needed)) {
900         ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
901         return FALSE;
902     }
903     ClosePrinter(hprn);
904
905     PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
906
907     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
908     PrintStructures->lpDevMode = NULL;
909
910     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
911     if(dmSize == -1) {
912         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
913         return FALSE;
914     }
915     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
916     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
917                                  DM_OUT_BUFFER);
918     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
919                           !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
920                                      (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
921       /* Supplied devicemode matches current printer so try to use it */
922         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
923                             DM_OUT_BUFFER | DM_IN_BUFFER);
924     }
925     if(lpdm)
926         GlobalUnlock(lppd->hDevMode);
927
928     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
929
930     if(!(lppd->Flags & PD_PRINTSETUP)) {
931       /* Print range (All/Range/Selection) */
932         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
933         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
934         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
935         if (lppd->Flags & PD_NOSELECTION)
936             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
937         else
938             if (lppd->Flags & PD_SELECTION)
939                 CheckRadioButton(hDlg, rad1, rad3, rad2);
940         if (lppd->Flags & PD_NOPAGENUMS) {
941             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
942             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
943             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
944             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
945             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
946         } else {
947             if (lppd->Flags & PD_PAGENUMS)
948                 CheckRadioButton(hDlg, rad1, rad3, rad3);
949         }
950
951         /* Collate pages
952          *
953          * FIXME: The ico3 is not displayed for some reason. I don't know why.
954          */
955         if (lppd->Flags & PD_COLLATE) {
956             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
957                                 (LPARAM)PrintStructures->hCollateIcon);
958             CheckDlgButton(hDlg, chx2, 1);
959         } else {
960             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
961                                 (LPARAM)PrintStructures->hNoCollateIcon);
962             CheckDlgButton(hDlg, chx2, 0);
963         }
964
965         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
966           /* if printer doesn't support it: no Collate */
967             if (!(lpdm->dmFields & DM_COLLATE)) {
968                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
969                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
970             }
971         }
972
973         /* nCopies */
974         {
975           INT copies;
976           if (lppd->hDevMode == 0)
977               copies = lppd->nCopies;
978           else
979               copies = lpdm->u1.s1.dmCopies;
980           if(copies == 0) copies = 1;
981           else if(copies < 0) copies = MAX_COPIES;
982           SetDlgItemInt(hDlg, edt3, copies, FALSE);
983         }
984
985         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
986           /* if printer doesn't support it: no nCopies */
987             if (!(lpdm->dmFields & DM_COPIES)) {
988                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
989                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
990             }
991         }
992
993         /* print to file */
994         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
995         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
996             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
997         if (lppd->Flags & PD_HIDEPRINTTOFILE)
998             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
999
1000     } else { /* PD_PRINTSETUP */
1001       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1002
1003       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
1004                                   PrintStructures->lpPrinterInfo->pPrinterName,
1005                                   PrintStructures->lpPrinterInfo->pPortName,
1006                                   lpdm);
1007       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
1008                                   PrintStructures->lpPrinterInfo->pPrinterName,
1009                                   PrintStructures->lpPrinterInfo->pPortName,
1010                                   lpdm);
1011       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1012       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1013                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1014                                    PrintStructures->hLandscapeIcon));
1015
1016     }
1017
1018     /* help button */
1019     if ((lppd->Flags & PD_SHOWHELP)==0) {
1020         /* hide if PD_SHOWHELP not specified */
1021         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1022     }
1023     return TRUE;
1024 }
1025
1026 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1027                                    PRINT_PTRW *PrintStructures)
1028 {
1029     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1030     LPDEVMODEW lpdm = NULL;
1031     LONG dmSize;
1032     DWORD needed;
1033     HANDLE hprn;
1034
1035     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1036     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1037     if(!OpenPrinterW(name, &hprn, NULL)) {
1038         ERR("Can't open printer %s\n", debugstr_w(name));
1039         return FALSE;
1040     }
1041     GetPrinterW(hprn, 2, NULL, 0, &needed);
1042     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1043     GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1044                 &needed);
1045     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1046     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1047     if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1048             needed, &needed)) {
1049         ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1050         return FALSE;
1051     }
1052     ClosePrinter(hprn);
1053
1054     PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1055
1056     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1057     PrintStructures->lpDevMode = NULL;
1058
1059     dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1060     if(dmSize == -1) {
1061         ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1062         return FALSE;
1063     }
1064     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1065     dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1066                                  DM_OUT_BUFFER);
1067     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1068                           !lstrcmpW(lpdm->dmDeviceName,
1069                                   PrintStructures->lpDevMode->dmDeviceName)) {
1070       /* Supplied devicemode matches current printer so try to use it */
1071         DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1072                             DM_OUT_BUFFER | DM_IN_BUFFER);
1073     }
1074     if(lpdm)
1075         GlobalUnlock(lppd->hDevMode);
1076
1077     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
1078
1079     if(!(lppd->Flags & PD_PRINTSETUP)) {
1080       /* Print range (All/Range/Selection) */
1081         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1082         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1083         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
1084         if (lppd->Flags & PD_NOSELECTION)
1085             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1086         else
1087             if (lppd->Flags & PD_SELECTION)
1088                 CheckRadioButton(hDlg, rad1, rad3, rad2);
1089         if (lppd->Flags & PD_NOPAGENUMS) {
1090             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1091             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1092             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1093             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1094             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1095         } else {
1096             if (lppd->Flags & PD_PAGENUMS)
1097                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1098         }
1099
1100         /* Collate pages
1101          *
1102          * FIXME: The ico3 is not displayed for some reason. I don't know why.
1103          */
1104         if (lppd->Flags & PD_COLLATE) {
1105             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1106                                 (LPARAM)PrintStructures->hCollateIcon);
1107             CheckDlgButton(hDlg, chx2, 1);
1108         } else {
1109             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1110                                 (LPARAM)PrintStructures->hNoCollateIcon);
1111             CheckDlgButton(hDlg, chx2, 0);
1112         }
1113
1114         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1115           /* if printer doesn't support it: no Collate */
1116             if (!(lpdm->dmFields & DM_COLLATE)) {
1117                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1118                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1119             }
1120         }
1121
1122         /* nCopies */
1123         {
1124           INT copies;
1125           if (lppd->hDevMode == 0)
1126               copies = lppd->nCopies;
1127           else
1128               copies = lpdm->u1.s1.dmCopies;
1129           if(copies == 0) copies = 1;
1130           else if(copies < 0) copies = MAX_COPIES;
1131           SetDlgItemInt(hDlg, edt3, copies, FALSE);
1132         }
1133
1134         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1135           /* if printer doesn't support it: no nCopies */
1136             if (!(lpdm->dmFields & DM_COPIES)) {
1137                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1138                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1139             }
1140         }
1141
1142         /* print to file */
1143         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1144         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1145             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1146         if (lppd->Flags & PD_HIDEPRINTTOFILE)
1147             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1148
1149     } else { /* PD_PRINTSETUP */
1150       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1151
1152       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1153                                   PrintStructures->lpPrinterInfo->pPrinterName,
1154                                   PrintStructures->lpPrinterInfo->pPortName,
1155                                   lpdm);
1156       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1157                                   PrintStructures->lpPrinterInfo->pPrinterName,
1158                                   PrintStructures->lpPrinterInfo->pPortName,
1159                                   lpdm);
1160       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1161       SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1162                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1163                                    PrintStructures->hLandscapeIcon));
1164
1165     }
1166
1167     /* help button */
1168     if ((lppd->Flags & PD_SHOWHELP)==0) {
1169         /* hide if PD_SHOWHELP not specified */
1170         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1171     }
1172     return TRUE;
1173 }
1174
1175  /***********************************************************************
1176  *           check_printer_setup                        [internal]
1177  */
1178 static LRESULT check_printer_setup(HWND hDlg)
1179 {
1180     DWORD needed,num;
1181     WCHAR resourcestr[256],resultstr[256];
1182     int res;
1183
1184     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1185     if(needed == 0)
1186     {
1187           EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1188     }
1189     if(needed > 0)
1190           return TRUE;
1191     else
1192     {
1193           LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
1194           LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1195           res = MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1196           return FALSE;
1197     }
1198 }
1199
1200 /***********************************************************************
1201  *           PRINTDLG_WMInitDialog                      [internal]
1202  */
1203 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
1204                                      PRINT_PTRA* PrintStructures)
1205 {
1206     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1207     DEVNAMES *pdn;
1208     DEVMODEA *pdm;
1209     char *name = NULL;
1210     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1211
1212     /* load Collate ICONs */
1213     /* We load these with LoadImage because they are not a standard
1214        size and we don't want them rescaled */
1215     PrintStructures->hCollateIcon =
1216       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1217     PrintStructures->hNoCollateIcon =
1218       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1219
1220     /* These can be done with LoadIcon */
1221     PrintStructures->hPortraitIcon =
1222       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1223     PrintStructures->hLandscapeIcon =
1224       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1225
1226     /* display the collate/no_collate icon */
1227     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1228                         (LPARAM)PrintStructures->hNoCollateIcon);
1229
1230     if(PrintStructures->hCollateIcon == 0 ||
1231        PrintStructures->hNoCollateIcon == 0 ||
1232        PrintStructures->hPortraitIcon == 0 ||
1233        PrintStructures->hLandscapeIcon == 0) {
1234         ERR("no icon in resourcefile\n");
1235         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1236         EndDialog(hDlg, FALSE);
1237     }
1238
1239     /*
1240      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1241      * must be registered and the Help button must be shown.
1242      */
1243     if (lppd->Flags & PD_SHOWHELP) {
1244         if((PrintStructures->HelpMessageID =
1245             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1246             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1247             return FALSE;
1248         }
1249     } else
1250         PrintStructures->HelpMessageID = 0;
1251
1252     if(!(lppd->Flags &PD_PRINTSETUP)) {
1253         PrintStructures->hwndUpDown =
1254           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1255                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1256                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1257                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1258                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1259     }
1260
1261     /* FIXME: I allow more freedom than either Win95 or WinNT,
1262      *        which do not agree to what errors should be thrown or not
1263      *        in case nToPage or nFromPage is out-of-range.
1264      */
1265     if (lppd->nMaxPage < lppd->nMinPage)
1266         lppd->nMaxPage = lppd->nMinPage;
1267     if (lppd->nMinPage == lppd->nMaxPage)
1268         lppd->Flags |= PD_NOPAGENUMS;
1269     if (lppd->nToPage < lppd->nMinPage)
1270         lppd->nToPage = lppd->nMinPage;
1271     if (lppd->nToPage > lppd->nMaxPage)
1272         lppd->nToPage = lppd->nMaxPage;
1273     if (lppd->nFromPage < lppd->nMinPage)
1274         lppd->nFromPage = lppd->nMinPage;
1275     if (lppd->nFromPage > lppd->nMaxPage)
1276         lppd->nFromPage = lppd->nMaxPage;
1277
1278     /* if we have the combo box, fill it */
1279     if (GetDlgItem(hDlg,comboID)) {
1280         /* Fill Combobox
1281          */
1282         pdn = GlobalLock(lppd->hDevNames);
1283         pdm = GlobalLock(lppd->hDevMode);
1284         if(pdn)
1285             name = (char*)pdn + pdn->wDeviceOffset;
1286         else if(pdm)
1287             name = (char*)pdm->dmDeviceName;
1288         PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1289         if(pdm) GlobalUnlock(lppd->hDevMode);
1290         if(pdn) GlobalUnlock(lppd->hDevNames);
1291
1292         /* Now find selected printer and update rest of dlg */
1293         name = HeapAlloc(GetProcessHeap(),0,256);
1294         if (GetDlgItemTextA(hDlg, comboID, name, 255))
1295             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1296         HeapFree(GetProcessHeap(),0,name);
1297     } else {
1298         /* else use default printer */
1299         char name[200];
1300         DWORD dwBufLen = sizeof(name);
1301         BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1302
1303         if (ret)
1304             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1305         else
1306             FIXME("No default printer found, expect problems!\n");
1307     }
1308     return TRUE;
1309 }
1310
1311 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1312                                      PRINT_PTRW* PrintStructures)
1313 {
1314     static const WCHAR PD32_COLLATE[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1315     static const WCHAR PD32_NOCOLLATE[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1316     static const WCHAR PD32_PORTRAIT[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
1317     static const WCHAR PD32_LANDSCAPE[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
1318     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1319     DEVNAMES *pdn;
1320     DEVMODEW *pdm;
1321     WCHAR *name = NULL;
1322     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1323
1324     /* load Collate ICONs */
1325     /* We load these with LoadImage because they are not a standard
1326        size and we don't want them rescaled */
1327     PrintStructures->hCollateIcon =
1328       LoadImageW(COMDLG32_hInstance, PD32_COLLATE, IMAGE_ICON, 0, 0, 0);
1329     PrintStructures->hNoCollateIcon =
1330       LoadImageW(COMDLG32_hInstance, PD32_NOCOLLATE, IMAGE_ICON, 0, 0, 0);
1331
1332     /* These can be done with LoadIcon */
1333     PrintStructures->hPortraitIcon =
1334       LoadIconW(COMDLG32_hInstance, PD32_PORTRAIT);
1335     PrintStructures->hLandscapeIcon =
1336       LoadIconW(COMDLG32_hInstance, PD32_LANDSCAPE);
1337
1338     /* display the collate/no_collate icon */
1339     SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1340                         (LPARAM)PrintStructures->hNoCollateIcon);
1341
1342     if(PrintStructures->hCollateIcon == 0 ||
1343        PrintStructures->hNoCollateIcon == 0 ||
1344        PrintStructures->hPortraitIcon == 0 ||
1345        PrintStructures->hLandscapeIcon == 0) {
1346         ERR("no icon in resourcefile\n");
1347         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1348         EndDialog(hDlg, FALSE);
1349     }
1350
1351     /*
1352      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1353      * must be registered and the Help button must be shown.
1354      */
1355     if (lppd->Flags & PD_SHOWHELP) {
1356         if((PrintStructures->HelpMessageID =
1357             RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1358             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1359             return FALSE;
1360         }
1361     } else
1362         PrintStructures->HelpMessageID = 0;
1363
1364     if(!(lppd->Flags &PD_PRINTSETUP)) {
1365         PrintStructures->hwndUpDown =
1366           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1367                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1368                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1369                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1370                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1371     }
1372
1373     /* FIXME: I allow more freedom than either Win95 or WinNT,
1374      *        which do not agree to what errors should be thrown or not
1375      *        in case nToPage or nFromPage is out-of-range.
1376      */
1377     if (lppd->nMaxPage < lppd->nMinPage)
1378         lppd->nMaxPage = lppd->nMinPage;
1379     if (lppd->nMinPage == lppd->nMaxPage)
1380         lppd->Flags |= PD_NOPAGENUMS;
1381     if (lppd->nToPage < lppd->nMinPage)
1382         lppd->nToPage = lppd->nMinPage;
1383     if (lppd->nToPage > lppd->nMaxPage)
1384         lppd->nToPage = lppd->nMaxPage;
1385     if (lppd->nFromPage < lppd->nMinPage)
1386         lppd->nFromPage = lppd->nMinPage;
1387     if (lppd->nFromPage > lppd->nMaxPage)
1388         lppd->nFromPage = lppd->nMaxPage;
1389
1390     /* if we have the combo box, fill it */
1391     if (GetDlgItem(hDlg,comboID)) {
1392         /* Fill Combobox
1393          */
1394         pdn = GlobalLock(lppd->hDevNames);
1395         pdm = GlobalLock(lppd->hDevMode);
1396         if(pdn)
1397             name = (WCHAR*)pdn + pdn->wDeviceOffset;
1398         else if(pdm)
1399             name = pdm->dmDeviceName;
1400         PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1401         if(pdm) GlobalUnlock(lppd->hDevMode);
1402         if(pdn) GlobalUnlock(lppd->hDevNames);
1403
1404         /* Now find selected printer and update rest of dlg */
1405         /* ansi is ok here */
1406         name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1407         if (GetDlgItemTextW(hDlg, comboID, name, 255))
1408             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1409         HeapFree(GetProcessHeap(),0,name);
1410     } else {
1411         /* else use default printer */
1412         WCHAR name[200];
1413         DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1414         BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1415
1416         if (ret)
1417             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1418         else
1419             FIXME("No default printer found, expect problems!\n");
1420     }
1421     return TRUE;
1422 }
1423
1424 /***********************************************************************
1425  *                              PRINTDLG_WMCommand               [internal]
1426  */
1427 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1428                         LPARAM lParam, PRINT_PTRA* PrintStructures)
1429 {
1430     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1431     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1432     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1433
1434     switch (LOWORD(wParam))  {
1435     case IDOK:
1436         TRACE(" OK button was hit\n");
1437         if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1438             FIXME("Update printdlg was not successful!\n");
1439             return(FALSE);
1440         }
1441         EndDialog(hDlg, TRUE);
1442         return(TRUE);
1443
1444     case IDCANCEL:
1445         TRACE(" CANCEL button was hit\n");
1446         EndDialog(hDlg, FALSE);
1447         return(FALSE);
1448
1449      case pshHelp:
1450         TRACE(" HELP button was hit\n");
1451         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1452                                 (WPARAM) hDlg, (LPARAM) lppd);
1453         break;
1454
1455      case chx2:                         /* collate pages checkbox */
1456         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1457             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1458                                     (LPARAM)PrintStructures->hCollateIcon);
1459         else
1460             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1461                                     (LPARAM)PrintStructures->hNoCollateIcon);
1462         break;
1463      case edt1:                         /* from page nr editbox */
1464      case edt2:                         /* to page nr editbox */
1465         if (HIWORD(wParam)==EN_CHANGE) {
1466             WORD nToPage;
1467             WORD nFromPage;
1468             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1469             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1470             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1471                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1472         }
1473         break;
1474
1475     case edt3:
1476         if(HIWORD(wParam) == EN_CHANGE) {
1477             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1478             if(copies <= 1)
1479                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1480             else
1481                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1482         }
1483         break;
1484
1485 #if 0
1486      case psh1:                       /* Print Setup */
1487         {
1488             PRINTDLG16  pdlg;
1489
1490             if (!PrintStructures->dlg.lpPrintDlg16) {
1491                 FIXME("The 32bit print dialog does not have this button!?\n");
1492                 break;
1493             }
1494
1495             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1496             pdlg.Flags |= PD_PRINTSETUP;
1497             pdlg.hwndOwner = HWND_16(hDlg);
1498             if (!PrintDlg16(&pdlg))
1499                 break;
1500         }
1501         break;
1502 #endif
1503      case psh2:                       /* Properties button */
1504        {
1505          HANDLE hPrinter;
1506          char   PrinterName[256];
1507
1508          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1509          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1510              FIXME(" Call to OpenPrinter did not succeed!\n");
1511              break;
1512          }
1513          DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1514                              PrintStructures->lpDevMode,
1515                              PrintStructures->lpDevMode,
1516                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1517          ClosePrinter(hPrinter);
1518          break;
1519        }
1520
1521     case rad1: /* Paperorientation */
1522         if (lppd->Flags & PD_PRINTSETUP)
1523         {
1524               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1525               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1526                           (LPARAM)(PrintStructures->hPortraitIcon));
1527         }
1528         break;
1529
1530     case rad2: /* Paperorientation */
1531         if (lppd->Flags & PD_PRINTSETUP)
1532         {
1533               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1534               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1535                           (LPARAM)(PrintStructures->hLandscapeIcon));
1536         }
1537         break;
1538
1539     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1540          if (PrinterComboID != LOWORD(wParam)) {
1541              FIXME("No handling for print quality combo box yet.\n");
1542              break;
1543          }
1544          /* FALLTHROUGH */
1545     case cmb4:                         /* Printer combobox */
1546          if (HIWORD(wParam)==CBN_SELCHANGE) {
1547              char   PrinterName[256];
1548              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1549              PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1550          }
1551          break;
1552
1553     case cmb2: /* Papersize */
1554       {
1555           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1556           if(Sel != CB_ERR)
1557               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1558                                                             CB_GETITEMDATA,
1559                                                             Sel, 0);
1560       }
1561       break;
1562
1563     case cmb3: /* Bin */
1564       {
1565           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1566           if(Sel != CB_ERR)
1567               lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1568                                                           CB_GETITEMDATA, Sel,
1569                                                           0);
1570       }
1571       break;
1572     }
1573     if(lppd->Flags & PD_PRINTSETUP) {
1574         switch (LOWORD(wParam)) {
1575         case rad1:                         /* orientation */
1576         case rad2:
1577             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1578                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1579                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1580                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1581                                         (WPARAM)IMAGE_ICON,
1582                                         (LPARAM)PrintStructures->hPortraitIcon);
1583                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1584                                         (WPARAM)IMAGE_ICON,
1585                                         (LPARAM)PrintStructures->hPortraitIcon);
1586                 }
1587             } else {
1588                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1589                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1590                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1591                                         (WPARAM)IMAGE_ICON,
1592                                         (LPARAM)PrintStructures->hLandscapeIcon);
1593                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1594                                         (WPARAM)IMAGE_ICON,
1595                                         (LPARAM)PrintStructures->hLandscapeIcon);
1596                 }
1597             }
1598             break;
1599         }
1600     }
1601     return FALSE;
1602 }
1603
1604 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1605                         LPARAM lParam, PRINT_PTRW* PrintStructures)
1606 {
1607     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1608     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1609     LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1610
1611     switch (LOWORD(wParam))  {
1612     case IDOK:
1613         TRACE(" OK button was hit\n");
1614         if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1615             FIXME("Update printdlg was not successful!\n");
1616             return(FALSE);
1617         }
1618         EndDialog(hDlg, TRUE);
1619         return(TRUE);
1620
1621     case IDCANCEL:
1622         TRACE(" CANCEL button was hit\n");
1623         EndDialog(hDlg, FALSE);
1624         return(FALSE);
1625
1626      case pshHelp:
1627         TRACE(" HELP button was hit\n");
1628         SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1629                                 (WPARAM) hDlg, (LPARAM) lppd);
1630         break;
1631
1632      case chx2:                         /* collate pages checkbox */
1633         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1634             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1635                                     (LPARAM)PrintStructures->hCollateIcon);
1636         else
1637             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1638                                     (LPARAM)PrintStructures->hNoCollateIcon);
1639         break;
1640      case edt1:                         /* from page nr editbox */
1641      case edt2:                         /* to page nr editbox */
1642         if (HIWORD(wParam)==EN_CHANGE) {
1643             WORD nToPage;
1644             WORD nFromPage;
1645             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1646             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1647             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1648                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1649         }
1650         break;
1651
1652     case edt3:
1653         if(HIWORD(wParam) == EN_CHANGE) {
1654             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1655             if(copies <= 1)
1656                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1657             else
1658                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1659         }
1660         break;
1661
1662      case psh1:                       /* Print Setup */
1663         {
1664                 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1665         }
1666         break;
1667      case psh2:                       /* Properties button */
1668        {
1669          HANDLE hPrinter;
1670          WCHAR  PrinterName[256];
1671
1672          if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1673          if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1674              FIXME(" Call to OpenPrinter did not succeed!\n");
1675              break;
1676          }
1677          DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1678                              PrintStructures->lpDevMode,
1679                              PrintStructures->lpDevMode,
1680                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1681          ClosePrinter(hPrinter);
1682          break;
1683        }
1684
1685     case rad1: /* Paperorientation */
1686         if (lppd->Flags & PD_PRINTSETUP)
1687         {
1688               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1689               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1690                           (LPARAM)(PrintStructures->hPortraitIcon));
1691         }
1692         break;
1693
1694     case rad2: /* Paperorientation */
1695         if (lppd->Flags & PD_PRINTSETUP)
1696         {
1697               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1698               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1699                           (LPARAM)(PrintStructures->hLandscapeIcon));
1700         }
1701         break;
1702
1703     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1704          if (PrinterComboID != LOWORD(wParam)) {
1705              FIXME("No handling for print quality combo box yet.\n");
1706              break;
1707          }
1708          /* FALLTHROUGH */
1709     case cmb4:                         /* Printer combobox */
1710          if (HIWORD(wParam)==CBN_SELCHANGE) {
1711              WCHAR   PrinterName[256];
1712              GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1713              PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1714          }
1715          break;
1716
1717     case cmb2: /* Papersize */
1718       {
1719           DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1720           if(Sel != CB_ERR)
1721               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1722                                                             CB_GETITEMDATA,
1723                                                             Sel, 0);
1724       }
1725       break;
1726
1727     case cmb3: /* Bin */
1728       {
1729           DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1730           if(Sel != CB_ERR)
1731               lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1732                                                           CB_GETITEMDATA, Sel,
1733                                                           0);
1734       }
1735       break;
1736     }
1737     if(lppd->Flags & PD_PRINTSETUP) {
1738         switch (LOWORD(wParam)) {
1739         case rad1:                         /* orientation */
1740         case rad2:
1741             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1742                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1743                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1744                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1745                                         (WPARAM)IMAGE_ICON,
1746                                         (LPARAM)PrintStructures->hPortraitIcon);
1747                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1748                                         (WPARAM)IMAGE_ICON,
1749                                         (LPARAM)PrintStructures->hPortraitIcon);
1750                 }
1751             } else {
1752                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1753                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1754                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1755                                         (WPARAM)IMAGE_ICON,
1756                                         (LPARAM)PrintStructures->hLandscapeIcon);
1757                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1758                                         (WPARAM)IMAGE_ICON,
1759                                         (LPARAM)PrintStructures->hLandscapeIcon);
1760                 }
1761             }
1762             break;
1763         }
1764     }
1765     return FALSE;
1766 }
1767
1768 /***********************************************************************
1769  *           PrintDlgProcA                      [internal]
1770  */
1771 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1772                                       LPARAM lParam)
1773 {
1774     PRINT_PTRA* PrintStructures;
1775     INT_PTR res = FALSE;
1776
1777     if (uMsg!=WM_INITDIALOG) {
1778         PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
1779         if (!PrintStructures)
1780             return FALSE;
1781     } else {
1782         PrintStructures = (PRINT_PTRA*) lParam;
1783         SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
1784         if(!check_printer_setup(hDlg))
1785         {
1786             EndDialog(hDlg,FALSE);
1787             return FALSE;
1788         }
1789         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1790
1791         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1792             res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1793                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1794             );
1795         return res;
1796     }
1797
1798     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1799         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1800                                                          lParam);
1801         if(res) return res;
1802     }
1803
1804     switch (uMsg) {
1805     case WM_COMMAND:
1806         return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1807
1808     case WM_DESTROY:
1809         DestroyIcon(PrintStructures->hCollateIcon);
1810         DestroyIcon(PrintStructures->hNoCollateIcon);
1811         DestroyIcon(PrintStructures->hPortraitIcon);
1812         DestroyIcon(PrintStructures->hLandscapeIcon);
1813         if(PrintStructures->hwndUpDown)
1814             DestroyWindow(PrintStructures->hwndUpDown);
1815         return FALSE;
1816     }
1817     return res;
1818 }
1819
1820 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1821                                       LPARAM lParam)
1822 {
1823     static const WCHAR propW[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
1824     PRINT_PTRW* PrintStructures;
1825     INT_PTR res = FALSE;
1826
1827     if (uMsg!=WM_INITDIALOG) {
1828         PrintStructures = (PRINT_PTRW*) GetPropW(hDlg, propW);
1829         if (!PrintStructures)
1830             return FALSE;
1831     } else {
1832         PrintStructures = (PRINT_PTRW*) lParam;
1833         SetPropW(hDlg, propW, PrintStructures);
1834         if(!check_printer_setup(hDlg))
1835         {
1836             EndDialog(hDlg,FALSE);
1837             return FALSE;
1838         }
1839         res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1840
1841         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1842             res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1843         return res;
1844     }
1845
1846     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1847         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1848         if(res) return res;
1849     }
1850
1851     switch (uMsg) {
1852     case WM_COMMAND:
1853         return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1854
1855     case WM_DESTROY:
1856         DestroyIcon(PrintStructures->hCollateIcon);
1857         DestroyIcon(PrintStructures->hNoCollateIcon);
1858         DestroyIcon(PrintStructures->hPortraitIcon);
1859         DestroyIcon(PrintStructures->hLandscapeIcon);
1860         if(PrintStructures->hwndUpDown)
1861             DestroyWindow(PrintStructures->hwndUpDown);
1862         return FALSE;
1863     }
1864     return res;
1865 }
1866
1867 /************************************************************
1868  *
1869  *      PRINTDLG_GetDlgTemplate
1870  *
1871  */
1872 static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
1873 {
1874     HRSRC hResInfo;
1875     HGLOBAL hDlgTmpl;
1876
1877     if (lppd->Flags & PD_PRINTSETUP) {
1878         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1879             hDlgTmpl = lppd->hSetupTemplate;
1880         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1881             hResInfo = FindResourceA(lppd->hInstance,
1882                                      lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1883             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1884         } else {
1885             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1886                                      (LPSTR)RT_DIALOG);
1887             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1888         }
1889     } else {
1890         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1891             hDlgTmpl = lppd->hPrintTemplate;
1892         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1893             hResInfo = FindResourceA(lppd->hInstance,
1894                                      lppd->lpPrintTemplateName,
1895                                      (LPSTR)RT_DIALOG);
1896             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1897         } else {
1898             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1899                                      (LPSTR)RT_DIALOG);
1900             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1901         }
1902     }
1903     return hDlgTmpl;
1904 }
1905
1906 static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
1907 {
1908     HRSRC hResInfo;
1909     HGLOBAL hDlgTmpl;
1910     static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1911     static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1912
1913     if (lppd->Flags & PD_PRINTSETUP) {
1914         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1915             hDlgTmpl = lppd->hSetupTemplate;
1916         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1917             hResInfo = FindResourceW(lppd->hInstance,
1918                                      lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1919             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1920         } else {
1921             hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1922             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1923         }
1924     } else {
1925         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1926             hDlgTmpl = lppd->hPrintTemplate;
1927         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1928             hResInfo = FindResourceW(lppd->hInstance,
1929                                      lppd->lpPrintTemplateName,
1930                                      (LPWSTR)RT_DIALOG);
1931             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1932         } else {
1933             hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1934             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1935         }
1936     }
1937     return hDlgTmpl;
1938 }
1939
1940 /***********************************************************************
1941  *
1942  *      PRINTDLG_CreateDC
1943  *
1944  */
1945 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1946 {
1947     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1948     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1949
1950     if(lppd->Flags & PD_RETURNDC) {
1951         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1952                               (char*)pdn + pdn->wDeviceOffset,
1953                               (char*)pdn + pdn->wOutputOffset,
1954                               pdm );
1955     } else if(lppd->Flags & PD_RETURNIC) {
1956         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1957                               (char*)pdn + pdn->wDeviceOffset,
1958                               (char*)pdn + pdn->wOutputOffset,
1959                               pdm );
1960     }
1961     GlobalUnlock(lppd->hDevNames);
1962     GlobalUnlock(lppd->hDevMode);
1963     return lppd->hDC ? TRUE : FALSE;
1964 }
1965
1966 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1967 {
1968     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1969     DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1970
1971     if(lppd->Flags & PD_RETURNDC) {
1972         lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1973                               (WCHAR*)pdn + pdn->wDeviceOffset,
1974                               (WCHAR*)pdn + pdn->wOutputOffset,
1975                               pdm );
1976     } else if(lppd->Flags & PD_RETURNIC) {
1977         lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1978                               (WCHAR*)pdn + pdn->wDeviceOffset,
1979                               (WCHAR*)pdn + pdn->wOutputOffset,
1980                               pdm );
1981     }
1982     GlobalUnlock(lppd->hDevNames);
1983     GlobalUnlock(lppd->hDevMode);
1984     return lppd->hDC ? TRUE : FALSE;
1985 }
1986
1987 /***********************************************************************
1988  *           PrintDlgA   (COMDLG32.@)
1989  *
1990  *  Displays the PRINT dialog box, which enables the user to specify
1991  *  specific properties of the print job.
1992  *  
1993  * PARAMS
1994  *  lppd  [IO] ptr to PRINTDLG32 struct
1995  * 
1996  * RETURNS
1997  *  nonzero if the user pressed the OK button
1998  *  zero    if the user cancelled the window or an error occurred
1999  *  
2000  * BUGS
2001  *  PrintDlg:
2002  *  * The Collate Icons do not display, even though they are in the code.
2003  *  * The Properties Button(s) should call DocumentPropertiesA().
2004  */
2005
2006 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
2007 {
2008     BOOL      bRet = FALSE;
2009     LPVOID    ptr;
2010     HINSTANCE hInst;
2011
2012     if (!lppd)
2013     {
2014         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2015         return FALSE;
2016     }
2017
2018     hInst = (HINSTANCE)GetWindowLongPtrA( lppd->hwndOwner, GWLP_HINSTANCE );
2019     if(TRACE_ON(commdlg)) {
2020         char flagstr[1000] = "";
2021         const struct pd_flags *pflag = pd_flags;
2022         for( ; pflag->name; pflag++) {
2023             if(lppd->Flags & pflag->flag)
2024                 strcat(flagstr, pflag->name);
2025         }
2026         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2027               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2028               "flags %08x (%s)\n",
2029               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2030               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2031               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2032     }
2033
2034     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2035         WARN("structure size failure !!!\n");
2036         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2037         return FALSE;
2038     }
2039
2040     if(lppd->Flags & PD_RETURNDEFAULT) {
2041         PRINTER_INFO_2A *pbuf;
2042         DRIVER_INFO_3A  *dbuf;
2043         HANDLE hprn;
2044         DWORD needed;
2045
2046         if(lppd->hDevMode || lppd->hDevNames) {
2047             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2048             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2049             return FALSE;
2050         }
2051         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2052             WARN("Can't find default printer\n");
2053             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2054             return FALSE;
2055         }
2056
2057         GetPrinterA(hprn, 2, NULL, 0, &needed);
2058         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2059         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2060
2061         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2062         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2063         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2064             ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2065                 GetLastError(),pbuf->pPrinterName);
2066             HeapFree(GetProcessHeap(), 0, dbuf);
2067             HeapFree(GetProcessHeap(), 0, pbuf);
2068             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2069             return FALSE;
2070         }
2071         ClosePrinter(hprn);
2072
2073         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2074                                   dbuf->pDriverPath,
2075                                   pbuf->pPrinterName,
2076                                   pbuf->pPortName);
2077         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2078                                      pbuf->pDevMode->dmDriverExtra);
2079         ptr = GlobalLock(lppd->hDevMode);
2080         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2081                pbuf->pDevMode->dmDriverExtra);
2082         GlobalUnlock(lppd->hDevMode);
2083         HeapFree(GetProcessHeap(), 0, pbuf);
2084         HeapFree(GetProcessHeap(), 0, dbuf);
2085         bRet = TRUE;
2086     } else {
2087         HGLOBAL hDlgTmpl;
2088         PRINT_PTRA *PrintStructures;
2089
2090     /* load Dialog resources,
2091      * depending on Flags indicates Print32 or Print32_setup dialog
2092      */
2093         hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2094         if (!hDlgTmpl) {
2095             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2096             return FALSE;
2097         }
2098         ptr = LockResource( hDlgTmpl );
2099         if (!ptr) {
2100             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2101             return FALSE;
2102         }
2103
2104         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2105                                     sizeof(PRINT_PTRA));
2106         PrintStructures->lpPrintDlg = lppd;
2107
2108         /* and create & process the dialog .
2109          * -1 is failure, 0 is broken hwnd, everything else is ok.
2110          */
2111         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2112                                            PrintDlgProcA,
2113                                            (LPARAM)PrintStructures));
2114
2115         if(bRet) {
2116             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2117             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2118             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2119
2120             if (lppd->hDevMode == 0) {
2121                 TRACE(" No hDevMode yet... Need to create my own\n");
2122                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2123                                         lpdm->dmSize + lpdm->dmDriverExtra);
2124             } else {
2125                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2126                                                lpdm->dmSize + lpdm->dmDriverExtra,
2127                                                GMEM_MOVEABLE);
2128             }
2129             lpdmReturn = GlobalLock(lppd->hDevMode);
2130             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2131
2132             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2133                     di->pDriverPath,
2134                     pi->pPrinterName,
2135                     pi->pPortName
2136             );
2137             GlobalUnlock(lppd->hDevMode);
2138         }
2139         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2140         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2141         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2142         HeapFree(GetProcessHeap(), 0, PrintStructures);
2143     }
2144     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2145         bRet = PRINTDLG_CreateDCA(lppd);
2146
2147     TRACE("exit! (%d)\n", bRet);
2148     return bRet;
2149 }
2150
2151 /***********************************************************************
2152  *           PrintDlgW   (COMDLG32.@)
2153  *
2154  * See PrintDlgA.
2155  */
2156 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
2157 {
2158     BOOL      bRet = FALSE;
2159     LPVOID    ptr;
2160     HINSTANCE hInst;
2161
2162     if (!lppd)
2163     {
2164         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2165         return FALSE;
2166     }
2167
2168     hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2169     if(TRACE_ON(commdlg)) {
2170         char flagstr[1000] = "";
2171         const struct pd_flags *pflag = pd_flags;
2172         for( ; pflag->name; pflag++) {
2173             if(lppd->Flags & pflag->flag)
2174                 strcat(flagstr, pflag->name);
2175         }
2176         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2177               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2178               "flags %08x (%s)\n",
2179               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2180               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2181               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2182     }
2183
2184     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2185         WARN("structure size failure !!!\n");
2186         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2187         return FALSE;
2188     }
2189
2190     if(lppd->Flags & PD_RETURNDEFAULT) {
2191         PRINTER_INFO_2W *pbuf;
2192         DRIVER_INFO_3W  *dbuf;
2193         HANDLE hprn;
2194         DWORD needed;
2195
2196         if(lppd->hDevMode || lppd->hDevNames) {
2197             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2198             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2199             return FALSE;
2200         }
2201         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2202             WARN("Can't find default printer\n");
2203             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2204             return FALSE;
2205         }
2206
2207         GetPrinterW(hprn, 2, NULL, 0, &needed);
2208         pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2209         GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2210
2211         GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2212         dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2213         if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2214             ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2215                 GetLastError(),debugstr_w(pbuf->pPrinterName));
2216             HeapFree(GetProcessHeap(), 0, dbuf);
2217             HeapFree(GetProcessHeap(), 0, pbuf);
2218             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2219             return FALSE;
2220         }
2221         ClosePrinter(hprn);
2222
2223         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2224                                   dbuf->pDriverPath,
2225                                   pbuf->pPrinterName,
2226                                   pbuf->pPortName);
2227         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2228                                      pbuf->pDevMode->dmDriverExtra);
2229         ptr = GlobalLock(lppd->hDevMode);
2230         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2231                pbuf->pDevMode->dmDriverExtra);
2232         GlobalUnlock(lppd->hDevMode);
2233         HeapFree(GetProcessHeap(), 0, pbuf);
2234         HeapFree(GetProcessHeap(), 0, dbuf);
2235         bRet = TRUE;
2236     } else {
2237         HGLOBAL hDlgTmpl;
2238         PRINT_PTRW *PrintStructures;
2239
2240     /* load Dialog resources,
2241      * depending on Flags indicates Print32 or Print32_setup dialog
2242      */
2243         hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2244         if (!hDlgTmpl) {
2245             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2246             return FALSE;
2247         }
2248         ptr = LockResource( hDlgTmpl );
2249         if (!ptr) {
2250             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2251             return FALSE;
2252         }
2253
2254         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2255                                     sizeof(PRINT_PTRW));
2256         PrintStructures->lpPrintDlg = lppd;
2257
2258         /* and create & process the dialog .
2259          * -1 is failure, 0 is broken hwnd, everything else is ok.
2260          */
2261         bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2262                                            PrintDlgProcW,
2263                                            (LPARAM)PrintStructures));
2264
2265         if(bRet) {
2266             DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2267             PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2268             DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2269
2270             if (lppd->hDevMode == 0) {
2271                 TRACE(" No hDevMode yet... Need to create my own\n");
2272                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2273                                         lpdm->dmSize + lpdm->dmDriverExtra);
2274             } else {
2275                 WORD locks;
2276                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2277                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2278                     while(locks--) {
2279                         GlobalUnlock(lppd->hDevMode);
2280                         TRACE("Now got %d locks\n", locks);
2281                     }
2282                 }
2283                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2284                                                lpdm->dmSize + lpdm->dmDriverExtra,
2285                                                GMEM_MOVEABLE);
2286             }
2287             lpdmReturn = GlobalLock(lppd->hDevMode);
2288             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2289
2290             if (lppd->hDevNames != 0) {
2291                 WORD locks;
2292                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2293                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2294                     while(locks--)
2295                         GlobalUnlock(lppd->hDevNames);
2296                 }
2297             }
2298             PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2299                     di->pDriverPath,
2300                     pi->pPrinterName,
2301                     pi->pPortName
2302             );
2303             GlobalUnlock(lppd->hDevMode);
2304         }
2305         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2306         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2307         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2308         HeapFree(GetProcessHeap(), 0, PrintStructures);
2309     }
2310     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2311         bRet = PRINTDLG_CreateDCW(lppd);
2312
2313     TRACE("exit! (%d)\n", bRet);
2314     return bRet;
2315 }
2316
2317 /***********************************************************************
2318  *
2319  *          PageSetupDlg
2320  * rad1 - portrait
2321  * rad2 - landscape
2322  * cmb1 - printer select (not in standard dialog template)
2323  * cmb2 - paper size
2324  * cmb3 - source (tray?)
2325  * edt4 - border left
2326  * edt5 - border top
2327  * edt6 - border right
2328  * edt7 - border bottom
2329  * psh3 - "Printer..."
2330  */
2331
2332 typedef struct {
2333     LPPAGESETUPDLGA     dlga; /* Handler to user defined struct */
2334     PRINTDLGA           pdlg;
2335     HWND                hDlg; /* Page Setup dialog handler */
2336     PAGESETUPDLGA       curdlg; /* Stores the current dialog state */
2337     RECT                rtDrawRect; /* Drawing rect for page */
2338 } PageSetupDataA;
2339
2340 typedef struct {
2341     LPPAGESETUPDLGW     dlga;
2342     PRINTDLGW           pdlg;
2343     PAGESETUPDLGW       curdlg; /* Current dialog state */
2344 } PageSetupDataW;
2345
2346
2347 static HGLOBAL PRINTDLG_GetPGSTemplateA(const PAGESETUPDLGA *lppd)
2348 {
2349     HRSRC hResInfo;
2350     HGLOBAL hDlgTmpl;
2351         
2352     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2353         hDlgTmpl = lppd->hPageSetupTemplate;
2354     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2355         hResInfo = FindResourceA(lppd->hInstance,
2356                                  lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2357         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2358     } else {
2359         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2360         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2361     }
2362     return hDlgTmpl;
2363 }
2364
2365 static HGLOBAL PRINTDLG_GetPGSTemplateW(const PAGESETUPDLGW *lppd)
2366 {
2367     HRSRC hResInfo;
2368     HGLOBAL hDlgTmpl;
2369
2370     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2371         hDlgTmpl = lppd->hPageSetupTemplate;
2372     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2373         hResInfo = FindResourceW(lppd->hInstance,
2374                                  lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2375         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2376     } else {
2377         hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2378         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2379     }
2380     return hDlgTmpl;
2381 }
2382
2383 static DWORD
2384 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2385     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2386         return 10*size*100/254;
2387     /* If we don't have a flag, we can choose one. Use millimeters
2388      * to avoid confusing me
2389      */
2390     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2391     return 10*size;
2392 }
2393
2394
2395 static DWORD
2396 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2397     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2398         return size;
2399     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2400         return (size*254)/100;
2401     /* if we don't have a flag, we can choose one. Use millimeters
2402      * to avoid confusing me
2403      */
2404     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2405     return (size*254)/100;
2406 }
2407
2408 static void
2409 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2410     strcpy(strout,"<undef>");
2411     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2412         sprintf(strout,"%d",(size)/100);
2413         return;
2414     }
2415     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2416         sprintf(strout,"%din",(size)/1000);
2417         return;
2418     }
2419     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2420     sprintf(strout,"%d",(size)/100);
2421     return;
2422 }
2423 static void
2424 _c_size2strW(PageSetupDataW *pda,DWORD size,LPWSTR strout) {
2425     static const char mm_fmt[] = "%.2f mm";
2426     static const char in_fmt[] = "%.2f in";
2427     char buf[20];
2428     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2429         sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2430     } else if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2431         sprintf(buf, in_fmt, (size * 1.0) / 1000.0);
2432     } else {
2433         pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2434         sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2435     }
2436
2437     MultiByteToWideChar(CP_ACP, 0, buf, -1, strout, 20);
2438 }
2439
2440 static DWORD
2441 _c_str2sizeA(const PAGESETUPDLGA *dlga, LPCSTR strin) {
2442     float       val;
2443     char        rest[200];
2444
2445     rest[0]='\0';
2446     if (!sscanf(strin,"%f%s",&val,rest))
2447         return 0;
2448
2449     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2450         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2451             return 1000*val;
2452         else
2453             return val*25.4*100;
2454     }
2455     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2456     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2457
2458     if (!strcmp(rest,"mm")) {
2459         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2460             return 100*val;
2461         else
2462             return 1000.0*val/25.4;
2463     }
2464     if (rest[0]=='\0') {
2465         /* use application supplied default */
2466         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2467             /* 100*mm */
2468             return 100.0*val;
2469         }
2470         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2471             /* 1000*inch */
2472             return 1000.0*val;
2473         }
2474     }
2475     ERR("Did not find a conversion for type '%s'!\n",rest);
2476     return 0;
2477 }
2478
2479
2480 static DWORD
2481 _c_str2sizeW(const PAGESETUPDLGW *dlga, LPCWSTR strin) {
2482     char        buf[200];
2483
2484     /* this W -> A transition is OK */
2485     /* we need a unicode version of sscanf to avoid it */
2486     WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2487     return _c_str2sizeA((const PAGESETUPDLGA *)dlga, buf);
2488 }
2489
2490
2491 /****************************************************************************
2492  * PRINTDLG_PS_UpdateDlgStructA
2493  *
2494  * Updates pda->dlga structure 
2495  * Function calls when user presses OK button
2496  *
2497  * PARAMS
2498  *  hDlg        [in]     main window dialog HANDLE
2499  *  pda         [in/out] ptr to PageSetupDataA structure
2500  *
2501  * RETURNS
2502  *  TRUE
2503  */
2504 static BOOL
2505 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2506     DEVNAMES    *dn;
2507     DEVMODEA    *dm;
2508     DWORD       paperword;
2509
2510     memcpy(pda->dlga, &pda->curdlg, sizeof(pda->curdlg));
2511     pda->dlga->hDevMode  = pda->pdlg.hDevMode;
2512     pda->dlga->hDevNames = pda->pdlg.hDevNames;
2513     
2514     dn = GlobalLock(pda->pdlg.hDevNames);
2515     dm = GlobalLock(pda->pdlg.hDevMode);
2516
2517     /* Save paper orientation into device context */
2518     if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y)
2519         dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2520     else
2521         dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2522
2523     /* Save paper size into the device context */
2524     paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2525         SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2526     if (paperword != CB_ERR)
2527         dm->u1.s1.dmPaperSize = paperword;
2528     else
2529         FIXME("could not get dialog text for papersize cmbbox?\n");
2530
2531     /* Save paper source into the device context */
2532     paperword = SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,
2533         SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL, 0, 0), 0);
2534     if (paperword != CB_ERR)
2535         dm->u1.s1.dmDefaultSource = paperword;
2536     else
2537         FIXME("could not get dialog text for papersize cmbbox?\n");
2538
2539     GlobalUnlock(pda->pdlg.hDevNames);
2540     GlobalUnlock(pda->pdlg.hDevMode);
2541
2542     return TRUE;
2543 }
2544
2545 static BOOL
2546 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2547     DEVNAMES    *dn;
2548     DEVMODEW    *dm;
2549     LPWSTR      devname,portname;
2550     WCHAR       papername[64];
2551     WCHAR       buf[200];
2552
2553     dn = GlobalLock(pda->pdlg.hDevNames);
2554     dm = GlobalLock(pda->pdlg.hDevMode);
2555     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2556     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2557
2558     /* Save paper size into device context */
2559     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2560     /* Save paper source into device context */
2561     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2562
2563     if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2564         PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2565         pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2566         pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2567     } else
2568         FIXME("could not get dialog text for papersize cmbbox?\n");
2569 #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); }
2570     GETVAL(edt4,pda->dlga->rtMargin.left);
2571     GETVAL(edt5,pda->dlga->rtMargin.top);
2572     GETVAL(edt6,pda->dlga->rtMargin.right);
2573     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2574 #undef GETVAL
2575
2576     /* If we are in landscape, swap x and y of page size */
2577     if (IsDlgButtonChecked(hDlg, rad2)) {
2578         DWORD tmp;
2579         tmp = pda->dlga->ptPaperSize.x;
2580         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2581         pda->dlga->ptPaperSize.y = tmp;
2582     }
2583
2584     /* Save orientation */
2585     if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2586         dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2587     else
2588         dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2589
2590     GlobalUnlock(pda->pdlg.hDevNames);
2591     GlobalUnlock(pda->pdlg.hDevMode);
2592     return TRUE;
2593 }
2594
2595 /**********************************************************************************************
2596  * PRINTDLG_PS_ChangeActivePrinerA
2597  *
2598  * Redefines hDevMode and hDevNames HANDLES and initialises it.
2599  * 
2600  * PARAMS
2601  *      name    [in]     Name of a printer for activation
2602  *      pda     [in/out] ptr to PageSetupDataA structure
2603  *      
2604  * RETURN 
2605  *      TRUE if success
2606  *      FALSE if fail
2607  */
2608 static BOOL
2609 PRINTDLG_PS_ChangeActivePrinterA(LPSTR name, PageSetupDataA *pda){
2610         HANDLE            hprn;
2611         DWORD             needed;
2612         LPPRINTER_INFO_2A lpPrinterInfo;
2613         LPDRIVER_INFO_3A  lpDriverInfo;
2614         DEVMODEA          *pDevMode, *dm;
2615         
2616         if(!OpenPrinterA(name, &hprn, NULL)){
2617                 ERR("Can't open printer %s\n", name);
2618                 return FALSE;
2619         }
2620         GetPrinterA(hprn, 2, NULL, 0, &needed);
2621         lpPrinterInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2622         GetPrinterA(hprn, 2, (LPBYTE)lpPrinterInfo, needed, &needed);
2623         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2624         lpDriverInfo  = HeapAlloc(GetProcessHeap(), 0, needed);
2625         if(!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)lpDriverInfo, needed, &needed)) {
2626                 ERR("GetPrinterDriverA failed for %s, fix your config!\n", lpPrinterInfo->pPrinterName);
2627                 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2628                 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2629                 return FALSE;
2630         }
2631         ClosePrinter(hprn);
2632         
2633         needed = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
2634         if(needed == -1) {
2635                 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
2636                 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2637                 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2638                 return FALSE;
2639         }
2640         pDevMode = HeapAlloc(GetProcessHeap(), 0, needed);
2641         DocumentPropertiesA(0, 0, name, pDevMode, NULL, DM_OUT_BUFFER);
2642
2643         pda->pdlg.hDevMode = GlobalReAlloc(pda->pdlg.hDevMode,
2644                                          pDevMode->dmSize + pDevMode->dmDriverExtra,
2645                                                          GMEM_MOVEABLE);
2646         dm = GlobalLock(pda->pdlg.hDevMode);
2647         memcpy(dm, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra);
2648         
2649         PRINTDLG_CreateDevNames(&(pda->pdlg.hDevNames),
2650                         lpDriverInfo->pDriverPath,
2651                         lpPrinterInfo->pPrinterName,
2652                         lpPrinterInfo->pPortName);
2653         
2654         GlobalUnlock(pda->pdlg.hDevMode);
2655         HeapFree(GetProcessHeap(), 0, pDevMode);
2656         HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2657         HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2658         return TRUE;
2659 }
2660
2661 /****************************************************************************************
2662  *  PRINTDLG_PS_ChangePrinterA
2663  *
2664  *  Fills Printers, Paper and Source combo
2665  *
2666  *  RETURNS 
2667  *   TRUE
2668  */
2669 static BOOL
2670 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2671     DEVNAMES    *dn;
2672     DEVMODEA    *dm;
2673     LPSTR       devname,portname;
2674         
2675     dn = GlobalLock(pda->pdlg.hDevNames);
2676     dm = GlobalLock(pda->pdlg.hDevMode);
2677     devname         = ((char*)dn)+dn->wDeviceOffset;
2678     portname    = ((char*)dn)+dn->wOutputOffset;
2679     PRINTDLG_SetUpPrinterListComboA(hDlg, cmb1, devname);
2680     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2681     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2682     GlobalUnlock(pda->pdlg.hDevNames);
2683     GlobalUnlock(pda->pdlg.hDevMode);
2684     return TRUE;
2685 }
2686
2687 static void PRINTDLG_PS_SetOrientationW(HWND hDlg, PageSetupDataW* pda)
2688 {
2689     WCHAR PaperName[64];
2690
2691     GetDlgItemTextW(hDlg, cmb2, PaperName, sizeof(PaperName)/sizeof(WCHAR));
2692     PRINTDLG_PaperSizeW(&pda->pdlg, PaperName, &pda->curdlg.ptPaperSize);
2693     pda->curdlg.ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga, pda->curdlg.ptPaperSize.x);
2694     pda->curdlg.ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga, pda->curdlg.ptPaperSize.y);
2695
2696     if(IsDlgButtonChecked(hDlg, rad2))
2697     {
2698         DWORD tmp = pda->curdlg.ptPaperSize.x;
2699         pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2700         pda->curdlg.ptPaperSize.y = tmp;
2701     }
2702 }
2703
2704 static void PRINTDLG_PS_UpdatePrintDlgW(PageSetupDataW* pda, HWND hDlg)
2705 {
2706     DEVMODEW* dm;
2707     DWORD sel;
2708
2709     dm = GlobalLock(pda->pdlg.hDevMode);
2710
2711     if(!dm)
2712         return;
2713
2714     if(pda->curdlg.ptPaperSize.y > pda->curdlg.ptPaperSize.x)
2715         dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2716     else
2717         dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2718
2719     sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
2720
2721     if(sel != CB_ERR)
2722         dm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, sel, 0);
2723
2724     GlobalUnlock(pda->pdlg.hDevMode);
2725 }
2726
2727 static BOOL
2728 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2729     DEVNAMES    *dn;
2730     DEVMODEW    *dm;
2731     LPWSTR      devname,portname;
2732
2733     dn = GlobalLock(pda->pdlg.hDevNames);
2734     dm = GlobalLock(pda->pdlg.hDevMode);
2735     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2736     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2737     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2738     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2739
2740     /* Landscape orientation */
2741     if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
2742         CheckRadioButton(hDlg, rad1, rad2, rad2);
2743     else /* this is default if papersize is not set */
2744         CheckRadioButton(hDlg, rad1, rad2, rad1);
2745
2746     GlobalUnlock(pda->pdlg.hDevNames);
2747     GlobalUnlock(pda->pdlg.hDevMode);
2748
2749     PRINTDLG_PS_SetOrientationW(hDlg, pda);
2750
2751     return TRUE;
2752 }
2753
2754 /******************************************************************************************
2755  * PRINTDLG_PS_ChangePaperPrev 
2756  * 
2757  * Changes paper preview size / position
2758  *
2759  * PARAMS:
2760  *      pda             [i] Pointer for current PageSetupDataA structure
2761  *
2762  * RETURNS:
2763  *  always - TRUE
2764  */
2765 static BOOL 
2766 PRINTDLG_PS_ChangePaperPrev(const PageSetupDataA *pda)
2767 {
2768     LONG width, height, x, y;
2769     RECT rtTmp;
2770     
2771     if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y) {
2772         width  = pda->rtDrawRect.right - pda->rtDrawRect.left;
2773         height = pda->curdlg.ptPaperSize.y * width / pda->curdlg.ptPaperSize.x;
2774     } else {
2775         height = pda->rtDrawRect.bottom - pda->rtDrawRect.top;
2776         width  = pda->curdlg.ptPaperSize.x * height / pda->curdlg.ptPaperSize.y;
2777     }
2778     x = (pda->rtDrawRect.right + pda->rtDrawRect.left - width) / 2;
2779     y = (pda->rtDrawRect.bottom + pda->rtDrawRect.top - height) / 2;
2780     TRACE("rtDrawRect(%d, %d, %d, %d) x=%d, y=%d, w=%d, h=%d\n",
2781         pda->rtDrawRect.left, pda->rtDrawRect.top, pda->rtDrawRect.right, pda->rtDrawRect.bottom,
2782         x, y, width, height);
2783
2784 #define SHADOW 4
2785     MoveWindow(GetDlgItem(pda->hDlg, rct2), x+width, y+SHADOW, SHADOW, height, FALSE);
2786     MoveWindow(GetDlgItem(pda->hDlg, rct3), x+SHADOW, y+height, width, SHADOW, FALSE);
2787     MoveWindow(GetDlgItem(pda->hDlg, rct1), x, y, width, height, FALSE);
2788     memcpy(&rtTmp, &pda->rtDrawRect, sizeof(RECT));
2789     rtTmp.right  += SHADOW;
2790     rtTmp.bottom += SHADOW;
2791 #undef SHADOW 
2792
2793     InvalidateRect(pda->hDlg, &rtTmp, TRUE);
2794     return TRUE;
2795 }
2796
2797 #define GETVAL(idc,val) \
2798 if(msg == EN_CHANGE){ \
2799     if (GetDlgItemTextA(hDlg,idc,buf,sizeof(buf)) > 0)\
2800         val = _c_str2sizeA(pda->dlga,buf); \
2801     else\
2802         FIXME("could not get dlgitemtexta for %x\n",id);  \
2803 }
2804
2805 /********************************************************************************
2806  * PRINTDLG_PS_WMCommandA
2807  * process WM_COMMAND message for PageSetupDlgA
2808  *
2809  * PARAMS
2810  *  hDlg        [in]    Main dialog HANDLE 
2811  *  wParam      [in]    WM_COMMAND wParam
2812  *  lParam      [in]    WM_COMMAND lParam
2813  *  pda         [in/out] ptr to PageSetupDataA
2814  */
2815
2816 static BOOL
2817 PRINTDLG_PS_WMCommandA(
2818     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2819 ) {
2820     WORD msg = HIWORD(wParam);
2821     WORD id  = LOWORD(wParam);
2822     char buf[200];
2823         
2824     TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
2825             LOWORD(lParam),wParam,lParam);
2826     switch (id)  {
2827     case IDOK:
2828         if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2829             return(FALSE);
2830         EndDialog(hDlg, TRUE);
2831         return TRUE ;
2832
2833     case IDCANCEL:
2834         EndDialog(hDlg, FALSE);
2835         return FALSE ;
2836
2837     case psh3: {
2838         pda->pdlg.Flags         = 0;
2839         pda->pdlg.hwndOwner     = hDlg;
2840         if (PrintDlgA(&(pda->pdlg)))
2841             PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2842         }
2843         return TRUE;
2844     case rad1:
2845     case rad2:
2846         if((id == rad1 && pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y) ||
2847            (id == rad2 && pda->curdlg.ptPaperSize.y > pda->curdlg.ptPaperSize.x))
2848         {
2849             char TmpText[25];
2850             char TmpText2[25];
2851             DWORD tmp = pda->curdlg.ptPaperSize.x;
2852
2853             pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2854             pda->curdlg.ptPaperSize.y = tmp;
2855
2856             GetDlgItemTextA(hDlg, edt4, TmpText, sizeof(TmpText));
2857             GetDlgItemTextA(hDlg, edt5, TmpText2, sizeof(TmpText2));
2858             SetDlgItemTextA(hDlg, edt5, TmpText);
2859             SetDlgItemTextA(hDlg, edt4, TmpText2);
2860
2861             GetDlgItemTextA(hDlg, edt6, TmpText, sizeof(TmpText));
2862             GetDlgItemTextA(hDlg, edt7, TmpText2, sizeof(TmpText2));
2863             SetDlgItemTextA(hDlg, edt7, TmpText);
2864             SetDlgItemTextA(hDlg, edt6, TmpText2);
2865
2866             PRINTDLG_PS_ChangePaperPrev(pda);
2867         }
2868         break;
2869     case cmb1: /* Printer combo */
2870             if(msg == CBN_SELCHANGE){
2871                 char crPrinterName[256];
2872                 GetDlgItemTextA(hDlg, id, crPrinterName, 255);
2873                 PRINTDLG_PS_ChangeActivePrinterA(crPrinterName, pda);
2874                 PRINTDLG_PS_ChangePrinterA(hDlg, pda);
2875             }
2876             break;
2877     case cmb2: /* Paper combo */
2878         if(msg == CBN_SELCHANGE){
2879             DWORD paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2880                 SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2881             if (paperword != CB_ERR) {
2882                 PRINTDLG_PaperSizeA(&(pda->pdlg), paperword,&(pda->curdlg.ptPaperSize));
2883                 pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.x);
2884                 pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.y);
2885             
2886                 if (IsDlgButtonChecked(hDlg, rad2)) {
2887                     DWORD tmp = pda->curdlg.ptPaperSize.x;
2888                     pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2889                     pda->curdlg.ptPaperSize.y = tmp;
2890                 }
2891                 PRINTDLG_PS_ChangePaperPrev(pda);
2892             } else
2893                 FIXME("could not get dialog text for papersize cmbbox?\n");
2894         }    
2895         break;
2896     case cmb3:
2897         if(msg == CBN_SELCHANGE){
2898             DEVMODEA *dm = GlobalLock(pda->pdlg.hDevMode);
2899             dm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,CB_GETITEMDATA,
2900                 SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
2901             GlobalUnlock(pda->pdlg.hDevMode);
2902         }
2903         break;
2904     case psh2:                       /* Printer Properties button */
2905        {
2906             HANDLE hPrinter;
2907             char   PrinterName[256];
2908             DEVMODEA *dm;
2909             LRESULT  count;
2910             int      i;
2911             
2912             GetDlgItemTextA(hDlg, cmb1, PrinterName, 255);
2913             if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
2914                 FIXME("Call to OpenPrinter did not succeed!\n");
2915                 break;
2916             }
2917             dm = GlobalLock(pda->pdlg.hDevMode);
2918             DocumentPropertiesA(hDlg, hPrinter, PrinterName, dm, dm,
2919                                 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
2920             ClosePrinter(hPrinter);
2921             /* Changing paper */
2922             PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u1.s1.dmPaperSize, &(pda->curdlg.ptPaperSize));
2923             pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
2924             pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
2925             if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE){
2926                 DWORD tmp = pda->curdlg.ptPaperSize.x;
2927                 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2928                 pda->curdlg.ptPaperSize.y = tmp;
2929                 CheckRadioButton(hDlg, rad1, rad2, rad2);
2930             }
2931             else
2932                 CheckRadioButton(hDlg, rad1, rad2, rad1);
2933             /* Changing paper preview */
2934             PRINTDLG_PS_ChangePaperPrev(pda);
2935             /* Selecting paper in combo */
2936             count = SendDlgItemMessageA(hDlg, cmb2, CB_GETCOUNT, 0, 0);
2937             if(count != CB_ERR){ 
2938                 for(i=0; i<count; ++i){
2939                     if(SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0) == dm->u1.s1.dmPaperSize) {
2940                         SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
2941                         break;
2942                     }
2943                 }
2944             }
2945                                                                             
2946             GlobalUnlock(pda->pdlg.hDevMode);
2947             break;
2948         }       
2949     case edt4:
2950         GETVAL(id, pda->curdlg.rtMargin.left);
2951         break;
2952     case edt5:
2953         GETVAL(id, pda->curdlg.rtMargin.top);
2954         break;
2955     case edt6:
2956         GETVAL(id, pda->curdlg.rtMargin.right);
2957         break;
2958     case edt7:
2959         GETVAL(id, pda->curdlg.rtMargin.bottom);
2960         break;
2961     }
2962     InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
2963     return FALSE;
2964 }
2965 #undef GETVAL                      
2966
2967 static BOOL
2968 PRINTDLG_PS_WMCommandW(
2969     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2970 ) {
2971     TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
2972             LOWORD(lParam),wParam,lParam);
2973     switch (LOWORD(wParam))  {
2974     case IDOK:
2975         if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2976             return(FALSE);
2977         EndDialog(hDlg, TRUE);
2978         return TRUE ;
2979
2980     case IDCANCEL:
2981         EndDialog(hDlg, FALSE);
2982         return FALSE ;
2983
2984     case rad1:
2985     case rad2:
2986         if((LOWORD(wParam) == rad1 && pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y) ||
2987            (LOWORD(wParam) == rad2 && pda->curdlg.ptPaperSize.y > pda->curdlg.ptPaperSize.x))
2988         {
2989             WCHAR tmpText[25];
2990             WCHAR tmpText2[25];
2991             DWORD tmp = pda->curdlg.ptPaperSize.y;
2992
2993             pda->curdlg.ptPaperSize.y = pda->curdlg.ptPaperSize.x;
2994             pda->curdlg.ptPaperSize.x = tmp;
2995
2996             GetDlgItemTextW(hDlg, edt4, tmpText, sizeof(tmpText)/sizeof(WCHAR));
2997             GetDlgItemTextW(hDlg, edt5, tmpText2, sizeof(tmpText2)/sizeof(WCHAR));
2998             SetDlgItemTextW(hDlg, edt5, tmpText);
2999             SetDlgItemTextW(hDlg, edt4, tmpText2);
3000
3001             GetDlgItemTextW(hDlg, edt6, tmpText, sizeof(tmpText)/sizeof(WCHAR));
3002             GetDlgItemTextW(hDlg, edt7, tmpText2, sizeof(tmpText2)/sizeof(WCHAR));
3003             SetDlgItemTextW(hDlg, edt7, tmpText);
3004             SetDlgItemTextW(hDlg, edt6, tmpText2);
3005         }
3006         break;
3007
3008     case psh3: {
3009         pda->pdlg.Flags         = 0;
3010         pda->pdlg.hwndOwner     = hDlg;
3011         PRINTDLG_PS_UpdatePrintDlgW(pda, hDlg);
3012         if (PrintDlgW(&(pda->pdlg)))
3013             PRINTDLG_PS_ChangePrinterW(hDlg,pda);
3014         return TRUE;
3015     }
3016     }
3017     return FALSE;
3018 }
3019
3020
3021 /***********************************************************************
3022  *           DefaultPagePaintHook
3023  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box 
3024  * whenever the sample page is redrawn.
3025 */
3026
3027 static UINT_PTR
3028 PRINTDLG_DefaultPagePaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
3029                               const PageSetupDataA *pda)
3030 {
3031     LPRECT lprc = (LPRECT) lParam;
3032     HDC hdc = (HDC) wParam;
3033     HPEN hpen, holdpen;
3034     LOGFONTW lf;
3035     HFONT hfont, holdfont;
3036     INT oldbkmode;
3037     TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3038     /* Call user paint hook if enable */
3039     if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK)
3040         if (pda->dlga->lpfnPagePaintHook(hwndDlg, uMsg, wParam, lParam))
3041             return TRUE;
3042
3043     switch (uMsg) {
3044        /* LPPAGESETUPDLG in lParam */
3045        case WM_PSD_PAGESETUPDLG:
3046        /* Inform about the sample page rectangle */
3047        case WM_PSD_FULLPAGERECT:
3048        /* Inform about the margin rectangle */
3049        case WM_PSD_MINMARGINRECT:
3050             return FALSE;
3051
3052         /* Draw dashed rectangle showing margins */
3053         case WM_PSD_MARGINRECT:
3054             hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
3055             holdpen = SelectObject(hdc, hpen);
3056             Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
3057             DeleteObject(SelectObject(hdc, holdpen));
3058             return TRUE;
3059         /* Draw the fake document */
3060         case WM_PSD_GREEKTEXTRECT:
3061             /* select a nice scalable font, because we want the text really small */
3062             SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3063             lf.lfHeight = 6; /* value chosen based on visual effect */
3064             hfont = CreateFontIndirectW(&lf);
3065             holdfont = SelectObject(hdc, hfont);
3066
3067             /* if text not loaded, then do so now */
3068             if (wszFakeDocumentText[0] == '\0')
3069                  LoadStringW(COMDLG32_hInstance,
3070                         IDS_FAKEDOCTEXT,
3071                         wszFakeDocumentText,
3072                         sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
3073
3074             oldbkmode = SetBkMode(hdc, TRANSPARENT);
3075             DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
3076             SetBkMode(hdc, oldbkmode);
3077
3078             DeleteObject(SelectObject(hdc, holdfont));
3079             return TRUE;
3080
3081         /* Envelope stamp */
3082         case WM_PSD_ENVSTAMPRECT:
3083         /* Return address */
3084         case WM_PSD_YAFULLPAGERECT:
3085             FIXME("envelope/stamp is not implemented\n");
3086             return FALSE;
3087         default:
3088             FIXME("Unknown message %x\n",uMsg);
3089             return FALSE;
3090     }
3091     return TRUE;
3092 }
3093
3094 /***********************************************************************
3095  *           PagePaintProc
3096  * The main paint procedure for the PageSetupDlg function.
3097  * The Page Setup dialog box includes an image of a sample page that shows how
3098  * the user's selections affect the appearance of the printed output.
3099  * The image consists of a rectangle that represents the selected paper
3100  * or envelope type, with a dotted-line rectangle representing
3101  * the current margins, and partial (Greek text) characters
3102  * to show how text looks on the printed page. 
3103  *
3104  * The following messages in the order sends to user hook procedure:
3105  *   WM_PSD_PAGESETUPDLG    Draw the contents of the sample page
3106  *   WM_PSD_FULLPAGERECT    Inform about the bounding rectangle
3107  *   WM_PSD_MINMARGINRECT   Inform about the margin rectangle (min margin?)
3108  *   WM_PSD_MARGINRECT      Draw the margin rectangle
3109  *   WM_PSD_GREEKTEXTRECT   Draw the Greek text inside the margin rectangle
3110  * If any of first three messages returns TRUE, painting done.
3111  *
3112  * PARAMS:
3113  *   hWnd   [in] Handle to the Page Setup dialog box
3114  *   uMsg   [in] Received message
3115  *
3116  * TODO:
3117  *   WM_PSD_ENVSTAMPRECT    Draw in the envelope-stamp rectangle (for envelopes only)
3118  *   WM_PSD_YAFULLPAGERECT  Draw the return address portion (for envelopes and other paper sizes)
3119  *
3120  * RETURNS:
3121  *   FALSE if all done correctly
3122  *
3123  */
3124
3125
3126 static LRESULT CALLBACK
3127 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3128 {
3129     PAINTSTRUCT ps;
3130     RECT rcClient, rcMargin;
3131     HPEN hpen, holdpen;
3132     HDC hdc;
3133     HBRUSH hbrush, holdbrush;
3134     PageSetupDataA *pda;
3135     int papersize=0, orientation=0; /* FIXME: set this values for user paint hook */
3136     double scalx, scaly;
3137 #define CALLPAINTHOOK(msg,lprc) PRINTDLG_DefaultPagePaintHook( hWnd, msg, (WPARAM)hdc, (LPARAM)lprc, pda)
3138
3139     if (uMsg != WM_PAINT)
3140         return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3141
3142     /* Processing WM_PAINT message */
3143     pda = (PageSetupDataA*)GetPropA(hWnd, "__WINE_PAGESETUPDLGDATA");
3144     if (!pda) {
3145         WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3146         return FALSE;
3147     }
3148     if (PRINTDLG_DefaultPagePaintHook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), (LPARAM)pda->dlga, pda))
3149         return FALSE;
3150
3151     hdc = BeginPaint(hWnd, &ps);
3152     GetClientRect(hWnd, &rcClient);
3153     
3154     scalx = rcClient.right  / (double)pda->curdlg.ptPaperSize.x;
3155     scaly = rcClient.bottom / (double)pda->curdlg.ptPaperSize.y; 
3156     rcMargin = rcClient;
3157
3158     rcMargin.left   += pda->curdlg.rtMargin.left   * scalx;
3159     rcMargin.top    += pda->curdlg.rtMargin.top    * scalx;
3160     rcMargin.right  -= pda->curdlg.rtMargin.right  * scaly;
3161     rcMargin.bottom -= pda->curdlg.rtMargin.bottom * scaly;
3162
3163     /* if the space is too small then we make sure to not draw anything */
3164     rcMargin.left = min(rcMargin.left, rcMargin.right);
3165     rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3166
3167     if (!CALLPAINTHOOK(WM_PSD_FULLPAGERECT, &rcClient) &&
3168         !CALLPAINTHOOK(WM_PSD_MINMARGINRECT, &rcMargin) )
3169     {
3170         /* fill background */
3171         hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3172         FillRect(hdc, &rcClient, hbrush);
3173         holdbrush = SelectObject(hdc, hbrush);
3174
3175         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3176         holdpen = SelectObject(hdc, hpen);
3177         
3178         /* paint left edge */
3179         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3180         LineTo(hdc, rcClient.left, rcClient.bottom-1);
3181
3182         /* paint top edge */
3183         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3184         LineTo(hdc, rcClient.right, rcClient.top);
3185
3186         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3187         DeleteObject(SelectObject(hdc, hpen));
3188
3189         /* paint right edge */
3190         MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3191         LineTo(hdc, rcClient.right-1, rcClient.bottom);
3192
3193         /* paint bottom edge */
3194         MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3195         LineTo(hdc, rcClient.right, rcClient.bottom-1);
3196
3197         DeleteObject(SelectObject(hdc, holdpen));
3198         DeleteObject(SelectObject(hdc, holdbrush));
3199
3200         CALLPAINTHOOK(WM_PSD_MARGINRECT, &rcMargin);
3201
3202         /* give text a bit of a space from the frame */
3203         rcMargin.left += 2;
3204         rcMargin.top += 2;
3205         rcMargin.right -= 2;
3206         rcMargin.bottom -= 2;
3207         
3208         /* if the space is too small then we make sure to not draw anything */
3209         rcMargin.left = min(rcMargin.left, rcMargin.right);
3210         rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3211
3212         CALLPAINTHOOK(WM_PSD_GREEKTEXTRECT, &rcMargin);
3213     }
3214
3215     EndPaint(hWnd, &ps);
3216     return FALSE;
3217 #undef CALLPAINTHOOK
3218 }
3219
3220 /***********************************************************************
3221  *           PRINTDLG_PageDlgProcA
3222  * Message handler for PageSetupDlgA
3223  */
3224 static INT_PTR CALLBACK
3225 PRINTDLG_PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3226 {
3227     DEVMODEA            *dm;
3228     PageSetupDataA      *pda;
3229     INT_PTR             res = FALSE;
3230     HWND                hDrawWnd;
3231
3232     if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3233         pda = (PageSetupDataA*)lParam;
3234         pda->hDlg   = hDlg; /* saving handle to main window to PageSetupDataA structure */
3235         pda->curdlg = *pda->dlga;
3236         
3237         hDrawWnd = GetDlgItem(hDlg, rct1); 
3238         TRACE("set property to %p\n", pda);
3239         SetPropA(hDlg, "__WINE_PAGESETUPDLGDATA", pda);
3240         SetPropA(hDrawWnd, "__WINE_PAGESETUPDLGDATA", pda);
3241         GetWindowRect(hDrawWnd, &pda->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3242         ScreenToClient(hDlg, (LPPOINT)&pda->rtDrawRect);
3243         ScreenToClient(hDlg, (LPPOINT)(&pda->rtDrawRect.right));
3244         lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3245             hDrawWnd,
3246             GWLP_WNDPROC,
3247             (ULONG_PTR)PRINTDLG_PagePaintProc);
3248         
3249         /* FIXME: Paint hook. Must it be at begin of initializtion or at end? */
3250         res = TRUE;
3251         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3252             if (!pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga))
3253                 FIXME("Setup page hook failed?\n");
3254         }
3255
3256         /* if printer button disabled */
3257         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3258             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3259         /* if margin edit boxes disabled */
3260         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3261             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3262             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3263             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3264             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3265         }
3266         /* Set orientation radiobutton properly */
3267         if(pda->dlga->hDevMode)
3268         {
3269             dm = GlobalLock(pda->dlga->hDevMode);
3270             if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
3271                 CheckRadioButton(hDlg, rad1, rad2, rad2);
3272             else /* this is default if papersize is not set */
3273                 CheckRadioButton(hDlg, rad1, rad2, rad1);
3274             GlobalUnlock(pda->dlga->hDevMode);
3275         }
3276
3277         /* if orientation disabled */
3278         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3279             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3280             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3281         }
3282         /* We fill them out enabled or not */
3283         if (pda->dlga->Flags & PSD_MARGINS) {
3284             char str[100];
3285             _c_size2strA(pda,pda->dlga->rtMargin.left,str);
3286             SetDlgItemTextA(hDlg,edt4,str);
3287             _c_size2strA(pda,pda->dlga->rtMargin.top,str);
3288             SetDlgItemTextA(hDlg,edt5,str);
3289             _c_size2strA(pda,pda->dlga->rtMargin.right,str);
3290             SetDlgItemTextA(hDlg,edt6,str);
3291             _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
3292             SetDlgItemTextA(hDlg,edt7,str);
3293         } else {
3294             /* default is 1 inch */
3295             DWORD size = _c_inch2size(pda->dlga,1000);
3296             char        str[20];
3297             _c_size2strA(pda,size,str);
3298             SetDlgItemTextA(hDlg,edt4,str);
3299             SetDlgItemTextA(hDlg,edt5,str);
3300             SetDlgItemTextA(hDlg,edt6,str);
3301             SetDlgItemTextA(hDlg,edt7,str);
3302             pda->curdlg.rtMargin.left   = size;
3303             pda->curdlg.rtMargin.top    = size;
3304             pda->curdlg.rtMargin.right  = size;
3305             pda->curdlg.rtMargin.bottom = size;
3306         }
3307         /* if paper disabled */
3308         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3309             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3310             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3311         }
3312         /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3313         PRINTDLG_PS_ChangePrinterA(hDlg, pda);
3314         dm = GlobalLock(pda->pdlg.hDevMode);
3315         if(dm){
3316             dm->u1.s1.dmDefaultSource = 15; /*FIXME: Automatic select. Does it always 15 at start? */
3317             PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u1.s1.dmPaperSize, &pda->curdlg.ptPaperSize);
3318             GlobalUnlock(pda->pdlg.hDevMode);
3319             pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
3320             pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
3321             if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) { /* Landscape orientation */
3322                 DWORD tmp = pda->curdlg.ptPaperSize.y;
3323                 pda->curdlg.ptPaperSize.y = pda->curdlg.ptPaperSize.x;
3324                 pda->curdlg.ptPaperSize.x = tmp;
3325             }
3326         } else 
3327             WARN("GlobalLock(pda->pdlg.hDevMode) fail? hDevMode=%p\n", pda->pdlg.hDevMode);
3328         /* Drawing paper prev */
3329         PRINTDLG_PS_ChangePaperPrev(pda);
3330         return TRUE;
3331     } else {
3332         pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
3333         if (!pda) {
3334             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3335             return FALSE;
3336         }
3337         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3338             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3339             if (res) return res;
3340         }
3341     }
3342     switch (uMsg) {
3343     case WM_COMMAND:
3344         return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
3345     }
3346     return FALSE;
3347 }
3348
3349 static INT_PTR CALLBACK
3350 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3351 {
3352     static const WCHAR __WINE_PAGESETUPDLGDATA[] = 
3353         { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E', 
3354           'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
3355     PageSetupDataW      *pda;
3356     BOOL                res = FALSE;
3357
3358     if (uMsg==WM_INITDIALOG) {
3359         res = TRUE;
3360         pda = (PageSetupDataW*)lParam;
3361         pda->curdlg = *pda->dlga;
3362         SetPropW(hDlg, __WINE_PAGESETUPDLGDATA, pda);
3363         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3364             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
3365             if (!res) {
3366                 FIXME("Setup page hook failed?\n");
3367                 res = TRUE;
3368             }
3369         }
3370
3371         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
3372             FIXME("PagePaintHook not yet implemented!\n");
3373         }
3374         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3375             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3376         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3377             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3378             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3379             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3380             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3381         }
3382
3383         PRINTDLG_PS_ChangePrinterW(hDlg,pda);
3384
3385         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3386             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3387             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3388         }
3389         /* We fill them out enabled or not */
3390         if (pda->dlga->Flags & PSD_MARGINS) {
3391             WCHAR str[100];
3392             _c_size2strW(pda,pda->dlga->rtMargin.left,str);
3393             SetDlgItemTextW(hDlg,edt4,str);
3394             _c_size2strW(pda,pda->dlga->rtMargin.top,str);
3395             SetDlgItemTextW(hDlg,edt5,str);
3396             _c_size2strW(pda,pda->dlga->rtMargin.right,str);
3397             SetDlgItemTextW(hDlg,edt6,str);
3398             _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
3399             SetDlgItemTextW(hDlg,edt7,str);
3400         } else {
3401             /* default is 1 inch */
3402             DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
3403             WCHAR       str[20];
3404             _c_size2strW(pda,size,str);
3405             SetDlgItemTextW(hDlg,edt4,str);
3406             SetDlgItemTextW(hDlg,edt5,str);
3407             SetDlgItemTextW(hDlg,edt6,str);
3408             SetDlgItemTextW(hDlg,edt7,str);
3409         }
3410
3411         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3412             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3413             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3414         }
3415
3416         return TRUE;
3417     } else {
3418         pda = (PageSetupDataW*)GetPropW(hDlg, __WINE_PAGESETUPDLGDATA);
3419         if (!pda) {
3420             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3421             return FALSE;
3422         }
3423         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3424             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3425             if (res) return res;
3426         }
3427     }
3428     switch (uMsg) {
3429     case WM_COMMAND:
3430         return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
3431     }
3432     return FALSE;
3433 }
3434
3435 /***********************************************************************
3436  *            PageSetupDlgA  (COMDLG32.@)
3437  *
3438  *  Displays the PAGE SETUP dialog box, which enables the user to specify
3439  *  specific properties of a printed page such as
3440  *  size, source, orientation and the width of the page margins.
3441  *
3442  * PARAMS
3443  *  setupdlg [IO] PAGESETUPDLGA struct
3444  *
3445  * RETURNS
3446  *  TRUE    if the user pressed the OK button
3447  *  FALSE   if the user cancelled the window or an error occurred
3448  *
3449  * NOTES
3450  *    The values of hDevMode and hDevNames are filled on output and can be
3451  *    changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3452  * 
3453  */
3454
3455 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
3456     HGLOBAL             hDlgTmpl;
3457     LPVOID              ptr;
3458     BOOL                bRet;
3459     PageSetupDataA      *pda;
3460     PRINTDLGA           pdlg;
3461
3462     if (setupdlg == NULL) {
3463            COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3464            return FALSE;
3465     }
3466
3467     /* TRACE */
3468     if(TRACE_ON(commdlg)) {
3469         char flagstr[1000] = "";
3470         const struct pd_flags *pflag = psd_flags;
3471         for( ; pflag->name; pflag++) {
3472             if(setupdlg->Flags & pflag->flag) {
3473                 strcat(flagstr, pflag->name);
3474                 strcat(flagstr, "|");
3475             }
3476         }
3477         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3478               "hinst %p, flags %08x (%s)\n",
3479               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3480               setupdlg->hDevNames,
3481               setupdlg->hInstance, setupdlg->Flags, flagstr);
3482     }
3483
3484     /* Checking setupdlg structure */
3485     if(setupdlg->lStructSize != sizeof(PAGESETUPDLGA)) {
3486            COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3487            return FALSE;
3488     }
3489     if ((setupdlg->Flags & PSD_ENABLEPAGEPAINTHOOK) &&
3490         (setupdlg->lpfnPagePaintHook == NULL)) {
3491             COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3492             return FALSE;
3493         }
3494
3495     /* Initialize default printer struct. If no printer device info is specified
3496        retrieve the default printer data. */
3497     memset(&pdlg,0,sizeof(pdlg));
3498     pdlg.lStructSize    = sizeof(pdlg);
3499     if (setupdlg->hDevMode && setupdlg->hDevNames) {
3500         pdlg.hDevMode = setupdlg->hDevMode;
3501         pdlg.hDevNames = setupdlg->hDevNames;
3502     } else {
3503         pdlg.Flags = PD_RETURNDEFAULT;
3504         bRet = PrintDlgA(&pdlg);
3505         if (!bRet){
3506             if (!(setupdlg->Flags & PSD_NOWARNING)) {
3507                 char errstr[256];
3508                 LoadStringA(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3509                 MessageBoxA(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3510             }
3511             return FALSE;
3512         }
3513     }
3514
3515     /* short cut exit, just return default values */
3516     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3517         DEVMODEA *dm;
3518
3519         setupdlg->hDevMode = pdlg.hDevMode;
3520         setupdlg->hDevNames = pdlg.hDevNames;
3521         dm = GlobalLock(pdlg.hDevMode);
3522         PRINTDLG_PaperSizeA(&pdlg, dm->u1.s1.dmPaperSize, &setupdlg->ptPaperSize);
3523         GlobalUnlock(pdlg.hDevMode);
3524         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
3525         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
3526         return TRUE;
3527     }
3528
3529     /* get dialog template */
3530     hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
3531     if (!hDlgTmpl) {
3532         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3533         return FALSE;
3534     }
3535     ptr = LockResource( hDlgTmpl );
3536     if (!ptr) {
3537         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3538         return FALSE;
3539     }
3540
3541     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
3542     pda->dlga = setupdlg;
3543     pda->pdlg = pdlg;
3544
3545     bRet = (0<DialogBoxIndirectParamA(
3546                 setupdlg->hInstance,
3547                 ptr,
3548                 setupdlg->hwndOwner,
3549                 PRINTDLG_PageDlgProcA,
3550                 (LPARAM)pda)
3551     );
3552
3553     HeapFree(GetProcessHeap(),0,pda);
3554     return bRet;
3555 }
3556 /***********************************************************************
3557  *            PageSetupDlgW  (COMDLG32.@)
3558  *
3559  * See PageSetupDlgA.
3560  */
3561 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
3562     HGLOBAL             hDlgTmpl;
3563     LPVOID              ptr;
3564     BOOL                bRet;
3565     PageSetupDataW      *pdw;
3566     PRINTDLGW           pdlg;
3567
3568     FIXME("Unicode implementation is not done yet\n");
3569
3570     if (setupdlg == NULL) {
3571            COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3572            return FALSE;
3573     }
3574
3575     if(TRACE_ON(commdlg)) {
3576         char flagstr[1000] = "";
3577         const struct pd_flags *pflag = psd_flags;
3578         for( ; pflag->name; pflag++) {
3579             if(setupdlg->Flags & pflag->flag) {
3580                 strcat(flagstr, pflag->name);
3581                 strcat(flagstr, "|");
3582             }
3583         }
3584         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3585               "hinst %p, flags %08x (%s)\n",
3586               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3587               setupdlg->hDevNames,
3588               setupdlg->hInstance, setupdlg->Flags, flagstr);
3589     }
3590
3591     /* Initialize default printer struct. If no printer device info is specified
3592        retrieve the default printer data. */
3593     memset(&pdlg,0,sizeof(pdlg));
3594     pdlg.lStructSize    = sizeof(pdlg);
3595     if (setupdlg->hDevMode && setupdlg->hDevNames) {
3596         pdlg.hDevMode = setupdlg->hDevMode;
3597         pdlg.hDevNames = setupdlg->hDevNames;
3598     } else {
3599         pdlg.Flags = PD_RETURNDEFAULT;
3600         bRet = PrintDlgW(&pdlg);
3601         if (!bRet){
3602             if (!(setupdlg->Flags & PSD_NOWARNING)) {
3603                 WCHAR errstr[256];
3604                 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3605                 MessageBoxW(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3606             }
3607             return FALSE;
3608         }
3609     }
3610
3611     /* short cut exit, just return default values */
3612     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3613         static const WCHAR a4[] = {'A','4',0};
3614         setupdlg->hDevMode      = pdlg.hDevMode;
3615         setupdlg->hDevNames     = pdlg.hDevNames;
3616         /* FIXME: Just return "A4" for now. */
3617         PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
3618         setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
3619         setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
3620         return TRUE;
3621     }
3622     hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
3623     if (!hDlgTmpl) {
3624         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3625         return FALSE;
3626     }
3627     ptr = LockResource( hDlgTmpl );
3628     if (!ptr) {
3629         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3630         return FALSE;
3631     }
3632     pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3633     pdw->dlga = setupdlg;
3634     pdw->pdlg = pdlg;
3635
3636     bRet = (0<DialogBoxIndirectParamW(
3637                 setupdlg->hInstance,
3638                 ptr,
3639                 setupdlg->hwndOwner,
3640                 PageDlgProcW,
3641                 (LPARAM)pdw)
3642     );
3643     return bRet;
3644 }
3645
3646 /***********************************************************************
3647  * PrintDlgExA (COMDLG32.@)
3648  *
3649  * See PrintDlgExW.
3650  *
3651  * BUGS
3652  *   Only a Stub
3653  *
3654  */
3655 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
3656 {
3657
3658     FIXME("(%p) stub\n", lppd);
3659     if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA))) {
3660         return E_INVALIDARG;
3661     }
3662
3663     if (!IsWindow(lppd->hwndOwner)) {
3664         return E_HANDLE;
3665     }
3666
3667     return E_NOTIMPL;
3668 }
3669
3670 /***********************************************************************
3671  * PrintDlgExW (COMDLG32.@)
3672  *
3673  * Display the property sheet style PRINT dialog box
3674  *  
3675  * PARAMS
3676  *  lppd  [IO] ptr to PRINTDLGEX struct
3677  * 
3678  * RETURNS
3679  *  Success: S_OK
3680  *  Failure: One of the following COM error codes:
3681  *    E_OUTOFMEMORY Insufficient memory.
3682  *    E_INVALIDARG  One or more arguments are invalid.
3683  *    E_POINTER     Invalid pointer.
3684  *    E_HANDLE      Invalid handle.
3685  *    E_FAIL        Unspecified error.
3686  *  
3687  * NOTES
3688  * This Dialog enables the user to specify specific properties of the print job.
3689  * The property sheet can also have additional application-specific and
3690  * driver-specific property pages.
3691  *
3692  * BUGS
3693  *   Only a Stub
3694  *
3695  */
3696 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
3697 {
3698
3699     FIXME("(%p) stub\n", lppd);
3700     if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
3701         return E_INVALIDARG;
3702     }
3703
3704     if (!IsWindow(lppd->hwndOwner)) {
3705         return E_HANDLE;
3706     }
3707
3708     return E_NOTIMPL;
3709 }