Added mappings for a few messages.
[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 #include <ctype.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "windef.h"
14 #include "winbase.h"
15 #include "wingdi.h"
16 #include "wine/wingdi16.h"
17 #include "winuser.h"
18 #include "wine/winuser16.h"
19 #include "commdlg.h"
20 #include "dlgs.h"
21 #include "debugtools.h"
22 #include "cderr.h"
23 #include "winspool.h"
24 #include "winerror.h"
25
26 DEFAULT_DEBUG_CHANNEL(commdlg);
27
28 #include "cdlg.h"
29
30 /* This PRINTDLGA internal structure stores
31  * pointers to several throughout useful structures.
32  * 
33  */
34 typedef struct  
35 {
36   LPDEVMODEA        lpDevMode;
37   struct {
38       LPPRINTDLGA       lpPrintDlg;
39       LPPRINTDLG16      lpPrintDlg16;
40   } dlg;
41   LPPRINTER_INFO_2A lpPrinterInfo;
42   LPDRIVER_INFO_3A  lpDriverInfo;
43   UINT              HelpMessageID;
44   HICON             hCollateIcon;    /* PrintDlg only */
45   HICON             hNoCollateIcon;  /* PrintDlg only */
46   HICON             hPortraitIcon;   /* PrintSetupDlg only */
47   HICON             hLandscapeIcon;  /* PrintSetupDlg only */
48   HWND              hwndUpDown;
49 } PRINT_PTRA;
50
51 /* Debugging info */
52 static struct pd_flags {
53   DWORD flag;
54   LPSTR name;
55 } pd_flags[] = {
56   {PD_SELECTION, "PD_SELECTION "},
57   {PD_PAGENUMS, "PD_PAGENUMS "},
58   {PD_NOSELECTION, "PD_NOSELECTION "},
59   {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
60   {PD_COLLATE, "PD_COLLATE "},
61   {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
62   {PD_PRINTSETUP, "PD_PRINTSETUP "},
63   {PD_NOWARNING, "PD_NOWARNING "},
64   {PD_RETURNDC, "PD_RETURNDC "},
65   {PD_RETURNIC, "PD_RETURNIC "},
66   {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
67   {PD_SHOWHELP, "PD_SHOWHELP "},
68   {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
69   {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
70   {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
71   {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
72   {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
73   {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
74   {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
75   {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
76   {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
77   {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
78   {-1, NULL}
79 };
80
81 /* Debugging info */
82 static struct pd_flags psd_flags[] = {
83   {PSD_MINMARGINS,"PSD_MINMARGINS"},
84   {PSD_MARGINS,"PSD_MARGINS"},
85   {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
86   {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
87   {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
88   {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
89   {PSD_NOWARNING,"PSD_NOWARNING"},
90   {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
91   {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
92   {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
93   {PSD_SHOWHELP,"PSD_SHOWHELP"},
94   {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
95   {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
96   {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
97   {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
98   {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
99   {-1, NULL}
100 };
101
102 /* Yes these constants are the same, but we're just copying win98 */
103 #define UPDOWN_ID 0x270f
104 #define MAX_COPIES 9999
105
106 /***********************************************************************
107  *    PRINTDLG_GetDefaultPrinterName
108  *
109  * Returns the default printer name in buf.
110  * Even under WinNT/2000 default printer is retrieved via GetProfileString - 
111  * these entries are mapped somewhere in the registry rather than win.ini.
112  *
113  * Returns TRUE on success else FALSE
114  */
115 static BOOL PRINTDLG_GetDefaultPrinterName(LPSTR buf, DWORD len)
116 {
117     char *ptr;
118
119     if(!GetProfileStringA("windows", "device", "", buf, len)) {
120         TRACE("No profile entry for default printer found.\n");
121         return FALSE;
122     }
123     if((ptr = strchr(buf, ',')) == NULL) {
124         FIXME("bad format for default printer (%s)!\n",buf);
125         return FALSE;
126     }
127     *ptr = '\0';
128     return TRUE;
129 }
130
131 /***********************************************************************
132  *    PRINTDLG_OpenDefaultPrinter
133  *
134  * Returns a winspool printer handle to the default printer in *hprn
135  * Caller must call ClosePrinter on the handle
136  *
137  * Returns TRUE on success else FALSE
138  */
139 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
140 {
141     char buf[260];
142     BOOL res;
143     if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
144         return FALSE;
145     res = OpenPrinterA(buf, hprn, NULL);
146     if (!res)
147         FIXME("Could not open printer %s?!\n",buf);
148     return res;
149 }
150
151 /***********************************************************************
152  *    PRINTDLG_SetUpPrinterListCombo
153  *
154  * Initializes printer list combox.
155  * hDlg:  HWND of dialog
156  * id:    Control id of combo
157  * name:  Name of printer to select
158  *
159  * Initializes combo with list of available printers.  Selects printer 'name'
160  * If name is NULL or does not exist select the default printer.
161  *
162  * Returns number of printers added to list.
163  */
164 static INT PRINTDLG_SetUpPrinterListCombo(HWND hDlg, UINT id, LPCSTR name)
165 {
166     DWORD needed, num;
167     INT i;
168     LPPRINTER_INFO_2A pi;
169     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
170     pi = HeapAlloc(GetProcessHeap(), 0, needed);
171     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed, 
172                   &num);
173
174     for(i = 0; i < num; i++) {
175         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
176                             (LPARAM)pi[i].pPrinterName );
177     }
178     HeapFree(GetProcessHeap(), 0, pi);
179     if(!name ||
180        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
181                                 (LPARAM)name)) == CB_ERR) {
182
183         char buf[260];
184         FIXME("Can't find '%s' in printer list so trying to find default\n",
185               name);
186         if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
187             return num;
188         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
189         if(i == CB_ERR)
190             FIXME("Can't find default printer in printer list\n");
191     }
192     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
193     return num;
194 }
195
196 /***********************************************************************
197  *             PRINTDLG_CreateDevNames          [internal]
198  *
199  *
200  *   creates a DevNames structure.
201  *
202  *  (NB. when we handle unicode the offsets will be in wchars).
203  */
204 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName, 
205                                     char* DeviceName, char* OutputPort)
206 {
207     long size;
208     char*   pDevNamesSpace;
209     char*   pTempPtr;
210     LPDEVNAMES lpDevNames;
211     char buf[260];
212
213     size = strlen(DeviceDriverName) + 1
214             + strlen(DeviceName) + 1
215             + strlen(OutputPort) + 1
216             + sizeof(DEVNAMES);
217             
218     if(*hmem)
219         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
220     else
221         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
222     if (*hmem == 0)
223         return FALSE;
224
225     pDevNamesSpace = GlobalLock(*hmem);
226     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
227
228     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
229     strcpy(pTempPtr, DeviceDriverName);
230     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
231
232     pTempPtr += strlen(DeviceDriverName) + 1;
233     strcpy(pTempPtr, DeviceName);
234     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
235         
236     pTempPtr += strlen(DeviceName) + 1;
237     strcpy(pTempPtr, OutputPort);
238     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
239
240     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
241     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
242     GlobalUnlock(*hmem);
243     return TRUE;
244 }
245
246 static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, char* DeviceDriverName, 
247                                       char* DeviceName, char* OutputPort)
248 {
249     long size;
250     char*   pDevNamesSpace;
251     char*   pTempPtr;
252     LPDEVNAMES lpDevNames;
253     char buf[260];
254
255     size = strlen(DeviceDriverName) + 1
256             + strlen(DeviceName) + 1
257             + strlen(OutputPort) + 1
258             + sizeof(DEVNAMES);
259             
260     if(*hmem)
261         *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE);
262     else
263         *hmem = GlobalAlloc16(GMEM_MOVEABLE, size);
264     if (*hmem == 0)
265         return FALSE;
266
267     pDevNamesSpace = GlobalLock16(*hmem);
268     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
269
270     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
271     strcpy(pTempPtr, DeviceDriverName);
272     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
273
274     pTempPtr += strlen(DeviceDriverName) + 1;
275     strcpy(pTempPtr, DeviceName);
276     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
277         
278     pTempPtr += strlen(DeviceName) + 1;
279     strcpy(pTempPtr, OutputPort);
280     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
281
282     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
283     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
284     GlobalUnlock16(*hmem);
285     return TRUE;
286 }
287
288
289 /***********************************************************************
290  *             PRINTDLG_UpdatePrintDlg          [internal]
291  *
292  *
293  *   updates the PrintDlg structure for returnvalues.
294  *      
295  * RETURNS
296  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
297  *   TRUE  if succesful.
298  */
299 static BOOL PRINTDLG_UpdatePrintDlg(HWND hDlg, 
300                                     PRINT_PTRA* PrintStructures)
301 {
302     LPPRINTDLGA       lppd = PrintStructures->dlg.lpPrintDlg;
303     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
304     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
305
306
307     if(!lpdm) {
308         FIXME("No lpdm ptr?\n");
309         return FALSE;
310     }
311
312
313     if(!(lppd->Flags & PD_PRINTSETUP)) {
314         /* check whether nFromPage and nToPage are within range defined by
315          * nMinPage and nMaxPage
316          */
317         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
318             WORD nToPage;
319             WORD nFromPage;
320             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
321             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
322             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
323                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
324                 char resourcestr[256];
325                 char resultstr[256];
326                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, 
327                             resourcestr, 255);
328                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
329                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE, 
330                             resourcestr, 255);
331                 MessageBoxA(hDlg, resultstr, resourcestr,
332                             MB_OK | MB_ICONWARNING);
333                 return FALSE;
334             }
335             lppd->nFromPage = nFromPage;
336             lppd->nToPage   = nToPage;
337         }
338
339         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
340             lppd->Flags |= PD_PRINTTOFILE;
341             pi->pPortName = "FILE:";
342         }
343
344         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
345             FIXME("Collate lppd not yet implemented as output\n");
346         }
347
348         /* set PD_Collate and nCopies */
349         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
350           /*  The application doesn't support multiple copies or collate...
351            */
352             lppd->Flags &= ~PD_COLLATE;
353             lppd->nCopies = 1;
354           /* if the printer driver supports it... store info there
355            * otherwise no collate & multiple copies !
356            */
357             if (lpdm->dmFields & DM_COLLATE)
358                 lpdm->dmCollate = 
359                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
360             if (lpdm->dmFields & DM_COPIES)
361                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
362         } else {
363             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
364                 lppd->Flags |= PD_COLLATE;
365             else
366                lppd->Flags &= ~PD_COLLATE;
367             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
368         }
369     }
370     return TRUE;
371 }
372
373 static BOOL PRINTDLG_PaperSize(
374         PRINTDLGA       *pdlga,const char *PaperSize,LPPOINT size
375 ) {
376     DEVNAMES    *dn;
377     DEVMODEA    *dm;
378     LPSTR       devname,portname;
379     int         i;
380     INT         NrOfEntries,ret;
381     char        *Names = NULL;
382     POINT       *points = NULL;
383     BOOL        retval = FALSE;
384     
385     dn = GlobalLock(pdlga->hDevNames);
386     dm = GlobalLock(pdlga->hDevMode);
387     devname     = ((char*)dn)+dn->wDeviceOffset;
388     portname    = ((char*)dn)+dn->wOutputOffset;
389
390
391     NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
392     if (!NrOfEntries) {
393         FIXME("No papernames found for %s/%s\n",devname,portname);
394         goto out;
395     }
396     if (NrOfEntries == -1) {
397         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
398         goto out;
399     }
400             
401     Names = (char*)HeapAlloc(GetProcessHeap(),0,NrOfEntries*64);
402     if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,Names,dm))) {
403         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
404         goto out;
405     }
406     for (i=0;i<NrOfEntries;i++)
407         if (!strcmp(PaperSize,Names+(64*i)))
408             break;
409     HeapFree(GetProcessHeap(),0,Names);
410     if (i==NrOfEntries) {
411         FIXME("Papersize %s not found in list?\n",PaperSize);
412         goto out;
413     }
414     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
415     if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPBYTE)points,dm))) {
416         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
417         goto out;
418     }
419     /* this is _10ths_ of a millimeter */
420     size->x=points[i].x;
421     size->y=points[i].y;
422     FIXME("papersize is %ld x %ld\n",size->x,size->y);
423     retval = TRUE;
424 out:
425     GlobalUnlock(pdlga->hDevNames);
426     GlobalUnlock(pdlga->hDevMode);
427     if (Names) HeapFree(GetProcessHeap(),0,Names);
428     if (points) HeapFree(GetProcessHeap(),0,points);
429     return retval;
430 }
431
432
433 /************************************************************************
434  * PRINTDLG_SetUpPaperComboBox
435  *
436  * Initialize either the papersize or inputslot combos of the Printer Setup
437  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
438  * We also try to re-select the old selection.
439  */
440 static BOOL PRINTDLG_SetUpPaperComboBox(HWND hDlg,
441                                         int   nIDComboBox,
442                                         char* PrinterName, 
443                                         char* PortName,
444                                         LPDEVMODEA dm)
445 {
446     int     i;
447     DWORD   NrOfEntries;
448     char*   Names;
449     WORD*   Words;
450     DWORD   Sel;
451     WORD    oldWord = 0;
452     int     NamesSize;
453     int     fwCapability_Names;
454     int     fwCapability_Words;
455     
456     TRACE(" Printer: %s, ComboID: %d\n",PrinterName,nIDComboBox);
457     
458     /* query the dialog box for the current selected value */
459     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
460     if(Sel != CB_ERR) {
461         /* we enter here only if a different printer is selected after
462          * the Print Setup dialog is opened. The current settings are
463          * stored into the newly selected printer.
464          */
465         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
466                                       Sel, 0);
467         if (dm) {
468             if (nIDComboBox == cmb2)
469                 dm->u1.s1.dmPaperSize = oldWord;
470             else
471                 dm->dmDefaultSource = oldWord;
472         }
473     }
474     else {
475         /* we enter here only when the Print setup dialog is initially
476          * opened. In this case the settings are restored from when
477          * the dialog was last closed.
478          */
479         if (dm) {
480             if (nIDComboBox == cmb2)
481                 oldWord = dm->u1.s1.dmPaperSize;
482             else
483                 oldWord = dm->dmDefaultSource;
484         }
485     }
486
487     if (nIDComboBox == cmb2) {
488          NamesSize          = 64;
489          fwCapability_Names = DC_PAPERNAMES;
490          fwCapability_Words = DC_PAPERS;
491     } else {
492          nIDComboBox        = cmb3;
493          NamesSize          = 24;
494          fwCapability_Names = DC_BINNAMES;
495          fwCapability_Words = DC_BINS;
496     }
497     
498     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the 
499      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
500      */
501     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
502     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
503                                       fwCapability_Names, NULL, dm);
504     if (NrOfEntries == 0)
505          WARN("no Name Entries found!\n");
506
507     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
508        != NrOfEntries) {
509         ERR("Number of caps is different\n");
510         NrOfEntries = 0;
511     }
512
513     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*NamesSize);
514     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
515     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
516                                       fwCapability_Names, Names, dm);
517     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
518                                       fwCapability_Words, (LPSTR)Words, dm);
519
520     /* reset any current content in the combobox */
521     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
522     
523     /* store new content */
524     for (i = 0; i < NrOfEntries; i++) {
525         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
526                                         (LPARAM)(&Names[i*NamesSize]) );
527         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos, 
528                             Words[i]);
529     }
530
531     /* Look for old selection - can't do this is previous loop since
532        item order will change as more items are added */
533     Sel = 0;
534     for (i = 0; i < NrOfEntries; i++) {
535         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
536            oldWord) {
537             Sel = i;
538             break;
539         }
540     }
541     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
542
543     HeapFree(GetProcessHeap(),0,Words);
544     HeapFree(GetProcessHeap(),0,Names);
545     return TRUE;
546 }
547
548 /***********************************************************************
549  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
550  */
551 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, LPPRINTER_INFO_2A pi)
552 {
553     char   StatusMsg[256];
554     char   ResourceString[256];
555     int    i;
556
557     /* Status Message */
558     StatusMsg[0]='\0';
559
560     /* add all status messages */
561     for (i = 0; i < 25; i++) {
562         if (pi->Status & (1<<i)) {
563             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i, 
564                         ResourceString, 255);
565             strcat(StatusMsg,ResourceString);
566         }
567     }
568     /* append "ready" */
569     /* FIXME: status==ready must only be appended if really so. 
570               but how to detect? */
571     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY, 
572                 ResourceString, 255);
573     strcat(StatusMsg,ResourceString);
574   
575     SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
576
577     /* set all other printer info texts */
578     SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)pi->pDriverName);
579     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
580         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pLocation);
581     else
582         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pPortName);
583     SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)(pi->pComment ?
584                         pi->pComment : ""));
585     return;
586 }
587
588
589 /*******************************************************************
590  *
591  *                 PRINTDLG_ChangePrinter
592  *
593  */
594 static BOOL PRINTDLG_ChangePrinter(HWND hDlg, char *name,
595                                    PRINT_PTRA *PrintStructures)
596 {
597     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
598     LPDEVMODEA lpdm = NULL;
599     LONG dmSize;
600     DWORD needed;
601     HANDLE hprn;
602
603     if(PrintStructures->lpPrinterInfo)
604         HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
605     if(PrintStructures->lpDriverInfo)
606         HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
607     if(!OpenPrinterA(name, &hprn, NULL)) {
608         ERR("Can't open printer %s\n", name);
609         return FALSE;
610     }
611     GetPrinterA(hprn, 2, NULL, 0, &needed);
612     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
613     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
614                 &needed);
615     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
616     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
617     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
618             needed, &needed)) {
619         ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
620         return FALSE;
621     }
622     ClosePrinter(hprn);
623
624     PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures->lpPrinterInfo);
625
626     if(PrintStructures->lpDevMode) {
627         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
628         PrintStructures->lpDevMode = NULL;
629     }
630
631     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
632     if(dmSize == -1) {
633         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
634         return FALSE;
635     }
636     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
637     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
638                                  DM_OUT_BUFFER);
639     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
640                           !strcmp(lpdm->dmDeviceName,
641                                   PrintStructures->lpDevMode->dmDeviceName)) {
642       /* Supplied devicemode matches current printer so try to use it */
643         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
644                             DM_OUT_BUFFER | DM_IN_BUFFER);
645     }
646     if(lpdm)
647         GlobalUnlock(lppd->hDevMode);
648
649     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
650
651     if(!(lppd->Flags & PD_PRINTSETUP)) {
652       /* Print range (All/Range/Selection) */
653         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
654         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
655         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
656         if (lppd->Flags & PD_NOSELECTION)
657             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
658         else
659             if (lppd->Flags & PD_SELECTION)
660                 CheckRadioButton(hDlg, rad1, rad3, rad2);
661         if (lppd->Flags & PD_NOPAGENUMS) {
662             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
663             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
664             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
665             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
666             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
667         } else {
668             if (lppd->Flags & PD_PAGENUMS)
669                 CheckRadioButton(hDlg, rad1, rad3, rad3);
670         }
671         /* "All xxx pages"... */
672         {
673             char        resourcestr[64];
674             char        result[64];
675             LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, 
676                         resourcestr, 49);
677             sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
678             SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
679         }
680         
681         /* Collate pages 
682          *
683          * FIXME: The ico3 is not displayed for some reason. I don't know why.
684          */
685         if (lppd->Flags & PD_COLLATE) {
686             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
687                                 (LPARAM)PrintStructures->hCollateIcon);
688             CheckDlgButton(hDlg, chx2, 1);
689         } else {
690             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
691                                 (LPARAM)PrintStructures->hNoCollateIcon);
692             CheckDlgButton(hDlg, chx2, 0);
693         }
694
695         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
696           /* if printer doesn't support it: no Collate */
697             if (!(lpdm->dmFields & DM_COLLATE)) {
698                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);    
699                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);    
700             }
701         }
702
703         /* nCopies */
704         {
705           INT copies;
706           if (lppd->hDevMode == 0)
707               copies = lppd->nCopies;
708           else
709               copies = lpdm->dmCopies;
710           if(copies == 0) copies = 1;
711           else if(copies < 0) copies = MAX_COPIES;
712           SetDlgItemInt(hDlg, edt3, copies, FALSE);
713         }
714
715         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
716           /* if printer doesn't support it: no nCopies */
717             if (!(lpdm->dmFields & DM_COPIES)) {
718                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);    
719                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);    
720             }
721         }
722
723         /* print to file */
724         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
725         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
726             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);    
727         if (lppd->Flags & PD_HIDEPRINTTOFILE)
728             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
729
730     } else { /* PD_PRINTSETUP */
731       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
732
733       PRINTDLG_SetUpPaperComboBox(hDlg, cmb2,
734                                   PrintStructures->lpPrinterInfo->pPrinterName,
735                                   PrintStructures->lpPrinterInfo->pPortName,
736                                   lpdm);
737       PRINTDLG_SetUpPaperComboBox(hDlg, cmb3,
738                                   PrintStructures->lpPrinterInfo->pPrinterName,
739                                   PrintStructures->lpPrinterInfo->pPortName,
740                                   lpdm);
741       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
742       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
743                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
744                                    PrintStructures->hLandscapeIcon));
745       
746     }
747
748     /* help button */
749     if ((lppd->Flags & PD_SHOWHELP)==0) {
750         /* hide if PD_SHOWHELP not specified */
751         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);         
752     }
753     return TRUE;
754 }
755
756 /***********************************************************************
757  *           PRINTDLG_WMInitDialog                      [internal]
758  */
759 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
760                                      PRINT_PTRA* PrintStructures)
761 {
762     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
763     DEVNAMES *pdn;
764     DEVMODEA *pdm;
765     char *name = NULL;
766     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
767
768     /* load Collate ICONs */
769     /* We load these with LoadImage becasue they are not a standard
770        size and we don't want them rescaled */
771     PrintStructures->hCollateIcon =
772       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
773     PrintStructures->hNoCollateIcon = 
774       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
775
776     /* These can be done with LoadIcon */
777     PrintStructures->hPortraitIcon =
778       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
779     PrintStructures->hLandscapeIcon =
780       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
781
782     if(PrintStructures->hCollateIcon == 0 ||
783        PrintStructures->hNoCollateIcon == 0 ||
784        PrintStructures->hPortraitIcon == 0 ||
785        PrintStructures->hLandscapeIcon == 0) {
786         ERR("no icon in resourcefile\n");
787         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
788         EndDialog(hDlg, FALSE);
789     }
790
791     /*
792      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
793      * must be registered and the Help button must be shown.
794      */
795     if (lppd->Flags & PD_SHOWHELP) {
796         if((PrintStructures->HelpMessageID = 
797             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
798             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
799             return FALSE;
800         }
801     } else
802         PrintStructures->HelpMessageID = 0;
803
804     if(!(lppd->Flags &PD_PRINTSETUP)) {
805         PrintStructures->hwndUpDown =
806           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
807                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
808                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
809                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
810                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
811     }
812
813     /* FIXME: I allow more freedom than either Win95 or WinNT,
814      *        which do not agree to what errors should be thrown or not
815      *        in case nToPage or nFromPage is out-of-range.
816      */
817     if (lppd->nMaxPage < lppd->nMinPage)
818         lppd->nMaxPage = lppd->nMinPage;
819     if (lppd->nMinPage == lppd->nMaxPage) 
820         lppd->Flags |= PD_NOPAGENUMS;        
821     if (lppd->nToPage < lppd->nMinPage)
822         lppd->nToPage = lppd->nMinPage;
823     if (lppd->nToPage > lppd->nMaxPage)
824         lppd->nToPage = lppd->nMaxPage;
825     if (lppd->nFromPage < lppd->nMinPage)
826         lppd->nFromPage = lppd->nMinPage;
827     if (lppd->nFromPage > lppd->nMaxPage)
828         lppd->nFromPage = lppd->nMaxPage;
829
830     /* if we have the combo box, fill it */
831     if (GetDlgItem(hDlg,comboID)) {
832         /* Fill Combobox 
833          */
834         pdn = GlobalLock(lppd->hDevNames);
835         pdm = GlobalLock(lppd->hDevMode);
836         if(pdn)
837             name = (char*)pdn + pdn->wDeviceOffset;
838         else if(pdm)
839             name = pdm->dmDeviceName;
840         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
841         if(pdm) GlobalUnlock(lppd->hDevMode);
842         if(pdn) GlobalUnlock(lppd->hDevNames);
843
844         /* Now find selected printer and update rest of dlg */
845         name = HeapAlloc(GetProcessHeap(),0,256);
846         if (GetDlgItemTextA(hDlg, comboID, name, 255))
847             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
848         HeapFree(GetProcessHeap(),0,name);
849     } else {
850         /* else use default printer */
851         char name[200];
852         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
853
854         if (ret)
855             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
856         else
857             FIXME("No default printer found, expect problems!\n");
858     }
859     return TRUE;
860 }
861
862 /***********************************************************************
863  *           PRINTDLG_WMInitDialog                      [internal]
864  */
865 static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam,
866                                      PRINT_PTRA* PrintStructures)
867 {
868     LPPRINTDLG16 lppd = PrintStructures->dlg.lpPrintDlg16;
869     DEVNAMES *pdn;
870     DEVMODEA *pdm;
871     char *name = NULL;
872     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
873
874     /* load Collate ICONs */
875     PrintStructures->hCollateIcon =
876       LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
877     PrintStructures->hNoCollateIcon = 
878       LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
879     if(PrintStructures->hCollateIcon == 0 ||
880        PrintStructures->hNoCollateIcon == 0) {
881         ERR("no icon in resourcefile\n");
882         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
883         EndDialog(hDlg, FALSE);
884     }
885
886     /* load Paper Orientation ICON */
887     /* FIXME: not implemented yet */
888
889     /*
890      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
891      * must be registered and the Help button must be shown.
892      */
893     if (lppd->Flags & PD_SHOWHELP) {
894         if((PrintStructures->HelpMessageID = 
895             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
896             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
897             return FALSE;
898         }
899     } else
900         PrintStructures->HelpMessageID = 0;
901
902     if (!(lppd->Flags & PD_PRINTSETUP)) {
903         /* We have a print quality combo box. What shall we do? */
904         if (GetDlgItem(hDlg,cmb1)) {
905             char buf [20];
906
907             FIXME("Print quality only displaying currently.\n");
908
909             pdm = GlobalLock16(lppd->hDevMode);
910             if(pdm) {
911                 switch (pdm->dmPrintQuality) {
912                 case DMRES_HIGH         : strcpy(buf,"High");break;
913                 case DMRES_MEDIUM       : strcpy(buf,"Medium");break;
914                 case DMRES_LOW          : strcpy(buf,"Low");break;
915                 case DMRES_DRAFT        : strcpy(buf,"Draft");break;
916                 case 0                  : strcpy(buf,"Default");break;
917                 default                 : sprintf(buf,"%ddpi",pdm->dmPrintQuality);break;
918                 }
919                 GlobalUnlock16(lppd->hDevMode);
920             } else 
921                 strcpy(buf,"Default");
922             SendDlgItemMessageA(hDlg,cmb1,CB_ADDSTRING,0,(LPARAM)buf);
923             SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0);
924             EnableWindow(GetDlgItem(hDlg,cmb1),FALSE);
925         }
926     }
927
928     /* FIXME: I allow more freedom than either Win95 or WinNT,
929      *        which do not agree to what errors should be thrown or not
930      *        in case nToPage or nFromPage is out-of-range.
931      */
932     if (lppd->nMaxPage < lppd->nMinPage)
933         lppd->nMaxPage = lppd->nMinPage;
934     if (lppd->nMinPage == lppd->nMaxPage) 
935         lppd->Flags |= PD_NOPAGENUMS;        
936     if (lppd->nToPage < lppd->nMinPage)
937         lppd->nToPage = lppd->nMinPage;
938     if (lppd->nToPage > lppd->nMaxPage)
939         lppd->nToPage = lppd->nMaxPage;
940     if (lppd->nFromPage < lppd->nMinPage)
941         lppd->nFromPage = lppd->nMinPage;
942     if (lppd->nFromPage > lppd->nMaxPage)
943         lppd->nFromPage = lppd->nMaxPage;
944
945     /* If the printer combo box is in the dialog, fill it */
946     if (GetDlgItem(hDlg,comboID)) {
947         /* Fill Combobox 
948          */
949         pdn = GlobalLock16(lppd->hDevNames);
950         pdm = GlobalLock16(lppd->hDevMode);
951         if(pdn)
952             name = (char*)pdn + pdn->wDeviceOffset;
953         else if(pdm)
954             name = pdm->dmDeviceName;
955         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
956         if(pdm) GlobalUnlock16(lppd->hDevMode);
957         if(pdn) GlobalUnlock16(lppd->hDevNames);
958
959         /* Now find selected printer and update rest of dlg */
960         name = HeapAlloc(GetProcessHeap(),0,256);
961         if (GetDlgItemTextA(hDlg, comboID, name, 255))
962             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
963     } else {
964         /* else just use default printer */
965         char name[200];
966         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
967
968         if (ret)
969             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
970         else
971             FIXME("No default printer found, expect problems!\n");
972     }
973     HeapFree(GetProcessHeap(),0,name);
974
975     return TRUE;
976 }
977
978 /***********************************************************************
979  *                              PRINTDLG_WMCommand               [internal]
980  */
981 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam, 
982                         LPARAM lParam, PRINT_PTRA* PrintStructures)
983 {
984     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
985     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
986     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
987
988     switch (LOWORD(wParam))  {
989     case IDOK:
990         TRACE(" OK button was hit\n");
991         if (PRINTDLG_UpdatePrintDlg(hDlg, PrintStructures)!=TRUE) {
992             FIXME("Update printdlg was not successful!\n");
993             return(FALSE);
994         }
995         EndDialog(hDlg, TRUE);
996         return(TRUE);
997
998     case IDCANCEL:
999         TRACE(" CANCEL button was hit\n");
1000         EndDialog(hDlg, FALSE);
1001         return(FALSE);
1002
1003      case pshHelp:
1004         TRACE(" HELP button was hit\n");
1005         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID, 
1006                                 (WPARAM) hDlg, (LPARAM) lppd);
1007         break;
1008
1009      case chx2:                         /* collate pages checkbox */
1010         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1011             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
1012                                     (LPARAM)PrintStructures->hCollateIcon);
1013         else
1014             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
1015                                     (LPARAM)PrintStructures->hNoCollateIcon);
1016         break;        
1017      case edt1:                         /* from page nr editbox */
1018      case edt2:                         /* to page nr editbox */
1019         if (HIWORD(wParam)==EN_CHANGE) {
1020             WORD nToPage;
1021             WORD nFromPage;
1022             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1023             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1024             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1025                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1026         }
1027         break;
1028
1029     case edt3:
1030         if(HIWORD(wParam) == EN_CHANGE) {
1031             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1032             if(copies <= 1)
1033                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1034             else
1035                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1036         }
1037         break;
1038
1039      case psh1:                       /* Print Setup */
1040         {
1041             PRINTDLG16  pdlg;
1042             
1043             if (!PrintStructures->dlg.lpPrintDlg16) {
1044                 FIXME("The 32bit print dialog does not have this button!?\n");
1045                 break;
1046             }
1047
1048             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1049             pdlg.Flags |= PD_PRINTSETUP;
1050             pdlg.hwndOwner = hDlg;
1051             if (!PrintDlg16(&pdlg))
1052                 break;
1053         }
1054         break;
1055      case psh2:                       /* Properties button */
1056        {
1057          HANDLE hPrinter;
1058          char   PrinterName[256];
1059
1060          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1061          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1062              FIXME(" Call to OpenPrinter did not succeed!\n");
1063              break;
1064          }
1065          DocumentPropertiesA(hDlg, hPrinter, PrinterName, 
1066                              PrintStructures->lpDevMode,
1067                              PrintStructures->lpDevMode,
1068                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1069          ClosePrinter(hPrinter);
1070          break;
1071        }
1072
1073     case rad1: /* Paperorientation */
1074         if (lppd->Flags & PD_PRINTSETUP)
1075         {
1076               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1077               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1078                           (LPARAM)(PrintStructures->hPortraitIcon));
1079         }
1080         break;
1081             
1082     case rad2: /* Paperorientation */
1083         if (lppd->Flags & PD_PRINTSETUP)
1084         {
1085               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1086               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1087                           (LPARAM)(PrintStructures->hLandscapeIcon));
1088         }
1089         break;
1090             
1091     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1092          if (PrinterComboID != wParam) {
1093              FIXME("No handling for print quality combo box yet.\n");
1094              break;
1095          }
1096          /* FALLTHROUGH */
1097     case cmb4:                         /* Printer combobox */
1098          if (HIWORD(wParam)==CBN_SELCHANGE) {
1099              char   PrinterName[256];
1100              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1101              PRINTDLG_ChangePrinter(hDlg, PrinterName, PrintStructures);
1102          }
1103          break;
1104
1105     case cmb2: /* Papersize */
1106       {
1107           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1108           if(Sel != CB_ERR)
1109               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1110                                                             CB_GETITEMDATA,
1111                                                             Sel, 0);
1112       }
1113       break;
1114
1115     case cmb3: /* Bin */
1116       {
1117           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1118           if(Sel != CB_ERR)
1119               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1120                                                           CB_GETITEMDATA, Sel,
1121                                                           0);
1122       }
1123       break; 
1124     }
1125     if(lppd->Flags & PD_PRINTSETUP) {
1126         switch (LOWORD(wParam)) {
1127         case rad1:                         /* orientation */
1128         case rad2:
1129             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1130                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1131                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1132                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1133                                         (WPARAM)IMAGE_ICON,
1134                                         (LPARAM)PrintStructures->hPortraitIcon);
1135                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1136                                         (WPARAM)IMAGE_ICON,
1137                                         (LPARAM)PrintStructures->hPortraitIcon);
1138                 }
1139             } else {
1140                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1141                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1142                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1143                                         (WPARAM)IMAGE_ICON,
1144                                         (LPARAM)PrintStructures->hLandscapeIcon);
1145                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1146                                         (WPARAM)IMAGE_ICON,
1147                                         (LPARAM)PrintStructures->hLandscapeIcon);
1148                 }
1149             }
1150             break;
1151         }
1152     }
1153     return FALSE;
1154 }    
1155
1156 /***********************************************************************
1157  *           PrintDlgProcA                      [internal]
1158  */
1159 BOOL WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1160                           LPARAM lParam)
1161 {
1162     PRINT_PTRA* PrintStructures;
1163     LRESULT res=FALSE;
1164
1165     if (uMsg!=WM_INITDIALOG) {
1166         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
1167         if (!PrintStructures)
1168             return FALSE;
1169     } else {
1170         PrintStructures = (PRINT_PTRA*) lParam;
1171         SetWindowLongA(hDlg, DWL_USER, lParam); 
1172         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1173
1174         if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1175             res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(
1176                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg
1177             ); 
1178         return res;
1179     }
1180   
1181     if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1182         res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1183                                                          lParam);
1184         if(res) return res;
1185     }
1186
1187     switch (uMsg) {
1188     case WM_COMMAND:
1189         return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
1190
1191     case WM_DESTROY:
1192         DestroyIcon(PrintStructures->hCollateIcon);
1193         DestroyIcon(PrintStructures->hNoCollateIcon);
1194         DestroyIcon(PrintStructures->hPortraitIcon);
1195         DestroyIcon(PrintStructures->hLandscapeIcon);
1196         if(PrintStructures->hwndUpDown)
1197             DestroyWindow(PrintStructures->hwndUpDown);
1198         return FALSE;
1199     }    
1200     return res;
1201 }
1202
1203
1204 /************************************************************
1205  *
1206  *      PRINTDLG_Get16TemplateFrom32             [Internal]
1207  *      Generates a 16 bits template from the Wine 32 bits resource
1208  *
1209  */
1210 static HGLOBAL16 PRINTDLG_Get16TemplateFrom32(char *PrintResourceName)
1211 {
1212         HANDLE hResInfo, hDlgTmpl32;
1213         LPCVOID template32;
1214         DWORD size;
1215         HGLOBAL16 hGlobal16;
1216         LPVOID template;
1217  
1218         if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
1219                PrintResourceName, RT_DIALOGA)))
1220         {
1221             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
1222             return 0;
1223         }
1224         if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
1225             !(template32 = LockResource( hDlgTmpl32 )))
1226         {
1227             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1228             return 0;
1229         }
1230         size = SizeofResource(COMMDLG_hInstance32, hResInfo);
1231         hGlobal16 = GlobalAlloc16(0, size);
1232         if (!hGlobal16)
1233         {
1234             COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
1235             ERR("alloc failure for %ld bytes\n", size);
1236             return 0;
1237         }
1238         template = GlobalLock16(hGlobal16);
1239         if (!template)
1240         {
1241             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
1242             ERR("global lock failure for %x handle\n", hGlobal16);
1243             GlobalFree16(hGlobal16);
1244             return 0;
1245         }
1246         ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
1247         GlobalUnlock16(hGlobal16);
1248         return hGlobal16;
1249 }
1250
1251 /************************************************************
1252  *
1253  *      PRINTDLG_GetDlgTemplate
1254  *
1255  */
1256 static HGLOBAL PRINTDLG_GetDlgTemplate(PRINTDLGA *lppd)
1257 {
1258     HGLOBAL hDlgTmpl, hResInfo;
1259
1260     if (lppd->Flags & PD_PRINTSETUP) {
1261         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1262             hDlgTmpl = lppd->hSetupTemplate;
1263         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1264             hResInfo = FindResourceA(lppd->hInstance,
1265                                      lppd->lpSetupTemplateName, RT_DIALOGA);
1266             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1267         } else {
1268             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1269                                      RT_DIALOGA);
1270             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1271         }
1272     } else {
1273         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1274             hDlgTmpl = lppd->hPrintTemplate;
1275         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1276             hResInfo = FindResourceA(lppd->hInstance,
1277                                      lppd->lpPrintTemplateName,
1278                                      RT_DIALOGA);
1279             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1280         } else {
1281             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1282                                      RT_DIALOGA);
1283             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1284         }
1285     }
1286     return hDlgTmpl;
1287 }
1288
1289
1290 /************************************************************
1291  *
1292  *      PRINTDLG_GetDlgTemplate
1293  *
1294  */
1295 static HGLOBAL16 PRINTDLG_GetDlgTemplate16(PRINTDLG16 *lppd)
1296 {
1297     HGLOBAL16 hDlgTmpl, hResInfo;
1298
1299     if (lppd->Flags & PD_PRINTSETUP) {
1300         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1301             hDlgTmpl = lppd->hSetupTemplate;
1302         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1303             hResInfo = FindResource16(lppd->hInstance,
1304                                      MapSL(lppd->lpSetupTemplateName), RT_DIALOGA);
1305             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1306         } else {
1307             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
1308         }
1309     } else {
1310         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1311             hDlgTmpl = lppd->hPrintTemplate;
1312         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1313             hResInfo = FindResource16(lppd->hInstance,
1314                                      MapSL(lppd->lpPrintTemplateName),
1315                                      RT_DIALOGA);
1316             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1317         } else {
1318             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32");
1319         }
1320     }
1321     return hDlgTmpl;
1322 }
1323
1324 /***********************************************************************
1325  *
1326  *      PRINTDLG_CreateDC
1327  *
1328  */
1329 static BOOL PRINTDLG_CreateDC(LPPRINTDLGA lppd)
1330 {
1331     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1332     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1333
1334     if(lppd->Flags & PD_RETURNDC) {
1335         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1336                               (char*)pdn + pdn->wDeviceOffset,
1337                               (char*)pdn + pdn->wOutputOffset,
1338                               pdm );
1339     } else if(lppd->Flags & PD_RETURNIC) {
1340         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1341                               (char*)pdn + pdn->wDeviceOffset,
1342                               (char*)pdn + pdn->wOutputOffset,
1343                               pdm );
1344     }
1345     GlobalUnlock(lppd->hDevNames);
1346     GlobalUnlock(lppd->hDevMode);
1347     return lppd->hDC ? TRUE : FALSE;
1348 }
1349
1350 static BOOL PRINTDLG_CreateDC16(LPPRINTDLG16 lppd)
1351 {
1352     DEVNAMES *pdn = GlobalLock16(lppd->hDevNames);
1353     DEVMODEA *pdm = GlobalLock16(lppd->hDevMode);
1354
1355     if(lppd->Flags & PD_RETURNDC) {
1356         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1357                               (char*)pdn + pdn->wDeviceOffset,
1358                               (char*)pdn + pdn->wOutputOffset,
1359                               pdm );
1360     } else if(lppd->Flags & PD_RETURNIC) {
1361         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1362                               (char*)pdn + pdn->wDeviceOffset,
1363                               (char*)pdn + pdn->wOutputOffset,
1364                               pdm );
1365     }
1366     GlobalUnlock16(lppd->hDevNames);
1367     GlobalUnlock16(lppd->hDevMode);
1368     return lppd->hDC ? TRUE : FALSE;
1369 }
1370
1371 /***********************************************************************
1372  *           PrintDlgA   (COMDLG32.@)
1373  *
1374  *  Displays the the PRINT dialog box, which enables the user to specify
1375  *  specific properties of the print job.
1376  *
1377  * RETURNS
1378  *  nonzero if the user pressed the OK button
1379  *  zero    if the user cancelled the window or an error occurred
1380  *
1381  * BUGS
1382  *  PrintDlg:
1383  *  * The Collate Icons do not display, even though they are in the code.
1384  *  * The Properties Button(s) should call DocumentPropertiesA().
1385  *  PrintSetupDlg:
1386  *  * The Paper Orientation Icons are not implemented yet.
1387  *  * The Properties Button(s) should call DocumentPropertiesA().
1388  *  * Settings are not yet taken from a provided DevMode or 
1389  *    default printer settings.
1390  */
1391 BOOL WINAPI PrintDlgA(
1392                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1393                       )
1394 {
1395     BOOL      bRet = FALSE;
1396     LPVOID   ptr;
1397     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1398
1399     if(TRACE_ON(commdlg)) {
1400         char flagstr[1000] = "";
1401         struct pd_flags *pflag = pd_flags;
1402         for( ; pflag->name; pflag++) {
1403             if(lppd->Flags & pflag->flag)
1404                 strcat(flagstr, pflag->name);
1405         }
1406         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1407               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1408               "flags %08lx (%s)\n",
1409               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1410               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1411               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1412     }
1413
1414     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1415         WARN("structure size failure !!!\n");
1416         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1417         return FALSE; 
1418     }
1419
1420     if(lppd->Flags & PD_RETURNDEFAULT) {
1421         PRINTER_INFO_2A *pbuf;
1422         DRIVER_INFO_3A  *dbuf;
1423         HANDLE hprn;
1424         DWORD needed;
1425
1426         if(lppd->hDevMode || lppd->hDevNames) {
1427             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1428             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1429             return FALSE;
1430         }
1431         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1432             WARN("Can't find default printer\n");
1433             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1434             return FALSE;
1435         }
1436
1437         GetPrinterA(hprn, 2, NULL, 0, &needed);
1438         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1439         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1440
1441         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1442         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
1443         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
1444             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
1445             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1446             return FALSE;
1447         }
1448         ClosePrinter(hprn);
1449
1450         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
1451                                   dbuf->pDriverPath,
1452                                   pbuf->pPrinterName,
1453                                   pbuf->pPortName);
1454         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
1455                                      pbuf->pDevMode->dmDriverExtra);
1456         ptr = GlobalLock(lppd->hDevMode);
1457         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1458                pbuf->pDevMode->dmDriverExtra);
1459         GlobalUnlock(lppd->hDevMode);
1460         HeapFree(GetProcessHeap(), 0, pbuf);
1461         HeapFree(GetProcessHeap(), 0, dbuf);
1462         bRet = TRUE;
1463     } else {
1464         HGLOBAL hDlgTmpl;
1465         PRINT_PTRA *PrintStructures;
1466
1467     /* load Dialog resources, 
1468      * depending on Flags indicates Print32 or Print32_setup dialog 
1469      */
1470         hDlgTmpl = PRINTDLG_GetDlgTemplate(lppd);
1471         if (!hDlgTmpl) {
1472             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1473             return FALSE;
1474         }
1475         ptr = LockResource( hDlgTmpl );
1476         if (!ptr) {
1477             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1478             return FALSE;
1479         }
1480
1481         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1482                                     sizeof(PRINT_PTRA));
1483         PrintStructures->dlg.lpPrintDlg = lppd;
1484
1485         /* and create & process the dialog .
1486          * -1 is failure, 0 is broken hwnd, everything else is ok.
1487          */
1488         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
1489                                            PrintDlgProcA,
1490                                            (LPARAM)PrintStructures));
1491
1492         if(bRet) {
1493             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1494             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1495             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
1496
1497             if (lppd->hDevMode == 0) {
1498                 TRACE(" No hDevMode yet... Need to create my own\n");
1499                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
1500                                         lpdm->dmSize + lpdm->dmDriverExtra);
1501             } else {
1502                 WORD locks;
1503                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
1504                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1505                     while(locks--) {
1506                         GlobalUnlock(lppd->hDevMode);
1507                         TRACE("Now got %d locks\n", locks);
1508                     }
1509                 }
1510                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
1511                                                lpdm->dmSize + lpdm->dmDriverExtra,
1512                                                GMEM_MOVEABLE);
1513             }
1514             lpdmReturn = GlobalLock(lppd->hDevMode);
1515             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1516
1517             if (lppd->hDevNames != 0) {
1518                 WORD locks;
1519                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
1520                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1521                     while(locks--)
1522                         GlobalUnlock(lppd->hDevNames);
1523                 }
1524             }
1525             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
1526                     di->pDriverPath,
1527                     pi->pPrinterName,
1528                     pi->pPortName
1529             );
1530             GlobalUnlock(lppd->hDevMode);
1531         }
1532         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1533         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1534         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
1535         HeapFree(GetProcessHeap(), 0, PrintStructures);
1536     }
1537     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1538         bRet = PRINTDLG_CreateDC(lppd);
1539
1540     TRACE("exit! (%d)\n", bRet);        
1541     return bRet;    
1542 }
1543
1544 /***********************************************************************
1545  *           PrintDlg   (COMMDLG.20)
1546  * 
1547  *  Displays the the PRINT dialog box, which enables the user to specify
1548  *  specific properties of the print job.
1549  *
1550  * RETURNS
1551  *  nonzero if the user pressed the OK button
1552  *  zero    if the user cancelled the window or an error occurred
1553  *
1554  * BUGS
1555  *  * calls up to the 32-bit versions of the Dialogs, which look different
1556  *  * Customizing is *not* implemented.
1557  */
1558
1559 BOOL16 WINAPI PrintDlg16(
1560               LPPRINTDLG16 lppd /* [in/out] ptr to PRINTDLG struct */
1561 ) {
1562     BOOL      bRet = FALSE;
1563     LPVOID   ptr;
1564     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1565
1566     if(TRACE_ON(commdlg)) {
1567         char flagstr[1000] = "";
1568         struct pd_flags *pflag = pd_flags;
1569         for( ; pflag->name; pflag++) {
1570             if(lppd->Flags & pflag->flag)
1571                 strcat(flagstr, pflag->name);
1572         }
1573         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1574               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1575               "flags %08lx (%s)\n",
1576               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1577               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1578               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1579     }
1580
1581     if(lppd->lStructSize != sizeof(PRINTDLG16)) {
1582         ERR("structure size (%ld/%d)\n",lppd->lStructSize,sizeof(PRINTDLG16));
1583         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1584         return FALSE;
1585     }
1586
1587     if(lppd->Flags & PD_RETURNDEFAULT) {
1588         PRINTER_INFO_2A *pbuf;
1589         DRIVER_INFO_3A  *dbuf;
1590         HANDLE hprn;
1591         DWORD needed;
1592
1593         if(lppd->hDevMode || lppd->hDevNames) {
1594             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1595             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1596             return FALSE;
1597         }
1598         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1599             WARN("Can't find default printer\n");
1600             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1601             return FALSE;
1602         }
1603
1604         GetPrinterA(hprn, 2, NULL, 0, &needed);
1605         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1606         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1607         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1608         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
1609         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
1610             ERR("GetPrinterDriverA failed for %s, le %ld, fix your config!\n",
1611                     pbuf->pPrinterName,GetLastError());
1612             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1613             return FALSE;
1614         }
1615         ClosePrinter(hprn);
1616         PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
1617                                 dbuf->pDriverPath,
1618                                 pbuf->pPrinterName,
1619                                 pbuf->pPortName);
1620         lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,pbuf->pDevMode->dmSize+
1621                                      pbuf->pDevMode->dmDriverExtra);
1622         ptr = GlobalLock16(lppd->hDevMode);
1623         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1624                pbuf->pDevMode->dmDriverExtra);
1625         GlobalUnlock16(lppd->hDevMode);
1626         HeapFree(GetProcessHeap(), 0, pbuf);
1627         HeapFree(GetProcessHeap(), 0, dbuf);
1628         bRet = TRUE;
1629     } else {
1630         HGLOBAL hDlgTmpl;
1631         PRINT_PTRA *PrintStructures;
1632
1633     /* load Dialog resources, 
1634      * depending on Flags indicates Print32 or Print32_setup dialog 
1635      */
1636         hDlgTmpl = PRINTDLG_GetDlgTemplate16(lppd);
1637         if (!hDlgTmpl) {
1638             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1639             return FALSE;
1640         }
1641         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1642                                     sizeof(PRINT_PTRA));
1643         PrintStructures->dlg.lpPrintDlg16 = lppd;
1644         PrintStructures->dlg.lpPrintDlg = (LPPRINTDLGA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PRINTDLGA));
1645 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
1646 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
1647         CVAL(Flags);CVAL(hwndOwner);CVAL(hDC);
1648         CVAL(nFromPage);CVAL(nToPage);CVAL(nMinPage);CVAL(nMaxPage);
1649         CVAL(nCopies);CVAL(hInstance);CVAL(lCustData);
1650         MVAL(lpPrintTemplateName);MVAL(lpSetupTemplateName);
1651         /* Don't copy rest, it is 16 bit specific */
1652 #undef MVAL
1653 #undef CVAL
1654
1655         PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA));
1656
1657         /* and create & process the dialog .
1658          * -1 is failure, 0 is broken hwnd, everything else is ok.
1659          */
1660         bRet =  (0<DialogBoxIndirectParam16(
1661                  hInst, hDlgTmpl, lppd->hwndOwner,
1662                  (DLGPROC16)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR)21),
1663                  (LPARAM)PrintStructures
1664                 )
1665         );
1666         if (!PrintStructures->lpPrinterInfo) bRet = FALSE;
1667         if(bRet) {
1668             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1669             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1670             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
1671
1672             if (lppd->hDevMode == 0) {
1673                 TRACE(" No hDevMode yet... Need to create my own\n");
1674                 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,
1675                                         lpdm->dmSize + lpdm->dmDriverExtra);
1676             } else {
1677                 WORD locks;
1678                 if((locks = (GlobalFlags16(lppd->hDevMode)&GMEM_LOCKCOUNT))) {
1679                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1680                     while(locks--) {
1681                         GlobalUnlock16(lppd->hDevMode);
1682                         TRACE("Now got %d locks\n", locks);
1683                     }
1684                 }
1685                 lppd->hDevMode = GlobalReAlloc16(lppd->hDevMode,
1686                                                lpdm->dmSize + lpdm->dmDriverExtra,
1687                                                GMEM_MOVEABLE);
1688             }
1689             lpdmReturn = GlobalLock16(lppd->hDevMode);
1690             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1691
1692             if (lppd->hDevNames != 0) {
1693                 WORD locks;
1694                 if((locks = (GlobalFlags16(lppd->hDevNames)&GMEM_LOCKCOUNT))) {
1695                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1696                     while(locks--)
1697                         GlobalUnlock16(lppd->hDevNames);
1698                 }
1699             }
1700             PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
1701                     di->pDriverPath,
1702                     pi->pPrinterName,
1703                     pi->pPortName
1704             );
1705             GlobalUnlock16(lppd->hDevMode);
1706         }
1707         if (!(lppd->Flags & (PD_ENABLESETUPTEMPLATEHANDLE | PD_ENABLESETUPTEMPLATE)))
1708             GlobalFree16(hDlgTmpl); /* created from the 32 bits resource */
1709         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1710         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1711         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
1712         HeapFree(GetProcessHeap(), 0, PrintStructures);
1713     }
1714     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1715         bRet = PRINTDLG_CreateDC16(lppd);
1716
1717     TRACE("exit! (%d)\n", bRet);        
1718     return bRet;    
1719 }
1720
1721
1722
1723 /***********************************************************************
1724  *           PrintDlgW   (COMDLG32.@)
1725  */
1726 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
1727 {
1728     FIXME("A really empty stub\n" );
1729     return FALSE;
1730 }
1731
1732 /***********************************************************************
1733  *
1734  *          PageSetupDlg
1735  * rad1 - portrait
1736  * rad2 - landscape
1737  * cmb2 - paper size
1738  * cmb3 - source (tray?)
1739  * edt4 - border left
1740  * edt5 - border top
1741  * edt6 - border right
1742  * edt7 - border bottom
1743  * psh3 - "Printer..."
1744  */
1745
1746 typedef struct {
1747     LPPAGESETUPDLGA     dlga;
1748
1749     PRINTDLGA           pdlg;
1750 } PageSetupData;
1751
1752 static HGLOBAL PRINTDLG_GetPGSTemplate(PAGESETUPDLGA *lppd)
1753 {
1754     HGLOBAL hDlgTmpl, hResInfo;
1755
1756     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
1757         hDlgTmpl = lppd->hPageSetupTemplate;
1758     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {      
1759         hResInfo = FindResourceA(lppd->hInstance,
1760                                  lppd->lpPageSetupTemplateName, RT_DIALOGA);
1761         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1762     } else {
1763         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,RT_DIALOGA);
1764         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
1765     }
1766     return hDlgTmpl;
1767 }
1768
1769 static DWORD
1770 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
1771     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1772         return 10*size*10/25.4;
1773     /* If we don't have a flag, we can choose one. Use millimeters
1774      * to avoid confusing me
1775      */
1776     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1777     FIXME("returning %ld/100 mm \n",size);
1778     return 10*size;
1779 }
1780
1781
1782 static DWORD
1783 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
1784     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1785         return size;
1786     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
1787         return (size*254)/10;
1788     /* if we don't have a flag, we can choose one. Use millimeters
1789      * to avoid confusing me
1790      */
1791     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1792     return (size*254)/10;
1793 }
1794
1795 static void
1796 _c_size2str(PageSetupData *pda,DWORD size,LPSTR strout) {
1797     strcpy(strout,"<undef>");
1798     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
1799         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
1800         return;
1801     }
1802     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
1803         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
1804         return;
1805     }
1806     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1807     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
1808     return;
1809 }
1810
1811 static DWORD
1812 _c_str2size(PageSetupData *pda,LPCSTR strin) {
1813     float       val;
1814     char        rest[200];
1815
1816     rest[0]='\0';
1817     if (!sscanf(strin,"%f%s",&val,rest))
1818         return 0;
1819
1820     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
1821         if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1822             return 1000*val;
1823         else
1824             return val*25.4*100;
1825     }
1826     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
1827     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
1828
1829     if (!strcmp(rest,"mm")) {
1830         if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
1831             return 100*val;
1832         else
1833             return 1000.0*val/25.4;
1834     }
1835     if (rest[0]=='\0') {
1836         /* use application supplied default */
1837         if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
1838             /* 100*mm */
1839             return 100.0*val;
1840         }
1841         if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
1842             /* 1000*inch */
1843             return 1000.0*val;
1844         }
1845     }
1846     ERR("Did not find a conversion for type '%s'!\n",rest);
1847     return 0;
1848 }
1849
1850
1851 /*
1852  * This is called on finish and will update the output fields of the
1853  * struct.
1854  */
1855 static BOOL
1856 PRINTDLG_PS_UpdateDlgStruct(HWND hDlg, PageSetupData *pda) {
1857     DEVNAMES    *dn;
1858     DEVMODEA    *dm;
1859     LPSTR       devname,portname;
1860     char        papername[64];
1861     char        buf[200];
1862     
1863     dn = GlobalLock(pda->pdlg.hDevNames);
1864     dm = GlobalLock(pda->pdlg.hDevMode);
1865     devname     = ((char*)dn)+dn->wDeviceOffset;
1866     portname    = ((char*)dn)+dn->wOutputOffset;
1867     PRINTDLG_SetUpPaperComboBox(hDlg,cmb2,devname,portname,dm);
1868     PRINTDLG_SetUpPaperComboBox(hDlg,cmb3,devname,portname,dm);
1869
1870     if (GetDlgItemTextA(hDlg,cmb2,papername,sizeof(papername))>0) {
1871         PRINTDLG_PaperSize(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
1872         pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.x);
1873         pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.y);
1874     } else
1875         FIXME("could not get dialog text for papersize cmbbox?\n");
1876 #define GETVAL(id,val) if (GetDlgItemTextA(hDlg,id,buf,sizeof(buf))>0) { val = _c_str2size(pda,buf); } else { FIXME("could not get dlgitemtexta for %x\n",id); }
1877     GETVAL(edt4,pda->dlga->rtMargin.left);
1878     GETVAL(edt5,pda->dlga->rtMargin.top);
1879     GETVAL(edt6,pda->dlga->rtMargin.right);
1880     GETVAL(edt7,pda->dlga->rtMargin.bottom);
1881 #undef GETVAL
1882
1883     /* If we are in landscape, swap x and y of page size */
1884     if (IsDlgButtonChecked(hDlg, rad2)) {
1885         DWORD tmp;
1886         tmp = pda->dlga->ptPaperSize.x;
1887         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
1888         pda->dlga->ptPaperSize.y = tmp;
1889     }
1890     GlobalUnlock(pda->pdlg.hDevNames);
1891     GlobalUnlock(pda->pdlg.hDevMode);
1892     return TRUE;
1893 }
1894
1895 /*
1896  * This is called after returning from PrintDlg().
1897  */
1898 static BOOL
1899 PRINTDLG_PS_ChangePrinter(HWND hDlg, PageSetupData *pda) {
1900     DEVNAMES    *dn;
1901     DEVMODEA    *dm;
1902     LPSTR       devname,portname;
1903     
1904     dn = GlobalLock(pda->pdlg.hDevNames);
1905     dm = GlobalLock(pda->pdlg.hDevMode);
1906     devname     = ((char*)dn)+dn->wDeviceOffset;
1907     portname    = ((char*)dn)+dn->wOutputOffset;
1908     PRINTDLG_SetUpPaperComboBox(hDlg,cmb2,devname,portname,dm);
1909     PRINTDLG_SetUpPaperComboBox(hDlg,cmb3,devname,portname,dm);
1910     GlobalUnlock(pda->pdlg.hDevNames);
1911     GlobalUnlock(pda->pdlg.hDevMode);
1912     return TRUE;
1913 }
1914
1915 static BOOL
1916 PRINTDLG_PS_WMCommand(
1917     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupData *pda
1918 ) {
1919     switch (LOWORD(wParam))  {
1920     case IDOK:
1921         if (!PRINTDLG_PS_UpdateDlgStruct(hDlg, pda))
1922             return(FALSE);
1923         EndDialog(hDlg, TRUE);
1924         return TRUE ;
1925
1926     case IDCANCEL:
1927         EndDialog(hDlg, FALSE);
1928         return FALSE ;
1929
1930     case psh3: {
1931         pda->pdlg.Flags         = 0;
1932         pda->pdlg.hwndOwner     = hDlg;
1933         if (PrintDlgA(&(pda->pdlg)))
1934             PRINTDLG_PS_ChangePrinter(hDlg,pda);
1935         return TRUE;
1936     }
1937     }
1938     FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n",
1939             LOWORD(lParam),wParam,lParam
1940     );
1941     return FALSE;
1942 }
1943
1944
1945 static BOOL WINAPI
1946 PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1947 {
1948     PageSetupData       *pda;
1949     BOOL                res = FALSE;
1950
1951     if (uMsg==WM_INITDIALOG) {
1952         res = TRUE;
1953         pda = (PageSetupData*)lParam;
1954         SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",lParam);
1955         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
1956             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
1957             if (!res) {
1958                 FIXME("Setup page hook failed?\n");
1959                 res = TRUE;
1960             }
1961         }
1962         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
1963             FIXME("PagePaintHook not yet implemented!\n");
1964         }
1965         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
1966             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);    
1967         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
1968             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);    
1969             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);    
1970             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);    
1971             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);    
1972         }
1973         /* width larger as height -> landscape */
1974         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
1975             CheckRadioButton(hDlg, rad1, rad2, rad2);
1976         else /* this is default if papersize is not set */
1977             CheckRadioButton(hDlg, rad1, rad2, rad1);
1978         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
1979             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
1980             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
1981         }
1982         /* We fill them out enabled or not */
1983         if (pda->dlga->Flags & PSD_MARGINS) {
1984             char str[100];
1985             _c_size2str(pda,pda->dlga->rtMargin.left,str);
1986             SetDlgItemTextA(hDlg,edt4,str);
1987             _c_size2str(pda,pda->dlga->rtMargin.top,str);
1988             SetDlgItemTextA(hDlg,edt5,str);
1989             _c_size2str(pda,pda->dlga->rtMargin.right,str);
1990             SetDlgItemTextA(hDlg,edt6,str);
1991             _c_size2str(pda,pda->dlga->rtMargin.bottom,str);
1992             SetDlgItemTextA(hDlg,edt7,str);
1993         } else {
1994             /* default is 1 inch */
1995             DWORD size = _c_inch2size(pda->dlga,1000);
1996             char        str[20];
1997             _c_size2str(pda,size,str);
1998             SetDlgItemTextA(hDlg,edt4,str);
1999             SetDlgItemTextA(hDlg,edt5,str);
2000             SetDlgItemTextA(hDlg,edt6,str);
2001             SetDlgItemTextA(hDlg,edt7,str);
2002         }
2003         PRINTDLG_PS_ChangePrinter(hDlg,pda);
2004         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2005             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2006             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2007         }
2008         return TRUE;
2009     } else {
2010         pda = (PageSetupData*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2011         if (!pda) {
2012             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2013             return FALSE;
2014         }
2015         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2016             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2017             if (res) return res;
2018         }
2019     }
2020     switch (uMsg) {
2021     case WM_COMMAND:
2022         return PRINTDLG_PS_WMCommand(hDlg, wParam, lParam, pda);
2023     }
2024     return FALSE;
2025 }
2026
2027 /***********************************************************************
2028  *            PageSetupDlgA  (COMDLG32.@)
2029  */
2030 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
2031     HGLOBAL             hDlgTmpl;
2032     LPVOID              ptr;
2033     BOOL                bRet;
2034     PageSetupData       *pda;
2035     PRINTDLGA           pdlg;
2036
2037     if(TRACE_ON(commdlg)) {
2038         char flagstr[1000] = "";
2039         struct pd_flags *pflag = psd_flags;
2040         for( ; pflag->name; pflag++) {
2041             if(setupdlg->Flags & pflag->flag) {
2042                 strcat(flagstr, pflag->name);
2043                 strcat(flagstr, "|");
2044             }
2045         }
2046         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
2047               "hinst %08x, flags %08lx (%s)\n",
2048               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2049               setupdlg->hDevNames, 
2050               setupdlg->hInstance, setupdlg->Flags, flagstr);
2051     }
2052
2053     /* First get default printer data, we need it right after that. */
2054     memset(&pdlg,0,sizeof(pdlg));
2055     pdlg.lStructSize    = sizeof(pdlg);
2056     pdlg.Flags          = PD_RETURNDEFAULT;
2057     bRet = PrintDlgA(&pdlg);
2058     if (!bRet) return FALSE;
2059
2060     /* short cut exit, just return default values */
2061     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2062         setupdlg->hDevMode      = pdlg.hDevMode;
2063         setupdlg->hDevNames     = pdlg.hDevNames;
2064         /* FIXME: Just return "A4" for now. */
2065         PRINTDLG_PaperSize(&pdlg,"A4",&setupdlg->ptPaperSize);
2066         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
2067         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
2068         return TRUE;
2069     }
2070     hDlgTmpl = PRINTDLG_GetPGSTemplate(setupdlg);
2071     if (!hDlgTmpl) {
2072         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2073         return FALSE;
2074     }
2075     ptr = LockResource( hDlgTmpl );
2076     if (!ptr) {
2077         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2078         return FALSE;
2079     }
2080     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
2081     pda->dlga = setupdlg;
2082     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
2083
2084     bRet = (0<DialogBoxIndirectParamA(
2085                 setupdlg->hInstance,
2086                 ptr,
2087                 setupdlg->hwndOwner,
2088                 PageDlgProcA,
2089                 (LPARAM)pda)
2090     );
2091     return bRet;
2092 }
2093 /***********************************************************************
2094  *            PageSetupDlgW  (COMDLG32.@)
2095  */
2096 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
2097         FIXME("(%p), stub!\n",setupdlg);
2098         return FALSE;
2099 }
2100
2101 /**********************************************************************
2102  *
2103  *      16 bit commdlg
2104  */
2105
2106 /***********************************************************************
2107  *           PrintDlgProc   (COMMDLG.21)
2108  */
2109 LRESULT WINAPI PrintDlgProc16(HWND16 hDlg, UINT16 uMsg, WPARAM16 wParam,
2110                             LPARAM lParam)
2111 {
2112     PRINT_PTRA* PrintStructures;
2113     LRESULT res=FALSE;
2114
2115     if (uMsg!=WM_INITDIALOG) {
2116         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
2117         if (!PrintStructures)
2118             return FALSE;
2119     } else {
2120         PrintStructures = (PRINT_PTRA*) lParam;
2121         SetWindowLongA(hDlg, DWL_USER, lParam); 
2122         res = PRINTDLG_WMInitDialog16(hDlg, wParam, PrintStructures);
2123
2124         if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
2125             res = CallWindowProc16(
2126                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
2127                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg16
2128             );
2129         }
2130         return res;
2131     }
2132   
2133     if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
2134         res = CallWindowProc16(
2135                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
2136                 hDlg,uMsg, wParam, lParam
2137         );
2138         if(LOWORD(res)) return res;
2139     }
2140
2141     switch (uMsg) {
2142     case WM_COMMAND: {
2143          /* We need to map those for the 32bit window procedure, compare
2144           * with 32Ato16 mapper in winproc.c
2145           */
2146         return PRINTDLG_WMCommand(
2147                 hDlg,
2148                 MAKEWPARAM(wParam,HIWORD(lParam)),
2149                 LOWORD(lParam),
2150                 PrintStructures
2151         );
2152     }
2153     case WM_DESTROY:
2154         DestroyIcon(PrintStructures->hCollateIcon);
2155         DestroyIcon(PrintStructures->hNoCollateIcon);
2156     /* FIXME: don't forget to delete the paper orientation icons here! */
2157
2158         return FALSE;
2159     }    
2160     return res;
2161 }
2162
2163
2164 /***********************************************************************
2165  *           PrintSetupDlgProc   (COMMDLG.22)
2166  */
2167 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
2168                                    LPARAM lParam)
2169 {
2170   switch (wMsg)
2171     {
2172     case WM_INITDIALOG:
2173       TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
2174       ShowWindow(hWnd, SW_SHOWNORMAL);
2175       return (TRUE);
2176     case WM_COMMAND:
2177       switch (wParam) {
2178       case IDOK:
2179         EndDialog(hWnd, TRUE);
2180         return(TRUE);
2181       case IDCANCEL:
2182         EndDialog(hWnd, FALSE);
2183         return(TRUE);
2184       }
2185       return(FALSE);
2186     }
2187   return FALSE;
2188 }
2189
2190
2191 /***********************************************************************
2192  *      PrintDlgExA (COMDLG32.@)
2193  */
2194 HRESULT WINAPI PrintDlgExA(LPVOID lpPrintDlgExA) /* [???] FIXME: LPPRINTDLGEXA */
2195 {
2196         FIXME("stub\n");
2197         return E_NOTIMPL;
2198 }
2199 /***********************************************************************
2200  *      PrintDlgExW (COMDLG32.@)
2201  */
2202 HRESULT WINAPI PrintDlgExW(LPVOID lpPrintDlgExW) /* [???] FIXME: LPPRINTDLGEXW */
2203 {
2204         FIXME("stub\n");
2205         return E_NOTIMPL;
2206 }