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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);
50 static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, char* DeviceDriverName,
51 char* DeviceName, char* OutputPort)
56 LPDEVNAMES lpDevNames;
59 size = strlen(DeviceDriverName) + 1
60 + strlen(DeviceName) + 1
61 + strlen(OutputPort) + 1
65 *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE);
67 *hmem = GlobalAlloc16(GMEM_MOVEABLE, size);
71 pDevNamesSpace = GlobalLock16(*hmem);
72 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
74 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
75 strcpy(pTempPtr, DeviceDriverName);
76 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
78 pTempPtr += strlen(DeviceDriverName) + 1;
79 strcpy(pTempPtr, DeviceName);
80 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
82 pTempPtr += strlen(DeviceName) + 1;
83 strcpy(pTempPtr, OutputPort);
84 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
86 PRINTDLG_GetDefaultPrinterNameA(buf, sizeof(buf));
87 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
88 GlobalUnlock16(*hmem);
93 /***********************************************************************
94 * PRINTDLG_WMInitDialog [internal]
96 static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam,
97 PRINT_PTRA* PrintStructures)
99 LPPRINTDLG16 lppd = PrintStructures->dlg.lpPrintDlg16;
103 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
105 /* load Collate ICONs */
106 PrintStructures->hCollateIcon =
107 LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
108 PrintStructures->hNoCollateIcon =
109 LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
110 if(PrintStructures->hCollateIcon == 0 ||
111 PrintStructures->hNoCollateIcon == 0) {
112 ERR("no icon in resourcefile\n");
113 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
114 EndDialog(hDlg, FALSE);
117 /* load Paper Orientation ICON */
118 /* FIXME: not implemented yet */
121 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
122 * must be registered and the Help button must be shown.
124 if (lppd->Flags & PD_SHOWHELP) {
125 if((PrintStructures->HelpMessageID =
126 RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
127 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
131 PrintStructures->HelpMessageID = 0;
133 if (!(lppd->Flags & PD_PRINTSETUP)) {
134 /* We have a print quality combo box. What shall we do? */
135 if (GetDlgItem(hDlg,cmb1)) {
138 FIXME("Print quality only displaying currently.\n");
140 pdm = GlobalLock16(lppd->hDevMode);
142 switch (pdm->dmPrintQuality) {
143 case DMRES_HIGH : strcpy(buf,"High");break;
144 case DMRES_MEDIUM : strcpy(buf,"Medium");break;
145 case DMRES_LOW : strcpy(buf,"Low");break;
146 case DMRES_DRAFT : strcpy(buf,"Draft");break;
147 case 0 : strcpy(buf,"Default");break;
148 default : sprintf(buf,"%ddpi",pdm->dmPrintQuality);break;
150 GlobalUnlock16(lppd->hDevMode);
152 strcpy(buf,"Default");
153 SendDlgItemMessageA(hDlg,cmb1,CB_ADDSTRING,0,(LPARAM)buf);
154 SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0);
155 EnableWindow(GetDlgItem(hDlg,cmb1),FALSE);
159 /* FIXME: I allow more freedom than either Win95 or WinNT,
160 * which do not agree to what errors should be thrown or not
161 * in case nToPage or nFromPage is out-of-range.
163 if (lppd->nMaxPage < lppd->nMinPage)
164 lppd->nMaxPage = lppd->nMinPage;
165 if (lppd->nMinPage == lppd->nMaxPage)
166 lppd->Flags |= PD_NOPAGENUMS;
167 if (lppd->nToPage < lppd->nMinPage)
168 lppd->nToPage = lppd->nMinPage;
169 if (lppd->nToPage > lppd->nMaxPage)
170 lppd->nToPage = lppd->nMaxPage;
171 if (lppd->nFromPage < lppd->nMinPage)
172 lppd->nFromPage = lppd->nMinPage;
173 if (lppd->nFromPage > lppd->nMaxPage)
174 lppd->nFromPage = lppd->nMaxPage;
176 /* If the printer combo box is in the dialog, fill it */
177 if (GetDlgItem(hDlg,comboID)) {
180 pdn = GlobalLock16(lppd->hDevNames);
181 pdm = GlobalLock16(lppd->hDevMode);
183 name = (char*)pdn + pdn->wDeviceOffset;
185 name = pdm->dmDeviceName;
186 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
187 if(pdm) GlobalUnlock16(lppd->hDevMode);
188 if(pdn) GlobalUnlock16(lppd->hDevNames);
190 /* Now find selected printer and update rest of dlg */
191 name = HeapAlloc(GetProcessHeap(),0,256);
192 if (GetDlgItemTextA(hDlg, comboID, name, 255))
193 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
195 /* else just use default printer */
197 BOOL ret = PRINTDLG_GetDefaultPrinterNameA(name, sizeof(name));
200 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
202 FIXME("No default printer found, expect problems!\n");
204 HeapFree(GetProcessHeap(),0,name);
209 /************************************************************
211 * PRINTDLG_Get16TemplateFrom32 [Internal]
212 * Generates a 16 bits template from the Wine 32 bits resource
215 static HGLOBAL16 PRINTDLG_Get16TemplateFrom32(char *PrintResourceName)
224 if (!(hResInfo = FindResourceA(COMDLG32_hInstance,
225 PrintResourceName, RT_DIALOGA)))
227 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
230 if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo )) ||
231 !(template32 = LockResource( hDlgTmpl32 )))
233 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
236 size = SizeofResource(COMDLG32_hInstance, hResInfo);
237 hGlobal16 = GlobalAlloc16(0, size);
240 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
241 ERR("alloc failure for %ld bytes\n", size);
244 template = GlobalLock16(hGlobal16);
247 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
248 ERR("global lock failure for %x handle\n", hGlobal16);
249 GlobalFree16(hGlobal16);
252 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
253 GlobalUnlock16(hGlobal16);
257 static BOOL PRINTDLG_CreateDC16(LPPRINTDLG16 lppd)
259 DEVNAMES *pdn = GlobalLock16(lppd->hDevNames);
260 DEVMODEA *pdm = GlobalLock16(lppd->hDevMode);
262 if(lppd->Flags & PD_RETURNDC) {
263 lppd->hDC = HDC_16(CreateDCA((char*)pdn + pdn->wDriverOffset,
264 (char*)pdn + pdn->wDeviceOffset,
265 (char*)pdn + pdn->wOutputOffset,
267 } else if(lppd->Flags & PD_RETURNIC) {
268 lppd->hDC = HDC_16(CreateICA((char*)pdn + pdn->wDriverOffset,
269 (char*)pdn + pdn->wDeviceOffset,
270 (char*)pdn + pdn->wOutputOffset,
273 GlobalUnlock16(lppd->hDevNames);
274 GlobalUnlock16(lppd->hDevMode);
275 return lppd->hDC ? TRUE : FALSE;
278 /************************************************************
280 * PRINTDLG_GetDlgTemplate
283 static HGLOBAL16 PRINTDLG_GetDlgTemplate16(PRINTDLG16 *lppd)
285 HGLOBAL16 hDlgTmpl, hResInfo;
287 if (lppd->Flags & PD_PRINTSETUP) {
288 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
289 hDlgTmpl = lppd->hSetupTemplate;
290 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
291 hResInfo = FindResource16(lppd->hInstance,
292 MapSL(lppd->lpSetupTemplateName), RT_DIALOGA);
293 hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
295 hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
298 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
299 hDlgTmpl = lppd->hPrintTemplate;
300 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
301 hResInfo = FindResource16(lppd->hInstance,
302 MapSL(lppd->lpPrintTemplateName),
304 hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
306 hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32");
312 /***********************************************************************
313 * PrintDlg (COMMDLG.20)
315 * Displays the the PRINT dialog box, which enables the user to specify
316 * specific properties of the print job.
319 * nonzero if the user pressed the OK button
320 * zero if the user cancelled the window or an error occurred
323 * * calls up to the 32-bit versions of the Dialogs, which look different
324 * * Customizing is *not* implemented.
327 BOOL16 WINAPI PrintDlg16(
328 LPPRINTDLG16 lppd /* [in/out] ptr to PRINTDLG struct */
332 HINSTANCE16 hInst = GetWindowWord( HWND_32(lppd->hwndOwner), GWL_HINSTANCE );
334 if(TRACE_ON(commdlg)) {
335 char flagstr[1000] = "";
336 struct pd_flags *pflag = pd_flags;
337 for( ; pflag->name; pflag++) {
338 if(lppd->Flags & pflag->flag)
339 strcat(flagstr, pflag->name);
341 TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
342 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
343 "flags %08lx (%s)\n",
344 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
345 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
346 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
349 if(lppd->lStructSize != sizeof(PRINTDLG16)) {
350 ERR("structure size (%ld/%d)\n",lppd->lStructSize,sizeof(PRINTDLG16));
351 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
355 if(lppd->Flags & PD_RETURNDEFAULT) {
356 PRINTER_INFO_2A *pbuf;
357 DRIVER_INFO_3A *dbuf;
361 if(lppd->hDevMode || lppd->hDevNames) {
362 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
363 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
366 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
367 WARN("Can't find default printer\n");
368 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
372 GetPrinterA(hprn, 2, NULL, 0, &needed);
373 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
374 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
375 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
376 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
377 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
378 ERR("GetPrinterDriverA failed for %s, le %ld, fix your config!\n",
379 pbuf->pPrinterName,GetLastError());
380 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
384 PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
388 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,pbuf->pDevMode->dmSize+
389 pbuf->pDevMode->dmDriverExtra);
390 ptr = GlobalLock16(lppd->hDevMode);
391 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
392 pbuf->pDevMode->dmDriverExtra);
393 GlobalUnlock16(lppd->hDevMode);
394 HeapFree(GetProcessHeap(), 0, pbuf);
395 HeapFree(GetProcessHeap(), 0, dbuf);
399 PRINT_PTRA *PrintStructures;
401 /* load Dialog resources,
402 * depending on Flags indicates Print32 or Print32_setup dialog
404 hDlgTmpl = PRINTDLG_GetDlgTemplate16(lppd);
406 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
409 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
411 PrintStructures->dlg.lpPrintDlg16 = lppd;
412 PrintStructures->dlg.lpPrintDlg = (LPPRINTDLGA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PRINTDLGA));
413 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
414 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
416 PrintStructures->dlg.lpPrintDlg->hwndOwner = HWND_32(lppd->hwndOwner);
417 PrintStructures->dlg.lpPrintDlg->hDC = HDC_32(lppd->hDC);
418 CVAL(nFromPage);CVAL(nToPage);CVAL(nMinPage);CVAL(nMaxPage);
420 PrintStructures->dlg.lpPrintDlg->hInstance = HINSTANCE_32(lppd->hInstance);
422 MVAL(lpPrintTemplateName);MVAL(lpSetupTemplateName);
423 /* Don't copy rest, it is 16 bit specific */
427 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA));
429 /* and create & process the dialog .
430 * -1 is failure, 0 is broken hwnd, everything else is ok.
432 bRet = (0<DialogBoxIndirectParam16(
433 hInst, hDlgTmpl, lppd->hwndOwner,
434 (DLGPROC16)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR)21),
435 (LPARAM)PrintStructures
438 if (!PrintStructures->lpPrinterInfo) bRet = FALSE;
440 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
441 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
442 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
444 if (lppd->hDevMode == 0) {
445 TRACE(" No hDevMode yet... Need to create my own\n");
446 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,
447 lpdm->dmSize + lpdm->dmDriverExtra);
450 if((locks = (GlobalFlags16(lppd->hDevMode)&GMEM_LOCKCOUNT))) {
451 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
453 GlobalUnlock16(lppd->hDevMode);
454 TRACE("Now got %d locks\n", locks);
457 lppd->hDevMode = GlobalReAlloc16(lppd->hDevMode,
458 lpdm->dmSize + lpdm->dmDriverExtra,
461 lpdmReturn = GlobalLock16(lppd->hDevMode);
462 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
464 if (lppd->hDevNames != 0) {
466 if((locks = (GlobalFlags16(lppd->hDevNames)&GMEM_LOCKCOUNT))) {
467 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
469 GlobalUnlock16(lppd->hDevNames);
472 PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
477 GlobalUnlock16(lppd->hDevMode);
479 if (!(lppd->Flags & (PD_ENABLESETUPTEMPLATEHANDLE | PD_ENABLESETUPTEMPLATE)))
480 GlobalFree16(hDlgTmpl); /* created from the 32 bits resource */
481 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
482 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
483 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
484 HeapFree(GetProcessHeap(), 0, PrintStructures);
486 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
487 bRet = PRINTDLG_CreateDC16(lppd);
489 TRACE("exit! (%d)\n", bRet);
493 /**********************************************************************
498 /***********************************************************************
499 * PrintDlgProc (COMMDLG.21)
501 BOOL16 CALLBACK PrintDlgProc16(HWND16 hDlg16, UINT16 uMsg, WPARAM16 wParam,
504 HWND hDlg = HWND_32(hDlg16);
505 PRINT_PTRA* PrintStructures;
508 if (uMsg!=WM_INITDIALOG) {
509 PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
510 if (!PrintStructures)
513 PrintStructures = (PRINT_PTRA*) lParam;
514 SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
515 res = PRINTDLG_WMInitDialog16(hDlg, wParam, PrintStructures);
517 if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
518 res = CallWindowProc16(
519 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
520 hDlg16, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg16
526 if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
527 res = CallWindowProc16(
528 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
529 hDlg16,uMsg, wParam, lParam
531 if(LOWORD(res)) return res;
536 /* We need to map those for the 32bit window procedure, compare
537 * with 32Ato16 mapper in winproc.c
539 return PRINTDLG_WMCommandA(
541 MAKEWPARAM(wParam,HIWORD(lParam)),
547 DestroyIcon(PrintStructures->hCollateIcon);
548 DestroyIcon(PrintStructures->hNoCollateIcon);
549 /* FIXME: don't forget to delete the paper orientation icons here! */
556 /***********************************************************************
557 * PrintSetupDlgProc (COMMDLG.22)
559 BOOL16 CALLBACK PrintSetupDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
562 HWND hWnd = HWND_32(hWnd16);
566 TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
567 ShowWindow(hWnd, SW_SHOWNORMAL);
572 EndDialog(hWnd, TRUE);
575 EndDialog(hWnd, FALSE);