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