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
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
35 #include "wine/wingdi16.h"
37 #include "wine/winuser16.h"
40 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
54 LPPRINTDLG16 lpPrintDlg16
;
57 /* Internal Functions */
59 static BOOL
PRINTDLG_CreateDevNames16(HGLOBAL16
*hmem
, char* DeviceDriverName
,
60 char* DeviceName
, char* OutputPort
)
65 LPDEVNAMES lpDevNames
;
67 DWORD dwBufLen
= sizeof(buf
);
69 size
= strlen(DeviceDriverName
) + 1
70 + strlen(DeviceName
) + 1
71 + strlen(OutputPort
) + 1
75 *hmem
= GlobalReAlloc16(*hmem
, size
, GMEM_MOVEABLE
);
77 *hmem
= GlobalAlloc16(GMEM_MOVEABLE
, size
);
81 pDevNamesSpace
= GlobalLock16(*hmem
);
82 lpDevNames
= (LPDEVNAMES
) pDevNamesSpace
;
84 pTempPtr
= pDevNamesSpace
+ sizeof(DEVNAMES
);
85 strcpy(pTempPtr
, DeviceDriverName
);
86 lpDevNames
->wDriverOffset
= pTempPtr
- pDevNamesSpace
;
88 pTempPtr
+= strlen(DeviceDriverName
) + 1;
89 strcpy(pTempPtr
, DeviceName
);
90 lpDevNames
->wDeviceOffset
= pTempPtr
- pDevNamesSpace
;
92 pTempPtr
+= strlen(DeviceName
) + 1;
93 strcpy(pTempPtr
, OutputPort
);
94 lpDevNames
->wOutputOffset
= pTempPtr
- pDevNamesSpace
;
96 GetDefaultPrinterA(buf
, &dwBufLen
);
97 lpDevNames
->wDefault
= (strcmp(buf
, DeviceName
) == 0) ? 1 : 0;
98 GlobalUnlock16(*hmem
);
103 /***********************************************************************
104 * PRINTDLG_WMInitDialog [internal]
106 static LRESULT
PRINTDLG_WMInitDialog16(HWND hDlg
, WPARAM wParam
, PRINT_PTRA16
* ptr16
)
108 PRINT_PTRA
*PrintStructures
= &ptr16
->print32
;
109 LPPRINTDLG16 lppd
= ptr16
->lpPrintDlg16
;
113 UINT comboID
= (lppd
->Flags
& PD_PRINTSETUP
) ? cmb1
: cmb4
;
115 /* load Collate ICONs */
116 PrintStructures
->hCollateIcon
=
117 LoadIconA(COMDLG32_hInstance
, "PD32_COLLATE");
118 PrintStructures
->hNoCollateIcon
=
119 LoadIconA(COMDLG32_hInstance
, "PD32_NOCOLLATE");
120 if(PrintStructures
->hCollateIcon
== 0 ||
121 PrintStructures
->hNoCollateIcon
== 0) {
122 ERR("no icon in resourcefile\n");
123 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
124 EndDialog(hDlg
, FALSE
);
127 /* load Paper Orientation ICON */
128 /* FIXME: not implemented yet */
131 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
132 * must be registered and the Help button must be shown.
134 if (lppd
->Flags
& PD_SHOWHELP
) {
135 if((PrintStructures
->HelpMessageID
=
136 RegisterWindowMessageA(HELPMSGSTRINGA
)) == 0) {
137 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL
);
141 PrintStructures
->HelpMessageID
= 0;
143 if (!(lppd
->Flags
& PD_PRINTSETUP
)) {
144 /* We have a print quality combo box. What shall we do? */
145 if (GetDlgItem(hDlg
,cmb1
)) {
148 FIXME("Print quality only displaying currently.\n");
150 pdm
= GlobalLock16(lppd
->hDevMode
);
152 switch (pdm
->dmPrintQuality
) {
153 case DMRES_HIGH
: strcpy(buf
,"High");break;
154 case DMRES_MEDIUM
: strcpy(buf
,"Medium");break;
155 case DMRES_LOW
: strcpy(buf
,"Low");break;
156 case DMRES_DRAFT
: strcpy(buf
,"Draft");break;
157 case 0 : strcpy(buf
,"Default");break;
158 default : sprintf(buf
,"%ddpi",pdm
->dmPrintQuality
);break;
160 GlobalUnlock16(lppd
->hDevMode
);
162 strcpy(buf
,"Default");
163 SendDlgItemMessageA(hDlg
,cmb1
,CB_ADDSTRING
,0,(LPARAM
)buf
);
164 SendDlgItemMessageA(hDlg
,cmb1
,CB_SETCURSEL
,0,0);
165 EnableWindow(GetDlgItem(hDlg
,cmb1
),FALSE
);
169 /* FIXME: I allow more freedom than either Win95 or WinNT,
170 * which do not agree to what errors should be thrown or not
171 * in case nToPage or nFromPage is out-of-range.
173 if (lppd
->nMaxPage
< lppd
->nMinPage
)
174 lppd
->nMaxPage
= lppd
->nMinPage
;
175 if (lppd
->nMinPage
== lppd
->nMaxPage
)
176 lppd
->Flags
|= PD_NOPAGENUMS
;
177 if (lppd
->nToPage
< lppd
->nMinPage
)
178 lppd
->nToPage
= lppd
->nMinPage
;
179 if (lppd
->nToPage
> lppd
->nMaxPage
)
180 lppd
->nToPage
= lppd
->nMaxPage
;
181 if (lppd
->nFromPage
< lppd
->nMinPage
)
182 lppd
->nFromPage
= lppd
->nMinPage
;
183 if (lppd
->nFromPage
> lppd
->nMaxPage
)
184 lppd
->nFromPage
= lppd
->nMaxPage
;
186 /* If the printer combo box is in the dialog, fill it */
187 if (GetDlgItem(hDlg
,comboID
)) {
190 pdn
= GlobalLock16(lppd
->hDevNames
);
191 pdm
= GlobalLock16(lppd
->hDevMode
);
193 name
= (char*)pdn
+ pdn
->wDeviceOffset
;
195 name
= (char*)pdm
->dmDeviceName
;
196 PRINTDLG_SetUpPrinterListComboA(hDlg
, comboID
, name
);
197 if(pdm
) GlobalUnlock16(lppd
->hDevMode
);
198 if(pdn
) GlobalUnlock16(lppd
->hDevNames
);
200 /* Now find selected printer and update rest of dlg */
201 name
= HeapAlloc(GetProcessHeap(),0,256);
202 if (GetDlgItemTextA(hDlg
, comboID
, name
, 255))
203 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
205 /* else just use default printer */
207 DWORD dwBufLen
= sizeof(name
);
208 BOOL ret
= GetDefaultPrinterA(name
, &dwBufLen
);
211 PRINTDLG_ChangePrinterA(hDlg
, name
, PrintStructures
);
213 FIXME("No default printer found, expect problems!\n");
215 HeapFree(GetProcessHeap(),0,name
);
220 /************************************************************
222 * PRINTDLG_Get16TemplateFrom32 [Internal]
223 * Generates a 16 bits template from the Wine 32 bits resource
226 static HGLOBAL16
PRINTDLG_Get16TemplateFrom32(LPCSTR PrintResourceName
)
235 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
236 PrintResourceName
, (LPSTR
)RT_DIALOG
)))
238 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
241 if (!(hDlgTmpl32
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
242 !(template32
= LockResource( hDlgTmpl32
)))
244 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
247 size
= SizeofResource(COMDLG32_hInstance
, hResInfo
);
248 hGlobal16
= GlobalAlloc16(0, size
);
251 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE
);
252 ERR("alloc failure for %ld bytes\n", size
);
255 template = GlobalLock16(hGlobal16
);
258 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE
);
259 ERR("global lock failure for %x handle\n", hGlobal16
);
260 GlobalFree16(hGlobal16
);
263 ConvertDialog32To16(template32
, size
, template);
264 GlobalUnlock16(hGlobal16
);
268 static BOOL
PRINTDLG_CreateDC16(LPPRINTDLG16 lppd
)
270 DEVNAMES
*pdn
= GlobalLock16(lppd
->hDevNames
);
271 DEVMODEA
*pdm
= GlobalLock16(lppd
->hDevMode
);
273 if(lppd
->Flags
& PD_RETURNDC
) {
274 lppd
->hDC
= HDC_16(CreateDCA((char*)pdn
+ pdn
->wDriverOffset
,
275 (char*)pdn
+ pdn
->wDeviceOffset
,
276 (char*)pdn
+ pdn
->wOutputOffset
,
278 } else if(lppd
->Flags
& PD_RETURNIC
) {
279 lppd
->hDC
= HDC_16(CreateICA((char*)pdn
+ pdn
->wDriverOffset
,
280 (char*)pdn
+ pdn
->wDeviceOffset
,
281 (char*)pdn
+ pdn
->wOutputOffset
,
284 GlobalUnlock16(lppd
->hDevNames
);
285 GlobalUnlock16(lppd
->hDevMode
);
286 return lppd
->hDC
? TRUE
: FALSE
;
289 /************************************************************
291 * PRINTDLG_GetDlgTemplate
294 static HGLOBAL16
PRINTDLG_GetDlgTemplate16(PRINTDLG16
*lppd
)
296 HGLOBAL16 hDlgTmpl
, hResInfo
;
298 if (lppd
->Flags
& PD_PRINTSETUP
) {
299 if(lppd
->Flags
& PD_ENABLESETUPTEMPLATEHANDLE
) {
300 hDlgTmpl
= lppd
->hSetupTemplate
;
301 } else if(lppd
->Flags
& PD_ENABLESETUPTEMPLATE
) {
302 hResInfo
= FindResource16(lppd
->hInstance
,
303 MapSL(lppd
->lpSetupTemplateName
), (LPSTR
)RT_DIALOG
);
304 hDlgTmpl
= LoadResource16(lppd
->hInstance
, hResInfo
);
306 hDlgTmpl
= PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
309 if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATEHANDLE
) {
310 hDlgTmpl
= lppd
->hPrintTemplate
;
311 } else if(lppd
->Flags
& PD_ENABLEPRINTTEMPLATE
) {
312 hResInfo
= FindResource16(lppd
->hInstance
,
313 MapSL(lppd
->lpPrintTemplateName
),
315 hDlgTmpl
= LoadResource16(lppd
->hInstance
, hResInfo
);
317 hDlgTmpl
= PRINTDLG_Get16TemplateFrom32("PRINT32");
323 /**********************************************************************
328 /***********************************************************************
329 * PrintDlg (COMMDLG.20)
331 * Displays the the PRINT dialog box, which enables the user to specify
332 * specific properties of the print job.
335 * nonzero if the user pressed the OK button
336 * zero if the user cancelled the window or an error occurred
339 * * calls up to the 32-bit versions of the Dialogs, which look different
340 * * Customizing is *not* implemented.
343 BOOL16 WINAPI
PrintDlg16(
344 LPPRINTDLG16 lppd
/* [in/out] ptr to PRINTDLG struct */
348 HINSTANCE16 hInst
= GetWindowLongPtrW( HWND_32(lppd
->hwndOwner
), GWLP_HINSTANCE
);
350 if(TRACE_ON(commdlg
)) {
351 char flagstr
[1000] = "";
352 struct pd_flags
*pflag
= pd_flags
;
353 for( ; pflag
->name
; pflag
++) {
354 if(lppd
->Flags
& pflag
->flag
)
355 strcat(flagstr
, pflag
->name
);
357 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
358 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
359 "flags %08lx (%s)\n",
360 lppd
, lppd
->hwndOwner
, lppd
->hDevMode
, lppd
->hDevNames
,
361 lppd
->nFromPage
, lppd
->nToPage
, lppd
->nMinPage
, lppd
->nMaxPage
,
362 lppd
->nCopies
, lppd
->hInstance
, lppd
->Flags
, flagstr
);
365 if(lppd
->lStructSize
!= sizeof(PRINTDLG16
)) {
366 ERR("structure size %ld\n",lppd
->lStructSize
);
367 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE
);
371 if(lppd
->Flags
& PD_RETURNDEFAULT
) {
372 PRINTER_INFO_2A
*pbuf
;
373 DRIVER_INFO_3A
*dbuf
;
377 if(lppd
->hDevMode
|| lppd
->hDevNames
) {
378 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
379 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
382 if(!PRINTDLG_OpenDefaultPrinter(&hprn
)) {
383 WARN("Can't find default printer\n");
384 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN
);
388 GetPrinterA(hprn
, 2, NULL
, 0, &needed
);
389 pbuf
= HeapAlloc(GetProcessHeap(), 0, needed
);
390 GetPrinterA(hprn
, 2, (LPBYTE
)pbuf
, needed
, &needed
);
391 GetPrinterDriverA(hprn
, NULL
, 3, NULL
, 0, &needed
);
392 dbuf
= HeapAlloc(GetProcessHeap(),0,needed
);
393 if (!GetPrinterDriverA(hprn
, NULL
, 3, (LPBYTE
)dbuf
, needed
, &needed
)) {
394 ERR("GetPrinterDriverA failed for %s, le %ld, fix your config!\n",
395 pbuf
->pPrinterName
,GetLastError());
396 HeapFree(GetProcessHeap(), 0, dbuf
);
397 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE
);
401 PRINTDLG_CreateDevNames16(&(lppd
->hDevNames
),
405 lppd
->hDevMode
= GlobalAlloc16(GMEM_MOVEABLE
,pbuf
->pDevMode
->dmSize
+
406 pbuf
->pDevMode
->dmDriverExtra
);
407 ptr
= GlobalLock16(lppd
->hDevMode
);
408 memcpy(ptr
, pbuf
->pDevMode
, pbuf
->pDevMode
->dmSize
+
409 pbuf
->pDevMode
->dmDriverExtra
);
410 GlobalUnlock16(lppd
->hDevMode
);
411 HeapFree(GetProcessHeap(), 0, pbuf
);
412 HeapFree(GetProcessHeap(), 0, dbuf
);
416 PRINT_PTRA
*PrintStructures
;
419 /* load Dialog resources,
420 * depending on Flags indicates Print32 or Print32_setup dialog
422 hDlgTmpl
= PRINTDLG_GetDlgTemplate16(lppd
);
424 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
427 ptr16
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PRINT_PTRA16
));
428 ptr16
->lpPrintDlg16
= lppd
;
429 PrintStructures
= &ptr16
->print32
;
430 PrintStructures
->lpPrintDlg
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(PRINTDLGA
));
431 #define CVAL(x) PrintStructures->lpPrintDlg->x = lppd->x;
432 #define MVAL(x) PrintStructures->lpPrintDlg->x = MapSL(lppd->x);
434 PrintStructures
->lpPrintDlg
->hwndOwner
= HWND_32(lppd
->hwndOwner
);
435 PrintStructures
->lpPrintDlg
->hDC
= HDC_32(lppd
->hDC
);
436 CVAL(nFromPage
);CVAL(nToPage
);CVAL(nMinPage
);CVAL(nMaxPage
);
438 PrintStructures
->lpPrintDlg
->hInstance
= HINSTANCE_32(lppd
->hInstance
);
440 MVAL(lpPrintTemplateName
);MVAL(lpSetupTemplateName
);
441 /* Don't copy rest, it is 16 bit specific */
445 PrintStructures
->lpDevMode
= HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA
));
447 /* and create & process the dialog .
448 * -1 is failure, 0 is broken hwnd, everything else is ok.
450 bRet
= (0<DialogBoxIndirectParam16(
451 hInst
, hDlgTmpl
, lppd
->hwndOwner
,
452 (DLGPROC16
)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR
)21),
453 (LPARAM
)PrintStructures
456 if (!PrintStructures
->lpPrinterInfo
) bRet
= FALSE
;
458 DEVMODEA
*lpdm
= PrintStructures
->lpDevMode
, *lpdmReturn
;
459 PRINTER_INFO_2A
*pi
= PrintStructures
->lpPrinterInfo
;
460 DRIVER_INFO_3A
*di
= PrintStructures
->lpDriverInfo
;
462 if (lppd
->hDevMode
== 0) {
463 TRACE(" No hDevMode yet... Need to create my own\n");
464 lppd
->hDevMode
= GlobalAlloc16(GMEM_MOVEABLE
,
465 lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
468 if((locks
= (GlobalFlags16(lppd
->hDevMode
)&GMEM_LOCKCOUNT
))) {
469 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks
);
471 GlobalUnlock16(lppd
->hDevMode
);
472 TRACE("Now got %d locks\n", locks
);
475 lppd
->hDevMode
= GlobalReAlloc16(lppd
->hDevMode
,
476 lpdm
->dmSize
+ lpdm
->dmDriverExtra
,
479 lpdmReturn
= GlobalLock16(lppd
->hDevMode
);
480 memcpy(lpdmReturn
, lpdm
, lpdm
->dmSize
+ lpdm
->dmDriverExtra
);
482 if (lppd
->hDevNames
!= 0) {
484 if((locks
= (GlobalFlags16(lppd
->hDevNames
)&GMEM_LOCKCOUNT
))) {
485 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks
);
487 GlobalUnlock16(lppd
->hDevNames
);
490 PRINTDLG_CreateDevNames16(&(lppd
->hDevNames
),
495 GlobalUnlock16(lppd
->hDevMode
);
496 /* Copy back the [out] integer parameters */
497 #define CVAL(x) lppd->x = PrintStructures->lpPrintDlg->x;
505 if (!(lppd
->Flags
& (PD_ENABLESETUPTEMPLATEHANDLE
| PD_ENABLESETUPTEMPLATE
)))
506 GlobalFree16(hDlgTmpl
); /* created from the 32 bits resource */
507 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDevMode
);
508 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpPrinterInfo
);
509 HeapFree(GetProcessHeap(), 0, PrintStructures
->lpDriverInfo
);
510 HeapFree(GetProcessHeap(), 0, PrintStructures
);
512 if(bRet
&& (lppd
->Flags
& PD_RETURNDC
|| lppd
->Flags
& PD_RETURNIC
))
513 bRet
= PRINTDLG_CreateDC16(lppd
);
515 TRACE("exit! (%d)\n", bRet
);
519 /***********************************************************************
520 * PrintDlgProc (COMMDLG.21)
522 BOOL16 CALLBACK
PrintDlgProc16(HWND16 hDlg16
, UINT16 uMsg
, WPARAM16 wParam
,
525 HWND hDlg
= HWND_32(hDlg16
);
526 PRINT_PTRA16
*PrintStructures
;
529 if (uMsg
!=WM_INITDIALOG
) {
530 PrintStructures
= (PRINT_PTRA16
*)GetPropA(hDlg
,"__WINE_PRINTDLGDATA");
531 if (!PrintStructures
)
534 PrintStructures
= (PRINT_PTRA16
*) lParam
;
535 SetPropA(hDlg
,"__WINE_PRINTDLGDATA",PrintStructures
);
536 res
= PRINTDLG_WMInitDialog16(hDlg
, wParam
, PrintStructures
);
538 if(PrintStructures
->lpPrintDlg16
->Flags
& PD_ENABLEPRINTHOOK
) {
539 res
= CallWindowProc16(
540 (WNDPROC16
)PrintStructures
->lpPrintDlg16
->lpfnPrintHook
,
541 hDlg16
, uMsg
, wParam
, (LPARAM
)PrintStructures
->lpPrintDlg16
547 if(PrintStructures
->lpPrintDlg16
->Flags
& PD_ENABLEPRINTHOOK
) {
548 res
= CallWindowProc16(
549 (WNDPROC16
)PrintStructures
->lpPrintDlg16
->lpfnPrintHook
,
550 hDlg16
,uMsg
, wParam
, lParam
552 if(LOWORD(res
)) return res
;
557 /* We need to map those for the 32bit window procedure, compare
558 * with 32Ato16 mapper in winproc.c
560 return PRINTDLG_WMCommandA(
562 MAKEWPARAM(wParam
,HIWORD(lParam
)),
564 &PrintStructures
->print32
568 DestroyIcon(PrintStructures
->print32
.hCollateIcon
);
569 DestroyIcon(PrintStructures
->print32
.hNoCollateIcon
);
570 /* FIXME: don't forget to delete the paper orientation icons here! */
577 /***********************************************************************
578 * PrintSetupDlgProc (COMMDLG.22)
580 BOOL16 CALLBACK
PrintSetupDlgProc16(HWND16 hWnd16
, UINT16 wMsg
, WPARAM16 wParam
,
583 HWND hWnd
= HWND_32(hWnd16
);
587 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam
);
588 ShowWindow(hWnd
, SW_SHOWNORMAL
);
593 EndDialog(hWnd
, TRUE
);
596 EndDialog(hWnd
, FALSE
);