Fixed ANSI C violations.
[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  */
8
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "winbase.h"
13 #include "wine/winbase16.h"
14 #include "wine/winuser16.h"
15 #include "ldt.h"
16 #include "commdlg.h"
17 #include "resource.h"
18 #include "dialog.h"
19 #include "dlgs.h"
20 #include "module.h"
21 #include "debugtools.h"
22 #include "winproc.h"
23 #include "cderr.h"
24 #include "winspool.h"
25 #include "winerror.h"
26
27 DEFAULT_DEBUG_CHANNEL(commdlg)
28
29 #include "cdlg.h"
30
31
32 /* This PRINTDLGA internal structure stores
33  * pointers to several throughout useful structures.
34  * 
35  */
36 typedef struct  
37 {
38   LPPRINTER_INFO_2A lpPrinterInfo;
39   UINT              CurrentPrinter;  /* used as lpPrinterInfo[CurrentPrinter] */
40   UINT              DefaultPrinter;  /* used as lpPrinterInfo[DefaultPrinter] */
41   DWORD             NrOfPrinterInfoEntries;
42   LPPRINTDLGA       lpPrintDlg;
43   UINT              HelpMessageID;
44   HICON             hCollateIcon;
45   HICON             hNoCollateIcon;
46 } PRINT_PTRA;
47
48
49 /* prototypes */
50 static BOOL PRINTDLG_ValidateAndDuplicateSettings(HWND hDlg, 
51                                                   PRINT_PTRA* PrintStructures);
52
53
54
55 /***********************************************************************
56  *           PrintDlg16   (COMMDLG.20)
57  */
58 BOOL16 WINAPI PrintDlg16( SEGPTR printdlg )
59 {
60     HANDLE16 hInst;
61     BOOL16 bRet = FALSE;
62     LPCVOID template;
63     HWND hwndDialog;
64     HANDLE hResInfo, hDlgTmpl;
65     LPSTR rscname;
66     LPPRINTDLG16 lpPrint = (LPPRINTDLG16)PTR_SEG_TO_LIN(printdlg);
67
68     TRACE("(%p) -- Flags=%08lX\n", lpPrint, lpPrint->Flags );
69
70     if (lpPrint->Flags & PD_RETURNDEFAULT)
71         /* FIXME: should fill lpPrint->hDevMode and lpPrint->hDevNames here */
72         return TRUE;
73
74     if (lpPrint->Flags & PD_PRINTSETUP)
75         rscname = "PRINT_SETUP";
76     else
77         rscname = "PRINT";
78
79     if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, rscname, RT_DIALOGA)))
80     {
81         COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
82         return FALSE;
83     }
84     if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
85         !(template = LockResource( hDlgTmpl )))
86     {
87         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
88         return FALSE;
89     }
90
91     hInst = GetWindowLongA( lpPrint->hwndOwner, GWL_HINSTANCE );
92     hwndDialog = DIALOG_CreateIndirect( hInst, template, TRUE,
93                                         lpPrint->hwndOwner,
94                                (DLGPROC16)((lpPrint->Flags & PD_PRINTSETUP) ?
95                                 /* FIXME: PrintSetupDlgProc */ PrintDlgProcA :
96                                 PrintDlgProcA ),
97                                 printdlg, WIN_PROC_32A );
98     if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpPrint->hwndOwner);
99     return bRet;
100 }
101
102
103 /***********************************************************************
104  *           PrintDlgA   (COMDLG32.17)
105  *
106  *  Displays the the PRINT dialog box, which enables the user to specify
107  *  specific properties of the print job.
108  *
109  *  (Note: according to the MS Platform SDK, this call was in the past 
110  *   also used to display some PRINT SETUP dialog. As this is superseded 
111  *   by PageSetupDlg, this now results in an error!)
112  *
113  * RETURNS
114  *  nonzero if the user pressed the OK button
115  *  zero    if the user cancelled the window or an error occurred
116  *
117  * BUGS
118  *  The Collate Icons do not display, even though they are in the code.
119  */
120 BOOL WINAPI PrintDlgA(
121                          LPPRINTDLGA lppd /* ptr to PRINTDLG32 struct */
122                          )
123 {
124 /* My implementing strategy:
125  * 
126  * step 1: display the dialog and implement the layout-flags
127  * step 2: enter valid information in the fields (e.g. real printers)
128  * step 3: fix the RETURN-TRUE-ALWAYS Fixme by checking lppd->Flags for
129  *         PD_RETURNDEFAULT
130  * step 4: implement all other specs
131  * step 5: allow customisation of the dialog box
132  *
133  * current implementation is in step 3.
134  */ 
135
136     HWND      hwndDialog;
137     BOOL      bRet = FALSE;
138     LPCVOID   ptr;
139     HANDLE    hResInfo, hDlgTmpl;
140     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
141     DWORD     EnumBytesNeeded;
142     DWORD     CopyOfEnumBytesNeeded;
143     PRINT_PTRA PrintStructures;
144
145     FIXME("KVG (%p): stub\n", lppd);
146     PrintStructures.lpPrintDlg = lppd;
147
148     /* load Dialog */
149     if (!(hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32", RT_DIALOGA)))
150     {
151         COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
152         return FALSE;
153     }
154     if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo )) ||
155         !(ptr = LockResource( hDlgTmpl )))
156     {
157         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
158         return FALSE;
159     }
160
161     /* load Collate ICON */
162     PrintStructures.hCollateIcon = 
163                               LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
164     PrintStructures.hNoCollateIcon = 
165                                 LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
166     if (PrintStructures.hCollateIcon==0 || PrintStructures.hNoCollateIcon==0)
167     {
168     ERR("no icon in resourcefile???");
169         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
170         return FALSE;
171     }
172
173     /*
174      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
175      * must be registered and the Help button must be shown.
176      */
177     if (lppd->Flags & PD_SHOWHELP)
178        {
179         if((PrintStructures.HelpMessageID = RegisterWindowMessageA(HELPMSGSTRING)) 
180                         == 0)
181             {
182              COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
183              return FALSE;
184             }
185        }
186     else
187         PrintStructures.HelpMessageID=0;
188         
189         if (lppd->Flags & PD_PRINTSETUP)
190                 {
191                  FIXME(": PrintDlg was requested to display PrintSetup box.\n");
192                  COMDLG32_SetCommDlgExtendedError(PDERR_INITFAILURE); 
193                  return(FALSE);
194                 }
195                 
196     /* Use EnumPrinters to obtain a list of PRINTER_INFO_2A's
197      * and store a pointer to this list in our "global structure"
198      * as reference for the rest of the PrintDlg routines
199      */
200     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 
201         0, &EnumBytesNeeded, &PrintStructures.NrOfPrinterInfoEntries);
202     CopyOfEnumBytesNeeded=EnumBytesNeeded+16;
203     PrintStructures.lpPrinterInfo = malloc(CopyOfEnumBytesNeeded*sizeof(char));
204     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, 
205         (LPBYTE)PrintStructures.lpPrinterInfo, 
206         CopyOfEnumBytesNeeded, &EnumBytesNeeded, 
207         &PrintStructures.NrOfPrinterInfoEntries);
208
209     /* Find the default printer.
210      * If not: display a warning message (unless PD_NOWARNING specified)
211      * and return PDERR_NODEFAULTPRN
212      */
213     /* FIXME: not implemented yet!!! */
214     if (!PrintStructures.NrOfPrinterInfoEntries)
215     {
216         COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
217         return FALSE;
218     }
219     PrintStructures.CurrentPrinter=0; 
220     PrintStructures.DefaultPrinter=0; 
221      
222     /* FIXME: Currently Unimplemented */
223     if (lppd->Flags & PD_NOWARNING)     
224            {
225             COMDLG32_SetCommDlgExtendedError(PDERR_INITFAILURE); 
226             WARN(": PD_NOWARNING Flag is not yet implemented.\n");
227            }
228         
229     /*
230      * FIXME : Should respond to TEMPLATE and HOOK flags here
231      * For now, only the standard dialog works.
232      */
233     if (lppd->Flags & (PD_ENABLEPRINTHOOK | PD_ENABLEPRINTTEMPLATE |
234                           PD_ENABLEPRINTTEMPLATEHANDLE | PD_ENABLESETUPHOOK | 
235                           PD_ENABLESETUPTEMPLATE|PD_ENABLESETUPTEMPLATEHANDLE)) 
236         FIXME(": unimplemented flag (ignored)\n");     
237         
238     /*
239      * if lppd->Flags PD_RETURNDEFAULT is specified, the PrintDlg function
240      * does not display the dialog box, but returns with valid entries
241      * for hDevMode and hDevNames .
242      *
243      * According to MSDN, it is required that hDevMode and hDevNames equal
244      * zero if this flag is set.
245      */
246     if (lppd->Flags & PD_RETURNDEFAULT)
247        {
248         TRACE(" PD_RETURNDEFAULT: was requested to return printer info only.\n");
249         if (lppd->hDevMode!=0 || lppd->hDevNames !=0)
250             {
251              COMDLG32_SetCommDlgExtendedError(PDERR_INITFAILURE); 
252              return(FALSE);
253             }
254         return(PRINTDLG_ValidateAndDuplicateSettings(0, &PrintStructures));
255        }
256         
257     /* and create & process the dialog 
258      */ 
259     hwndDialog= DIALOG_CreateIndirect(hInst, ptr, TRUE, lppd->hwndOwner,
260             (DLGPROC16)PrintDlgProcA, (LPARAM)&PrintStructures, WIN_PROC_32A );
261     if (hwndDialog) 
262         bRet = DIALOG_DoDialogBox(hwndDialog, lppd->hwndOwner);  
263      
264     /* free memory & resources
265      */   
266     free(PrintStructures.lpPrinterInfo);
267     DeleteObject(PrintStructures.hCollateIcon);
268     DeleteObject(PrintStructures.hNoCollateIcon);
269
270   TRACE(" exit! (%d)", bRet);        
271   return bRet;            
272 }
273
274
275
276 /***********************************************************************
277  *           PrintDlg32W   (COMDLG32.18)
278  */
279 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
280 {
281     FIXME("A really empty stub\n" );
282     return FALSE;
283 }
284
285
286 /***********************************************************************
287  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
288  */
289 void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, PRINT_PTRA* PrintStructures)
290 {
291     char   StatusMsg[256];
292     char   ResourceString[256];
293     int    i;
294     LPPRINTER_INFO_2A lpPi = &(PrintStructures->lpPrinterInfo
295                                              [PrintStructures->CurrentPrinter]);
296     
297     /* Status Message */
298     StatusMsg[0]='\0';
299     /* FIXME: if default printer, add this first */
300     ;
301     /* add all status messages */
302     for (i=0; i< 25; i++)
303     {
304         if (lpPi->Status & (1<<i))
305         {
306          LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i, 
307                         ResourceString, 255);
308          strcat(StatusMsg,ResourceString);
309         }
310     }
311     /* append "ready" */
312     /* FIXME: status==ready must only be appended if really so. 
313               but how to detect??? */
314     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY, 
315                         ResourceString, 255);
316     strcat(StatusMsg,ResourceString);
317   
318     SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
319
320     /* set all other printer info texts */
321     SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)lpPi->pDriverName);
322     if (lpPi->pLocation != NULL && lpPi->pLocation[0]!='\0')
323         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)lpPi->pLocation);
324     else                                        
325         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0, (LPARAM)lpPi->pPortName);
326     SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)lpPi->pComment);
327 }
328
329
330 /***********************************************************************
331  *           PRINTDLG_WMInitDialog                      [internal]
332  */
333 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam,
334                                      PRINT_PTRA* PrintStructures)
335 {
336  int               i;
337  LPPRINTDLGA       lppd     = PrintStructures->lpPrintDlg;
338  LPPRINTER_INFO_2A lppi     = PrintStructures->lpPrinterInfo;
339  PDEVMODEA         pDevMode = lppi[PrintStructures->CurrentPrinter].pDevMode; 
340  
341         SetWindowLongA(hDlg, DWL_USER, lParam); 
342         TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
343
344         if (lppd->lStructSize != sizeof(PRINTDLGA))
345         {
346                 FIXME("structure size failure !!!\n");
347 /*              EndDialog (hDlg, 0); 
348                 return FALSE; 
349 */      }
350
351 /* Fill Combobox according to info from PRINTER_INFO2A
352  * structure inside PrintStructures,
353  * select the default printer and generate an
354  * update-message to have the rest of the dialog box updated.
355  */ 
356     for (i=0; i < PrintStructures->NrOfPrinterInfoEntries; i++)
357            SendDlgItemMessageA(hDlg, cmb4, CB_ADDSTRING, 0,
358                         (LPARAM)lppi[i].pPrinterName );
359     i=SendDlgItemMessageA(hDlg, cmb4, CB_SELECTSTRING, 
360         (WPARAM) -1,
361         (LPARAM) lppi[PrintStructures->CurrentPrinter].pPrinterName);
362     SendDlgItemMessageA(hDlg, cmb4, CB_SETCURSEL, 
363         (WPARAM)i, (LPARAM)0);
364     PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures);
365
366 /* Flag processing to set the according buttons on/off and
367  * Initialise the various values
368  */
369
370     /* Print range (All/Range/Selection) */
371     /* FIXME: I allow more freedom than either Win95 or WinNT,
372      *        which do not agree to what errors should be thrown or not
373      *        in case nToPage or nFromPage is out-of-range.
374      */
375     if (lppd->nMaxPage < lppd->nMinPage)
376         lppd->nMaxPage = lppd->nMinPage;
377     if (lppd->nMinPage == lppd->nMaxPage) 
378         lppd->Flags |= PD_NOPAGENUMS;        
379     if (lppd->nToPage < lppd->nMinPage)
380         lppd->nToPage = lppd->nMinPage;
381     if (lppd->nToPage > lppd->nMaxPage)
382         lppd->nToPage = lppd->nMaxPage;
383     if (lppd->nFromPage < lppd->nMinPage)
384         lppd->nFromPage = lppd->nMinPage;
385     if (lppd->nFromPage > lppd->nMaxPage)
386         lppd->nFromPage = lppd->nMaxPage;
387     SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
388     SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
389     CheckRadioButton(hDlg, rad1, rad3, rad1);           /* default */
390     if (lppd->Flags & PD_NOSELECTION)
391                 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
392     else
393                 if (lppd->Flags & PD_SELECTION)
394                 CheckRadioButton(hDlg, rad1, rad3, rad2);
395     if (lppd->Flags & PD_NOPAGENUMS)
396        {
397                 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
398                 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
399                 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
400                 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
401                 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
402        }
403     else
404        {
405                 if (lppd->Flags & PD_PAGENUMS)
406                 CheckRadioButton(hDlg, rad1, rad3, rad3);
407        }
408         /* "All xxx pages"... */
409     {
410      char        resourcestr[64];
411      char        result[64];
412      LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, 
413                 resourcestr, 49);
414      sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
415      SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
416     }
417         
418     /* Collate pages 
419      *
420      * FIXME: The ico3 is not displayed for some reason. I don't know why.
421      */
422     if (lppd->Flags & PD_COLLATE)
423        {
424         SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
425                                     (LPARAM)PrintStructures->hCollateIcon);
426             CheckDlgButton(hDlg, chx2, 1);
427        }
428     else
429        {
430             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
431                                     (LPARAM)PrintStructures->hNoCollateIcon);
432             CheckDlgButton(hDlg, chx2, 0);
433        }
434        
435     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE ||
436         lppd->Flags & PD_USEDEVMODECOPIES)
437         {
438          /* if printer doesn't support it: no Collate */
439          if (!(pDevMode->dmFields & DM_COLLATE))
440             {
441                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);    
442                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);    
443             }
444         }
445         
446     /* nCopies */
447     if (lppd->hDevMode == 0)
448         {
449          SetDlgItemInt(hDlg, edt3, lppd->nCopies, FALSE);
450         }
451     else
452         {
453          SetDlgItemInt(hDlg, edt1, pDevMode->dmCopies, FALSE);
454         }
455     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE ||
456         lppd->Flags & PD_USEDEVMODECOPIES)
457         {
458          /* if printer doesn't support it: no nCopies */
459          if (!(pDevMode->dmFields & DM_COPIES))
460             {
461                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);    
462                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);    
463             }
464         }
465
466     /* print to file */
467         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
468     if (lppd->Flags & PD_DISABLEPRINTTOFILE)
469                 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);    
470     if (lppd->Flags & PD_HIDEPRINTTOFILE)
471                 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
472
473     /* help button */
474         if ((lppd->Flags & PD_SHOWHELP)==0)
475         {       /* hide if PD_SHOWHELP not specified */
476                  ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);         
477         }
478
479   GlobalUnlock(lppd->hDevMode);
480   return TRUE;
481 }
482
483
484
485 /***********************************************************************
486  *             PRINTDLG_CreateDevNames          [internal]
487  *
488  *
489  *   creates a DevNames structure.
490  * RETURNS
491  *   HGLOBAL to DevNames memory object on success or
492  *   zero on faillure
493  */
494 HGLOBAL PRINTDLG_CreateDevNames(
495                     char* DeviceDriverName, 
496                     char* DeviceName, 
497                     char* OutputPort, 
498                     WORD  Flags)
499 {
500     long size;
501     HGLOBAL hDevNames;
502     char*   pDevNamesSpace;
503     char*   pTempPtr;
504     LPDEVNAMES lpDevNames;
505     
506     size = strlen(DeviceDriverName) +1
507             + strlen(DeviceName) + 1
508             + strlen(OutputPort) + 1
509             + sizeof(DEVNAMES);
510             
511     hDevNames = GlobalAlloc(GMEM_MOVEABLE, size*sizeof(char));
512     if (hDevNames != 0)
513     {
514         pDevNamesSpace = GlobalLock(hDevNames);
515         lpDevNames = (LPDEVNAMES) pDevNamesSpace;
516         
517         pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
518         strcpy(pTempPtr, DeviceDriverName);
519         lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
520         
521         pTempPtr += strlen(DeviceDriverName) + 1;
522         strcpy(pTempPtr, DeviceName);
523         lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
524         
525         pTempPtr += strlen(DeviceName) + 1;
526         strcpy(pTempPtr, OutputPort);
527         lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
528         
529         lpDevNames->wDefault = Flags;
530         
531         GlobalUnlock(hDevNames);
532     }
533     return(hDevNames);
534 }
535             
536     
537            
538     
539 /***********************************************************************
540  *             PRINTDLG_ValidateAndDuplicateSettings          [internal]
541  *
542  *
543  *   updates the PrintDlg structure for returnvalues.
544  *   (yep, the name was chosen a bit stupid...)
545  *
546  *   if hDlg equals zero, only hDevModes and hDevNames are adapted.
547  *      
548  * RETURNS
549  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
550  *   TRUE  if succesful.
551  */
552 static BOOL PRINTDLG_ValidateAndDuplicateSettings(HWND hDlg, 
553                                                   PRINT_PTRA* PrintStructures)
554 {
555  LPPRINTER_INFO_2A lpPi = &(PrintStructures->lpPrinterInfo
556                                              [PrintStructures->CurrentPrinter]);
557  LPPRINTDLGA       lppd = PrintStructures->lpPrintDlg;
558  PDEVMODEA         pDevMode;
559  
560  if (hDlg!=0)
561  {
562     /* check whether nFromPage and nToPage are within range defined by
563      * nMinPage and nMaxPage
564      */
565     if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED)
566     {
567         WORD nToPage;
568         WORD nFromPage;
569         nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
570         nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
571         if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
572             nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage)
573         {
574             char resourcestr[256];
575             char resultstr[256];
576             LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, 
577                 resourcestr, 255);
578             sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
579             LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE, 
580                 resourcestr, 255);
581             MessageBoxA(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
582             return(FALSE);
583         }
584         lppd->nFromPage = nFromPage;
585         lppd->nToPage   = nToPage;
586     }
587      
588     
589     if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED)
590        {
591         lppd->Flags |= PD_PRINTTOFILE;
592         lpPi->pPortName = "FILE:";
593        }
594
595     if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
596        {
597         FIXME("Collate lppd not yet implemented as output\n");
598        }
599  } /* end-of-if(hDlg!=0) */
600
601     /* 
602      * create or modify hDevMode 
603      */     
604     if (lppd->hDevMode == 0)
605        {
606         TRACE(" No hDevMode yet... Need to create my own\n");
607         /* FIXME: possible memory leak? Memory never freed again! */
608         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, lpPi->pDevMode->dmSize);
609         pDevMode    = GlobalLock(lppd->hDevMode);
610         memcpy(pDevMode, lpPi->pDevMode, lpPi->pDevMode->dmSize);
611        }
612     else
613        {
614         FIXME(" already hDevMode... must adjust it... Not implemented yet\n");
615         pDevMode    = GlobalLock(lppd->hDevMode);
616        }
617               
618     /* If hDevNames already exists, trash it.
619      * But create a new one anyway
620      */
621     if (lppd->hDevNames != 0)
622        {
623         if ( (GlobalFlags(lppd->hDevNames)&0xFF) != 0)
624             ERR(" Tried to free hDevNames, but your application still has a"
625                 " lock on hDevNames. Possible program crash...");
626         GlobalFree(lppd->hDevNames);
627        }
628     /* FIXME: The first entry  of DevNames is fixed to "winspool", 
629      * because I don't know of any printerdriver which doesn't return 
630      * winspool there. But I guess they do exist... 
631      */
632     lppd->hDevNames = PRINTDLG_CreateDevNames("winspool",
633                       lpPi->pDriverName, lpPi->pPortName, 
634                       (PrintStructures->DefaultPrinter ==
635                                 PrintStructures->CurrentPrinter)?1:0);
636
637     /* set PD_Collate and nCopies */
638     if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE ||
639         lppd->Flags & PD_USEDEVMODECOPIES)
640         {
641          /* if one of the above flags was set, the application doesn't
642            * (want to) support multiple copies or collate...
643            */
644          lppd->Flags &= ~PD_COLLATE;
645          lppd->nCopies = 1;
646           /* if the printer driver supports it... store info there
647            * otherwise no collate & multiple copies !
648            */
649          if (pDevMode->dmFields & DM_COLLATE)
650            {
651             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
652                 pDevMode->dmCollate = 1;         
653             else
654                 pDevMode->dmCollate = 0;
655            }
656          if (pDevMode->dmFields & DM_COPIES)
657             {
658              WORD nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
659              pDevMode->dmCopies = nCopies;       
660             }
661         }
662     else
663         {
664          /* set Collate & nCopies according to dialog */
665          if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
666             lppd->Flags |= PD_COLLATE;
667          else
668             lppd->Flags &= ~PD_COLLATE;
669          lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
670         }
671
672
673     GlobalUnlock(lppd->hDevMode);
674
675  return(TRUE);   
676 }
677
678
679 /***********************************************************************
680  *                              PRINTDLG_WMCommand               [internal]
681  */
682 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam, 
683                         LPARAM lParam, PRINT_PTRA* PrintStructures)
684 {
685     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
686     LPPRINTER_INFO_2A lppi = &(PrintStructures->lpPrinterInfo
687                                         [PrintStructures->CurrentPrinter]);
688     
689
690     switch (LOWORD(wParam)) 
691     {
692          case IDOK:
693         TRACE(" OK button was hit\n");
694         if (PRINTDLG_ValidateAndDuplicateSettings(hDlg, PrintStructures) != TRUE)
695                 return(FALSE);
696             DestroyWindow(hDlg);
697             return(TRUE);
698          case IDCANCEL:
699         TRACE(" CANCEL button was hit\n");
700         EndDialog(hDlg, FALSE);
701             return(FALSE);
702      case pshHelp:
703         TRACE(" HELP button was hit\n");
704         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID, 
705                                 (WPARAM) hDlg, (LPARAM) lppd);
706         break;
707      case chx2:                         /* collate pages checkbox */
708         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
709             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
710                                     (LPARAM)PrintStructures->hCollateIcon);
711         else
712             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
713                                     (LPARAM)PrintStructures->hNoCollateIcon);
714         break;        
715      case edt1:                         /* from page nr editbox */
716      case edt2:                         /* to page nr editbox */
717         if (HIWORD(wParam)==EN_CHANGE)
718            {
719             WORD nToPage;
720                 WORD nFromPage;
721                 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
722                 nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
723             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
724                             CheckRadioButton(hDlg, rad1, rad3, rad3);
725     }
726         break;
727      case psh2:                         /* Properties button */
728         {
729          HANDLE hPrinter;
730          char   PrinterName[256];
731          GetDlgItemTextA(hDlg, cmb4, PrinterName, 255);
732          if (OpenPrinterA(PrinterName, &hPrinter, NULL))
733             {
734              PrinterProperties(hDlg, hPrinter);
735              ClosePrinter(hPrinter);
736             }
737          else
738             WARN(" Call to OpenPrinter did not succeed!\n");
739          break;
740         }
741      case cmb4:                         /* Printer combobox */
742         if (HIWORD(wParam)==CBN_SELCHANGE)
743            {
744             int i;
745                 char   PrinterName[256];
746
747             /* look the newly selected Printer up in 
748              * our array Printer_Info2As
749              */
750                 GetDlgItemTextA(hDlg, cmb4, PrinterName, 255);
751             for (i=0; i < PrintStructures->NrOfPrinterInfoEntries; i++)
752                    {
753                 if (strcmp(PrintStructures->lpPrinterInfo[i].pPrinterName, 
754                            PrinterName)==0)
755                      break;
756                }
757             PrintStructures->CurrentPrinter = i;   
758             PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures);
759             lppi = &(PrintStructures->lpPrinterInfo
760                                        [PrintStructures->CurrentPrinter]);
761             if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE ||
762                 lppd->Flags & PD_USEDEVMODECOPIES)
763                 {
764                  /* if printer doesn't support it: no nCopies */
765                  if (!(lppi->pDevMode->dmFields & DM_COPIES))
766                     {
767                         EnableWindow(GetDlgItem(hDlg, edt3), FALSE);    
768                         EnableWindow(GetDlgItem(hDlg, stc5), FALSE);    
769                     }
770                  else
771                     {
772                         EnableWindow(GetDlgItem(hDlg, edt3), TRUE);    
773                         EnableWindow(GetDlgItem(hDlg, stc5), TRUE);    
774                     }
775                  /* if printer doesn't support it: no Collate */
776                  if (!(lppi->pDevMode->dmFields & DM_COPIES))
777                     {
778                         EnableWindow(GetDlgItem(hDlg, ico3), FALSE);    
779                         EnableWindow(GetDlgItem(hDlg, chx2), FALSE);    
780                     }
781                  else
782                     {
783                         EnableWindow(GetDlgItem(hDlg, ico3), TRUE);
784                         EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
785                     }
786                 }
787
788            }
789         break;
790     }
791     return FALSE;
792 }    
793
794
795
796 /***********************************************************************
797  *           PrintDlgProcA                      [internal]
798  */
799 LRESULT WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
800                                     LPARAM lParam)
801 {
802   PRINT_PTRA* PrintStructures;
803   LRESULT res=FALSE;
804   if (uMsg!=WM_INITDIALOG)
805   {
806    PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
807    if (!PrintStructures)
808     return FALSE;
809 }
810   else
811   {
812     PrintStructures=(PRINT_PTRA*) lParam;
813     if (!PRINTDLG_WMInitDialog(hDlg, wParam, lParam, PrintStructures)) 
814     {
815       TRACE("PRINTDLG_WMInitDialog returned FALSE\n");
816       return FALSE;
817     }  
818   }
819   switch (uMsg)
820   {
821         case WM_COMMAND:
822        return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
823     case WM_DESTROY:
824             return FALSE;
825   }
826   
827  return res;
828 }
829
830
831
832
833 /***********************************************************************
834  *           PrintDlgProc16   (COMMDLG.21)
835  */
836 LRESULT WINAPI PrintDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
837                             LPARAM lParam)
838 {
839   switch (wMsg)
840     {
841     case WM_INITDIALOG:
842       TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
843       ShowWindow16(hWnd, SW_SHOWNORMAL);
844       return (TRUE);
845     case WM_COMMAND:
846       switch (wParam)
847         {
848         case IDOK:
849           EndDialog(hWnd, TRUE);
850           return(TRUE);
851         case IDCANCEL:
852           EndDialog(hWnd, FALSE);
853           return(TRUE);
854         }
855       return(FALSE);
856     }
857   return FALSE;
858 }
859
860
861 /***********************************************************************
862  *           PrintSetupDlgProc   (COMMDLG.22)
863  */
864 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
865                                  LPARAM lParam)
866 {
867   switch (wMsg)
868     {
869     case WM_INITDIALOG:
870       TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
871       ShowWindow16(hWnd, SW_SHOWNORMAL);
872       return (TRUE);
873     case WM_COMMAND:
874       switch (wParam) {
875       case IDOK:
876         EndDialog(hWnd, TRUE);
877         return(TRUE);
878       case IDCANCEL:
879         EndDialog(hWnd, FALSE);
880         return(TRUE);
881       }
882       return(FALSE);
883     }
884   return FALSE;
885 }
886
887
888
889
890 /***********************************************************************
891  *            PageSetupDlgA  (COMDLG32.15)
892  */
893 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
894         FIXME("(%p), stub!\n",setupdlg);
895         return FALSE;
896 }