67669c543321643c737dce39f3a4b6c981e854fd
[reactos.git] / reactos / dll / win32 / comdlg32 / printdlg.c
1 /*
2 * COMMDLG - Print Dialog
3 *
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1999 Klaas van Gend
7 * Copyright 2000 Huw D M Davies
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include <precomp.h>
25
26 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
27
28 /* Yes these constants are the same, but we're just copying win98 */
29 #define UPDOWN_ID 0x270f
30 #define MAX_COPIES 9999
31
32 /* Debugging info */
33 static struct pd_flags psd_flags[] = {
34 {PSD_MINMARGINS,"PSD_MINMARGINS"},
35 {PSD_MARGINS,"PSD_MARGINS"},
36 {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
37 {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
38 {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
39 {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
40 {PSD_NOWARNING,"PSD_NOWARNING"},
41 {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
42 {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
43 {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
44 {PSD_SHOWHELP,"PSD_SHOWHELP"},
45 {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
46 {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
47 {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
48 {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
49 {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
50 {-1, NULL}
51 };
52
53 /* address of wndproc for subclassed Static control */
54 static WNDPROC lpfnStaticWndProc;
55 /* the text of the fake document to render for the Page Setup dialog */
56 static WCHAR wszFakeDocumentText[1024];
57
58 /***********************************************************************
59 * PRINTDLG_OpenDefaultPrinter
60 *
61 * Returns a winspool printer handle to the default printer in *hprn
62 * Caller must call ClosePrinter on the handle
63 *
64 * Returns TRUE on success else FALSE
65 */
66 BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
67 {
68 WCHAR buf[260];
69 DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
70 BOOL res;
71 if(!GetDefaultPrinterW(buf, &dwBufLen))
72 return FALSE;
73 res = OpenPrinterW(buf, hprn, NULL);
74 if (!res)
75 WARN("Could not open printer %s\n", debugstr_w(buf));
76 return res;
77 }
78
79 /***********************************************************************
80 * PRINTDLG_SetUpPrinterListCombo
81 *
82 * Initializes printer list combox.
83 * hDlg: HWND of dialog
84 * id: Control id of combo
85 * name: Name of printer to select
86 *
87 * Initializes combo with list of available printers. Selects printer 'name'
88 * If name is NULL or does not exist select the default printer.
89 *
90 * Returns number of printers added to list.
91 */
92 INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
93 {
94 DWORD needed, num;
95 INT i;
96 LPPRINTER_INFO_2A pi;
97 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
98 pi = HeapAlloc(GetProcessHeap(), 0, needed);
99 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
100 &num);
101
102 SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
103
104 for(i = 0; i < num; i++) {
105 SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
106 (LPARAM)pi[i].pPrinterName );
107 }
108 HeapFree(GetProcessHeap(), 0, pi);
109 if(!name ||
110 (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
111 (LPARAM)name)) == CB_ERR) {
112
113 char buf[260];
114 DWORD dwBufLen = sizeof(buf);
115 FIXME("Can't find '%s' in printer list so trying to find default\n",
116 name);
117 if(!GetDefaultPrinterA(buf, &dwBufLen))
118 return num;
119 i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
120 if(i == CB_ERR)
121 FIXME("Can't find default printer in printer list\n");
122 }
123 SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
124 return num;
125 }
126
127 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
128 {
129 DWORD needed, num;
130 INT i;
131 LPPRINTER_INFO_2W pi;
132 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
133 pi = HeapAlloc(GetProcessHeap(), 0, needed);
134 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
135 &num);
136
137 for(i = 0; i < num; i++) {
138 SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
139 (LPARAM)pi[i].pPrinterName );
140 }
141 HeapFree(GetProcessHeap(), 0, pi);
142 if(!name ||
143 (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
144 (LPARAM)name)) == CB_ERR) {
145 WCHAR buf[260];
146 DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
147 TRACE("Can't find '%s' in printer list so trying to find default\n",
148 debugstr_w(name));
149 if(!GetDefaultPrinterW(buf, &dwBufLen))
150 return num;
151 i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
152 if(i == CB_ERR)
153 TRACE("Can't find default printer in printer list\n");
154 }
155 SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
156 return num;
157 }
158
159 /***********************************************************************
160 * PRINTDLG_CreateDevNames [internal]
161 *
162 *
163 * creates a DevNames structure.
164 *
165 * (NB. when we handle unicode the offsets will be in wchars).
166 */
167 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName,
168 char* DeviceName, char* OutputPort)
169 {
170 long size;
171 char* pDevNamesSpace;
172 char* pTempPtr;
173 LPDEVNAMES lpDevNames;
174 char buf[260];
175 DWORD dwBufLen = sizeof(buf);
176
177 size = strlen(DeviceDriverName) + 1
178 + strlen(DeviceName) + 1
179 + strlen(OutputPort) + 1
180 + sizeof(DEVNAMES);
181
182 if(*hmem)
183 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
184 else
185 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
186 if (*hmem == 0)
187 return FALSE;
188
189 pDevNamesSpace = GlobalLock(*hmem);
190 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
191
192 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
193 strcpy(pTempPtr, DeviceDriverName);
194 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
195
196 pTempPtr += strlen(DeviceDriverName) + 1;
197 strcpy(pTempPtr, DeviceName);
198 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
199
200 pTempPtr += strlen(DeviceName) + 1;
201 strcpy(pTempPtr, OutputPort);
202 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
203
204 GetDefaultPrinterA(buf, &dwBufLen);
205 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
206 GlobalUnlock(*hmem);
207 return TRUE;
208 }
209
210 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
211 LPCWSTR DeviceName, LPCWSTR OutputPort)
212 {
213 long size;
214 LPWSTR pDevNamesSpace;
215 LPWSTR pTempPtr;
216 LPDEVNAMES lpDevNames;
217 WCHAR bufW[260];
218 DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
219
220 size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
221 + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
222 + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
223 + sizeof(DEVNAMES);
224
225 if(*hmem)
226 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
227 else
228 *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
229 if (*hmem == 0)
230 return FALSE;
231
232 pDevNamesSpace = GlobalLock(*hmem);
233 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
234
235 pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
236 lstrcpyW(pTempPtr, DeviceDriverName);
237 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
238
239 pTempPtr += lstrlenW(DeviceDriverName) + 1;
240 lstrcpyW(pTempPtr, DeviceName);
241 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
242
243 pTempPtr += lstrlenW(DeviceName) + 1;
244 lstrcpyW(pTempPtr, OutputPort);
245 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
246
247 GetDefaultPrinterW(bufW, &dwBufLen);
248 lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
249 GlobalUnlock(*hmem);
250 return TRUE;
251 }
252
253 /***********************************************************************
254 * PRINTDLG_UpdatePrintDlg [internal]
255 *
256 *
257 * updates the PrintDlg structure for return values.
258 *
259 * RETURNS
260 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
261 * TRUE if successful.
262 */
263 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
264 PRINT_PTRA* PrintStructures)
265 {
266 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
267 PDEVMODEA lpdm = PrintStructures->lpDevMode;
268 LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
269
270
271 if(!lpdm) {
272 FIXME("No lpdm ptr?\n");
273 return FALSE;
274 }
275
276
277 if(!(lppd->Flags & PD_PRINTSETUP)) {
278 /* check whether nFromPage and nToPage are within range defined by
279 * nMinPage and nMaxPage
280 */
281 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
282 WORD nToPage;
283 WORD nFromPage;
284 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
285 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
286 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
287 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
288 char resourcestr[256];
289 char resultstr[256];
290 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
291 resourcestr, 255);
292 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
293 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
294 resourcestr, 255);
295 MessageBoxA(hDlg, resultstr, resourcestr,
296 MB_OK | MB_ICONWARNING);
297 return FALSE;
298 }
299 lppd->nFromPage = nFromPage;
300 lppd->nToPage = nToPage;
301 lppd->Flags |= PD_PAGENUMS;
302 }
303 else
304 lppd->Flags &= ~PD_PAGENUMS;
305
306 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
307 static char file[] = "FILE:";
308 lppd->Flags |= PD_PRINTTOFILE;
309 pi->pPortName = file;
310 }
311
312 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
313 FIXME("Collate lppd not yet implemented as output\n");
314 }
315
316 /* set PD_Collate and nCopies */
317 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
318 /* The application doesn't support multiple copies or collate...
319 */
320 lppd->Flags &= ~PD_COLLATE;
321 lppd->nCopies = 1;
322 /* if the printer driver supports it... store info there
323 * otherwise no collate & multiple copies !
324 */
325 if (lpdm->dmFields & DM_COLLATE)
326 lpdm->dmCollate =
327 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
328 if (lpdm->dmFields & DM_COPIES)
329 lpdm->u.s.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
330 } else {
331 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
332 lppd->Flags |= PD_COLLATE;
333 else
334 lppd->Flags &= ~PD_COLLATE;
335 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
336 }
337 }
338 return TRUE;
339 }
340
341 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
342 PRINT_PTRW* PrintStructures)
343 {
344 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
345 PDEVMODEW lpdm = PrintStructures->lpDevMode;
346 LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
347
348
349 if(!lpdm) {
350 FIXME("No lpdm ptr?\n");
351 return FALSE;
352 }
353
354
355 if(!(lppd->Flags & PD_PRINTSETUP)) {
356 /* check whether nFromPage and nToPage are within range defined by
357 * nMinPage and nMaxPage
358 */
359 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
360 WORD nToPage;
361 WORD nFromPage;
362 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
363 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
364 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
365 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
366 WCHAR resourcestr[256];
367 WCHAR resultstr[256];
368 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
369 resourcestr, 255);
370 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
371 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
372 resourcestr, 255);
373 MessageBoxW(hDlg, resultstr, resourcestr,
374 MB_OK | MB_ICONWARNING);
375 return FALSE;
376 }
377 lppd->nFromPage = nFromPage;
378 lppd->nToPage = nToPage;
379 }
380
381 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
382 static WCHAR file[] = {'F','I','L','E',':',0};
383 lppd->Flags |= PD_PRINTTOFILE;
384 pi->pPortName = file;
385 }
386
387 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
388 FIXME("Collate lppd not yet implemented as output\n");
389 }
390
391 /* set PD_Collate and nCopies */
392 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
393 /* The application doesn't support multiple copies or collate...
394 */
395 lppd->Flags &= ~PD_COLLATE;
396 lppd->nCopies = 1;
397 /* if the printer driver supports it... store info there
398 * otherwise no collate & multiple copies !
399 */
400 if (lpdm->dmFields & DM_COLLATE)
401 lpdm->dmCollate =
402 (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
403 if (lpdm->dmFields & DM_COPIES)
404 lpdm->u.s.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
405 } else {
406 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
407 lppd->Flags |= PD_COLLATE;
408 else
409 lppd->Flags &= ~PD_COLLATE;
410 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
411 }
412 }
413 return TRUE;
414 }
415
416 static BOOL PRINTDLG_PaperSizeA(
417 PRINTDLGA *pdlga,const WORD PaperSize,LPPOINT size
418 ) {
419 DEVNAMES *dn;
420 DEVMODEA *dm;
421 LPSTR devname,portname;
422 int i;
423 INT NrOfEntries,ret;
424 WORD *Words = NULL;
425 POINT *points = NULL;
426 BOOL retval = FALSE;
427
428 dn = GlobalLock(pdlga->hDevNames);
429 dm = GlobalLock(pdlga->hDevMode);
430 devname = ((char*)dn)+dn->wDeviceOffset;
431 portname = ((char*)dn)+dn->wOutputOffset;
432
433
434 NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
435 if (!NrOfEntries) {
436 FIXME("No papernames found for %s/%s\n",devname,portname);
437 goto out;
438 }
439 if (NrOfEntries == -1) {
440 ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
441 goto out;
442 }
443
444 Words = HeapAlloc(GetProcessHeap(),0,NrOfEntries*sizeof(WORD));
445 if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERS,(LPSTR)Words,dm))) {
446 FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
447 goto out;
448 }
449 for (i=0;i<NrOfEntries;i++)
450 if (Words[i] == PaperSize)
451 break;
452 HeapFree(GetProcessHeap(),0,Words);
453 if (i == NrOfEntries) {
454 FIXME("Papersize %d not found in list?\n",PaperSize);
455 goto out;
456 }
457 points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
458 if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPSTR)points,dm))) {
459 FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
460 goto out;
461 }
462 /* this is _10ths_ of a millimeter */
463 size->x=points[i].x;
464 size->y=points[i].y;
465 retval = TRUE;
466 out:
467 GlobalUnlock(pdlga->hDevNames);
468 GlobalUnlock(pdlga->hDevMode);
469 HeapFree(GetProcessHeap(),0,Words);
470 HeapFree(GetProcessHeap(),0,points);
471 return retval;
472 }
473
474 static BOOL PRINTDLG_PaperSizeW(
475 PRINTDLGW *pdlga,const WCHAR *PaperSize,LPPOINT size
476 ) {
477 DEVNAMES *dn;
478 DEVMODEW *dm;
479 LPWSTR devname,portname;
480 int i;
481 INT NrOfEntries,ret;
482 WCHAR *Names = NULL;
483 POINT *points = NULL;
484 BOOL retval = FALSE;
485
486 dn = GlobalLock(pdlga->hDevNames);
487 dm = GlobalLock(pdlga->hDevMode);
488 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
489 portname = ((WCHAR*)dn)+dn->wOutputOffset;
490
491
492 NrOfEntries = DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,NULL,dm);
493 if (!NrOfEntries) {
494 FIXME("No papernames found for %s/%s\n",debugstr_w(devname),debugstr_w(portname));
495 goto out;
496 }
497 if (NrOfEntries == -1) {
498 ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
499 goto out;
500 }
501
502 Names = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*NrOfEntries*64);
503 if (NrOfEntries != (ret=DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,Names,dm))) {
504 FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
505 goto out;
506 }
507 for (i=0;i<NrOfEntries;i++)
508 if (!lstrcmpW(PaperSize,Names+(64*i)))
509 break;
510 HeapFree(GetProcessHeap(),0,Names);
511 if (i==NrOfEntries) {
512 FIXME("Papersize %s not found in list?\n",debugstr_w(PaperSize));
513 goto out;
514 }
515 points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
516 if (NrOfEntries!=(ret=DeviceCapabilitiesW(devname,portname,DC_PAPERSIZE,(LPWSTR)points,dm))) {
517 FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
518 goto out;
519 }
520 /* this is _10ths_ of a millimeter */
521 size->x=points[i].x;
522 size->y=points[i].y;
523 retval = TRUE;
524 out:
525 GlobalUnlock(pdlga->hDevNames);
526 GlobalUnlock(pdlga->hDevMode);
527 HeapFree(GetProcessHeap(),0,Names);
528 HeapFree(GetProcessHeap(),0,points);
529 return retval;
530 }
531
532
533 /************************************************************************
534 * PRINTDLG_SetUpPaperComboBox
535 *
536 * Initialize either the papersize or inputslot combos of the Printer Setup
537 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
538 * We also try to re-select the old selection.
539 */
540 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
541 int nIDComboBox,
542 char* PrinterName,
543 char* PortName,
544 LPDEVMODEA dm)
545 {
546 int i;
547 int NrOfEntries;
548 char* Names;
549 WORD* Words;
550 DWORD Sel;
551 WORD oldWord = 0;
552 int NamesSize;
553 int fwCapability_Names;
554 int fwCapability_Words;
555
556 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
557
558 /* query the dialog box for the current selected value */
559 Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
560 if(Sel != CB_ERR) {
561 /* we enter here only if a different printer is selected after
562 * the Print Setup dialog is opened. The current settings are
563 * stored into the newly selected printer.
564 */
565 oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
566 Sel, 0);
567 if (dm) {
568 if (nIDComboBox == cmb2)
569 dm->u.s.dmPaperSize = oldWord;
570 else
571 dm->u.s.dmDefaultSource = oldWord;
572 }
573 }
574 else {
575 /* we enter here only when the Print setup dialog is initially
576 * opened. In this case the settings are restored from when
577 * the dialog was last closed.
578 */
579 if (dm) {
580 if (nIDComboBox == cmb2)
581 oldWord = dm->u.s.dmPaperSize;
582 else
583 oldWord = dm->u.s.dmDefaultSource;
584 }
585 }
586
587 if (nIDComboBox == cmb2) {
588 NamesSize = 64;
589 fwCapability_Names = DC_PAPERNAMES;
590 fwCapability_Words = DC_PAPERS;
591 } else {
592 nIDComboBox = cmb3;
593 NamesSize = 24;
594 fwCapability_Names = DC_BINNAMES;
595 fwCapability_Words = DC_BINS;
596 }
597
598 /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
599 * paper settings. As Wine doesn't allow VXDs, this results in a crash.
600 */
601 WARN(" if your printer driver uses VXDs, expect a crash now!\n");
602 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
603 fwCapability_Names, NULL, dm);
604 if (NrOfEntries == 0)
605 WARN("no Name Entries found!\n");
606 else if (NrOfEntries < 0)
607 return FALSE;
608
609 if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
610 != NrOfEntries) {
611 ERR("Number of caps is different\n");
612 NrOfEntries = 0;
613 }
614
615 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
616 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
617 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
618 fwCapability_Names, Names, dm);
619 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
620 fwCapability_Words, (LPSTR)Words, dm);
621
622 /* reset any current content in the combobox */
623 SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
624
625 /* store new content */
626 for (i = 0; i < NrOfEntries; i++) {
627 DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
628 (LPARAM)(&Names[i*NamesSize]) );
629 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
630 Words[i]);
631 }
632
633 /* Look for old selection - can't do this is previous loop since
634 item order will change as more items are added */
635 Sel = 0;
636 for (i = 0; i < NrOfEntries; i++) {
637 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
638 oldWord) {
639 Sel = i;
640 break;
641 }
642 }
643 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
644
645 HeapFree(GetProcessHeap(),0,Words);
646 HeapFree(GetProcessHeap(),0,Names);
647 return TRUE;
648 }
649
650 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
651 int nIDComboBox,
652 WCHAR* PrinterName,
653 WCHAR* PortName,
654 LPDEVMODEW dm)
655 {
656 int i;
657 int NrOfEntries;
658 WCHAR* Names;
659 WORD* Words;
660 DWORD Sel;
661 WORD oldWord = 0;
662 int NamesSize;
663 int fwCapability_Names;
664 int fwCapability_Words;
665
666 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
667
668 /* query the dialog box for the current selected value */
669 Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
670 if(Sel != CB_ERR) {
671 /* we enter here only if a different printer is selected after
672 * the Print Setup dialog is opened. The current settings are
673 * stored into the newly selected printer.
674 */
675 oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
676 Sel, 0);
677 if (dm) {
678 if (nIDComboBox == cmb2)
679 dm->u.s.dmPaperSize = oldWord;
680 else
681 dm->u.s.dmDefaultSource = oldWord;
682 }
683 }
684 else {
685 /* we enter here only when the Print setup dialog is initially
686 * opened. In this case the settings are restored from when
687 * the dialog was last closed.
688 */
689 if (dm) {
690 if (nIDComboBox == cmb2)
691 oldWord = dm->u.s.dmPaperSize;
692 else
693 oldWord = dm->u.s.dmDefaultSource;
694 }
695 }
696
697 if (nIDComboBox == cmb2) {
698 NamesSize = 64;
699 fwCapability_Names = DC_PAPERNAMES;
700 fwCapability_Words = DC_PAPERS;
701 } else {
702 nIDComboBox = cmb3;
703 NamesSize = 24;
704 fwCapability_Names = DC_BINNAMES;
705 fwCapability_Words = DC_BINS;
706 }
707
708 /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
709 * paper settings. As Wine doesn't allow VXDs, this results in a crash.
710 */
711 WARN(" if your printer driver uses VXDs, expect a crash now!\n");
712 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
713 fwCapability_Names, NULL, dm);
714 if (NrOfEntries == 0)
715 WARN("no Name Entries found!\n");
716 else if (NrOfEntries < 0)
717 return FALSE;
718
719 if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
720 != NrOfEntries) {
721 ERR("Number of caps is different\n");
722 NrOfEntries = 0;
723 }
724
725 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
726 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
727 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
728 fwCapability_Names, Names, dm);
729 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
730 fwCapability_Words, (LPWSTR)Words, dm);
731
732 /* reset any current content in the combobox */
733 SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
734
735 /* store new content */
736 for (i = 0; i < NrOfEntries; i++) {
737 DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
738 (LPARAM)(&Names[i*NamesSize]) );
739 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
740 Words[i]);
741 }
742
743 /* Look for old selection - can't do this is previous loop since
744 item order will change as more items are added */
745 Sel = 0;
746 for (i = 0; i < NrOfEntries; i++) {
747 if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
748 oldWord) {
749 Sel = i;
750 break;
751 }
752 }
753 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
754
755 HeapFree(GetProcessHeap(),0,Words);
756 HeapFree(GetProcessHeap(),0,Names);
757 return TRUE;
758 }
759
760
761 /***********************************************************************
762 * PRINTDLG_UpdatePrinterInfoTexts [internal]
763 */
764 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, LPPRINTER_INFO_2A pi)
765 {
766 char StatusMsg[256];
767 char ResourceString[256];
768 int i;
769
770 /* Status Message */
771 StatusMsg[0]='\0';
772
773 /* add all status messages */
774 for (i = 0; i < 25; i++) {
775 if (pi->Status & (1<<i)) {
776 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
777 ResourceString, 255);
778 strcat(StatusMsg,ResourceString);
779 }
780 }
781 /* append "ready" */
782 /* FIXME: status==ready must only be appended if really so.
783 but how to detect? */
784 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
785 ResourceString, 255);
786 strcat(StatusMsg,ResourceString);
787 SetDlgItemTextA(hDlg, stc12, StatusMsg);
788
789 /* set all other printer info texts */
790 SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
791
792 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
793 SetDlgItemTextA(hDlg, stc14, pi->pLocation);
794 else
795 SetDlgItemTextA(hDlg, stc14, pi->pPortName);
796 SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
797 return;
798 }
799
800 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, LPPRINTER_INFO_2W pi)
801 {
802 WCHAR StatusMsg[256];
803 WCHAR ResourceString[256];
804 static const WCHAR emptyW[] = {0};
805 int i;
806
807 /* Status Message */
808 StatusMsg[0]='\0';
809
810 /* add all status messages */
811 for (i = 0; i < 25; i++) {
812 if (pi->Status & (1<<i)) {
813 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
814 ResourceString, 255);
815 lstrcatW(StatusMsg,ResourceString);
816 }
817 }
818 /* append "ready" */
819 /* FIXME: status==ready must only be appended if really so.
820 but how to detect? */
821 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
822 ResourceString, 255);
823 lstrcatW(StatusMsg,ResourceString);
824 SetDlgItemTextW(hDlg, stc12, StatusMsg);
825
826 /* set all other printer info texts */
827 SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
828 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
829 SetDlgItemTextW(hDlg, stc14, pi->pLocation);
830 else
831 SetDlgItemTextW(hDlg, stc14, pi->pPortName);
832 SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
833 }
834
835
836 /*******************************************************************
837 *
838 * PRINTDLG_ChangePrinter
839 *
840 */
841 BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name,
842 PRINT_PTRA *PrintStructures)
843 {
844 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
845 LPDEVMODEA lpdm = NULL;
846 LONG dmSize;
847 DWORD needed;
848 HANDLE hprn;
849
850 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
851 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
852 if(!OpenPrinterA(name, &hprn, NULL)) {
853 ERR("Can't open printer %s\n", name);
854 return FALSE;
855 }
856 GetPrinterA(hprn, 2, NULL, 0, &needed);
857 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
858 GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
859 &needed);
860 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
861 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
862 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
863 needed, &needed)) {
864 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
865 return FALSE;
866 }
867 ClosePrinter(hprn);
868
869 PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
870
871 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
872 PrintStructures->lpDevMode = NULL;
873
874 dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
875 if(dmSize == -1) {
876 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
877 return FALSE;
878 }
879 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
880 dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
881 DM_OUT_BUFFER);
882 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
883 !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
884 (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
885 /* Supplied devicemode matches current printer so try to use it */
886 DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
887 DM_OUT_BUFFER | DM_IN_BUFFER);
888 }
889 if(lpdm)
890 GlobalUnlock(lppd->hDevMode);
891
892 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
893
894 if(!(lppd->Flags & PD_PRINTSETUP)) {
895 /* Print range (All/Range/Selection) */
896 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
897 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
898 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
899 if (lppd->Flags & PD_NOSELECTION)
900 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
901 else
902 if (lppd->Flags & PD_SELECTION)
903 CheckRadioButton(hDlg, rad1, rad3, rad2);
904 if (lppd->Flags & PD_NOPAGENUMS) {
905 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
906 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
907 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
908 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
909 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
910 } else {
911 if (lppd->Flags & PD_PAGENUMS)
912 CheckRadioButton(hDlg, rad1, rad3, rad3);
913 }
914
915 /* Collate pages
916 *
917 * FIXME: The ico3 is not displayed for some reason. I don't know why.
918 */
919 if (lppd->Flags & PD_COLLATE) {
920 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
921 (LPARAM)PrintStructures->hCollateIcon);
922 CheckDlgButton(hDlg, chx2, 1);
923 } else {
924 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
925 (LPARAM)PrintStructures->hNoCollateIcon);
926 CheckDlgButton(hDlg, chx2, 0);
927 }
928
929 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
930 /* if printer doesn't support it: no Collate */
931 if (!(lpdm->dmFields & DM_COLLATE)) {
932 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
933 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
934 }
935 }
936
937 /* nCopies */
938 {
939 INT copies;
940 if (lppd->hDevMode == 0)
941 copies = lppd->nCopies;
942 else
943 copies = lpdm->u.s.dmCopies;
944 if(copies == 0) copies = 1;
945 else if(copies < 0) copies = MAX_COPIES;
946 SetDlgItemInt(hDlg, edt3, copies, FALSE);
947 }
948
949 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
950 /* if printer doesn't support it: no nCopies */
951 if (!(lpdm->dmFields & DM_COPIES)) {
952 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
953 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
954 }
955 }
956
957 /* print to file */
958 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
959 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
960 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
961 if (lppd->Flags & PD_HIDEPRINTTOFILE)
962 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
963
964 } else { /* PD_PRINTSETUP */
965 BOOL bPortrait = (lpdm->u.s.dmOrientation == DMORIENT_PORTRAIT);
966
967 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
968 PrintStructures->lpPrinterInfo->pPrinterName,
969 PrintStructures->lpPrinterInfo->pPortName,
970 lpdm);
971 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
972 PrintStructures->lpPrinterInfo->pPrinterName,
973 PrintStructures->lpPrinterInfo->pPortName,
974 lpdm);
975 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
976 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
977 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
978 PrintStructures->hLandscapeIcon));
979
980 }
981
982 /* help button */
983 if ((lppd->Flags & PD_SHOWHELP)==0) {
984 /* hide if PD_SHOWHELP not specified */
985 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
986 }
987 return TRUE;
988 }
989
990 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
991 PRINT_PTRW *PrintStructures)
992 {
993 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
994 LPDEVMODEW lpdm = NULL;
995 LONG dmSize;
996 DWORD needed;
997 HANDLE hprn;
998
999 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1000 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1001 if(!OpenPrinterW(name, &hprn, NULL)) {
1002 ERR("Can't open printer %s\n", debugstr_w(name));
1003 return FALSE;
1004 }
1005 GetPrinterW(hprn, 2, NULL, 0, &needed);
1006 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1007 GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1008 &needed);
1009 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1010 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1011 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1012 needed, &needed)) {
1013 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1014 return FALSE;
1015 }
1016 ClosePrinter(hprn);
1017
1018 PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1019
1020 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1021 PrintStructures->lpDevMode = NULL;
1022
1023 dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1024 if(dmSize == -1) {
1025 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1026 return FALSE;
1027 }
1028 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1029 dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1030 DM_OUT_BUFFER);
1031 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1032 !lstrcmpW(lpdm->dmDeviceName,
1033 PrintStructures->lpDevMode->dmDeviceName)) {
1034 /* Supplied devicemode matches current printer so try to use it */
1035 DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1036 DM_OUT_BUFFER | DM_IN_BUFFER);
1037 }
1038 if(lpdm)
1039 GlobalUnlock(lppd->hDevMode);
1040
1041 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1042
1043 if(!(lppd->Flags & PD_PRINTSETUP)) {
1044 /* Print range (All/Range/Selection) */
1045 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1046 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1047 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1048 if (lppd->Flags & PD_NOSELECTION)
1049 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1050 else
1051 if (lppd->Flags & PD_SELECTION)
1052 CheckRadioButton(hDlg, rad1, rad3, rad2);
1053 if (lppd->Flags & PD_NOPAGENUMS) {
1054 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1055 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1056 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1057 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1058 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1059 } else {
1060 if (lppd->Flags & PD_PAGENUMS)
1061 CheckRadioButton(hDlg, rad1, rad3, rad3);
1062 }
1063
1064 /* Collate pages
1065 *
1066 * FIXME: The ico3 is not displayed for some reason. I don't know why.
1067 */
1068 if (lppd->Flags & PD_COLLATE) {
1069 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1070 (LPARAM)PrintStructures->hCollateIcon);
1071 CheckDlgButton(hDlg, chx2, 1);
1072 } else {
1073 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1074 (LPARAM)PrintStructures->hNoCollateIcon);
1075 CheckDlgButton(hDlg, chx2, 0);
1076 }
1077
1078 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1079 /* if printer doesn't support it: no Collate */
1080 if (!(lpdm->dmFields & DM_COLLATE)) {
1081 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1082 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1083 }
1084 }
1085
1086 /* nCopies */
1087 {
1088 INT copies;
1089 if (lppd->hDevMode == 0)
1090 copies = lppd->nCopies;
1091 else
1092 copies = lpdm->u.s.dmCopies;
1093 if(copies == 0) copies = 1;
1094 else if(copies < 0) copies = MAX_COPIES;
1095 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1096 }
1097
1098 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1099 /* if printer doesn't support it: no nCopies */
1100 if (!(lpdm->dmFields & DM_COPIES)) {
1101 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1102 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1103 }
1104 }
1105
1106 /* print to file */
1107 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1108 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1109 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1110 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1111 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1112
1113 } else { /* PD_PRINTSETUP */
1114 BOOL bPortrait = (lpdm->u.s.dmOrientation == DMORIENT_PORTRAIT);
1115
1116 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1117 PrintStructures->lpPrinterInfo->pPrinterName,
1118 PrintStructures->lpPrinterInfo->pPortName,
1119 lpdm);
1120 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1121 PrintStructures->lpPrinterInfo->pPrinterName,
1122 PrintStructures->lpPrinterInfo->pPortName,
1123 lpdm);
1124 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1125 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1126 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1127 PrintStructures->hLandscapeIcon));
1128
1129 }
1130
1131 /* help button */
1132 if ((lppd->Flags & PD_SHOWHELP)==0) {
1133 /* hide if PD_SHOWHELP not specified */
1134 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1135 }
1136 return TRUE;
1137 }
1138
1139 /***********************************************************************
1140 * check_printer_setup [internal]
1141 */
1142 static LRESULT check_printer_setup(HWND hDlg)
1143 {
1144 DWORD needed,num;
1145 WCHAR resourcestr[256],resultstr[256];
1146 int res;
1147
1148 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1149 if(needed == 0)
1150 {
1151 EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1152 }
1153 if(needed > 0)
1154 return TRUE;
1155 else
1156 {
1157 LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
1158 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1159 res = MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1160 return FALSE;
1161 }
1162 }
1163
1164 /***********************************************************************
1165 * PRINTDLG_WMInitDialog [internal]
1166 */
1167 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
1168 PRINT_PTRA* PrintStructures)
1169 {
1170 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1171 DEVNAMES *pdn;
1172 DEVMODEA *pdm;
1173 char *name = NULL;
1174 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1175
1176 /* load Collate ICONs */
1177 /* We load these with LoadImage because they are not a standard
1178 size and we don't want them rescaled */
1179 PrintStructures->hCollateIcon =
1180 LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1181 PrintStructures->hNoCollateIcon =
1182 LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1183
1184 /* These can be done with LoadIcon */
1185 PrintStructures->hPortraitIcon =
1186 LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1187 PrintStructures->hLandscapeIcon =
1188 LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1189
1190 /* display the collate/no_collate icon */
1191 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1192 (LPARAM)PrintStructures->hNoCollateIcon);
1193
1194 if(PrintStructures->hCollateIcon == 0 ||
1195 PrintStructures->hNoCollateIcon == 0 ||
1196 PrintStructures->hPortraitIcon == 0 ||
1197 PrintStructures->hLandscapeIcon == 0) {
1198 ERR("no icon in resourcefile\n");
1199 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1200 EndDialog(hDlg, FALSE);
1201 }
1202
1203 /*
1204 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1205 * must be registered and the Help button must be shown.
1206 */
1207 if (lppd->Flags & PD_SHOWHELP) {
1208 if((PrintStructures->HelpMessageID =
1209 RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1210 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1211 return FALSE;
1212 }
1213 } else
1214 PrintStructures->HelpMessageID = 0;
1215
1216 if(!(lppd->Flags &PD_PRINTSETUP)) {
1217 PrintStructures->hwndUpDown =
1218 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1219 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1220 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1221 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1222 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1223 }
1224
1225 /* FIXME: I allow more freedom than either Win95 or WinNT,
1226 * which do not agree to what errors should be thrown or not
1227 * in case nToPage or nFromPage is out-of-range.
1228 */
1229 if (lppd->nMaxPage < lppd->nMinPage)
1230 lppd->nMaxPage = lppd->nMinPage;
1231 if (lppd->nMinPage == lppd->nMaxPage)
1232 lppd->Flags |= PD_NOPAGENUMS;
1233 if (lppd->nToPage < lppd->nMinPage)
1234 lppd->nToPage = lppd->nMinPage;
1235 if (lppd->nToPage > lppd->nMaxPage)
1236 lppd->nToPage = lppd->nMaxPage;
1237 if (lppd->nFromPage < lppd->nMinPage)
1238 lppd->nFromPage = lppd->nMinPage;
1239 if (lppd->nFromPage > lppd->nMaxPage)
1240 lppd->nFromPage = lppd->nMaxPage;
1241
1242 /* if we have the combo box, fill it */
1243 if (GetDlgItem(hDlg,comboID)) {
1244 /* Fill Combobox
1245 */
1246 pdn = GlobalLock(lppd->hDevNames);
1247 pdm = GlobalLock(lppd->hDevMode);
1248 if(pdn)
1249 name = (char*)pdn + pdn->wDeviceOffset;
1250 else if(pdm)
1251 name = (char*)pdm->dmDeviceName;
1252 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1253 if(pdm) GlobalUnlock(lppd->hDevMode);
1254 if(pdn) GlobalUnlock(lppd->hDevNames);
1255
1256 /* Now find selected printer and update rest of dlg */
1257 name = HeapAlloc(GetProcessHeap(),0,256);
1258 if (GetDlgItemTextA(hDlg, comboID, name, 255))
1259 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1260 HeapFree(GetProcessHeap(),0,name);
1261 } else {
1262 /* else use default printer */
1263 char name[200];
1264 DWORD dwBufLen = sizeof(name);
1265 BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1266
1267 if (ret)
1268 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1269 else
1270 FIXME("No default printer found, expect problems!\n");
1271 }
1272 return TRUE;
1273 }
1274
1275 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1276 PRINT_PTRW* PrintStructures)
1277 {
1278 static const WCHAR PD32_COLLATE[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1279 static const WCHAR PD32_NOCOLLATE[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1280 static const WCHAR PD32_PORTRAIT[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
1281 static const WCHAR PD32_LANDSCAPE[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
1282 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1283 DEVNAMES *pdn;
1284 DEVMODEW *pdm;
1285 WCHAR *name = NULL;
1286 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1287
1288 /* load Collate ICONs */
1289 /* We load these with LoadImage because they are not a standard
1290 size and we don't want them rescaled */
1291 PrintStructures->hCollateIcon =
1292 LoadImageW(COMDLG32_hInstance, PD32_COLLATE, IMAGE_ICON, 0, 0, 0);
1293 PrintStructures->hNoCollateIcon =
1294 LoadImageW(COMDLG32_hInstance, PD32_NOCOLLATE, IMAGE_ICON, 0, 0, 0);
1295
1296 /* These can be done with LoadIcon */
1297 PrintStructures->hPortraitIcon =
1298 LoadIconW(COMDLG32_hInstance, PD32_PORTRAIT);
1299 PrintStructures->hLandscapeIcon =
1300 LoadIconW(COMDLG32_hInstance, PD32_LANDSCAPE);
1301
1302 /* display the collate/no_collate icon */
1303 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1304 (LPARAM)PrintStructures->hNoCollateIcon);
1305
1306 if(PrintStructures->hCollateIcon == 0 ||
1307 PrintStructures->hNoCollateIcon == 0 ||
1308 PrintStructures->hPortraitIcon == 0 ||
1309 PrintStructures->hLandscapeIcon == 0) {
1310 ERR("no icon in resourcefile\n");
1311 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1312 EndDialog(hDlg, FALSE);
1313 }
1314
1315 /*
1316 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1317 * must be registered and the Help button must be shown.
1318 */
1319 if (lppd->Flags & PD_SHOWHELP) {
1320 if((PrintStructures->HelpMessageID =
1321 RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1322 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1323 return FALSE;
1324 }
1325 } else
1326 PrintStructures->HelpMessageID = 0;
1327
1328 if(!(lppd->Flags &PD_PRINTSETUP)) {
1329 PrintStructures->hwndUpDown =
1330 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1331 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1332 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1333 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1334 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1335 }
1336
1337 /* FIXME: I allow more freedom than either Win95 or WinNT,
1338 * which do not agree to what errors should be thrown or not
1339 * in case nToPage or nFromPage is out-of-range.
1340 */
1341 if (lppd->nMaxPage < lppd->nMinPage)
1342 lppd->nMaxPage = lppd->nMinPage;
1343 if (lppd->nMinPage == lppd->nMaxPage)
1344 lppd->Flags |= PD_NOPAGENUMS;
1345 if (lppd->nToPage < lppd->nMinPage)
1346 lppd->nToPage = lppd->nMinPage;
1347 if (lppd->nToPage > lppd->nMaxPage)
1348 lppd->nToPage = lppd->nMaxPage;
1349 if (lppd->nFromPage < lppd->nMinPage)
1350 lppd->nFromPage = lppd->nMinPage;
1351 if (lppd->nFromPage > lppd->nMaxPage)
1352 lppd->nFromPage = lppd->nMaxPage;
1353
1354 /* if we have the combo box, fill it */
1355 if (GetDlgItem(hDlg,comboID)) {
1356 /* Fill Combobox
1357 */
1358 pdn = GlobalLock(lppd->hDevNames);
1359 pdm = GlobalLock(lppd->hDevMode);
1360 if(pdn)
1361 name = (WCHAR*)pdn + pdn->wDeviceOffset;
1362 else if(pdm)
1363 name = pdm->dmDeviceName;
1364 PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1365 if(pdm) GlobalUnlock(lppd->hDevMode);
1366 if(pdn) GlobalUnlock(lppd->hDevNames);
1367
1368 /* Now find selected printer and update rest of dlg */
1369 /* ansi is ok here */
1370 name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1371 if (GetDlgItemTextW(hDlg, comboID, name, 255))
1372 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1373 HeapFree(GetProcessHeap(),0,name);
1374 } else {
1375 /* else use default printer */
1376 WCHAR name[200];
1377 DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1378 BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1379
1380 if (ret)
1381 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1382 else
1383 FIXME("No default printer found, expect problems!\n");
1384 }
1385 return TRUE;
1386 }
1387
1388 /***********************************************************************
1389 * PRINTDLG_WMCommand [internal]
1390 */
1391 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1392 LPARAM lParam, PRINT_PTRA* PrintStructures)
1393 {
1394 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1395 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1396 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1397
1398 switch (LOWORD(wParam)) {
1399 case IDOK:
1400 TRACE(" OK button was hit\n");
1401 if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1402 FIXME("Update printdlg was not successful!\n");
1403 return(FALSE);
1404 }
1405 EndDialog(hDlg, TRUE);
1406 return(TRUE);
1407
1408 case IDCANCEL:
1409 TRACE(" CANCEL button was hit\n");
1410 EndDialog(hDlg, FALSE);
1411 return(FALSE);
1412
1413 case pshHelp:
1414 TRACE(" HELP button was hit\n");
1415 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1416 (WPARAM) hDlg, (LPARAM) lppd);
1417 break;
1418
1419 case chx2: /* collate pages checkbox */
1420 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1421 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1422 (LPARAM)PrintStructures->hCollateIcon);
1423 else
1424 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1425 (LPARAM)PrintStructures->hNoCollateIcon);
1426 break;
1427 case edt1: /* from page nr editbox */
1428 case edt2: /* to page nr editbox */
1429 if (HIWORD(wParam)==EN_CHANGE) {
1430 WORD nToPage;
1431 WORD nFromPage;
1432 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1433 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1434 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1435 CheckRadioButton(hDlg, rad1, rad3, rad3);
1436 }
1437 break;
1438
1439 case edt3:
1440 if(HIWORD(wParam) == EN_CHANGE) {
1441 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1442 if(copies <= 1)
1443 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1444 else
1445 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1446 }
1447 break;
1448
1449 #if 0
1450 case psh1: /* Print Setup */
1451 {
1452 PRINTDLG16 pdlg;
1453
1454 if (!PrintStructures->dlg.lpPrintDlg16) {
1455 FIXME("The 32bit print dialog does not have this button!?\n");
1456 break;
1457 }
1458
1459 memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1460 pdlg.Flags |= PD_PRINTSETUP;
1461 pdlg.hwndOwner = HWND_16(hDlg);
1462 if (!PrintDlg16(&pdlg))
1463 break;
1464 }
1465 break;
1466 #endif
1467 case psh2: /* Properties button */
1468 {
1469 HANDLE hPrinter;
1470 char PrinterName[256];
1471
1472 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1473 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1474 FIXME(" Call to OpenPrinter did not succeed!\n");
1475 break;
1476 }
1477 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1478 PrintStructures->lpDevMode,
1479 PrintStructures->lpDevMode,
1480 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1481 ClosePrinter(hPrinter);
1482 break;
1483 }
1484
1485 case rad1: /* Paperorientation */
1486 if (lppd->Flags & PD_PRINTSETUP)
1487 {
1488 lpdm->u.s.dmOrientation = DMORIENT_PORTRAIT;
1489 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1490 (LPARAM)(PrintStructures->hPortraitIcon));
1491 }
1492 break;
1493
1494 case rad2: /* Paperorientation */
1495 if (lppd->Flags & PD_PRINTSETUP)
1496 {
1497 lpdm->u.s.dmOrientation = DMORIENT_LANDSCAPE;
1498 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1499 (LPARAM)(PrintStructures->hLandscapeIcon));
1500 }
1501 break;
1502
1503 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1504 if (PrinterComboID != LOWORD(wParam)) {
1505 FIXME("No handling for print quality combo box yet.\n");
1506 break;
1507 }
1508 /* FALLTHROUGH */
1509 case cmb4: /* Printer combobox */
1510 if (HIWORD(wParam)==CBN_SELCHANGE) {
1511 char PrinterName[256];
1512 GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1513 PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1514 }
1515 break;
1516
1517 case cmb2: /* Papersize */
1518 {
1519 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1520 if(Sel != CB_ERR)
1521 lpdm->u.s.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1522 CB_GETITEMDATA,
1523 Sel, 0);
1524 }
1525 break;
1526
1527 case cmb3: /* Bin */
1528 {
1529 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1530 if(Sel != CB_ERR)
1531 lpdm->u.s.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1532 CB_GETITEMDATA, Sel,
1533 0);
1534 }
1535 break;
1536 }
1537 if(lppd->Flags & PD_PRINTSETUP) {
1538 switch (LOWORD(wParam)) {
1539 case rad1: /* orientation */
1540 case rad2:
1541 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1542 if(lpdm->u.s.dmOrientation != DMORIENT_PORTRAIT) {
1543 lpdm->u.s.dmOrientation = DMORIENT_PORTRAIT;
1544 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1545 (WPARAM)IMAGE_ICON,
1546 (LPARAM)PrintStructures->hPortraitIcon);
1547 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1548 (WPARAM)IMAGE_ICON,
1549 (LPARAM)PrintStructures->hPortraitIcon);
1550 }
1551 } else {
1552 if(lpdm->u.s.dmOrientation != DMORIENT_LANDSCAPE) {
1553 lpdm->u.s.dmOrientation = DMORIENT_LANDSCAPE;
1554 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1555 (WPARAM)IMAGE_ICON,
1556 (LPARAM)PrintStructures->hLandscapeIcon);
1557 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1558 (WPARAM)IMAGE_ICON,
1559 (LPARAM)PrintStructures->hLandscapeIcon);
1560 }
1561 }
1562 break;
1563 }
1564 }
1565 return FALSE;
1566 }
1567
1568 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1569 LPARAM lParam, PRINT_PTRW* PrintStructures)
1570 {
1571 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1572 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1573 LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1574
1575 switch (LOWORD(wParam)) {
1576 case IDOK:
1577 TRACE(" OK button was hit\n");
1578 if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1579 FIXME("Update printdlg was not successful!\n");
1580 return(FALSE);
1581 }
1582 EndDialog(hDlg, TRUE);
1583 return(TRUE);
1584
1585 case IDCANCEL:
1586 TRACE(" CANCEL button was hit\n");
1587 EndDialog(hDlg, FALSE);
1588 return(FALSE);
1589
1590 case pshHelp:
1591 TRACE(" HELP button was hit\n");
1592 SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1593 (WPARAM) hDlg, (LPARAM) lppd);
1594 break;
1595
1596 case chx2: /* collate pages checkbox */
1597 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1598 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1599 (LPARAM)PrintStructures->hCollateIcon);
1600 else
1601 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1602 (LPARAM)PrintStructures->hNoCollateIcon);
1603 break;
1604 case edt1: /* from page nr editbox */
1605 case edt2: /* to page nr editbox */
1606 if (HIWORD(wParam)==EN_CHANGE) {
1607 WORD nToPage;
1608 WORD nFromPage;
1609 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1610 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1611 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1612 CheckRadioButton(hDlg, rad1, rad3, rad3);
1613 }
1614 break;
1615
1616 case edt3:
1617 if(HIWORD(wParam) == EN_CHANGE) {
1618 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1619 if(copies <= 1)
1620 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1621 else
1622 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1623 }
1624 break;
1625
1626 case psh1: /* Print Setup */
1627 {
1628 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1629 }
1630 break;
1631 case psh2: /* Properties button */
1632 {
1633 HANDLE hPrinter;
1634 WCHAR PrinterName[256];
1635
1636 if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1637 if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1638 FIXME(" Call to OpenPrinter did not succeed!\n");
1639 break;
1640 }
1641 DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1642 PrintStructures->lpDevMode,
1643 PrintStructures->lpDevMode,
1644 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1645 ClosePrinter(hPrinter);
1646 break;
1647 }
1648
1649 case rad1: /* Paperorientation */
1650 if (lppd->Flags & PD_PRINTSETUP)
1651 {
1652 lpdm->u.s.dmOrientation = DMORIENT_PORTRAIT;
1653 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1654 (LPARAM)(PrintStructures->hPortraitIcon));
1655 }
1656 break;
1657
1658 case rad2: /* Paperorientation */
1659 if (lppd->Flags & PD_PRINTSETUP)
1660 {
1661 lpdm->u.s.dmOrientation = DMORIENT_LANDSCAPE;
1662 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1663 (LPARAM)(PrintStructures->hLandscapeIcon));
1664 }
1665 break;
1666
1667 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1668 if (PrinterComboID != LOWORD(wParam)) {
1669 FIXME("No handling for print quality combo box yet.\n");
1670 break;
1671 }
1672 /* FALLTHROUGH */
1673 case cmb4: /* Printer combobox */
1674 if (HIWORD(wParam)==CBN_SELCHANGE) {
1675 WCHAR PrinterName[256];
1676 GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1677 PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1678 }
1679 break;
1680
1681 case cmb2: /* Papersize */
1682 {
1683 DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1684 if(Sel != CB_ERR)
1685 lpdm->u.s.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1686 CB_GETITEMDATA,
1687 Sel, 0);
1688 }
1689 break;
1690
1691 case cmb3: /* Bin */
1692 {
1693 DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1694 if(Sel != CB_ERR)
1695 lpdm->u.s.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1696 CB_GETITEMDATA, Sel,
1697 0);
1698 }
1699 break;
1700 }
1701 if(lppd->Flags & PD_PRINTSETUP) {
1702 switch (LOWORD(wParam)) {
1703 case rad1: /* orientation */
1704 case rad2:
1705 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1706 if(lpdm->u.s.dmOrientation != DMORIENT_PORTRAIT) {
1707 lpdm->u.s.dmOrientation = DMORIENT_PORTRAIT;
1708 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1709 (WPARAM)IMAGE_ICON,
1710 (LPARAM)PrintStructures->hPortraitIcon);
1711 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1712 (WPARAM)IMAGE_ICON,
1713 (LPARAM)PrintStructures->hPortraitIcon);
1714 }
1715 } else {
1716 if(lpdm->u.s.dmOrientation != DMORIENT_LANDSCAPE) {
1717 lpdm->u.s.dmOrientation = DMORIENT_LANDSCAPE;
1718 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1719 (WPARAM)IMAGE_ICON,
1720 (LPARAM)PrintStructures->hLandscapeIcon);
1721 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1722 (WPARAM)IMAGE_ICON,
1723 (LPARAM)PrintStructures->hLandscapeIcon);
1724 }
1725 }
1726 break;
1727 }
1728 }
1729 return FALSE;
1730 }
1731
1732 /***********************************************************************
1733 * PrintDlgProcA [internal]
1734 */
1735 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1736 LPARAM lParam)
1737 {
1738 PRINT_PTRA* PrintStructures;
1739 INT_PTR res = FALSE;
1740
1741 if (uMsg!=WM_INITDIALOG) {
1742 PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
1743 if (!PrintStructures)
1744 return FALSE;
1745 } else {
1746 PrintStructures = (PRINT_PTRA*) lParam;
1747 SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
1748 if(!check_printer_setup(hDlg))
1749 {
1750 EndDialog(hDlg,FALSE);
1751 return FALSE;
1752 }
1753 res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1754
1755 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1756 res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1757 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1758 );
1759 return res;
1760 }
1761
1762 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1763 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1764 lParam);
1765 if(res) return res;
1766 }
1767
1768 switch (uMsg) {
1769 case WM_COMMAND:
1770 return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1771
1772 case WM_DESTROY:
1773 DestroyIcon(PrintStructures->hCollateIcon);
1774 DestroyIcon(PrintStructures->hNoCollateIcon);
1775 DestroyIcon(PrintStructures->hPortraitIcon);
1776 DestroyIcon(PrintStructures->hLandscapeIcon);
1777 if(PrintStructures->hwndUpDown)
1778 DestroyWindow(PrintStructures->hwndUpDown);
1779 return FALSE;
1780 }
1781 return res;
1782 }
1783
1784 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1785 LPARAM lParam)
1786 {
1787 static const WCHAR propW[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
1788 PRINT_PTRW* PrintStructures;
1789 INT_PTR res = FALSE;
1790
1791 if (uMsg!=WM_INITDIALOG) {
1792 PrintStructures = (PRINT_PTRW*) GetPropW(hDlg, propW);
1793 if (!PrintStructures)
1794 return FALSE;
1795 } else {
1796 PrintStructures = (PRINT_PTRW*) lParam;
1797 SetPropW(hDlg, propW, PrintStructures);
1798 if(!check_printer_setup(hDlg))
1799 {
1800 EndDialog(hDlg,FALSE);
1801 return FALSE;
1802 }
1803 res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1804
1805 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1806 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1807 return res;
1808 }
1809
1810 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1811 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1812 if(res) return res;
1813 }
1814
1815 switch (uMsg) {
1816 case WM_COMMAND:
1817 return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1818
1819 case WM_DESTROY:
1820 DestroyIcon(PrintStructures->hCollateIcon);
1821 DestroyIcon(PrintStructures->hNoCollateIcon);
1822 DestroyIcon(PrintStructures->hPortraitIcon);
1823 DestroyIcon(PrintStructures->hLandscapeIcon);
1824 if(PrintStructures->hwndUpDown)
1825 DestroyWindow(PrintStructures->hwndUpDown);
1826 return FALSE;
1827 }
1828 return res;
1829 }
1830
1831 /************************************************************
1832 *
1833 * PRINTDLG_GetDlgTemplate
1834 *
1835 */
1836 static HGLOBAL PRINTDLG_GetDlgTemplateA(PRINTDLGA *lppd)
1837 {
1838 HRSRC hResInfo;
1839 HGLOBAL hDlgTmpl;
1840
1841 if (lppd->Flags & PD_PRINTSETUP) {
1842 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1843 hDlgTmpl = lppd->hSetupTemplate;
1844 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1845 hResInfo = FindResourceA(lppd->hInstance,
1846 lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1847 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1848 } else {
1849 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1850 (LPSTR)RT_DIALOG);
1851 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1852 }
1853 } else {
1854 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1855 hDlgTmpl = lppd->hPrintTemplate;
1856 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1857 hResInfo = FindResourceA(lppd->hInstance,
1858 lppd->lpPrintTemplateName,
1859 (LPSTR)RT_DIALOG);
1860 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1861 } else {
1862 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1863 (LPSTR)RT_DIALOG);
1864 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1865 }
1866 }
1867 return hDlgTmpl;
1868 }
1869
1870 static HGLOBAL PRINTDLG_GetDlgTemplateW(PRINTDLGW *lppd)
1871 {
1872 HRSRC hResInfo;
1873 HGLOBAL hDlgTmpl;
1874 static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1875 static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1876
1877 if (lppd->Flags & PD_PRINTSETUP) {
1878 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1879 hDlgTmpl = lppd->hSetupTemplate;
1880 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1881 hResInfo = FindResourceW(lppd->hInstance,
1882 lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1883 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1884 } else {
1885 hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1886 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1887 }
1888 } else {
1889 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1890 hDlgTmpl = lppd->hPrintTemplate;
1891 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1892 hResInfo = FindResourceW(lppd->hInstance,
1893 lppd->lpPrintTemplateName,
1894 (LPWSTR)RT_DIALOG);
1895 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1896 } else {
1897 hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1898 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1899 }
1900 }
1901 return hDlgTmpl;
1902 }
1903
1904 /***********************************************************************
1905 *
1906 * PRINTDLG_CreateDC
1907 *
1908 */
1909 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1910 {
1911 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1912 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1913
1914 if(lppd->Flags & PD_RETURNDC) {
1915 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1916 (char*)pdn + pdn->wDeviceOffset,
1917 (char*)pdn + pdn->wOutputOffset,
1918 pdm );
1919 } else if(lppd->Flags & PD_RETURNIC) {
1920 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1921 (char*)pdn + pdn->wDeviceOffset,
1922 (char*)pdn + pdn->wOutputOffset,
1923 pdm );
1924 }
1925 GlobalUnlock(lppd->hDevNames);
1926 GlobalUnlock(lppd->hDevMode);
1927 return lppd->hDC ? TRUE : FALSE;
1928 }
1929
1930 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1931 {
1932 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1933 DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1934
1935 if(lppd->Flags & PD_RETURNDC) {
1936 lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1937 (WCHAR*)pdn + pdn->wDeviceOffset,
1938 (WCHAR*)pdn + pdn->wOutputOffset,
1939 pdm );
1940 } else if(lppd->Flags & PD_RETURNIC) {
1941 lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1942 (WCHAR*)pdn + pdn->wDeviceOffset,
1943 (WCHAR*)pdn + pdn->wOutputOffset,
1944 pdm );
1945 }
1946 GlobalUnlock(lppd->hDevNames);
1947 GlobalUnlock(lppd->hDevMode);
1948 return lppd->hDC ? TRUE : FALSE;
1949 }
1950
1951 /***********************************************************************
1952 * PrintDlgA (COMDLG32.@)
1953 *
1954 * Displays the the PRINT dialog box, which enables the user to specify
1955 * specific properties of the print job.
1956 *
1957 * PARAMS
1958 * lppd [IO] ptr to PRINTDLG32 struct
1959 *
1960 * RETURNS
1961 * nonzero if the user pressed the OK button
1962 * zero if the user cancelled the window or an error occurred
1963 *
1964 * BUGS
1965 * PrintDlg:
1966 * * The Collate Icons do not display, even though they are in the code.
1967 * * The Properties Button(s) should call DocumentPropertiesA().
1968 */
1969
1970 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
1971 {
1972 BOOL bRet = FALSE;
1973 LPVOID ptr;
1974 HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrA( lppd->hwndOwner, GWLP_HINSTANCE );
1975
1976 if(TRACE_ON(commdlg)) {
1977 char flagstr[1000] = "";
1978 struct pd_flags *pflag = pd_flags;
1979 for( ; pflag->name; pflag++) {
1980 if(lppd->Flags & pflag->flag)
1981 strcat(flagstr, pflag->name);
1982 }
1983 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
1984 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
1985 "flags %08lx (%s)\n",
1986 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1987 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1988 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1989 }
1990
1991 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1992 WARN("structure size failure !!!\n");
1993 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1994 return FALSE;
1995 }
1996
1997 if(lppd->Flags & PD_RETURNDEFAULT) {
1998 PRINTER_INFO_2A *pbuf;
1999 DRIVER_INFO_3A *dbuf;
2000 HANDLE hprn;
2001 DWORD needed;
2002
2003 if(lppd->hDevMode || lppd->hDevNames) {
2004 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2005 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2006 return FALSE;
2007 }
2008 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2009 WARN("Can't find default printer\n");
2010 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2011 return FALSE;
2012 }
2013
2014 GetPrinterA(hprn, 2, NULL, 0, &needed);
2015 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2016 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2017
2018 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2019 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2020 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2021 ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
2022 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2023 return FALSE;
2024 }
2025 ClosePrinter(hprn);
2026
2027 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2028 dbuf->pDriverPath,
2029 pbuf->pPrinterName,
2030 pbuf->pPortName);
2031 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2032 pbuf->pDevMode->dmDriverExtra);
2033 ptr = GlobalLock(lppd->hDevMode);
2034 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2035 pbuf->pDevMode->dmDriverExtra);
2036 GlobalUnlock(lppd->hDevMode);
2037 HeapFree(GetProcessHeap(), 0, pbuf);
2038 HeapFree(GetProcessHeap(), 0, dbuf);
2039 bRet = TRUE;
2040 } else {
2041 HGLOBAL hDlgTmpl;
2042 PRINT_PTRA *PrintStructures;
2043
2044 /* load Dialog resources,
2045 * depending on Flags indicates Print32 or Print32_setup dialog
2046 */
2047 hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2048 if (!hDlgTmpl) {
2049 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2050 return FALSE;
2051 }
2052 ptr = LockResource( hDlgTmpl );
2053 if (!ptr) {
2054 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2055 return FALSE;
2056 }
2057
2058 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2059 sizeof(PRINT_PTRA));
2060 PrintStructures->lpPrintDlg = lppd;
2061
2062 /* and create & process the dialog .
2063 * -1 is failure, 0 is broken hwnd, everything else is ok.
2064 */
2065 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2066 PrintDlgProcA,
2067 (LPARAM)PrintStructures));
2068
2069 if(bRet) {
2070 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2071 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2072 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2073
2074 if (lppd->hDevMode == 0) {
2075 TRACE(" No hDevMode yet... Need to create my own\n");
2076 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2077 lpdm->dmSize + lpdm->dmDriverExtra);
2078 } else {
2079 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2080 lpdm->dmSize + lpdm->dmDriverExtra,
2081 GMEM_MOVEABLE);
2082 }
2083 lpdmReturn = GlobalLock(lppd->hDevMode);
2084 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2085
2086 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2087 di->pDriverPath,
2088 pi->pPrinterName,
2089 pi->pPortName
2090 );
2091 GlobalUnlock(lppd->hDevMode);
2092 }
2093 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2094 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2095 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2096 HeapFree(GetProcessHeap(), 0, PrintStructures);
2097 }
2098 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2099 bRet = PRINTDLG_CreateDCA(lppd);
2100
2101 TRACE("exit! (%d)\n", bRet);
2102 return bRet;
2103 }
2104
2105 /***********************************************************************
2106 * PrintDlgW (COMDLG32.@)
2107 *
2108 * See PrintDlgA.
2109 */
2110 BOOL WINAPI PrintDlgW(
2111 LPPRINTDLGW lppd /* [in/out] ptr to PRINTDLG32 struct */
2112 )
2113 {
2114 BOOL bRet = FALSE;
2115 LPVOID ptr;
2116 HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2117
2118 if(TRACE_ON(commdlg)) {
2119 char flagstr[1000] = "";
2120 struct pd_flags *pflag = pd_flags;
2121 for( ; pflag->name; pflag++) {
2122 if(lppd->Flags & pflag->flag)
2123 strcat(flagstr, pflag->name);
2124 }
2125 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2126 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2127 "flags %08lx (%s)\n",
2128 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2129 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2130 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2131 }
2132
2133 if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2134 WARN("structure size failure !!!\n");
2135 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2136 return FALSE;
2137 }
2138
2139 if(lppd->Flags & PD_RETURNDEFAULT) {
2140 PRINTER_INFO_2W *pbuf;
2141 DRIVER_INFO_3W *dbuf;
2142 HANDLE hprn;
2143 DWORD needed;
2144
2145 if(lppd->hDevMode || lppd->hDevNames) {
2146 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2147 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2148 return FALSE;
2149 }
2150 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2151 WARN("Can't find default printer\n");
2152 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2153 return FALSE;
2154 }
2155
2156 GetPrinterW(hprn, 2, NULL, 0, &needed);
2157 pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2158 GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2159
2160 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2161 dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2162 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2163 ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),debugstr_w(pbuf->pPrinterName));
2164 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2165 return FALSE;
2166 }
2167 ClosePrinter(hprn);
2168
2169 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2170 dbuf->pDriverPath,
2171 pbuf->pPrinterName,
2172 pbuf->pPortName);
2173 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2174 pbuf->pDevMode->dmDriverExtra);
2175 ptr = GlobalLock(lppd->hDevMode);
2176 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2177 pbuf->pDevMode->dmDriverExtra);
2178 GlobalUnlock(lppd->hDevMode);
2179 HeapFree(GetProcessHeap(), 0, pbuf);
2180 HeapFree(GetProcessHeap(), 0, dbuf);
2181 bRet = TRUE;
2182 } else {
2183 HGLOBAL hDlgTmpl;
2184 PRINT_PTRW *PrintStructures;
2185
2186 /* load Dialog resources,
2187 * depending on Flags indicates Print32 or Print32_setup dialog
2188 */
2189 hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2190 if (!hDlgTmpl) {
2191 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2192 return FALSE;
2193 }
2194 ptr = LockResource( hDlgTmpl );
2195 if (!ptr) {
2196 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2197 return FALSE;
2198 }
2199
2200 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2201 sizeof(PRINT_PTRW));
2202 PrintStructures->lpPrintDlg = lppd;
2203
2204 /* and create & process the dialog .
2205 * -1 is failure, 0 is broken hwnd, everything else is ok.
2206 */
2207 bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2208 PrintDlgProcW,
2209 (LPARAM)PrintStructures));
2210
2211 if(bRet) {
2212 DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2213 PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2214 DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2215
2216 if (lppd->hDevMode == 0) {
2217 TRACE(" No hDevMode yet... Need to create my own\n");
2218 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2219 lpdm->dmSize + lpdm->dmDriverExtra);
2220 } else {
2221 WORD locks;
2222 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2223 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2224 while(locks--) {
2225 GlobalUnlock(lppd->hDevMode);
2226 TRACE("Now got %d locks\n", locks);
2227 }
2228 }
2229 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2230 lpdm->dmSize + lpdm->dmDriverExtra,
2231 GMEM_MOVEABLE);
2232 }
2233 lpdmReturn = GlobalLock(lppd->hDevMode);
2234 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2235
2236 if (lppd->hDevNames != 0) {
2237 WORD locks;
2238 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2239 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2240 while(locks--)
2241 GlobalUnlock(lppd->hDevNames);
2242 }
2243 }
2244 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2245 di->pDriverPath,
2246 pi->pPrinterName,
2247 pi->pPortName
2248 );
2249 GlobalUnlock(lppd->hDevMode);
2250 }
2251 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2252 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2253 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2254 HeapFree(GetProcessHeap(), 0, PrintStructures);
2255 }
2256 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2257 bRet = PRINTDLG_CreateDCW(lppd);
2258
2259 TRACE("exit! (%d)\n", bRet);
2260 return bRet;
2261 }
2262
2263 /***********************************************************************
2264 *
2265 * PageSetupDlg
2266 * rad1 - portrait
2267 * rad2 - landscape
2268 * cmb1 - printer select (not in standart dialog template)
2269 * cmb2 - paper size
2270 * cmb3 - source (tray?)
2271 * edt4 - border left
2272 * edt5 - border top
2273 * edt6 - border right
2274 * edt7 - border bottom
2275 * psh3 - "Printer..."
2276 */
2277
2278 typedef struct {
2279 LPPAGESETUPDLGA dlga; /* Handler to user defined struct */
2280 PRINTDLGA pdlg;
2281 HWND hDlg; /* Page Setup dialog handler */
2282 PAGESETUPDLGA curdlg; /* Struct means cerrent dialog state */
2283 RECT rtDrawRect; /* Drawing rect for page */
2284 } PageSetupDataA;
2285
2286 typedef struct {
2287 LPPAGESETUPDLGW dlga;
2288 PRINTDLGW pdlg;
2289 } PageSetupDataW;
2290
2291
2292 static HGLOBAL PRINTDLG_GetPGSTemplateA(PAGESETUPDLGA *lppd)
2293 {
2294 HRSRC hResInfo;
2295 HGLOBAL hDlgTmpl;
2296
2297 if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2298 hDlgTmpl = lppd->hPageSetupTemplate;
2299 } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2300 hResInfo = FindResourceA(lppd->hInstance,
2301 lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2302 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2303 } else {
2304 hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2305 hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2306 }
2307 return hDlgTmpl;
2308 }
2309
2310 static HGLOBAL PRINTDLG_GetPGSTemplateW(PAGESETUPDLGW *lppd)
2311 {
2312 HRSRC hResInfo;
2313 HGLOBAL hDlgTmpl;
2314
2315 if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2316 hDlgTmpl = lppd->hPageSetupTemplate;
2317 } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2318 hResInfo = FindResourceW(lppd->hInstance,
2319 lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2320 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2321 } else {
2322 hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2323 hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2324 }
2325 return hDlgTmpl;
2326 }
2327
2328 static DWORD
2329 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2330 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2331 return 10*size*100/254;
2332 /* If we don't have a flag, we can choose one. Use millimeters
2333 * to avoid confusing me
2334 */
2335 dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2336 return 10*size;
2337 }
2338
2339
2340 static DWORD
2341 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2342 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2343 return size;
2344 if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2345 return (size*254)/100;
2346 /* if we don't have a flag, we can choose one. Use millimeters
2347 * to avoid confusing me
2348 */
2349 dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2350 return (size*254)/100;
2351 }
2352
2353 static void
2354 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2355 strcpy(strout,"<undef>");
2356 if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2357 sprintf(strout,"%ld",(size)/100);
2358 return;
2359 }
2360 if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2361 sprintf(strout,"%ldin",(size)/1000);
2362 return;
2363 }
2364 pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2365 sprintf(strout,"%ld",(size)/100);
2366 return;
2367 }
2368 static void
2369 _c_size2strW(PageSetupDataW *pda,DWORD size,LPWSTR strout) {
2370 static const WCHAR UNDEF[] = { '<', 'u', 'n', 'd', 'e', 'f', '>', 0 };
2371 static const WCHAR mm_fmt[] = { '%', '.', '2', 'f', 'm', 'm', 0 };
2372 static const WCHAR in_fmt[] = { '%', '.', '2', 'f', 'i', 'n', 0 };
2373 lstrcpyW(strout, UNDEF);
2374 if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2375 wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2376 return;
2377 }
2378 if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2379 wsprintfW(strout,in_fmt,(size*1.0)/1000.0);
2380 return;
2381 }
2382 pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2383 wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2384 return;
2385 }
2386
2387 static DWORD
2388 _c_str2sizeA(PAGESETUPDLGA *dlga,LPCSTR strin) {
2389 float val;
2390 char rest[200];
2391
2392 rest[0]='\0';
2393 if (!sscanf(strin,"%f%s",&val,rest))
2394 return 0;
2395
2396 if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2397 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2398 return 1000*val;
2399 else
2400 return val*25.4*100;
2401 }
2402 if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2403 if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2404
2405 if (!strcmp(rest,"mm")) {
2406 if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2407 return 100*val;
2408 else
2409 return 1000.0*val/25.4;
2410 }
2411 if (rest[0]=='\0') {
2412 /* use application supplied default */
2413 if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2414 /* 100*mm */
2415 return 100.0*val;
2416 }
2417 if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2418 /* 1000*inch */
2419 return 1000.0*val;
2420 }
2421 }
2422 ERR("Did not find a conversion for type '%s'!\n",rest);
2423 return 0;
2424 }
2425
2426
2427 static DWORD
2428 _c_str2sizeW(PAGESETUPDLGW *dlga, LPCWSTR strin) {
2429 char buf[200];
2430
2431 /* this W -> A transition is OK */
2432 /* we need a unicode version of sscanf to avoid it */
2433 WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2434 return _c_str2sizeA((PAGESETUPDLGA *)dlga, buf);
2435 }
2436
2437
2438 /****************************************************************************
2439 * PRINTDLG_PS_UpdateDlgStructA
2440 *
2441 * Updates pda->dlga structure
2442 * Function calls when user presses OK button
2443 *
2444 * PARAMS
2445 * hDlg [in] main window dialog HANDLE
2446 * pda [in/out] ptr to PageSetupDataA structere
2447 *
2448 * RETURNS
2449 * TRUE
2450 */
2451 static BOOL
2452 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2453 DEVNAMES *dn;
2454 DEVMODEA *dm;
2455 DWORD paperword;
2456
2457 memcpy(pda->dlga, &pda->curdlg, sizeof(pda->curdlg));
2458 pda->dlga->hDevMode = pda->pdlg.hDevMode;
2459 pda->dlga->hDevNames = pda->pdlg.hDevNames;
2460
2461 dn = GlobalLock(pda->pdlg.hDevNames);
2462 dm = GlobalLock(pda->pdlg.hDevMode);
2463
2464 /* Save paper orientation into device context */
2465 if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y)
2466 dm->u.s.dmOrientation = DMORIENT_LANDSCAPE;
2467 else
2468 dm->u.s.dmOrientation = DMORIENT_PORTRAIT;
2469
2470 /* Save paper size into the device context */
2471 paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2472 SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2473 if (paperword != CB_ERR)
2474 dm->u.s.dmPaperSize = paperword;
2475 else
2476 FIXME("could not get dialog text for papersize cmbbox?\n");
2477
2478 /* Save paper source into the device context */
2479 paperword = SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,
2480 SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL, 0, 0), 0);
2481 if (paperword != CB_ERR)
2482 dm->u.s.dmDefaultSource = paperword;
2483 else
2484 FIXME("could not get dialog text for papersize cmbbox?\n");
2485
2486 GlobalUnlock(pda->pdlg.hDevNames);
2487 GlobalUnlock(pda->pdlg.hDevMode);
2488
2489 return TRUE;
2490 }
2491
2492 static BOOL
2493 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2494 DEVNAMES *dn;
2495 DEVMODEW *dm;
2496 LPWSTR devname,portname;
2497 WCHAR papername[64];
2498 WCHAR buf[200];
2499
2500 dn = GlobalLock(pda->pdlg.hDevNames);
2501 dm = GlobalLock(pda->pdlg.hDevMode);
2502 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
2503 portname = ((WCHAR*)dn)+dn->wOutputOffset;
2504
2505 /* Save paper size into device context */
2506 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2507 /* Save paper source into device context */
2508 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2509
2510 if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2511 PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2512 pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2513 pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2514 } else
2515 FIXME("could not get dialog text for papersize cmbbox?\n");
2516 #define GETVAL(id,val) if (GetDlgItemTextW(hDlg,id,buf,sizeof(buf)/sizeof(buf[0]))>0) { val = _c_str2sizeW(pda->dlga,buf); } else { FIXME("could not get dlgitemtextw for %x\n",id); }
2517 GETVAL(edt4,pda->dlga->rtMargin.left);
2518 GETVAL(edt5,pda->dlga->rtMargin.top);
2519 GETVAL(edt6,pda->dlga->rtMargin.right);
2520 GETVAL(edt7,pda->dlga->rtMargin.bottom);
2521 #undef GETVAL
2522
2523 /* If we are in landscape, swap x and y of page size */
2524 if (IsDlgButtonChecked(hDlg, rad2)) {
2525 DWORD tmp;
2526 tmp = pda->dlga->ptPaperSize.x;
2527 pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2528 pda->dlga->ptPaperSize.y = tmp;
2529 }
2530 GlobalUnlock(pda->pdlg.hDevNames);
2531 GlobalUnlock(pda->pdlg.hDevMode);
2532 return TRUE;
2533 }
2534
2535 /**********************************************************************************************
2536 * PRINTDLG_PS_ChangeActivePrinerA
2537 *
2538 * Redefines hDevMode and hDevNames HANDLES and initialises it.
2539 *
2540 * PARAMS
2541 * name [in] Name of a printer for activation
2542 * pda [in/out] ptr to PageSetupDataA structure
2543 *
2544 * RETURN
2545 * TRUE if success
2546 * FALSE if fail
2547 */
2548 static BOOL
2549 PRINTDLG_PS_ChangeActivePrinterA(LPSTR name, PageSetupDataA *pda){
2550 HANDLE hprn;
2551 DWORD needed;
2552 LPPRINTER_INFO_2A lpPrinterInfo;
2553 LPDRIVER_INFO_3A lpDriverInfo;
2554 DEVMODEA *pDevMode, *dm;
2555
2556 if(!OpenPrinterA(name, &hprn, NULL)){
2557 ERR("Can't open printer %s\n", name);
2558 return FALSE;
2559 }
2560 GetPrinterA(hprn, 2, NULL, 0, &needed);
2561 lpPrinterInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2562 GetPrinterA(hprn, 2, (LPBYTE)lpPrinterInfo, needed, &needed);
2563 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2564 lpDriverInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2565 if(!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)lpDriverInfo, needed, &needed)) {
2566 ERR("GetPrinterDriverA failed for %s, fix your config!\n", lpPrinterInfo->pPrinterName);
2567 return FALSE;
2568 }
2569 ClosePrinter(hprn);
2570
2571 needed = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
2572 if(needed == -1) {
2573 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
2574 return FALSE;
2575 }
2576 pDevMode = HeapAlloc(GetProcessHeap(), 0, needed);
2577 DocumentPropertiesA(0, 0, name, pDevMode, NULL, DM_OUT_BUFFER);
2578
2579 pda->pdlg.hDevMode = GlobalReAlloc(pda->pdlg.hDevMode,
2580 pDevMode->dmSize + pDevMode->dmDriverExtra,
2581 GMEM_MOVEABLE);
2582 dm = GlobalLock(pda->pdlg.hDevMode);
2583 memcpy(dm, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra);
2584
2585 PRINTDLG_CreateDevNames(&(pda->pdlg.hDevNames),
2586 lpDriverInfo->pDriverPath,
2587 lpPrinterInfo->pPrinterName,
2588 lpPrinterInfo->pPortName);
2589
2590 GlobalUnlock(pda->pdlg.hDevMode);
2591 HeapFree(GetProcessHeap(), 0, pDevMode);
2592 HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2593 HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2594 return TRUE;
2595 }
2596
2597 /****************************************************************************************
2598 * PRINTDLG_PS_ChangePrinterA
2599 *
2600 * Fills Printers, Paper and Source combo
2601 *
2602 * RETURNS
2603 * TRUE
2604 */
2605 static BOOL
2606 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2607 DEVNAMES *dn;
2608 DEVMODEA *dm;
2609 LPSTR devname,portname;
2610
2611 dn = GlobalLock(pda->pdlg.hDevNames);
2612 dm = GlobalLock(pda->pdlg.hDevMode);
2613 devname = ((char*)dn)+dn->wDeviceOffset;
2614 portname = ((char*)dn)+dn->wOutputOffset;
2615 PRINTDLG_SetUpPrinterListComboA(hDlg, cmb1, devname);
2616 PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2617 PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2618 GlobalUnlock(pda->pdlg.hDevNames);
2619 GlobalUnlock(pda->pdlg.hDevMode);
2620 return TRUE;
2621 }
2622
2623 static BOOL
2624 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2625 DEVNAMES *dn;
2626 DEVMODEW *dm;
2627 LPWSTR devname,portname;
2628
2629 dn = GlobalLock(pda->pdlg.hDevNames);
2630 dm = GlobalLock(pda->pdlg.hDevMode);
2631 devname = ((WCHAR*)dn)+dn->wDeviceOffset;
2632 portname = ((WCHAR*)dn)+dn->wOutputOffset;
2633 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2634 PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2635 GlobalUnlock(pda->pdlg.hDevNames);
2636 GlobalUnlock(pda->pdlg.hDevMode);
2637 return TRUE;
2638 }
2639
2640 /******************************************************************************************
2641 * PRINTDLG_PS_ChangePaperPrev
2642 *
2643 * Changes paper preview size / position
2644 *
2645 * PARAMS:
2646 * pda [i] Pointer for current PageSetupDataA structure
2647 *
2648 * RETURNS:
2649 * always - TRUE
2650 */
2651 static BOOL
2652 PRINTDLG_PS_ChangePaperPrev(PageSetupDataA *pda)
2653 {
2654 LONG width, height, x, y;
2655 RECT rtTmp;
2656
2657 if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y) {
2658 width = pda->rtDrawRect.right - pda->rtDrawRect.left;
2659 height = pda->curdlg.ptPaperSize.y * width / pda->curdlg.ptPaperSize.x;
2660 } else {
2661 height = pda->rtDrawRect.bottom - pda->rtDrawRect.top;
2662 width = pda->curdlg.ptPaperSize.x * height / pda->curdlg.ptPaperSize.y;
2663 }
2664 x = (pda->rtDrawRect.right + pda->rtDrawRect.left - width) / 2;
2665 y = (pda->rtDrawRect.bottom + pda->rtDrawRect.top - height) / 2;
2666 TRACE("rtDrawRect(%ld, %ld, %ld, %ld) x=%ld, y=%ld, w=%ld, h=%ld",
2667 pda->rtDrawRect.left, pda->rtDrawRect.top, pda->rtDrawRect.right, pda->rtDrawRect.bottom,
2668 x, y, width, height);
2669
2670 #define SHADOW 4
2671 MoveWindow(GetDlgItem(pda->hDlg, rct2), x+width, y+SHADOW, SHADOW, height, FALSE);
2672 MoveWindow(GetDlgItem(pda->hDlg, rct3), x+SHADOW, y+height, width, SHADOW, FALSE);
2673 MoveWindow(GetDlgItem(pda->hDlg, rct1), x, y, width, height, FALSE);
2674 memcpy(&rtTmp, &pda->rtDrawRect, sizeof(RECT));
2675 rtTmp.right += SHADOW;
2676 rtTmp.bottom += SHADOW;
2677 #undef SHADOW
2678
2679 InvalidateRect(pda->hDlg, &rtTmp, TRUE);
2680 return TRUE;
2681 }
2682
2683 #define GETVAL(idc,val) \
2684 if(msg == EN_CHANGE){ \
2685 if (GetDlgItemTextA(hDlg,idc,buf,sizeof(buf)) > 0)\
2686 val = _c_str2sizeA(pda->dlga,buf); \
2687 else\
2688 FIXME("could not get dlgitemtexta for %x\n",id); \
2689 }
2690
2691 /********************************************************************************
2692 * PRINTDLG_PS_WMCommandA
2693 * process WM_COMMAND message for PageSetupDlgA
2694 *
2695 * PARAMS
2696 * hDlg [in] Main dialog HANDLE
2697 * wParam [in] WM_COMMAND wParam
2698 * lParam [in] WM_COMMAND lParam
2699 * pda [in/out] ptr to PageSetupDataA
2700 */
2701
2702 static BOOL
2703 PRINTDLG_PS_WMCommandA(
2704 HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2705 ) {
2706 WORD msg = HIWORD(wParam);
2707 WORD id = LOWORD(wParam);
2708 char buf[200];
2709
2710 TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2711 LOWORD(lParam),wParam,lParam);
2712 switch (id) {
2713 case IDOK:
2714 if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2715 return(FALSE);
2716 EndDialog(hDlg, TRUE);
2717 return TRUE ;
2718
2719 case IDCANCEL:
2720 EndDialog(hDlg, FALSE);
2721 return FALSE ;
2722
2723 case psh3: {
2724 pda->pdlg.Flags = 0;
2725 pda->pdlg.hwndOwner = hDlg;
2726 if (PrintDlgA(&(pda->pdlg)))
2727 PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2728 }
2729 return TRUE;
2730 case rad1:
2731 if (pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y){
2732 DWORD tmp = pda->curdlg.ptPaperSize.x;
2733 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2734 pda->curdlg.ptPaperSize.y = tmp;
2735 }
2736 PRINTDLG_PS_ChangePaperPrev(pda);
2737 break;
2738 case rad2:
2739 if (pda->curdlg.ptPaperSize.y > pda->curdlg.ptPaperSize.x){
2740 DWORD tmp = pda->curdlg.ptPaperSize.x;
2741 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2742 pda->curdlg.ptPaperSize.y = tmp;
2743 }
2744 PRINTDLG_PS_ChangePaperPrev(pda);
2745 break;
2746 case cmb1: /* Printer combo */
2747 if(msg == CBN_SELCHANGE){
2748 char crPrinterName[256];
2749 GetDlgItemTextA(hDlg, id, crPrinterName, 255);
2750 PRINTDLG_PS_ChangeActivePrinterA(crPrinterName, pda);
2751 PRINTDLG_PS_ChangePrinterA(hDlg, pda);
2752 }
2753 break;
2754 case cmb2: /* Paper combo */
2755 if(msg == CBN_SELCHANGE){
2756 DWORD paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2757 SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2758 if (paperword != CB_ERR) {
2759 PRINTDLG_PaperSizeA(&(pda->pdlg), paperword,&(pda->curdlg.ptPaperSize));
2760 pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.x);
2761 pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.y);
2762
2763 if (IsDlgButtonChecked(hDlg, rad2)) {
2764 DWORD tmp = pda->curdlg.ptPaperSize.x;
2765 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2766 pda->curdlg.ptPaperSize.y = tmp;
2767 }
2768 PRINTDLG_PS_ChangePaperPrev(pda);
2769 } else
2770 FIXME("could not get dialog text for papersize cmbbox?\n");
2771 }
2772 break;
2773 case cmb3:
2774 if(msg == CBN_SELCHANGE){
2775 DEVMODEA *dm = GlobalLock(pda->pdlg.hDevMode);
2776 dm->u.s.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,CB_GETITEMDATA,
2777 SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
2778 GlobalUnlock(pda->pdlg.hDevMode);
2779 }
2780 break;
2781 case psh2: /* Printer Properties button */
2782 {
2783 HANDLE hPrinter;
2784 char PrinterName[256];
2785 DEVMODEA *dm;
2786 LRESULT count;
2787 int i;
2788
2789 GetDlgItemTextA(hDlg, cmb1, PrinterName, 255);
2790 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
2791 FIXME("Call to OpenPrinter did not succeed!\n");
2792 break;
2793 }
2794 dm = GlobalLock(pda->pdlg.hDevMode);
2795 DocumentPropertiesA(hDlg, hPrinter, PrinterName, dm, dm,
2796 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
2797 ClosePrinter(hPrinter);
2798 /* Changing paper */
2799 PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u.s.dmPaperSize, &(pda->curdlg.ptPaperSize));
2800 pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
2801 pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
2802 if (dm->u.s.dmOrientation == DMORIENT_LANDSCAPE){
2803 DWORD tmp = pda->curdlg.ptPaperSize.x;
2804 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2805 pda->curdlg.ptPaperSize.y = tmp;
2806 CheckRadioButton(hDlg, rad1, rad2, rad2);
2807 }
2808 else
2809 CheckRadioButton(hDlg, rad1, rad2, rad1);
2810 /* Changing paper preview */
2811 PRINTDLG_PS_ChangePaperPrev(pda);
2812 /* Selecting paper in combo */
2813 count = SendDlgItemMessageA(hDlg, cmb2, CB_GETCOUNT, 0, 0);
2814 if(count != CB_ERR){
2815 for(i=0; i<count; ++i){
2816 if(SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0) == dm->u.s.dmPaperSize) {
2817 SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
2818 break;
2819 }
2820 }
2821 }
2822
2823 GlobalUnlock(pda->pdlg.hDevMode);
2824 break;
2825 }
2826 case edt4:
2827 GETVAL(id, pda->curdlg.rtMargin.left);
2828 break;
2829 case edt5:
2830 GETVAL(id, pda->curdlg.rtMargin.right);
2831 break;
2832 case edt6:
2833 GETVAL(id, pda->curdlg.rtMargin.top);
2834 break;
2835 case edt7:
2836 GETVAL(id, pda->curdlg.rtMargin.bottom);
2837 break;
2838 }
2839 InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
2840 return FALSE;
2841 }
2842 #undef GETVAL
2843
2844 static BOOL
2845 PRINTDLG_PS_WMCommandW(
2846 HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2847 ) {
2848 TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2849 LOWORD(lParam),wParam,lParam);
2850 switch (LOWORD(wParam)) {
2851 case IDOK:
2852 if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2853 return(FALSE);
2854 EndDialog(hDlg, TRUE);
2855 return TRUE ;
2856
2857 case IDCANCEL:
2858 EndDialog(hDlg, FALSE);
2859 return FALSE ;
2860
2861 case psh3: {
2862 pda->pdlg.Flags = 0;
2863 pda->pdlg.hwndOwner = hDlg;
2864 if (PrintDlgW(&(pda->pdlg)))
2865 PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2866 return TRUE;
2867 }
2868 }
2869 return FALSE;
2870 }
2871
2872
2873 /***********************************************************************
2874 * DefaultPagePaintHook
2875 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
2876 * whenever the sample page is redrawn.
2877 */
2878
2879 static UINT_PTR
2880 PRINTDLG_DefaultPagePaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda)
2881 {
2882 LPRECT lprc = (LPRECT) lParam;
2883 HDC hdc = (HDC) wParam;
2884 HPEN hpen, holdpen;
2885 LOGFONTW lf;
2886 HFONT hfont, holdfont;
2887 INT oldbkmode;
2888 TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
2889 /* Call user paint hook if enable */
2890 if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK)
2891 if (pda->dlga->lpfnPagePaintHook(hwndDlg, uMsg, wParam, lParam))
2892 return TRUE;
2893
2894 switch (uMsg) {
2895 /* LPPAGESETUPDLG in lParam */
2896 case WM_PSD_PAGESETUPDLG:
2897 /* Inform about the sample page rectangle */
2898 case WM_PSD_FULLPAGERECT:
2899 /* Inform about the margin rectangle */
2900 case WM_PSD_MINMARGINRECT:
2901 return FALSE;
2902
2903 /* Draw dashed rectangle showing margins */
2904 case WM_PSD_MARGINRECT:
2905 hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
2906 holdpen = SelectObject(hdc, hpen);
2907 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
2908 DeleteObject(SelectObject(hdc, holdpen));
2909 return TRUE;
2910 /* Draw the fake document */
2911 case WM_PSD_GREEKTEXTRECT:
2912 /* select a nice scalable font, because we want the text really small */
2913 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2914 lf.lfHeight = 6; /* value chosen based on visual effect */
2915 hfont = CreateFontIndirectW(&lf);
2916 holdfont = SelectObject(hdc, hfont);
2917
2918 /* if text not loaded, then do so now */
2919 if (wszFakeDocumentText[0] == '\0')
2920 LoadStringW(COMDLG32_hInstance,
2921 IDS_FAKEDOCTEXT,
2922 wszFakeDocumentText,
2923 sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
2924
2925 oldbkmode = SetBkMode(hdc, TRANSPARENT);
2926 DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
2927 SetBkMode(hdc, oldbkmode);
2928
2929 DeleteObject(SelectObject(hdc, holdfont));
2930 return TRUE;
2931
2932 /* Envelope stamp */
2933 case WM_PSD_ENVSTAMPRECT:
2934 /* Return address */
2935 case WM_PSD_YAFULLPAGERECT:
2936 FIXME("envelope/stamp is not implemented\n");
2937 return FALSE;
2938 default:
2939 FIXME("Unknown message %x\n",uMsg);
2940 return FALSE;
2941 }
2942 return TRUE;
2943 }
2944
2945 /***********************************************************************
2946 * PagePaintProc
2947 * The main paint procedure for the PageSetupDlg function.
2948 * The Page Setup dialog box includes an image of a sample page that shows how
2949 * the user's selections affect the appearance of the printed output.
2950 * The image consists of a rectangle that represents the selected paper
2951 * or envelope type, with a dotted-line rectangle representing
2952 * the current margins, and partial (Greek text) characters
2953 * to show how text looks on the printed page.
2954 *
2955 * The following messages in the order sends to user hook procedure:
2956 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
2957 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
2958 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
2959 * WM_PSD_MARGINRECT Draw the margin rectangle
2960 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
2961 * If any of first three messages returns TRUE, painting done.
2962 *
2963 * PARAMS:
2964 * hWnd [in] Handle to the Page Setup dialog box
2965 * uMsg [in] Received message
2966 *
2967 * TODO:
2968 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
2969 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
2970 *
2971 * RETURNS:
2972 * FALSE if all done correctly
2973 *
2974 */
2975
2976
2977 static LRESULT CALLBACK
2978 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2979 {
2980 PAINTSTRUCT ps;
2981 RECT rcClient, rcMargin;
2982 HPEN hpen, holdpen;
2983 HDC hdc;
2984 HBRUSH hbrush, holdbrush;
2985 PageSetupDataA *pda;
2986 int papersize=0, orientation=0; /* FIXME: set this values for user paint hook */
2987 double scalx, scaly;
2988 #define CALLPAINTHOOK(msg,lprc) PRINTDLG_DefaultPagePaintHook( hWnd, msg, (WPARAM)hdc, (LPARAM)lprc, pda)
2989
2990 if (uMsg != WM_PAINT)
2991 return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
2992
2993 /* Processing WM_PAINT message */
2994 pda = (PageSetupDataA*)GetPropA(hWnd, "__WINE_PAGESETUPDLGDATA");
2995 if (!pda) {
2996 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2997 return FALSE;
2998 }
2999 if (PRINTDLG_DefaultPagePaintHook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), (LPARAM)pda->dlga, pda))
3000 return FALSE;
3001
3002 hdc = BeginPaint(hWnd, &ps);
3003 GetClientRect(hWnd, &rcClient);
3004
3005 scalx = rcClient.right / (double)pda->curdlg.ptPaperSize.x;
3006 scaly = rcClient.bottom / (double)pda->curdlg.ptPaperSize.y;
3007 rcMargin = rcClient;
3008
3009 rcMargin.left += (LONG)pda->curdlg.rtMargin.left * scalx;
3010 rcMargin.top += (LONG)pda->curdlg.rtMargin.top * scalx;
3011 rcMargin.right -= (LONG)pda->curdlg.rtMargin.right * scaly;
3012 rcMargin.bottom -= (LONG)pda->curdlg.rtMargin.bottom * scaly;
3013
3014 /* if the space is too small then we make sure to not draw anything */
3015 rcMargin.left = min(rcMargin.left, rcMargin.right);
3016 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3017
3018 if (!CALLPAINTHOOK(WM_PSD_FULLPAGERECT, &rcClient) &&
3019 !CALLPAINTHOOK(WM_PSD_MINMARGINRECT, &rcMargin) )
3020 {
3021 /* fill background */
3022 hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3023 FillRect(hdc, &rcClient, hbrush);
3024 holdbrush = SelectObject(hdc, hbrush);
3025
3026 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3027 holdpen = SelectObject(hdc, hpen);
3028
3029 /* paint left edge */
3030 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3031 LineTo(hdc, rcClient.left, rcClient.bottom-1);
3032
3033 /* paint top edge */
3034 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3035 LineTo(hdc, rcClient.right, rcClient.top);
3036
3037 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3038 DeleteObject(SelectObject(hdc, hpen));
3039
3040 /* paint right edge */
3041 MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3042 LineTo(hdc, rcClient.right-1, rcClient.bottom);
3043
3044 /* paint bottom edge */
3045 MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3046 LineTo(hdc, rcClient.right, rcClient.bottom-1);
3047
3048 DeleteObject(SelectObject(hdc, holdpen));
3049 DeleteObject(SelectObject(hdc, holdbrush));
3050
3051 CALLPAINTHOOK(WM_PSD_MARGINRECT, &rcMargin);
3052
3053 /* give text a bit of a space from the frame */
3054 rcMargin.left += 2;
3055 rcMargin.top += 2;
3056 rcMargin.right -= 2;
3057 rcMargin.bottom -= 2;
3058
3059 /* if the space is too small then we make sure to not draw anything */
3060 rcMargin.left = min(rcMargin.left, rcMargin.right);
3061 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3062
3063 CALLPAINTHOOK(WM_PSD_GREEKTEXTRECT, &rcMargin);
3064 }
3065
3066 EndPaint(hWnd, &ps);
3067 return FALSE;
3068 #undef CALLPAINTHOOK
3069 }
3070
3071 /***********************************************************************
3072 * PRINTDLG_PageDlgProcA
3073 * Message handler for PageSetupDlgA
3074 */
3075 static INT_PTR CALLBACK
3076 PRINTDLG_PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3077 {
3078 DEVMODEA *dm;
3079 PageSetupDataA *pda;
3080 INT_PTR res = FALSE;
3081 HWND hDrawWnd;
3082
3083 if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3084 pda = (PageSetupDataA*)lParam;
3085 pda->hDlg = hDlg; /* saving handle to main window to PageSetupDataA structure */
3086 memcpy(&pda->curdlg, pda->dlga, sizeof(pda->curdlg));
3087
3088 hDrawWnd = GetDlgItem(hDlg, rct1);
3089 TRACE("set property to %p", pda);
3090 SetPropA(hDlg, "__WINE_PAGESETUPDLGDATA", pda);
3091 SetPropA(hDrawWnd, "__WINE_PAGESETUPDLGDATA", pda);
3092 GetWindowRect(hDrawWnd, &pda->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3093 ScreenToClient(hDlg, (LPPOINT)&pda->rtDrawRect);
3094 ScreenToClient(hDlg, (LPPOINT)(&pda->rtDrawRect.right));
3095 lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3096 hDrawWnd,
3097 GWLP_WNDPROC,
3098 (ULONG_PTR)PRINTDLG_PagePaintProc);
3099
3100 /* FIXME: Paint hook. Must it be at begin of initializtion or at end? */
3101 res = TRUE;
3102 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3103 if (!pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga))
3104 FIXME("Setup page hook failed?\n");
3105 }
3106
3107 /* if printer button disabled */
3108 if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3109 EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3110 /* if margin edit boxes disabled */
3111 if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3112 EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3113 EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3114 EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3115 EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3116 }
3117 /* Set orientation radiobutton properly */
3118 dm = GlobalLock(pda->dlga->hDevMode);
3119 if (dm->u.s.dmOrientation == DMORIENT_LANDSCAPE)
3120 CheckRadioButton(hDlg, rad1, rad2, rad2);
3121 else /* this is default if papersize is not set */
3122 CheckRadioButton(hDlg, rad1, rad2, rad1);
3123 GlobalUnlock(pda->dlga->hDevMode);
3124
3125 /* if orientation disabled */
3126 if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3127 EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3128 EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3129 }
3130 /* We fill them out enabled or not */
3131 if (pda->dlga->Flags & PSD_MARGINS) {
3132 char str[100];
3133 _c_size2strA(pda,pda->dlga->rtMargin.left,str);
3134 SetDlgItemTextA(hDlg,edt4,str);
3135 _c_size2strA(pda,pda->dlga->rtMargin.top,str);
3136 SetDlgItemTextA(hDlg,edt5,str);
3137 _c_size2strA(pda,pda->dlga->rtMargin.right,str);
3138 SetDlgItemTextA(hDlg,edt6,str);
3139 _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
3140 SetDlgItemTextA(hDlg,edt7,str);
3141 } else {
3142 /* default is 1 inch */
3143 DWORD size = _c_inch2size(pda->dlga,1000);
3144 char str[20];
3145 _c_size2strA(pda,size,str);
3146 SetDlgItemTextA(hDlg,edt4,str);
3147 SetDlgItemTextA(hDlg,edt5,str);
3148 SetDlgItemTextA(hDlg,edt6,str);
3149 SetDlgItemTextA(hDlg,edt7,str);
3150 pda->curdlg.rtMargin.left = size;
3151 pda->curdlg.rtMargin.top = size;
3152 pda->curdlg.rtMargin.right = size;
3153 pda->curdlg.rtMargin.bottom = size;
3154 }
3155 /* if paper disabled */
3156 if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3157 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3158 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3159 }
3160 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3161 PRINTDLG_PS_ChangePrinterA(hDlg, pda);
3162 dm = GlobalLock(pda->pdlg.hDevMode);
3163 if(dm){
3164 dm->u.s.dmDefaultSource = 15; /*FIXME: Automatic select. Does it always 15 at start? */
3165 PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u.s.dmPaperSize, &pda->curdlg.ptPaperSize);
3166 GlobalUnlock(pda->pdlg.hDevMode);
3167 pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
3168 pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
3169 if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) { /* Landscape orientation */
3170 DWORD tmp = pda->curdlg.ptPaperSize.y;
3171 pda->curdlg.ptPaperSize.y = pda->curdlg.ptPaperSize.x;
3172 pda->curdlg.ptPaperSize.x = tmp;
3173 }
3174 } else
3175 WARN("GlobalLock(pda->pdlg.hDevMode) fail? hDevMode=%p", pda->pdlg.hDevMode);
3176 /* Drawing paper prev */
3177 PRINTDLG_PS_ChangePaperPrev(pda);
3178 return TRUE;
3179 } else {
3180 pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
3181 if (!pda) {
3182 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3183 return FALSE;
3184 }
3185 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3186 res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3187 if (res) return res;
3188 }
3189 }
3190 switch (uMsg) {
3191 case WM_COMMAND:
3192 return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
3193 }
3194 return FALSE;
3195 }
3196
3197 static INT_PTR CALLBACK
3198 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3199 {
3200 static const WCHAR __WINE_PAGESETUPDLGDATA[] =
3201 { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
3202 'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
3203 PageSetupDataW *pda;
3204 BOOL res = FALSE;
3205
3206 if (uMsg==WM_INITDIALOG) {
3207 res = TRUE;
3208 pda = (PageSetupDataW*)lParam;
3209 SetPropW(hDlg, __WINE_PAGESETUPDLGDATA, pda);
3210 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3211 res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
3212 if (!res) {
3213 FIXME("Setup page hook failed?\n");
3214 res = TRUE;
3215 }
3216 }
3217
3218 if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
3219 FIXME("PagePaintHook not yet implemented!\n");
3220 }
3221 if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3222 EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3223 if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3224 EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3225 EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3226 EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3227 EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3228 }
3229 /* width larger as height -> landscape */
3230 if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
3231 CheckRadioButton(hDlg, rad1, rad2, rad2);
3232 else /* this is default if papersize is not set */
3233 CheckRadioButton(hDlg, rad1, rad2, rad1);
3234 if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3235 EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3236 EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3237 }
3238 /* We fill them out enabled or not */
3239 if (pda->dlga->Flags & PSD_MARGINS) {
3240 WCHAR str[100];
3241 _c_size2strW(pda,pda->dlga->rtMargin.left,str);
3242 SetDlgItemTextW(hDlg,edt4,str);
3243 _c_size2strW(pda,pda->dlga->rtMargin.top,str);
3244 SetDlgItemTextW(hDlg,edt5,str);
3245 _c_size2strW(pda,pda->dlga->rtMargin.right,str);
3246 SetDlgItemTextW(hDlg,edt6,str);
3247 _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
3248 SetDlgItemTextW(hDlg,edt7,str);
3249 } else {
3250 /* default is 1 inch */
3251 DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
3252 WCHAR str[20];
3253 _c_size2strW(pda,size,str);
3254 SetDlgItemTextW(hDlg,edt4,str);
3255 SetDlgItemTextW(hDlg,edt5,str);
3256 SetDlgItemTextW(hDlg,edt6,str);
3257 SetDlgItemTextW(hDlg,edt7,str);
3258 }
3259 PRINTDLG_PS_ChangePrinterW(hDlg,pda);
3260 if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3261 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3262 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3263 }
3264
3265 return TRUE;
3266 } else {
3267 pda = (PageSetupDataW*)GetPropW(hDlg, __WINE_PAGESETUPDLGDATA);
3268 if (!pda) {
3269 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3270 return FALSE;
3271 }
3272 if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3273 res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3274 if (res) return res;
3275 }
3276 }
3277 switch (uMsg) {
3278 case WM_COMMAND:
3279 return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
3280 }
3281 return FALSE;
3282 }
3283
3284 /***********************************************************************
3285 * PageSetupDlgA (COMDLG32.@)
3286 *
3287 * Displays the the PAGE SETUP dialog box, which enables the user to specify
3288 * specific properties of a printed page such as
3289 * size, source, orientation and the width of the page margins.
3290 *
3291 * PARAMS
3292 * setupdlg [IO] PAGESETUPDLGA struct
3293 *
3294 * RETURNS
3295 * TRUE if the user pressed the OK button
3296 * FALSE if the user cancelled the window or an error occurred
3297 *
3298 * NOTES
3299 * The values of hDevMode and hDevNames are filled on output and can be
3300 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3301 *
3302 */
3303
3304 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
3305 HGLOBAL hDlgTmpl;
3306 LPVOID ptr;
3307 BOOL bRet;
3308 PageSetupDataA *pda;
3309 PRINTDLGA pdlg;
3310
3311 /* TRACE */
3312 if(TRACE_ON(commdlg)) {
3313 char flagstr[1000] = "";
3314 struct pd_flags *pflag = psd_flags;
3315 for( ; pflag->name; pflag++) {
3316 if(setupdlg->Flags & pflag->flag) {
3317 strcat(flagstr, pflag->name);
3318 strcat(flagstr, "|");
3319 }
3320 }
3321 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3322 "hinst %p, flags %08lx (%s)\n",
3323 setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3324 setupdlg->hDevNames,
3325 setupdlg->hInstance, setupdlg->Flags, flagstr);
3326 }
3327 /* Checking setupdlg structure */
3328 if (setupdlg == NULL) {
3329 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3330 return FALSE;
3331 }
3332 if(setupdlg->lStructSize != sizeof(PAGESETUPDLGA)) {
3333 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3334 return FALSE;
3335 }
3336 if ((setupdlg->Flags & PSD_ENABLEPAGEPAINTHOOK) &&
3337 (setupdlg->lpfnPagePaintHook == NULL)) {
3338 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3339 return FALSE;
3340 }
3341
3342 /* Initialize default printer struct. If no printer device info is specified
3343 retrieve the default printer data. */
3344 memset(&pdlg,0,sizeof(pdlg));
3345 pdlg.lStructSize = sizeof(pdlg);
3346 if (setupdlg->hDevMode && setupdlg->hDevNames) {
3347 pdlg.hDevMode = setupdlg->hDevMode;
3348 pdlg.hDevNames = setupdlg->hDevNames;
3349 } else {
3350 pdlg.Flags = PD_RETURNDEFAULT;
3351 bRet = PrintDlgA(&pdlg);
3352 if (!bRet){
3353 if (!(setupdlg->Flags & PSD_NOWARNING)) {
3354 char errstr[256];
3355 LoadStringA(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3356 MessageBoxA(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3357 }
3358 return FALSE;
3359 }
3360 }
3361
3362 /* short cut exit, just return default values */
3363 if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3364 DEVMODEA *dm;
3365
3366 dm = GlobalLock(pdlg.hDevMode);
3367 PRINTDLG_PaperSizeA(&pdlg, dm->u.s.dmPaperSize, &setupdlg->ptPaperSize);
3368 GlobalUnlock(pdlg.hDevMode);
3369 setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
3370 setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
3371 return TRUE;
3372 }
3373
3374 /* get dialog template */
3375 hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
3376 if (!hDlgTmpl) {
3377 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3378 return FALSE;
3379 }
3380 ptr = LockResource( hDlgTmpl );
3381 if (!ptr) {
3382 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3383 return FALSE;
3384 }
3385
3386 pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
3387 pda->dlga = setupdlg;
3388 memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
3389
3390 bRet = (0<DialogBoxIndirectParamA(
3391 setupdlg->hInstance,
3392 ptr,
3393 setupdlg->hwndOwner,
3394 PRINTDLG_PageDlgProcA,
3395 (LPARAM)pda)
3396 );
3397
3398 HeapFree(GetProcessHeap(),0,pda);
3399 return bRet;
3400 }
3401 /***********************************************************************
3402 * PageSetupDlgW (COMDLG32.@)
3403 *
3404 * See PageSetupDlgA.
3405 */
3406 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
3407 HGLOBAL hDlgTmpl;
3408 LPVOID ptr;
3409 BOOL bRet;
3410 PageSetupDataW *pdw;
3411 PRINTDLGW pdlg;
3412
3413 FIXME("Unicode implementation is not done yet\n");
3414 if(TRACE_ON(commdlg)) {
3415 char flagstr[1000] = "";
3416 struct pd_flags *pflag = psd_flags;
3417 for( ; pflag->name; pflag++) {
3418 if(setupdlg->Flags & pflag->flag) {
3419 strcat(flagstr, pflag->name);
3420 strcat(flagstr, "|");
3421 }
3422 }
3423 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3424 "hinst %p, flags %08lx (%s)\n",
3425 setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3426 setupdlg->hDevNames,
3427 setupdlg->hInstance, setupdlg->Flags, flagstr);
3428 }
3429
3430 /* Initialize default printer struct. If no printer device info is specified
3431 retrieve the default printer data. */
3432 memset(&pdlg,0,sizeof(pdlg));
3433 pdlg.lStructSize = sizeof(pdlg);
3434 if (setupdlg->hDevMode && setupdlg->hDevNames) {
3435 pdlg.hDevMode = setupdlg->hDevMode;
3436 pdlg.hDevNames = setupdlg->hDevNames;
3437 } else {
3438 pdlg.Flags = PD_RETURNDEFAULT;
3439 bRet = PrintDlgW(&pdlg);
3440 if (!bRet){
3441 if (!(setupdlg->Flags & PSD_NOWARNING)) {
3442 WCHAR errstr[256];
3443 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3444 MessageBoxW(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3445 }
3446 return FALSE;
3447 }
3448 }
3449
3450 /* short cut exit, just return default values */
3451 if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3452 static const WCHAR a4[] = {'A','4',0};
3453 setupdlg->hDevMode = pdlg.hDevMode;
3454 setupdlg->hDevNames = pdlg.hDevNames;
3455 /* FIXME: Just return "A4" for now. */
3456 PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
3457 setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
3458 setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
3459 return TRUE;
3460 }
3461 hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
3462 if (!hDlgTmpl) {
3463 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3464 return FALSE;
3465 }
3466 ptr = LockResource( hDlgTmpl );
3467 if (!ptr) {
3468 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3469 return FALSE;
3470 }
3471 pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3472 pdw->dlga = setupdlg;
3473 memcpy(&pdw->pdlg,&pdlg,sizeof(pdlg));
3474
3475 bRet = (0<DialogBoxIndirectParamW(
3476 setupdlg->hInstance,
3477 ptr,
3478 setupdlg->hwndOwner,
3479 PageDlgProcW,
3480 (LPARAM)pdw)
3481 );
3482 return bRet;
3483 }
3484
3485 /***********************************************************************
3486 * PrintDlgExA (COMDLG32.@)
3487 *
3488 * See PrintDlgExW.
3489 *
3490 * FIXME
3491 * Stub
3492 */
3493 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lpPrintDlgExA)
3494 {
3495 FIXME("stub\n");
3496 return E_NOTIMPL;
3497 }
3498
3499 /***********************************************************************
3500 * PrintDlgExW (COMDLG32.@)
3501 *
3502 * Display the the PRINT dialog box, which enables the user to specify
3503 * specific properties of the print job. The property sheet can also have
3504 * additional application-specific and driver-specific property pages.
3505 *
3506 * PARAMS
3507 * lppd [IO] ptr to PRINTDLGEX struct
3508 *
3509 * RETURNS
3510 * Success: S_OK
3511 * Failure: One of the following COM error codes:
3512 * E_OUTOFMEMORY Insufficient memory.
3513 * E_INVALIDARG One or more arguments are invalid.
3514 * E_POINTER Invalid pointer.
3515 * E_HANDLE Invalid handle.
3516 * E_FAIL Unspecified error.
3517 *
3518 * FIXME
3519 * Stub
3520 */
3521 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lpPrintDlgExW)
3522 {
3523 FIXME("stub\n");
3524 return E_NOTIMPL;
3525 }