Implement PrintDlg16 better (adding PrintDlgProc16 and several other
[wine/multimedia.git] / dlls / commdlg / printdlg.c
blobb1131c138ffbf95a8c35a1392f3669a2bb8c3897
1 /*
2 * COMMDLG - Print Dialog
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"
26 DEFAULT_DEBUG_CHANNEL(commdlg);
28 #include "cdlg.h"
30 /* This PRINTDLGA internal structure stores
31 * pointers to several throughout useful structures.
34 typedef struct
36 LPDEVMODEA lpDevMode;
37 struct {
38 LPPRINTDLGA lpPrintDlg;
39 LPPRINTDLG16 lpPrintDlg16;
40 } dlg;
41 LPPRINTER_INFO_2A lpPrinterInfo;
42 UINT HelpMessageID;
43 HICON hCollateIcon; /* PrintDlg only */
44 HICON hNoCollateIcon; /* PrintDlg only */
45 HICON hPortraitIcon; /* PrintSetupDlg only */
46 HICON hLandscapeIcon; /* PrintSetupDlg only */
47 } PRINT_PTRA;
49 /* Debugiging info */
50 static struct pd_flags {
51 DWORD flag;
52 LPSTR name;
53 } pd_flags[] = {
54 {PD_SELECTION, "PD_SELECTION "},
55 {PD_PAGENUMS, "PD_PAGENUMS "},
56 {PD_NOSELECTION, "PD_NOSELECTION "},
57 {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
58 {PD_COLLATE, "PD_COLLATE "},
59 {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
60 {PD_PRINTSETUP, "PD_PRINTSETUP "},
61 {PD_NOWARNING, "PD_NOWARNING "},
62 {PD_RETURNDC, "PD_RETURNDC "},
63 {PD_RETURNIC, "PD_RETURNIC "},
64 {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
65 {PD_SHOWHELP, "PD_SHOWHELP "},
66 {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
67 {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
68 {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
69 {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
70 {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
71 {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
72 {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
73 {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
74 {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
75 {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
76 {-1, NULL}
80 /***********************************************************************
81 * PRINTDLG_GetDefaultPrinterName
83 * Returns the default printer name in buf.
84 * Even under WinNT/2000 default printer is retrieved via GetProfileString -
85 * these entries are mapped somewhere in the registry rather than win.ini.
87 * Returns TRUE on success else FALSE
89 static BOOL PRINTDLG_GetDefaultPrinterName(LPSTR buf, DWORD len)
91 char *ptr;
93 if(!GetProfileStringA("windows", "device", "", buf, len)) {
94 TRACE("No profile entry for default printer found.\n");
95 return FALSE;
97 if((ptr = strchr(buf, ',')) == NULL) {
98 FIXME("bad format for default printer (%s)!\n",buf);
99 return FALSE;
101 *ptr = '\0';
102 return TRUE;
105 /***********************************************************************
106 * PRINTDLG_OpenDefaultPrinter
108 * Returns a winspool printer handle to the default printer in *hprn
109 * Caller must call ClosePrinter on the handle
111 * Returns TRUE on success else FALSE
113 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
115 char buf[260];
116 BOOL res;
117 if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
118 return FALSE;
119 res = OpenPrinterA(buf, hprn, NULL);
120 if (!res)
121 FIXME("Could not open printer %s?!\n",buf);
122 return res;
125 /***********************************************************************
126 * PRINTDLG_SetUpPrinterListCombo
128 * Initializes printer list combox.
129 * hDlg: HWND of dialog
130 * id: Control id of combo
131 * name: Name of printer to select
133 * Initializes combo with list of available printers. Selects printer 'name'
134 * If name is NULL or does not exist select the default printer.
136 * Returns number of printers added to list.
138 static INT PRINTDLG_SetUpPrinterListCombo(HWND hDlg, UINT id, LPCSTR name)
140 DWORD needed, num;
141 INT i;
142 LPPRINTER_INFO_2A pi;
143 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
144 pi = HeapAlloc(GetProcessHeap(), 0, needed);
145 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
146 &num);
148 for(i = 0; i < num; i++) {
149 SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
150 (LPARAM)pi[i].pPrinterName );
152 HeapFree(GetProcessHeap(), 0, pi);
153 if(!name ||
154 (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
155 (LPARAM)name)) == CB_ERR) {
157 char buf[260];
158 FIXME("Can't find '%s' in printer list so trying to find default\n",
159 name);
160 if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
161 return num;
162 i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
163 if(i == CB_ERR)
164 FIXME("Can't find default printer in printer list\n");
166 SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
167 return num;
170 /***********************************************************************
171 * PRINTDLG_CreateDevNames [internal]
174 * creates a DevNames structure.
176 * (NB. when we handle unicode the offsets will be in wchars).
178 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName,
179 char* DeviceName, char* OutputPort)
181 long size;
182 char* pDevNamesSpace;
183 char* pTempPtr;
184 LPDEVNAMES lpDevNames;
185 char buf[260];
187 size = strlen(DeviceDriverName) + 1
188 + strlen(DeviceName) + 1
189 + strlen(OutputPort) + 1
190 + sizeof(DEVNAMES);
192 if(*hmem)
193 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
194 else
195 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
196 if (*hmem == 0)
197 return FALSE;
199 pDevNamesSpace = GlobalLock(*hmem);
200 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
202 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
203 strcpy(pTempPtr, DeviceDriverName);
204 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
206 pTempPtr += strlen(DeviceDriverName) + 1;
207 strcpy(pTempPtr, DeviceName);
208 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
210 pTempPtr += strlen(DeviceName) + 1;
211 strcpy(pTempPtr, OutputPort);
212 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
214 PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
215 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
216 GlobalUnlock(*hmem);
217 return TRUE;
220 static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, char* DeviceDriverName,
221 char* DeviceName, char* OutputPort)
223 long size;
224 char* pDevNamesSpace;
225 char* pTempPtr;
226 LPDEVNAMES lpDevNames;
227 char buf[260];
229 size = strlen(DeviceDriverName) + 1
230 + strlen(DeviceName) + 1
231 + strlen(OutputPort) + 1
232 + sizeof(DEVNAMES);
234 if(*hmem)
235 *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE);
236 else
237 *hmem = GlobalAlloc16(GMEM_MOVEABLE, size);
238 if (*hmem == 0)
239 return FALSE;
241 pDevNamesSpace = GlobalLock16(*hmem);
242 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
244 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
245 strcpy(pTempPtr, DeviceDriverName);
246 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
248 pTempPtr += strlen(DeviceDriverName) + 1;
249 strcpy(pTempPtr, DeviceName);
250 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
252 pTempPtr += strlen(DeviceName) + 1;
253 strcpy(pTempPtr, OutputPort);
254 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
256 PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
257 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
258 GlobalUnlock16(*hmem);
259 return TRUE;
263 /***********************************************************************
264 * PRINTDLG_UpdatePrintDlg [internal]
267 * updates the PrintDlg structure for returnvalues.
269 * RETURNS
270 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
271 * TRUE if succesful.
273 static BOOL PRINTDLG_UpdatePrintDlg(HWND hDlg,
274 PRINT_PTRA* PrintStructures)
276 LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
277 PDEVMODEA lpdm = PrintStructures->lpDevMode;
278 LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
281 if(!lpdm) {
282 FIXME("No lpdm ptr?\n");
283 return FALSE;
287 if(!(lppd->Flags & PD_PRINTSETUP)) {
288 /* check whether nFromPage and nToPage are within range defined by
289 * nMinPage and nMaxPage
291 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
292 WORD nToPage;
293 WORD nFromPage;
294 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
295 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
296 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
297 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
298 char resourcestr[256];
299 char resultstr[256];
300 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
301 resourcestr, 255);
302 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
303 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
304 resourcestr, 255);
305 MessageBoxA(hDlg, resultstr, resourcestr,
306 MB_OK | MB_ICONWARNING);
307 return FALSE;
309 lppd->nFromPage = nFromPage;
310 lppd->nToPage = nToPage;
313 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
314 lppd->Flags |= PD_PRINTTOFILE;
315 pi->pPortName = "FILE:";
318 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
319 FIXME("Collate lppd not yet implemented as output\n");
322 /* set PD_Collate and nCopies */
323 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
324 /* The application doesn't support multiple copies or collate...
326 lppd->Flags &= ~PD_COLLATE;
327 lppd->nCopies = 1;
328 /* if the printer driver supports it... store info there
329 * otherwise no collate & multiple copies !
331 if (lpdm->dmFields & DM_COLLATE)
332 lpdm->dmCollate =
333 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
334 if (lpdm->dmFields & DM_COPIES)
335 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
336 } else {
337 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
338 lppd->Flags |= PD_COLLATE;
339 else
340 lppd->Flags &= ~PD_COLLATE;
341 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
344 return TRUE;
348 /************************************************************************
349 * PRINTDLG_SetUpPaperComboBox
351 * Initialize either the papersize or inputslot combos of the Printer Setup
352 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
353 * We also try to re-select the old selection.
355 static BOOL PRINTDLG_SetUpPaperComboBox(HWND hDlg,
356 int nIDComboBox,
357 char* PrinterName,
358 char* PortName,
359 LPDEVMODEA dm)
361 int i;
362 DWORD NrOfEntries;
363 char* Names;
364 WORD* Words;
365 DWORD Sel;
366 WORD oldWord = 0;
367 int NamesSize;
368 int fwCapability_Names;
369 int fwCapability_Words;
371 TRACE(" Printer: %s, ComboID: %d\n",PrinterName,nIDComboBox);
373 /* query the dialog box for the current selected value */
374 Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
375 if(Sel != CB_ERR) {
376 oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, Sel,
380 if (nIDComboBox == cmb2) {
381 NamesSize = 64;
382 fwCapability_Names = DC_PAPERNAMES;
383 fwCapability_Words = DC_PAPERS;
384 } else {
385 nIDComboBox = cmb3;
386 NamesSize = 24;
387 fwCapability_Names = DC_BINNAMES;
388 fwCapability_Words = DC_BINS;
391 /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
392 * paper settings. As Wine doesn't allow VXDs, this results in a crash.
394 WARN(" if your printer driver uses VXDs, expect a crash now!\n");
395 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
396 fwCapability_Names, NULL, dm);
397 if (NrOfEntries == 0)
398 WARN("no Name Entries found!\n");
400 if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
401 != NrOfEntries) {
402 ERR("Number of caps is different\n");
403 NrOfEntries = 0;
406 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*NamesSize);
407 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
408 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
409 fwCapability_Names, Names, dm);
410 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
411 fwCapability_Words, (LPSTR)Words, dm);
413 /* reset any current content in the combobox */
414 SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
416 /* store new content */
417 for (i = 0; i < NrOfEntries; i++) {
418 DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
419 (LPARAM)(&Names[i*NamesSize]) );
420 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
421 Words[i]);
424 /* Look for old selection - can't do this is previous loop since
425 item order will change as more items are added */
426 Sel = 0;
427 for (i = 0; i < NrOfEntries; i++) {
428 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
429 oldWord) {
430 Sel = i;
431 break;
434 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
436 HeapFree(GetProcessHeap(),0,Words);
437 HeapFree(GetProcessHeap(),0,Names);
438 return TRUE;
441 /***********************************************************************
442 * PRINTDLG_UpdatePrinterInfoTexts [internal]
444 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, LPPRINTER_INFO_2A pi)
446 char StatusMsg[256];
447 char ResourceString[256];
448 int i;
450 /* Status Message */
451 StatusMsg[0]='\0';
453 /* add all status messages */
454 for (i = 0; i < 25; i++) {
455 if (pi->Status & (1<<i)) {
456 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
457 ResourceString, 255);
458 strcat(StatusMsg,ResourceString);
461 /* append "ready" */
462 /* FIXME: status==ready must only be appended if really so.
463 but how to detect? */
464 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
465 ResourceString, 255);
466 strcat(StatusMsg,ResourceString);
468 SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
470 /* set all other printer info texts */
471 SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)pi->pDriverName);
472 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
473 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pLocation);
474 else
475 SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pPortName);
476 SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)pi->pComment);
477 return;
481 /*******************************************************************
483 * PRINTDLG_ChangePrinter
486 static BOOL PRINTDLG_ChangePrinter(HWND hDlg, char *name,
487 PRINT_PTRA *PrintStructures)
489 LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
490 LPDEVMODEA lpdm = NULL;
491 LONG dmSize;
492 DWORD needed;
493 HANDLE hprn;
495 if(PrintStructures->lpPrinterInfo)
496 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
497 if(!OpenPrinterA(name, &hprn, NULL)) {
498 ERR("Can't open printer %s\n", name);
499 return FALSE;
501 GetPrinterA(hprn, 2, NULL, 0, &needed);
502 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
503 GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
504 &needed);
505 ClosePrinter(hprn);
507 PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures->lpPrinterInfo);
509 if(PrintStructures->lpDevMode) {
510 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
511 PrintStructures->lpDevMode = NULL;
514 dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
515 if(dmSize == -1) {
516 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
517 return FALSE;
519 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
520 dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
521 DM_OUT_BUFFER);
522 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
523 !strcmp(lpdm->dmDeviceName,
524 PrintStructures->lpDevMode->dmDeviceName)) {
525 /* Supplied devicemode matches current printer so try to use it */
526 DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
527 DM_OUT_BUFFER | DM_IN_BUFFER);
529 if(lpdm)
530 GlobalUnlock(lppd->hDevMode);
532 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
534 if(!(lppd->Flags & PD_PRINTSETUP)) {
535 /* Print range (All/Range/Selection) */
536 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
537 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
538 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
539 if (lppd->Flags & PD_NOSELECTION)
540 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
541 else
542 if (lppd->Flags & PD_SELECTION)
543 CheckRadioButton(hDlg, rad1, rad3, rad2);
544 if (lppd->Flags & PD_NOPAGENUMS) {
545 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
546 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
547 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
548 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
549 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
550 } else {
551 if (lppd->Flags & PD_PAGENUMS)
552 CheckRadioButton(hDlg, rad1, rad3, rad3);
554 /* "All xxx pages"... */
556 char resourcestr[64];
557 char result[64];
558 LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES,
559 resourcestr, 49);
560 sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
561 SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
564 /* Collate pages
566 * FIXME: The ico3 is not displayed for some reason. I don't know why.
568 if (lppd->Flags & PD_COLLATE) {
569 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
570 (LPARAM)PrintStructures->hCollateIcon);
571 CheckDlgButton(hDlg, chx2, 1);
572 } else {
573 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
574 (LPARAM)PrintStructures->hNoCollateIcon);
575 CheckDlgButton(hDlg, chx2, 0);
578 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
579 /* if printer doesn't support it: no Collate */
580 if (!(lpdm->dmFields & DM_COLLATE)) {
581 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
582 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
586 /* nCopies */
587 if (lppd->hDevMode == 0)
588 SetDlgItemInt(hDlg, edt3, lppd->nCopies, FALSE);
589 else
590 SetDlgItemInt(hDlg, edt3, lpdm->dmCopies, FALSE);
592 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
593 /* if printer doesn't support it: no nCopies */
594 if (!(lpdm->dmFields & DM_COPIES)) {
595 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
596 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
600 /* print to file */
601 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
602 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
603 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
604 if (lppd->Flags & PD_HIDEPRINTTOFILE)
605 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
607 } else { /* PD_PRINTSETUP */
608 PRINTDLG_SetUpPaperComboBox(hDlg, cmb2,
609 PrintStructures->lpPrinterInfo->pPrinterName,
610 PrintStructures->lpPrinterInfo->pPortName,
611 lpdm);
612 PRINTDLG_SetUpPaperComboBox(hDlg, cmb3,
613 PrintStructures->lpPrinterInfo->pPrinterName,
614 PrintStructures->lpPrinterInfo->pPortName,
615 lpdm);
616 CheckRadioButton(hDlg, rad1, rad2,
617 (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT) ?
618 rad1: rad2);
621 /* help button */
622 if ((lppd->Flags & PD_SHOWHELP)==0) {
623 /* hide if PD_SHOWHELP not specified */
624 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
626 return TRUE;
629 /***********************************************************************
630 * PRINTDLG_WMInitDialog [internal]
632 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
633 PRINT_PTRA* PrintStructures)
635 LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
636 DEVNAMES *pdn;
637 DEVMODEA *pdm;
638 char *name = NULL;
639 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
641 /* load Collate ICONs */
642 PrintStructures->hCollateIcon =
643 LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
644 PrintStructures->hNoCollateIcon =
645 LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
646 if(PrintStructures->hCollateIcon == 0 ||
647 PrintStructures->hNoCollateIcon == 0) {
648 ERR("no icon in resourcefile\n");
649 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
650 EndDialog(hDlg, FALSE);
653 /* load Paper Orientation ICON */
654 /* FIXME: not implemented yet */
657 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
658 * must be registered and the Help button must be shown.
660 if (lppd->Flags & PD_SHOWHELP) {
661 if((PrintStructures->HelpMessageID =
662 RegisterWindowMessageA(HELPMSGSTRING)) == 0) {
663 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
664 return FALSE;
666 } else
667 PrintStructures->HelpMessageID = 0;
669 /* FIXME: I allow more freedom than either Win95 or WinNT,
670 * which do not agree to what errors should be thrown or not
671 * in case nToPage or nFromPage is out-of-range.
673 if (lppd->nMaxPage < lppd->nMinPage)
674 lppd->nMaxPage = lppd->nMinPage;
675 if (lppd->nMinPage == lppd->nMaxPage)
676 lppd->Flags |= PD_NOPAGENUMS;
677 if (lppd->nToPage < lppd->nMinPage)
678 lppd->nToPage = lppd->nMinPage;
679 if (lppd->nToPage > lppd->nMaxPage)
680 lppd->nToPage = lppd->nMaxPage;
681 if (lppd->nFromPage < lppd->nMinPage)
682 lppd->nFromPage = lppd->nMinPage;
683 if (lppd->nFromPage > lppd->nMaxPage)
684 lppd->nFromPage = lppd->nMaxPage;
686 /* if we have the combo box, fill it */
687 if (GetDlgItem(hDlg,comboID)) {
688 /* Fill Combobox
690 pdn = GlobalLock(lppd->hDevNames);
691 pdm = GlobalLock(lppd->hDevMode);
692 if(pdn)
693 name = (char*)pdn + pdn->wDeviceOffset;
694 else if(pdm)
695 name = pdm->dmDeviceName;
696 PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
697 if(pdm) GlobalUnlock(lppd->hDevMode);
698 if(pdn) GlobalUnlock(lppd->hDevNames);
700 /* Now find selected printer and update rest of dlg */
701 name = HeapAlloc(GetProcessHeap(),0,256);
702 if (GetDlgItemTextA(hDlg, comboID, name, 255))
703 PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
704 HeapFree(GetProcessHeap(),0,name);
705 } else {
706 /* else use default printer */
707 char name[200];
708 BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
710 if (ret)
711 PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
712 else
713 FIXME("No default printer found, expect problems!\n");
715 return TRUE;
718 /***********************************************************************
719 * PRINTDLG_WMInitDialog [internal]
721 static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam,
722 PRINT_PTRA* PrintStructures)
724 LPPRINTDLG16 lppd = PrintStructures->dlg.lpPrintDlg16;
725 DEVNAMES *pdn;
726 DEVMODEA *pdm;
727 char *name = NULL;
728 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
730 /* load Collate ICONs */
731 PrintStructures->hCollateIcon =
732 LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
733 PrintStructures->hNoCollateIcon =
734 LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
735 if(PrintStructures->hCollateIcon == 0 ||
736 PrintStructures->hNoCollateIcon == 0) {
737 ERR("no icon in resourcefile\n");
738 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
739 EndDialog(hDlg, FALSE);
742 /* load Paper Orientation ICON */
743 /* FIXME: not implemented yet */
746 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
747 * must be registered and the Help button must be shown.
749 if (lppd->Flags & PD_SHOWHELP) {
750 if((PrintStructures->HelpMessageID =
751 RegisterWindowMessageA(HELPMSGSTRING)) == 0) {
752 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
753 return FALSE;
755 } else
756 PrintStructures->HelpMessageID = 0;
758 /* FIXME: I allow more freedom than either Win95 or WinNT,
759 * which do not agree to what errors should be thrown or not
760 * in case nToPage or nFromPage is out-of-range.
762 if (lppd->nMaxPage < lppd->nMinPage)
763 lppd->nMaxPage = lppd->nMinPage;
764 if (lppd->nMinPage == lppd->nMaxPage)
765 lppd->Flags |= PD_NOPAGENUMS;
766 if (lppd->nToPage < lppd->nMinPage)
767 lppd->nToPage = lppd->nMinPage;
768 if (lppd->nToPage > lppd->nMaxPage)
769 lppd->nToPage = lppd->nMaxPage;
770 if (lppd->nFromPage < lppd->nMinPage)
771 lppd->nFromPage = lppd->nMinPage;
772 if (lppd->nFromPage > lppd->nMaxPage)
773 lppd->nFromPage = lppd->nMaxPage;
775 /* If the printer combo box is in the dialog, fill it */
776 if (GetDlgItem(hDlg,comboID)) {
777 /* Fill Combobox
779 pdn = GlobalLock16(lppd->hDevNames);
780 pdm = GlobalLock16(lppd->hDevMode);
781 if(pdn)
782 name = (char*)pdn + pdn->wDeviceOffset;
783 else if(pdm)
784 name = pdm->dmDeviceName;
785 PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
786 if(pdm) GlobalUnlock16(lppd->hDevMode);
787 if(pdn) GlobalUnlock16(lppd->hDevNames);
789 /* Now find selected printer and update rest of dlg */
790 name = HeapAlloc(GetProcessHeap(),0,256);
791 if (GetDlgItemTextA(hDlg, comboID, name, 255))
792 PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
793 } else {
794 /* else just use default printer */
795 char name[200];
796 BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
798 if (ret)
799 PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
800 else
801 FIXME("No default printer found, expect problems!\n");
803 HeapFree(GetProcessHeap(),0,name);
805 return TRUE;
808 /***********************************************************************
809 * PRINTDLG_WMCommand [internal]
811 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam,
812 LPARAM lParam, PRINT_PTRA* PrintStructures)
814 LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
815 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
816 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
818 switch (LOWORD(wParam)) {
819 case IDOK:
820 TRACE(" OK button was hit\n");
821 if (PRINTDLG_UpdatePrintDlg(hDlg, PrintStructures)!=TRUE) {
822 FIXME("Update printdlg was not successful!\n");
823 return(FALSE);
825 EndDialog(hDlg, TRUE);
826 return(TRUE);
828 case IDCANCEL:
829 TRACE(" CANCEL button was hit\n");
830 EndDialog(hDlg, FALSE);
831 return(FALSE);
833 case pshHelp:
834 TRACE(" HELP button was hit\n");
835 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
836 (WPARAM) hDlg, (LPARAM) lppd);
837 break;
839 case chx2: /* collate pages checkbox */
840 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
841 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
842 (LPARAM)PrintStructures->hCollateIcon);
843 else
844 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
845 (LPARAM)PrintStructures->hNoCollateIcon);
846 break;
847 case edt1: /* from page nr editbox */
848 case edt2: /* to page nr editbox */
849 if (HIWORD(wParam)==EN_CHANGE) {
850 WORD nToPage;
851 WORD nFromPage;
852 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
853 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
854 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
855 CheckRadioButton(hDlg, rad1, rad3, rad3);
857 break;
858 case psh2: /* Properties button */
860 HANDLE hPrinter;
861 char PrinterName[256];
863 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
864 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
865 FIXME(" Call to OpenPrinter did not succeed!\n");
866 break;
868 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
869 PrintStructures->lpDevMode,
870 PrintStructures->lpDevMode,
871 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
872 ClosePrinter(hPrinter);
873 break;
876 case cmb1:
877 case cmb4: /* Printer combobox */
878 if (HIWORD(wParam)==CBN_SELCHANGE) {
879 char PrinterName[256];
880 GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
881 PRINTDLG_ChangePrinter(hDlg, PrinterName, PrintStructures);
883 break;
885 case cmb2: /* Papersize */
887 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
888 if(Sel != CB_ERR)
889 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
890 CB_GETITEMDATA,
891 Sel, 0);
893 break;
895 case cmb3: /* Bin */
897 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
898 if(Sel != CB_ERR)
899 lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
900 CB_GETITEMDATA, Sel,
903 break;
905 return FALSE;
908 /***********************************************************************
909 * PrintDlgProcA [internal]
911 BOOL WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
912 LPARAM lParam)
914 PRINT_PTRA* PrintStructures;
915 LRESULT res=FALSE;
917 if (uMsg!=WM_INITDIALOG) {
918 PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);
919 if (!PrintStructures)
920 return FALSE;
921 } else {
922 PrintStructures = (PRINT_PTRA*) lParam;
923 SetWindowLongA(hDlg, DWL_USER, lParam);
924 res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
926 if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
927 res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(
928 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg
930 return res;
933 if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
934 res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
935 lParam);
936 if(res) return res;
939 switch (uMsg) {
940 case WM_COMMAND:
941 return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
943 case WM_DESTROY:
944 DestroyIcon(PrintStructures->hCollateIcon);
945 DestroyIcon(PrintStructures->hNoCollateIcon);
946 /* FIXME: don't forget to delete the paper orientation icons here! */
948 return FALSE;
950 return res;
953 /************************************************************
955 * PRINTDLG_GetDlgTemplate
958 static HGLOBAL PRINTDLG_GetDlgTemplate(PRINTDLGA *lppd)
960 HGLOBAL hDlgTmpl, hResInfo;
962 if (lppd->Flags & PD_PRINTSETUP) {
963 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
964 hDlgTmpl = lppd->hSetupTemplate;
965 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
966 hResInfo = FindResourceA(lppd->hInstance,
967 lppd->lpSetupTemplateName, RT_DIALOGA);
968 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
969 } else {
970 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
971 RT_DIALOGA);
972 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
974 } else {
975 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
976 hDlgTmpl = lppd->hPrintTemplate;
977 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
978 hResInfo = FindResourceA(lppd->hInstance,
979 lppd->lpPrintTemplateName,
980 RT_DIALOGA);
981 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
982 } else {
983 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
984 RT_DIALOGA);
985 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
988 return hDlgTmpl;
991 /************************************************************
993 * PRINTDLG_GetDlgTemplate
996 static HGLOBAL16 PRINTDLG_GetDlgTemplate16(PRINTDLG16 *lppd)
998 HGLOBAL16 hDlgTmpl, hResInfo;
1000 if (lppd->Flags & PD_PRINTSETUP) {
1001 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1002 hDlgTmpl = lppd->hSetupTemplate;
1003 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1004 hResInfo = FindResource16(lppd->hInstance,
1005 MapSL(lppd->lpSetupTemplateName), RT_DIALOGA);
1006 hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1007 } else {
1008 ERR("no comctl32 templates for printing setup currently!\n");
1009 hDlgTmpl = 0;
1011 } else {
1012 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1013 hDlgTmpl = lppd->hPrintTemplate;
1014 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1015 hResInfo = FindResource16(lppd->hInstance,
1016 MapSL(lppd->lpPrintTemplateName),
1017 RT_DIALOGA);
1018 hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1019 } else {
1020 ERR("no comctl32 templates for printing currently!\n");
1021 hDlgTmpl = 0;
1024 return hDlgTmpl;
1027 /***********************************************************************
1029 * PRINTDLG_CreateDC
1032 static BOOL PRINTDLG_CreateDC(LPPRINTDLGA lppd)
1034 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1035 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1037 if(lppd->Flags & PD_RETURNDC) {
1038 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1039 (char*)pdn + pdn->wDeviceOffset,
1040 (char*)pdn + pdn->wOutputOffset,
1041 pdm );
1042 } else if(lppd->Flags & PD_RETURNIC) {
1043 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1044 (char*)pdn + pdn->wDeviceOffset,
1045 (char*)pdn + pdn->wOutputOffset,
1046 pdm );
1048 GlobalUnlock(lppd->hDevNames);
1049 GlobalUnlock(lppd->hDevMode);
1050 return lppd->hDC ? TRUE : FALSE;
1053 static BOOL PRINTDLG_CreateDC16(LPPRINTDLG16 lppd)
1055 DEVNAMES *pdn = GlobalLock16(lppd->hDevNames);
1056 DEVMODEA *pdm = GlobalLock16(lppd->hDevMode);
1058 if(lppd->Flags & PD_RETURNDC) {
1059 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1060 (char*)pdn + pdn->wDeviceOffset,
1061 (char*)pdn + pdn->wOutputOffset,
1062 pdm );
1063 } else if(lppd->Flags & PD_RETURNIC) {
1064 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1065 (char*)pdn + pdn->wDeviceOffset,
1066 (char*)pdn + pdn->wOutputOffset,
1067 pdm );
1069 GlobalUnlock16(lppd->hDevNames);
1070 GlobalUnlock16(lppd->hDevMode);
1071 return lppd->hDC ? TRUE : FALSE;
1074 /***********************************************************************
1075 * PrintDlgA (COMDLG32.17)
1077 * Displays the the PRINT dialog box, which enables the user to specify
1078 * specific properties of the print job.
1080 * RETURNS
1081 * nonzero if the user pressed the OK button
1082 * zero if the user cancelled the window or an error occurred
1084 * BUGS
1085 * PrintDlg:
1086 * * The Collate Icons do not display, even though they are in the code.
1087 * * The Properties Button(s) should call DocumentPropertiesA().
1088 * PrintSetupDlg:
1089 * * The Paper Orientation Icons are not implemented yet.
1090 * * The Properties Button(s) should call DocumentPropertiesA().
1091 * * Settings are not yet taken from a provided DevMode or
1092 * default printer settings.
1094 BOOL WINAPI PrintDlgA(
1095 LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1098 BOOL bRet = FALSE;
1099 LPVOID ptr;
1100 HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1102 if(TRACE_ON(commdlg)) {
1103 char flagstr[1000] = "";
1104 struct pd_flags *pflag = pd_flags;
1105 for( ; pflag->name; pflag++) {
1106 if(lppd->Flags & pflag->flag)
1107 strcat(flagstr, pflag->name);
1109 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1110 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1111 "flags %08lx (%s)\n",
1112 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1113 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1114 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1117 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1118 WARN("structure size failure !!!\n");
1119 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1120 return FALSE;
1123 if(lppd->Flags & PD_RETURNDEFAULT) {
1124 PRINTER_INFO_2A *pbuf;
1125 HANDLE hprn;
1126 DWORD needed;
1128 if(lppd->hDevMode || lppd->hDevNames) {
1129 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1130 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
1131 return FALSE;
1133 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1134 WARN("Can't find default printer\n");
1135 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
1136 return FALSE;
1139 GetPrinterA(hprn, 2, NULL, 0, &needed);
1140 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1141 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1142 ClosePrinter(hprn);
1143 PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
1144 pbuf->pDevMode->dmDeviceName,
1145 pbuf->pPortName);
1146 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
1147 pbuf->pDevMode->dmDriverExtra);
1148 ptr = GlobalLock(lppd->hDevMode);
1149 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1150 pbuf->pDevMode->dmDriverExtra);
1151 GlobalUnlock(lppd->hDevMode);
1152 HeapFree(GetProcessHeap(), 0, pbuf);
1153 bRet = TRUE;
1154 } else {
1155 HGLOBAL hDlgTmpl;
1156 PRINT_PTRA *PrintStructures;
1158 /* load Dialog resources,
1159 * depending on Flags indicates Print32 or Print32_setup dialog
1161 hDlgTmpl = PRINTDLG_GetDlgTemplate(lppd);
1162 if (!hDlgTmpl) {
1163 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1164 return FALSE;
1166 ptr = LockResource( hDlgTmpl );
1167 if (!ptr) {
1168 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1169 return FALSE;
1172 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1173 sizeof(PRINT_PTRA));
1174 PrintStructures->dlg.lpPrintDlg = lppd;
1176 /* and create & process the dialog .
1177 * -1 is failure, 0 is broken hwnd, everything else is ok.
1179 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
1180 PrintDlgProcA,
1181 (LPARAM)PrintStructures));
1183 if(bRet) {
1184 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1185 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1187 if (lppd->hDevMode == 0) {
1188 TRACE(" No hDevMode yet... Need to create my own\n");
1189 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
1190 lpdm->dmSize + lpdm->dmDriverExtra);
1191 } else {
1192 WORD locks;
1193 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
1194 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1195 while(locks--) {
1196 GlobalUnlock(lppd->hDevMode);
1197 TRACE("Now got %d locks\n", locks);
1200 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
1201 lpdm->dmSize + lpdm->dmDriverExtra,
1202 GMEM_MOVEABLE);
1204 lpdmReturn = GlobalLock(lppd->hDevMode);
1205 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1207 if (lppd->hDevNames != 0) {
1208 WORD locks;
1209 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
1210 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1211 while(locks--)
1212 GlobalUnlock(lppd->hDevNames);
1215 PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
1216 lpdmReturn->dmDeviceName, pi->pPortName);
1217 GlobalUnlock(lppd->hDevMode);
1219 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1220 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1221 HeapFree(GetProcessHeap(), 0, PrintStructures);
1223 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1224 bRet = PRINTDLG_CreateDC(lppd);
1226 TRACE("exit! (%d)\n", bRet);
1227 return bRet;
1230 /***********************************************************************
1231 * PrintDlg16 (COMMDLG.20)
1233 * Displays the the PRINT dialog box, which enables the user to specify
1234 * specific properties of the print job.
1236 * RETURNS
1237 * nonzero if the user pressed the OK button
1238 * zero if the user cancelled the window or an error occurred
1240 * BUGS
1241 * * calls up to the 32-bit versions of the Dialogs, which look different
1242 * * Customizing is *not* implemented.
1245 BOOL16 WINAPI PrintDlg16(
1246 LPPRINTDLG16 lppd /* [in/out] ptr to PRINTDLG struct */
1248 BOOL bRet = FALSE;
1249 LPVOID ptr;
1250 HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1252 if(TRACE_ON(commdlg)) {
1253 char flagstr[1000] = "";
1254 struct pd_flags *pflag = pd_flags;
1255 for( ; pflag->name; pflag++) {
1256 if(lppd->Flags & pflag->flag)
1257 strcat(flagstr, pflag->name);
1259 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1260 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1261 "flags %08lx (%s)\n",
1262 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1263 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1264 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1267 if(lppd->lStructSize != sizeof(PRINTDLG16)) {
1268 ERR("structure size (%ld/%d)\n",lppd->lStructSize,sizeof(PRINTDLG16));
1269 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1270 return FALSE;
1273 if(lppd->Flags & PD_RETURNDEFAULT) {
1274 PRINTER_INFO_2A *pbuf;
1275 HANDLE hprn;
1276 DWORD needed;
1278 if(lppd->hDevMode || lppd->hDevNames) {
1279 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1280 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
1281 return FALSE;
1283 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1284 WARN("Can't find default printer\n");
1285 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
1286 return FALSE;
1289 GetPrinterA(hprn, 2, NULL, 0, &needed);
1290 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1291 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1292 ClosePrinter(hprn);
1293 PRINTDLG_CreateDevNames16(&(lppd->hDevNames), "winspool",
1294 pbuf->pDevMode->dmDeviceName,
1295 pbuf->pPortName);
1296 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,pbuf->pDevMode->dmSize+
1297 pbuf->pDevMode->dmDriverExtra);
1298 ptr = GlobalLock16(lppd->hDevMode);
1299 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1300 pbuf->pDevMode->dmDriverExtra);
1301 GlobalUnlock16(lppd->hDevMode);
1302 HeapFree(GetProcessHeap(), 0, pbuf);
1303 bRet = TRUE;
1304 } else {
1305 HGLOBAL hDlgTmpl;
1306 PRINT_PTRA *PrintStructures;
1308 /* load Dialog resources,
1309 * depending on Flags indicates Print32 or Print32_setup dialog
1311 hDlgTmpl = PRINTDLG_GetDlgTemplate16(lppd);
1312 if (!hDlgTmpl) {
1313 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1314 return FALSE;
1316 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1317 sizeof(PRINT_PTRA));
1318 PrintStructures->dlg.lpPrintDlg16 = lppd;
1319 PrintStructures->dlg.lpPrintDlg = (LPPRINTDLGA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PRINTDLGA));
1320 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
1321 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
1322 CVAL(Flags);CVAL(hwndOwner);CVAL(hDC);
1323 CVAL(nFromPage);CVAL(nToPage);CVAL(nMinPage);CVAL(nMaxPage);
1324 CVAL(nCopies);CVAL(hInstance);CVAL(lCustData);
1325 MVAL(lpPrintTemplateName);MVAL(lpSetupTemplateName);
1326 /* Don't copy rest, it is 16 bit specific */
1327 #undef MVAL
1328 #undef CVAL
1330 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA));
1332 /* and create & process the dialog .
1333 * -1 is failure, 0 is broken hwnd, everything else is ok.
1335 bRet = (0<DialogBoxIndirectParam16(
1336 hInst, hDlgTmpl, lppd->hwndOwner,
1337 (DLGPROC16)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR)21),
1338 (LPARAM)PrintStructures
1341 if (!PrintStructures->lpPrinterInfo) bRet = FALSE;
1342 if(bRet) {
1343 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1344 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1346 if (lppd->hDevMode == 0) {
1347 TRACE(" No hDevMode yet... Need to create my own\n");
1348 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,
1349 lpdm->dmSize + lpdm->dmDriverExtra);
1350 } else {
1351 WORD locks;
1352 if((locks = (GlobalFlags16(lppd->hDevMode)&GMEM_LOCKCOUNT))) {
1353 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1354 while(locks--) {
1355 GlobalUnlock16(lppd->hDevMode);
1356 TRACE("Now got %d locks\n", locks);
1359 lppd->hDevMode = GlobalReAlloc16(lppd->hDevMode,
1360 lpdm->dmSize + lpdm->dmDriverExtra,
1361 GMEM_MOVEABLE);
1363 lpdmReturn = GlobalLock16(lppd->hDevMode);
1364 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1366 if (lppd->hDevNames != 0) {
1367 WORD locks;
1368 if((locks = (GlobalFlags16(lppd->hDevNames)&GMEM_LOCKCOUNT))) {
1369 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1370 while(locks--)
1371 GlobalUnlock16(lppd->hDevNames);
1374 PRINTDLG_CreateDevNames16(&(lppd->hDevNames), "winspool",
1375 lpdmReturn->dmDeviceName, pi->pPortName);
1376 GlobalUnlock16(lppd->hDevMode);
1378 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1379 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1380 HeapFree(GetProcessHeap(), 0, PrintStructures);
1382 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1383 bRet = PRINTDLG_CreateDC16(lppd);
1385 TRACE("exit! (%d)\n", bRet);
1386 return bRet;
1391 /***********************************************************************
1392 * PrintDlgW (COMDLG32.18)
1394 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
1396 FIXME("A really empty stub\n" );
1397 return FALSE;
1400 /***********************************************************************
1402 * PageSetupDlg
1405 /***********************************************************************
1406 * PageSetupDlgA (COMDLG32.15)
1408 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
1409 FIXME("(%p), stub!\n",setupdlg);
1410 return FALSE;
1412 /***********************************************************************
1413 * PageSetupDlgW (COMDLG32.16)
1415 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
1416 FIXME("(%p), stub!\n",setupdlg);
1417 return FALSE;
1420 /**********************************************************************
1422 * 16 bit commdlg
1425 /***********************************************************************
1426 * PrintDlgProc16 (COMMDLG.21)
1428 LRESULT WINAPI PrintDlgProc16(HWND16 hDlg, UINT16 uMsg, WPARAM16 wParam,
1429 LPARAM lParam)
1431 PRINT_PTRA* PrintStructures;
1432 LRESULT res=FALSE;
1434 if (uMsg!=WM_INITDIALOG) {
1435 PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);
1436 if (!PrintStructures)
1437 return FALSE;
1438 } else {
1439 PrintStructures = (PRINT_PTRA*) lParam;
1440 SetWindowLongA(hDlg, DWL_USER, lParam);
1441 res = PRINTDLG_WMInitDialog16(hDlg, wParam, PrintStructures);
1443 if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
1444 res = CallWindowProc16(
1445 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
1446 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg16
1449 return res;
1452 if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
1453 res = CallWindowProc16(
1454 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
1455 hDlg,uMsg, wParam, lParam
1457 if(res) return res;
1460 switch (uMsg) {
1461 case WM_COMMAND:
1462 return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
1464 case WM_DESTROY:
1465 DestroyIcon(PrintStructures->hCollateIcon);
1466 DestroyIcon(PrintStructures->hNoCollateIcon);
1467 /* FIXME: don't forget to delete the paper orientation icons here! */
1469 return FALSE;
1471 return res;
1475 /***********************************************************************
1476 * PrintSetupDlgProc16 (COMMDLG.22)
1478 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1479 LPARAM lParam)
1481 switch (wMsg)
1483 case WM_INITDIALOG:
1484 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
1485 ShowWindow(hWnd, SW_SHOWNORMAL);
1486 return (TRUE);
1487 case WM_COMMAND:
1488 switch (wParam) {
1489 case IDOK:
1490 EndDialog(hWnd, TRUE);
1491 return(TRUE);
1492 case IDCANCEL:
1493 EndDialog(hWnd, FALSE);
1494 return(TRUE);
1496 return(FALSE);
1498 return FALSE;
1502 /***********************************************************************
1503 * PrintDlgExA
1505 HRESULT WINAPI PrintDlgExA(LPVOID lpPrintDlgExA) /* [???] FIXME: LPPRINTDLGEXA */
1507 FIXME("stub\n");
1508 return E_NOTIMPL;
1510 /***********************************************************************
1511 * PrintDlgExW
1513 HRESULT WINAPI PrintDlgExW(LPVOID lpPrintDlgExW) /* [???] FIXME: LPPRINTDLGEXW */
1515 FIXME("stub\n");
1516 return E_NOTIMPL;