Replaced all occurences of SYSMETRICS_xx and sysMetrics[SM_xx] by
[wine/wine64.git] / dlls / commdlg / printdlg.c
blob5e371b5a285bcd2292269e7ea18469220b17a6e6
1 /*
2 * COMMDLG - Print Dialog
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1999 Klaas van Gend
7 */
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 "debug.h"
22 #include "winproc.h"
23 #include "cderr.h"
24 #include "winspool.h"
26 DEFAULT_DEBUG_CHANNEL(commdlg)
28 #include "cdlg.h"
30 /***********************************************************************
31 * PrintDlg16 (COMMDLG.20)
33 BOOL16 WINAPI PrintDlg16( SEGPTR printdlg )
35 HANDLE16 hInst;
36 BOOL16 bRet = FALSE;
37 LPCVOID template;
38 HWND hwndDialog;
39 HANDLE hResInfo, hDlgTmpl;
40 LPSTR rscname;
41 LPPRINTDLG16 lpPrint = (LPPRINTDLG16)PTR_SEG_TO_LIN(printdlg);
43 TRACE(commdlg,"(%p) -- Flags=%08lX\n", lpPrint, lpPrint->Flags );
45 if (lpPrint->Flags & PD_RETURNDEFAULT)
46 /* FIXME: should fill lpPrint->hDevMode and lpPrint->hDevNames here */
47 return TRUE;
49 if (lpPrint->Flags & PD_PRINTSETUP)
50 rscname = "PRINT_SETUP";
51 else
52 rscname = "PRINT";
54 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, rscname, RT_DIALOGA)))
56 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
57 return FALSE;
59 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
60 !(template = LockResource( hDlgTmpl )))
62 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
63 return FALSE;
66 hInst = GetWindowLongA( lpPrint->hwndOwner, GWL_HINSTANCE );
67 hwndDialog = DIALOG_CreateIndirect( hInst, template, TRUE,
68 lpPrint->hwndOwner,
69 (DLGPROC16)((lpPrint->Flags & PD_PRINTSETUP) ?
70 MODULE_GetWndProcEntry16("PrintSetupDlgProc") :
71 MODULE_GetWndProcEntry16("PrintDlgProc")),
72 printdlg, WIN_PROC_16 );
73 if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpPrint->hwndOwner);
74 return bRet;
78 /* This PRINTDLGA internal structure stores
79 * pointers to several throughout useful structures.
82 typedef struct
84 LPPRINTER_INFO_2A lpPrinterInfo;
85 DWORD NrOfPrinterInfoEntries;
86 LPPRINTDLGA lpPrintDlg;
87 UINT HelpMessageID;
88 } PRINT_PTRA;
90 /***********************************************************************
91 * PrintDlgA (COMDLG32.17)
93 * Displays the the PRINT dialog box, which enables the user to specify
94 * specific properties of the print job.
96 * (Note: according to the MS Platform SDK, this call was in the past
97 * also used to display some PRINT SETUP dialog. As this is superseded
98 * by PageSetupDlg, this now results in an error!)
100 * RETURNS
101 * nonzero if the user pressed the OK button
102 * zero if the user cancelled the window or an error occurred
104 * BUGS
105 * The function is a stub only, returning TRUE to allow more programs
106 * to function.
108 BOOL WINAPI PrintDlgA(
109 LPPRINTDLGA lppd /* ptr to PRINTDLG32 struct */
112 /* My implementing strategy:
114 * step 1: display the dialog and implement the layout-flags
115 * step 2: enter valid information in the fields (e.g. real printers)
116 * step 3: fix the RETURN-TRUE-ALWAYS Fixme by checking lppd->Flags for
117 * PD_RETURNDEFAULT
118 * step 4: implement all other specs
119 * step 5: allow customisation of the dialog box
121 * current implementation is in step 2, nearly going to 3.
124 HWND hwndDialog;
125 BOOL bRet = FALSE;
126 LPCVOID ptr;
127 HANDLE hResInfo, hDlgTmpl;
128 HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
129 DWORD EnumBytesNeeded;
130 DWORD CopyOfEnumBytesNeeded;
131 PRINT_PTRA PrintStructures;
133 FIXME(commdlg, "KVG (%p): stub\n", lppd);
134 PrintStructures.lpPrintDlg = lppd;
136 if (!(hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32", RT_DIALOGA)))
138 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
139 return FALSE;
141 if (!(hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo )) ||
142 !(ptr = LockResource( hDlgTmpl )))
144 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
145 return FALSE;
149 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
150 * must be registered and the Help button must be shown.
152 if (lppd->Flags & PD_SHOWHELP)
154 if((PrintStructures.HelpMessageID = RegisterWindowMessageA(HELPMSGSTRING))
155 == 0)
157 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
158 return FALSE;
161 else
162 PrintStructures.HelpMessageID=0;
165 * if lppd->Flags PD_RETURNDEFAULT is specified, the PrintDlg function
166 * does not display the dialog box, but returns with valid entries
167 * for hDevMode and hDevNames .
169 * Currently the flag is recognised, but we return empty hDevMode and
170 * and hDevNames. This will be fixed when I am in step 3.
172 if (lppd->Flags & PD_RETURNDEFAULT)
174 WARN(commdlg, ": PrintDlg was requested to return printer info only."
175 "\n The return value currently does NOT provide these.\n");
176 COMDLG32_SetCommDlgExtendedError(PDERR_NODEVICES);
177 /* return TRUE, thus never checked! */
178 return(TRUE);
181 if (lppd->Flags & PD_PRINTSETUP)
183 FIXME(commdlg, ": PrintDlg was requested to display PrintSetup box.\n");
184 COMDLG32_SetCommDlgExtendedError(PDERR_INITFAILURE);
185 return(FALSE);
188 /* Use EnumPrinters to obtain a list of PRINTER_INFO_2A's
189 * and store a pointer to this list in our "global structure"
190 * as reference for the rest of the PrintDlg routines
192 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL,
193 0, &EnumBytesNeeded, &PrintStructures.NrOfPrinterInfoEntries);
194 CopyOfEnumBytesNeeded=EnumBytesNeeded+16;
195 PrintStructures.lpPrinterInfo = malloc(CopyOfEnumBytesNeeded*sizeof(char));
196 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2,
197 (LPBYTE)PrintStructures.lpPrinterInfo,
198 CopyOfEnumBytesNeeded, &EnumBytesNeeded,
199 &PrintStructures.NrOfPrinterInfoEntries);
201 /* Find the default printer.
202 * If not: display a warning message (unless PD_NOWARNING specified)
204 /* FIXME: Currently Unimplemented */
205 if (lppd->Flags & PD_NOWARNING)
207 WARN(commdlg, ": PD_NOWARNING Flag is not yet implemented.\n");
211 * FIXME : Should respond to TEMPLATE and HOOK flags here
212 * For now, only the standard dialog works.
214 if (lppd->Flags & (PD_ENABLEPRINTHOOK | PD_ENABLEPRINTTEMPLATE |
215 PD_ENABLEPRINTTEMPLATEHANDLE | PD_ENABLESETUPHOOK |
216 PD_ENABLESETUPTEMPLATE|PD_ENABLESETUPTEMPLATEHANDLE))
217 FIXME(commdlg, ": unimplemented flag (ignored)\n");
220 hwndDialog= DIALOG_CreateIndirect(hInst, ptr, TRUE, lppd->hwndOwner,
221 (DLGPROC16)PrintDlgProcA, (LPARAM)&PrintStructures, WIN_PROC_32A );
222 if (hwndDialog)
223 bRet = DIALOG_DoDialogBox(hwndDialog, lppd->hwndOwner);
225 free(PrintStructures.lpPrinterInfo);
227 return bRet;
232 /***********************************************************************
233 * PrintDlg32W (COMDLG32.18)
235 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
237 FIXME(commdlg, "A really empty stub\n" );
238 return FALSE;
242 /***********************************************************************
243 * PRINTDLG_UpdatePrinterInfoTexts [internal]
245 void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, PRINT_PTRA* PrintStructures)
247 char PrinterName[256];
248 char StatusMsg[256];
249 int i;
250 LPPRINTER_INFO_2A lpPi = NULL;
251 GetDlgItemTextA(hDlg, cmb4, PrinterName, 255);
253 /* look the selected PrinterName up in our array Printer_Info2As*/
254 for (i=0; i < PrintStructures->NrOfPrinterInfoEntries; i++)
256 lpPi = &PrintStructures->lpPrinterInfo[i];
257 if (strcmp(lpPi->pPrinterName, PrinterName)==0)
258 break;
260 /* FIXME: the status byte must be converted to user-understandable text...*/
261 sprintf(StatusMsg,"%ld = 0x%08lx", lpPi->Status, lpPi->Status);
262 SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
263 SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)lpPi->pDriverName);
264 if (lpPi->pLocation != NULL && lpPi->pLocation[0]!='\0')
265 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)lpPi->pLocation);
266 else
267 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0, (LPARAM)lpPi->pPortName);
268 SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)lpPi->pComment);
272 /***********************************************************************
273 * PRINTDLG_WMInitDialog [internal]
275 LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam,
276 PRINT_PTRA* PrintStructures)
278 int i;
279 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
280 LPPRINTER_INFO_2A lppi = PrintStructures->lpPrinterInfo;
282 SetWindowLongA(hDlg, DWL_USER, lParam);
283 TRACE(commdlg,"WM_INITDIALOG lParam=%08lX\n", lParam);
285 if (lppd->lStructSize != sizeof(PRINTDLGA))
287 FIXME(commdlg,"structure size failure !!!\n");
288 /* EndDialog (hDlg, 0);
289 return FALSE;
290 */ }
292 /* Fill Combobox according to info from PRINTER_INFO2A
293 * structure inside PrintStructures and generate an
294 * update-message to have the rest of the dialog box updated.
296 for (i=0; i < PrintStructures->NrOfPrinterInfoEntries; i++)
297 SendDlgItemMessageA(hDlg, cmb4, CB_ADDSTRING, 0,
298 (LPARAM)lppi[i].pPrinterName );
299 PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures);
301 /* Flag processing to set the according buttons on/off and
302 * Initialise the various values
305 /* Print range (All/Range/Selection) */
306 /* FIXME: I allow more freedom than either Win95 or WinNT,
307 * which do not agree to what errors should be thrown or not
308 * in case nToPage or nFromPage is out-of-range.
310 if (lppd->nMaxPage < lppd->nMinPage)
311 lppd->nMaxPage = lppd->nMinPage;
312 if (lppd->nMinPage == lppd->nMaxPage)
313 lppd->Flags |= PD_NOPAGENUMS;
314 if (lppd->nToPage < lppd->nMinPage)
315 lppd->nToPage = lppd->nMinPage;
316 if (lppd->nToPage > lppd->nMaxPage)
317 lppd->nToPage = lppd->nMaxPage;
318 if (lppd->nFromPage < lppd->nMinPage)
319 lppd->nFromPage = lppd->nMinPage;
320 if (lppd->nFromPage > lppd->nMaxPage)
321 lppd->nFromPage = lppd->nMaxPage;
322 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
323 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
324 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
325 if (lppd->Flags & PD_NOSELECTION)
326 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
327 else
328 if (lppd->Flags & PD_SELECTION)
329 CheckRadioButton(hDlg, rad1, rad3, rad2);
330 if (lppd->Flags & PD_NOPAGENUMS)
332 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
333 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
334 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
335 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
336 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
338 else
340 if (lppd->Flags & PD_PAGENUMS)
341 CheckRadioButton(hDlg, rad1, rad3, rad3);
343 /* FIXME: in Win95, the radiobutton "All" is displayed as
344 * "Print all xxx pages"... This is not done here (yet?)
347 /* Collate pages */
348 if (lppd->Flags & PD_COLLATE)
349 FIXME(commdlg, "PD_COLLATE not implemented yet\n");
351 /* print to file */
352 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
353 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
354 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
355 if (lppd->Flags & PD_HIDEPRINTTOFILE)
356 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
358 /* status */
360 /* help button */
361 if ((lppd->Flags & PD_SHOWHELP)==0)
362 { /* hide if PD_SHOWHELP not specified */
363 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
366 TRACE(commdlg, "succesful!\n");
367 return TRUE;
371 /***********************************************************************
372 * PRINTDLG_ValidateAndDuplicateSettings [internal]
375 * updates the PrintDlg structure for returnvalues.
376 * RETURNS
377 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
378 * TRUE if succesful.
380 BOOL PRINTDLG_ValidateAndDuplicateSettings(HWND hDlg,
381 PRINT_PTRA* PrintStructures)
383 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
385 /* check whether nFromPage and nToPage are within range defined by
386 * nMinPage and nMaxPage
388 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED)
390 WORD nToPage;
391 WORD nFromPage;
392 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
393 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
394 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
395 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage)
397 char TempBuffer[256];
398 FIXME(commdlg, "This MessageBox is not internationalised.");
399 sprintf(TempBuffer, "This value lies not within Page range\n"
400 "Please enter a value between %d and %d",
401 lppd->nMinPage, lppd->nMaxPage);
402 MessageBoxA(hDlg, TempBuffer, "Print", MB_OK | MB_ICONWARNING);
403 return(FALSE);
405 lppd->nFromPage = nFromPage;
406 lppd->nToPage = nToPage;
409 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED)
411 lppd->Flags |= PD_PRINTTOFILE;
412 /* FIXME: insert code to set "FILE:" in DEVNAMES structure */
415 return(TRUE);
419 /***********************************************************************
420 * PRINTDLG_WMCommand [internal]
422 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam,
423 LPARAM lParam, PRINT_PTRA* PrintStructures)
425 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
427 switch (LOWORD(wParam))
429 case IDOK:
430 TRACE(commdlg, " OK button was hit\n");
431 if (PRINTDLG_ValidateAndDuplicateSettings(hDlg, PrintStructures) != TRUE)
432 return(FALSE);
433 DestroyWindow(hDlg);
434 return(TRUE);
435 case IDCANCEL:
436 TRACE(commdlg, " CANCEL button was hit\n");
437 EndDialog(hDlg, FALSE);
438 return(FALSE);
439 case pshHelp:
440 TRACE(commdlg, " HELP button was hit\n");
441 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
442 (WPARAM) hDlg, (LPARAM) lppd);
443 break;
444 case edt1: /* from page nr editbox */
445 case edt2: /* to page nr editbox */
446 if (HIWORD(wParam)==EN_CHANGE)
448 WORD nToPage;
449 WORD nFromPage;
450 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
451 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
452 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
453 CheckRadioButton(hDlg, rad1, rad3, rad3);
455 break;
456 case psh2: /* Properties button */
458 HANDLE hPrinter;
459 char PrinterName[256];
460 GetDlgItemTextA(hDlg, cmb4, PrinterName, 255);
461 if (OpenPrinterA(PrinterName, &hPrinter, NULL))
463 PrinterProperties(hDlg, hPrinter);
464 ClosePrinter(hPrinter);
466 else
467 WARN(commdlg, " Call to OpenPrinter did not succeed!\n");
468 break;
470 case cmb4: /* Printer combobox */
471 if (HIWORD(wParam)==CBN_SELCHANGE)
472 PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures);
473 break;
474 /* default:
475 printf("wParam: 0x%x ",wParam);
476 break;
477 */ }
478 return FALSE;
483 /***********************************************************************
484 * PrintDlgProcA [internal]
486 LRESULT WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
487 LPARAM lParam)
489 PRINT_PTRA* PrintStructures;
490 LRESULT res=FALSE;
491 if (uMsg!=WM_INITDIALOG)
493 PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);
494 if (!PrintStructures)
495 return FALSE;
497 else
499 PrintStructures=(PRINT_PTRA*) lParam;
500 if (!PRINTDLG_WMInitDialog(hDlg, wParam, lParam, PrintStructures))
502 TRACE(commdlg, "PRINTDLG_WMInitDialog returned FALSE\n");
503 return FALSE;
505 MessageBoxA(hDlg,"Warning: this dialog has no functionality yet!",
506 NULL, MB_OK);
508 switch (uMsg)
510 case WM_COMMAND:
511 return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
512 case WM_DESTROY:
513 return FALSE;
516 return res;
522 /***********************************************************************
523 * PrintDlgProc16 (COMMDLG.21)
525 LRESULT WINAPI PrintDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
526 LPARAM lParam)
528 switch (wMsg)
530 case WM_INITDIALOG:
531 TRACE(commdlg,"WM_INITDIALOG lParam=%08lX\n", lParam);
532 ShowWindow16(hWnd, SW_SHOWNORMAL);
533 return (TRUE);
534 case WM_COMMAND:
535 switch (wParam)
537 case IDOK:
538 EndDialog(hWnd, TRUE);
539 return(TRUE);
540 case IDCANCEL:
541 EndDialog(hWnd, FALSE);
542 return(TRUE);
544 return(FALSE);
546 return FALSE;
550 /***********************************************************************
551 * PrintSetupDlgProc (COMMDLG.22)
553 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
554 LPARAM lParam)
556 switch (wMsg)
558 case WM_INITDIALOG:
559 TRACE(commdlg,"WM_INITDIALOG lParam=%08lX\n", lParam);
560 ShowWindow16(hWnd, SW_SHOWNORMAL);
561 return (TRUE);
562 case WM_COMMAND:
563 switch (wParam) {
564 case IDOK:
565 EndDialog(hWnd, TRUE);
566 return(TRUE);
567 case IDCANCEL:
568 EndDialog(hWnd, FALSE);
569 return(TRUE);
571 return(FALSE);
573 return FALSE;
579 /***********************************************************************
580 * PageSetupDlgA (COMDLG32.15)
582 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
583 FIXME(commdlg,"(%p), stub!\n",setupdlg);
584 return FALSE;