ReactOS 0.4.15-dev-7704-gc07eb9f
printdlg.c
Go to the documentation of this file.
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 * Copyright 2010 Vitaly Perov
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24#include <ctype.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29#include <assert.h>
30
31#define COBJMACROS
32#define NONAMELESSUNION
33#define NONAMELESSSTRUCT
34#include "windef.h"
35#include "winbase.h"
36#include "wingdi.h"
37#include "winuser.h"
38#include "winspool.h"
39#include "winerror.h"
40#include "objbase.h"
41#include "commdlg.h"
42
43#include "wine/debug.h"
44
45#include "dlgs.h"
46#include "cderr.h"
47#include "cdlg.h"
48
50
51/* Yes these constants are the same, but we're just copying win98 */
52#define UPDOWN_ID 0x270f
53#define MAX_COPIES 9999
54
55/* This PRINTDLGA internal structure stores
56 * pointers to several throughout useful structures.
57 */
58
59typedef struct
60{
66 HICON hCollateIcon; /* PrintDlg only */
67 HICON hNoCollateIcon; /* PrintDlg only */
68 HICON hPortraitIcon; /* PrintSetupDlg only */
69 HICON hLandscapeIcon; /* PrintSetupDlg only */
72
73typedef struct
74{
80 HICON hCollateIcon; /* PrintDlg only */
81 HICON hNoCollateIcon; /* PrintDlg only */
82 HICON hPortraitIcon; /* PrintSetupDlg only */
83 HICON hLandscapeIcon; /* PrintSetupDlg only */
86
87/* Debugging info */
89{
92};
93
94static const struct pd_flags psd_flags[] = {
95 {PSD_MINMARGINS,"PSD_MINMARGINS"},
96 {PSD_MARGINS,"PSD_MARGINS"},
97 {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
98 {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
99 {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
100 {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
101 {PSD_NOWARNING,"PSD_NOWARNING"},
102 {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
103 {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
104 {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
105 {PSD_SHOWHELP,"PSD_SHOWHELP"},
106 {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
107 {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
108 {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
109 {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
110 {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
111 {-1, NULL}
112};
113
114static const struct pd_flags pd_flags[] = {
115 {PD_SELECTION, "PD_SELECTION "},
116 {PD_PAGENUMS, "PD_PAGENUMS "},
117 {PD_NOSELECTION, "PD_NOSELECTION "},
118 {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
119 {PD_COLLATE, "PD_COLLATE "},
120 {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
121 {PD_PRINTSETUP, "PD_PRINTSETUP "},
122 {PD_NOWARNING, "PD_NOWARNING "},
123 {PD_RETURNDC, "PD_RETURNDC "},
124 {PD_RETURNIC, "PD_RETURNIC "},
125 {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
126 {PD_SHOWHELP, "PD_SHOWHELP "},
127 {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
128 {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
129 {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
130 {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
131 {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
132 {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
133 {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
134 {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
135 {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
136 {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
137 {-1, NULL}
138};
139/* address of wndproc for subclassed Static control */
142/* the text of the fake document to render for the Page Setup dialog */
144static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
145static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
146static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
147static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
148static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
149static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
150 'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
151
152
154{
155 LPWSTR ret;
156 DWORD len;
157
158 if(!p) return NULL;
159 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
161 memcpy(ret, p, len);
162 return ret;
163}
164
165/***********************************************************************
166 * get_driver_info [internal]
167 *
168 * get DRIVER_INFO_3W for the current printer handle,
169 * alloc the buffer, when needed
170 */
172{
173 DRIVER_INFO_3W *di3 = NULL;
174 DWORD needed = 0;
175 BOOL res;
176
177 res = GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
179 di3 = HeapAlloc(GetProcessHeap(), 0, needed);
180 res = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
181 }
182
183 if (res)
184 return di3;
185
186 TRACE("GetPrinterDriverW failed with %u\n", GetLastError());
187 HeapFree(GetProcessHeap(), 0, di3);
188 return NULL;
189}
190
192{
193 DRIVER_INFO_3A *di3 = NULL;
194 DWORD needed = 0;
195 BOOL res;
196
197 res = GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
199 di3 = HeapAlloc(GetProcessHeap(), 0, needed);
200 res = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
201 }
202
203 if (res)
204 return di3;
205
206 TRACE("GetPrinterDriverA failed with %u\n", GetLastError());
207 HeapFree(GetProcessHeap(), 0, di3);
208 return NULL;
209}
210
211
212/***********************************************************************
213 * get_printer_info [internal]
214 *
215 * get PRINTER_INFO_2W for the current printer handle,
216 * alloc the buffer, when needed
217 */
219{
220 PRINTER_INFO_2W *pi2 = NULL;
221 DWORD needed = 0;
222 BOOL res;
223
224 res = GetPrinterW(hprn, 2, NULL, 0, &needed);
226 pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
227 res = GetPrinterW(hprn, 2, (LPBYTE)pi2, needed, &needed);
228 }
229
230 if (res)
231 return pi2;
232
233 TRACE("GetPrinterW failed with %u\n", GetLastError());
234 HeapFree(GetProcessHeap(), 0, pi2);
235 return NULL;
236}
237
239{
240 PRINTER_INFO_2A *pi2 = NULL;
241 DWORD needed = 0;
242 BOOL res;
243
244 res = GetPrinterA(hprn, 2, NULL, 0, &needed);
246 pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
247 res = GetPrinterA(hprn, 2, (LPBYTE)pi2, needed, &needed);
248 }
249
250 if (res)
251 return pi2;
252
253 TRACE("GetPrinterA failed with %u\n", GetLastError());
254 HeapFree(GetProcessHeap(), 0, pi2);
255 return NULL;
256}
257
258
259/***********************************************************************
260 * update_devmode_handle [internal]
261 *
262 * update a devmode handle for the given DEVMODE, alloc the buffer, when needed
263 */
265{
266 SIZE_T size = GlobalSize(hdm);
267 LPVOID ptr;
268
269 /* Increase / alloc the global memory block, when needed */
270 if ((dm->dmSize + dm->dmDriverExtra) > size) {
271 if (hdm)
272 hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
273 else
275 }
276
277 if (hdm) {
278 ptr = GlobalLock(hdm);
279 if (ptr) {
280 memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
281 GlobalUnlock(hdm);
282 }
283 else
284 {
285 GlobalFree(hdm);
286 hdm = NULL;
287 }
288 }
289 return hdm;
290}
291
293{
294 SIZE_T size = GlobalSize(hdm);
295 LPVOID ptr;
296
297 /* Increase / alloc the global memory block, when needed */
298 if ((dm->dmSize + dm->dmDriverExtra) > size) {
299 if (hdm)
300 hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
301 else
303 }
304
305 if (hdm) {
306 ptr = GlobalLock(hdm);
307 if (ptr) {
308 memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
309 GlobalUnlock(hdm);
310 }
311 else
312 {
313 GlobalFree(hdm);
314 hdm = NULL;
315 }
316 }
317 return hdm;
318}
319
320/***********************************************************
321 * convert_to_devmodeA
322 *
323 * Creates an ansi copy of supplied devmode
324 */
326{
327 DEVMODEA *dmA;
328 DWORD size;
329
330 if (!dmW) return NULL;
331 size = dmW->dmSize - CCHDEVICENAME -
332 ((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
333
334 dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra);
335 if (!dmA) return NULL;
336
339
340 if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
341 {
343 dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
344 }
345 else
346 {
348 FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
351
352 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
353 }
354
355 dmA->dmSize = size;
356 memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
357 return dmA;
358}
359
360/***********************************************************************
361 * PRINTDLG_OpenDefaultPrinter
362 *
363 * Returns a winspool printer handle to the default printer in *hprn
364 * Caller must call ClosePrinter on the handle
365 *
366 * Returns TRUE on success else FALSE
367 */
369{
370 WCHAR buf[260];
372 BOOL res;
374 return FALSE;
375 res = OpenPrinterW(buf, hprn, NULL);
376 if (!res)
377 WARN("Could not open printer %s\n", debugstr_w(buf));
378 return res;
379}
380
381/***********************************************************************
382 * PRINTDLG_SetUpPrinterListCombo
383 *
384 * Initializes printer list combox.
385 * hDlg: HWND of dialog
386 * id: Control id of combo
387 * name: Name of printer to select
388 *
389 * Initializes combo with list of available printers. Selects printer 'name'
390 * If name is NULL or does not exist select the default printer.
391 *
392 * Returns number of printers added to list.
393 */
395{
396 DWORD needed, num;
397 INT i;
399 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
400 pi = HeapAlloc(GetProcessHeap(), 0, needed);
401 EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
402 &num);
403
404 SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
405
406 for(i = 0; i < num; i++) {
408 (LPARAM)pi[i].pPrinterName );
409 }
411 if(!name ||
413 (LPARAM)name)) == CB_ERR) {
414
415 char buf[260];
417 if (name != NULL)
418 WARN("Can't find %s in printer list so trying to find default\n",
421 return num;
423 if(i == CB_ERR)
424 FIXME("Can't find default printer in printer list\n");
425 }
426 SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
427 return num;
428}
429
431{
432 DWORD needed, num;
433 INT i;
435 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
436 pi = HeapAlloc(GetProcessHeap(), 0, needed);
437 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
438 &num);
439
440 for(i = 0; i < num; i++) {
442 (LPARAM)pi[i].pPrinterName );
443 }
445 if(!name ||
447 (LPARAM)name)) == CB_ERR) {
448 WCHAR buf[260];
450 if (name != NULL)
451 WARN("Can't find %s in printer list so trying to find default\n",
454 return num;
456 if(i == CB_ERR)
457 TRACE("Can't find default printer in printer list\n");
458 }
459 SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
460 return num;
461}
462
463#ifdef __REACTOS__
464static const CHAR cDriverName[] = "winspool";
465static const WCHAR wDriverName[] = L"winspool";
466#endif
467
468/***********************************************************************
469 * PRINTDLG_CreateDevNames [internal]
470 *
471 *
472 * creates a DevNames structure.
473 *
474 * (NB. when we handle unicode the offsets will be in wchars).
475 */
476static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
477 const char* DeviceName, const char* OutputPort)
478{
479 long size;
480 char* pDevNamesSpace;
481 char* pTempPtr;
482 LPDEVNAMES lpDevNames;
483 char buf[260];
485 const char *p;
486
487 p = strrchr( DeviceDriverName, '\\' );
488 if (p) DeviceDriverName = p + 1;
489#ifndef __REACTOS__
490 size = strlen(DeviceDriverName) + 1
491#else
492 size = strlen(cDriverName) + 1
493#endif
494 + strlen(DeviceName) + 1
495 + strlen(OutputPort) + 1
496 + sizeof(DEVNAMES);
497
498 if(*hmem)
499 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
500 else
502 if (*hmem == 0)
503 return FALSE;
504
505 pDevNamesSpace = GlobalLock(*hmem);
506 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
507
508 pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
509#ifndef __REACTOS__
510 strcpy(pTempPtr, DeviceDriverName);
511#else
512 strcpy(pTempPtr, cDriverName);
513#endif
514 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
515
516 pTempPtr += strlen(DeviceDriverName) + 1;
517 strcpy(pTempPtr, DeviceName);
518 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
519
520 pTempPtr += strlen(DeviceName) + 1;
521 strcpy(pTempPtr, OutputPort);
522 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
523
525 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
526 GlobalUnlock(*hmem);
527 return TRUE;
528}
529
530static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
531 LPCWSTR DeviceName, LPCWSTR OutputPort)
532{
533 long size;
534 LPWSTR pDevNamesSpace;
535 LPWSTR pTempPtr;
536 LPDEVNAMES lpDevNames;
537 WCHAR bufW[260];
538 DWORD dwBufLen = ARRAY_SIZE(bufW);
539 const WCHAR *p;
540
541 p = wcsrchr( DeviceDriverName, '\\' );
542 if (p) DeviceDriverName = p + 1;
543#ifndef __REACTOS__
544 size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
545#else
546 size = sizeof(WCHAR)*lstrlenW(wDriverName) + 2
547#endif
548 + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
549 + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
550 + sizeof(DEVNAMES);
551
552 if(*hmem)
553 *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
554 else
556 if (*hmem == 0)
557 return FALSE;
558
559 pDevNamesSpace = GlobalLock(*hmem);
560 lpDevNames = (LPDEVNAMES) pDevNamesSpace;
561
562 pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
563#ifndef __REACTOS__
564 lstrcpyW(pTempPtr, DeviceDriverName);
565#else
566 lstrcpyW(pTempPtr, wDriverName);
567#endif
568 lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
569
570 pTempPtr += lstrlenW(DeviceDriverName) + 1;
571 lstrcpyW(pTempPtr, DeviceName);
572 lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
573
574 pTempPtr += lstrlenW(DeviceName) + 1;
575 lstrcpyW(pTempPtr, OutputPort);
576 lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
577
579 lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
580 GlobalUnlock(*hmem);
581 return TRUE;
582}
583
584/***********************************************************************
585 * PRINTDLG_UpdatePrintDlg [internal]
586 *
587 *
588 * updates the PrintDlg structure for return values.
589 *
590 * RETURNS
591 * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
592 * TRUE if successful.
593 */
595 PRINT_PTRA* PrintStructures)
596{
597 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
598 PDEVMODEA lpdm = PrintStructures->lpDevMode;
599 LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
600
601
602 if(!lpdm) {
603 FIXME("No lpdm ptr?\n");
604 return FALSE;
605 }
606
607
608 if(!(lppd->Flags & PD_PRINTSETUP)) {
609 /* check whether nFromPage and nToPage are within range defined by
610 * nMinPage and nMaxPage
611 */
612 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
613 WORD nToPage;
614 WORD nFromPage;
615 BOOL translated;
616 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
617 nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
618
619 /* if no ToPage value is entered, use the FromPage value */
620 if(!translated) nToPage = nFromPage;
621
622 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
623 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
624 WCHAR resourcestr[256];
625 WCHAR resultstr[256];
627 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
629 MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
630 return FALSE;
631 }
632 lppd->nFromPage = nFromPage;
633 lppd->nToPage = nToPage;
634 lppd->Flags |= PD_PAGENUMS;
635 }
636 else
637 lppd->Flags &= ~PD_PAGENUMS;
638
639 if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
640 lppd->Flags |= PD_SELECTION;
641 else
642 lppd->Flags &= ~PD_SELECTION;
643
644 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
645 static char file[] = "FILE:";
646 lppd->Flags |= PD_PRINTTOFILE;
647 pi->pPortName = file;
648 }
649
650 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
651 FIXME("Collate lppd not yet implemented as output\n");
652 }
653
654 /* set PD_Collate and nCopies */
656 /* The application doesn't support multiple copies or collate...
657 */
658 lppd->Flags &= ~PD_COLLATE;
659 lppd->nCopies = 1;
660 /* if the printer driver supports it... store info there
661 * otherwise no collate & multiple copies !
662 */
663 if (lpdm->dmFields & DM_COLLATE)
664 lpdm->dmCollate =
666 if (lpdm->dmFields & DM_COPIES)
667 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
668 } else {
669 /* Application is responsible for multiple copies */
670 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
671 lppd->Flags |= PD_COLLATE;
672 else
673 lppd->Flags &= ~PD_COLLATE;
674 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
675 /* multiple copies already included in the document. Driver must print only one copy */
676 lpdm->u1.s1.dmCopies = 1;
677 }
678
679 /* Print quality, PrintDlg16 */
680 if(GetDlgItem(hDlg, cmb1))
681 {
682 HWND hQuality = GetDlgItem(hDlg, cmb1);
683 int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
684
685 if(Sel != CB_ERR)
686 {
687 LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
689 lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
690 lpdm->dmYResolution = HIWORD(dpi);
691 }
692 }
693 }
694 return TRUE;
695}
696
698 PRINT_PTRW* PrintStructures)
699{
700 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
701 PDEVMODEW lpdm = PrintStructures->lpDevMode;
702 LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
703
704
705 if(!lpdm) {
706 FIXME("No lpdm ptr?\n");
707 return FALSE;
708 }
709
710
711 if(!(lppd->Flags & PD_PRINTSETUP)) {
712 /* check whether nFromPage and nToPage are within range defined by
713 * nMinPage and nMaxPage
714 */
715 if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
716 WORD nToPage;
717 WORD nFromPage;
718 BOOL translated;
719 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
720 nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
721
722 /* if no ToPage value is entered, use the FromPage value */
723 if(!translated) nToPage = nFromPage;
724
725 if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
726 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
727 WCHAR resourcestr[256];
728 WCHAR resultstr[256];
729 DWORD_PTR args[2];
731 resourcestr, 255);
732 args[0] = lppd->nMinPage;
733 args[1] = lppd->nMaxPage;
735 resourcestr, 0, 0, resultstr,
736 ARRAY_SIZE(resultstr),
739 resourcestr, 255);
740 MessageBoxW(hDlg, resultstr, resourcestr,
742 return FALSE;
743 }
744 lppd->nFromPage = nFromPage;
745 lppd->nToPage = nToPage;
746 lppd->Flags |= PD_PAGENUMS;
747 }
748 else
749 lppd->Flags &= ~PD_PAGENUMS;
750
751 if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
752 lppd->Flags |= PD_SELECTION;
753 else
754 lppd->Flags &= ~PD_SELECTION;
755
756 if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
757 static WCHAR file[] = {'F','I','L','E',':',0};
758 lppd->Flags |= PD_PRINTTOFILE;
759 pi->pPortName = file;
760 }
761
762 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
763 FIXME("Collate lppd not yet implemented as output\n");
764 }
765
766 /* set PD_Collate and nCopies */
768 /* The application doesn't support multiple copies or collate...
769 */
770 lppd->Flags &= ~PD_COLLATE;
771 lppd->nCopies = 1;
772 /* if the printer driver supports it... store info there
773 * otherwise no collate & multiple copies !
774 */
775 if (lpdm->dmFields & DM_COLLATE)
776 lpdm->dmCollate =
778 if (lpdm->dmFields & DM_COPIES)
779 lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
780 } else {
781 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
782 lppd->Flags |= PD_COLLATE;
783 else
784 lppd->Flags &= ~PD_COLLATE;
785 lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
786 }
787 }
788 return TRUE;
789}
790
791/************************************************************************
792 * PRINTDLG_SetUpPaperComboBox
793 *
794 * Initialize either the papersize or inputslot combos of the Printer Setup
795 * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
796 * We also try to re-select the old selection.
797 */
799 int nIDComboBox,
800 char* PrinterName,
801 char* PortName,
802 LPDEVMODEA dm)
803{
804 int i;
805 int NrOfEntries;
806 char* Names;
807 WORD* Words;
808 DWORD Sel, old_Sel;
809 WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
810 int NamesSize;
811 int fwCapability_Names;
812 int fwCapability_Words;
813
814 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
815
816 /* query the dialog box for the current selected value */
817 Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
818 if(Sel != CB_ERR) {
819 /* we enter here only if a different printer is selected after
820 * the Print Setup dialog is opened. The current settings are
821 * stored into the newly selected printer.
822 */
823 oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
824 Sel, 0);
825 if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
826 oldWord = 0; /* There's no point in trying to keep custom
827 paper / bin sizes across printers */
828 }
829
830 if (dm)
831 newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
832
833 if (nIDComboBox == cmb2) {
834 NamesSize = 64;
835 fwCapability_Names = DC_PAPERNAMES;
836 fwCapability_Words = DC_PAPERS;
837 } else {
838 nIDComboBox = cmb3;
839 NamesSize = 24;
840 fwCapability_Names = DC_BINNAMES;
841 fwCapability_Words = DC_BINS;
842 }
843
844 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
845 fwCapability_Names, NULL, dm);
846 if (NrOfEntries == 0)
847 WARN("no Name Entries found!\n");
848 else if (NrOfEntries < 0)
849 return FALSE;
850
851 if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
852 != NrOfEntries) {
853 ERR("Number of caps is different\n");
854 NrOfEntries = 0;
855 }
856
857 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
858 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
859 DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Names, Names, dm);
860 NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
861 fwCapability_Words, (LPSTR)Words, dm);
862
863 /* reset any current content in the combobox */
864 SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
865
866 /* store new content */
867 for (i = 0; i < NrOfEntries; i++) {
868 DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
869 (LPARAM)(&Names[i*NamesSize]) );
870 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
871 Words[i]);
872 }
873
874 /* Look for old selection or the new default.
875 Can't do this is previous loop since item order will change as more items are added */
876 Sel = 0;
877 old_Sel = NrOfEntries;
878 for (i = 0; i < NrOfEntries; i++) {
879 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
880 oldWord) {
881 old_Sel = i;
882 break;
883 }
884 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
885 Sel = i;
886 }
887
888 if(old_Sel < NrOfEntries)
889 {
890 if (dm)
891 {
892 if(nIDComboBox == cmb2)
893 dm->u1.s1.dmPaperSize = oldWord;
894 else
895 dm->u1.s1.dmDefaultSource = oldWord;
896 }
897 Sel = old_Sel;
898 }
899
900 SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
901
902 HeapFree(GetProcessHeap(),0,Words);
904 return TRUE;
905}
906
908 int nIDComboBox,
909 const WCHAR* PrinterName,
910 const WCHAR* PortName,
911 LPDEVMODEW dm)
912{
913 int i;
914 int NrOfEntries;
915 WCHAR* Names;
916 WORD* Words;
917 DWORD Sel, old_Sel;
918 WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
919 int NamesSize;
920 int fwCapability_Names;
921 int fwCapability_Words;
922
923 TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
924
925 /* query the dialog box for the current selected value */
926 Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
927 if(Sel != CB_ERR) {
928 /* we enter here only if a different printer is selected after
929 * the Print Setup dialog is opened. The current settings are
930 * stored into the newly selected printer.
931 */
932 oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
933 Sel, 0);
934
935 if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
936 oldWord = 0; /* There's no point in trying to keep custom
937 paper / bin sizes across printers */
938 }
939
940 if (dm)
941 newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
942
943 if (nIDComboBox == cmb2) {
944 NamesSize = 64;
945 fwCapability_Names = DC_PAPERNAMES;
946 fwCapability_Words = DC_PAPERS;
947 } else {
948 nIDComboBox = cmb3;
949 NamesSize = 24;
950 fwCapability_Names = DC_BINNAMES;
951 fwCapability_Words = DC_BINS;
952 }
953
954 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
955 fwCapability_Names, NULL, dm);
956 if (NrOfEntries == 0)
957 WARN("no Name Entries found!\n");
958 else if (NrOfEntries < 0)
959 return FALSE;
960
961 if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
962 != NrOfEntries) {
963 ERR("Number of caps is different\n");
964 NrOfEntries = 0;
965 }
966
967 Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
968 Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
969 DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Names, Names, dm);
970 NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
971 fwCapability_Words, Words, dm);
972
973 /* reset any current content in the combobox */
974 SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
975
976 /* store new content */
977 for (i = 0; i < NrOfEntries; i++) {
978 DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
979 (LPARAM)(&Names[i*NamesSize]) );
980 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
981 Words[i]);
982 }
983
984 /* Look for old selection or the new default.
985 Can't do this is previous loop since item order will change as more items are added */
986 Sel = 0;
987 old_Sel = NrOfEntries;
988 for (i = 0; i < NrOfEntries; i++) {
989 if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
990 oldWord) {
991 old_Sel = i;
992 break;
993 }
994 if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
995 Sel = i;
996 }
997
998 if(old_Sel < NrOfEntries)
999 {
1000 if (dm)
1001 {
1002 if(nIDComboBox == cmb2)
1003 dm->u1.s1.dmPaperSize = oldWord;
1004 else
1005 dm->u1.s1.dmDefaultSource = oldWord;
1006 }
1007 Sel = old_Sel;
1008 }
1009
1010 SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
1011
1012 HeapFree(GetProcessHeap(),0,Words);
1014 return TRUE;
1015}
1016
1017
1018/***********************************************************************
1019 * PRINTDLG_UpdatePrinterInfoTexts [internal]
1020 */
1022{
1023 char StatusMsg[256];
1024 char ResourceString[256];
1025 int i;
1026
1027 /* Status Message */
1028 StatusMsg[0]='\0';
1029
1030 /* add all status messages */
1031 for (i = 0; i < 25; i++) {
1032 if (pi->Status & (1<<i)) {
1034 ResourceString, 255);
1035 strcat(StatusMsg,ResourceString);
1036 }
1037 }
1038 /* append "ready" */
1039 /* FIXME: status==ready must only be appended if really so.
1040 but how to detect? */
1042 ResourceString, 255);
1043 strcat(StatusMsg,ResourceString);
1044 SetDlgItemTextA(hDlg, stc12, StatusMsg);
1045
1046 /* set all other printer info texts */
1047 SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
1048
1049 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1050 SetDlgItemTextA(hDlg, stc14, pi->pLocation);
1051 else
1052 SetDlgItemTextA(hDlg, stc14, pi->pPortName);
1053 SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
1054 return;
1055}
1056
1058{
1059 WCHAR StatusMsg[256];
1060 WCHAR ResourceString[256];
1061 static const WCHAR emptyW[] = {0};
1062 int i;
1063
1064 /* Status Message */
1065 StatusMsg[0]='\0';
1066
1067 /* add all status messages */
1068 for (i = 0; i < 25; i++) {
1069 if (pi->Status & (1<<i)) {
1071 ResourceString, 255);
1072 lstrcatW(StatusMsg,ResourceString);
1073 }
1074 }
1075 /* append "ready" */
1076 /* FIXME: status==ready must only be appended if really so.
1077 but how to detect? */
1079 ResourceString, 255);
1080 lstrcatW(StatusMsg,ResourceString);
1081 SetDlgItemTextW(hDlg, stc12, StatusMsg);
1082
1083 /* set all other printer info texts */
1084 SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
1085 if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1086 SetDlgItemTextW(hDlg, stc14, pi->pLocation);
1087 else
1088 SetDlgItemTextW(hDlg, stc14, pi->pPortName);
1089 SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
1090}
1091
1092
1093/*******************************************************************
1094 *
1095 * PRINTDLG_ChangePrinter
1096 *
1097 */
1098static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
1099{
1100 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1101 LPDEVMODEA lpdm = NULL;
1102 LONG dmSize;
1103 DWORD needed;
1104 HANDLE hprn;
1105
1106 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1107 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1108 if(!OpenPrinterA(name, &hprn, NULL)) {
1109 ERR("Can't open printer %s\n", name);
1110 return FALSE;
1111 }
1112 GetPrinterA(hprn, 2, NULL, 0, &needed);
1113 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1114 GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1115 &needed);
1116 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1117 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1118 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1119 needed, &needed)) {
1120 ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
1121 return FALSE;
1122 }
1123 ClosePrinter(hprn);
1124
1125 PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
1126
1127 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1128 PrintStructures->lpDevMode = NULL;
1129
1130 dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
1131 if(dmSize == -1) {
1132 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
1133 return FALSE;
1134 }
1135 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1136 dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
1138 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1139 !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
1140 (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
1141 /* Supplied devicemode matches current printer so try to use it */
1142 DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
1144 }
1145 if(lpdm)
1146 GlobalUnlock(lppd->hDevMode);
1147
1148 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1149
1150 if(!(lppd->Flags & PD_PRINTSETUP)) {
1151 /* Print range (All/Range/Selection) */
1152 if(lppd->nFromPage != 0xffff)
1153 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1154 if(lppd->nToPage != 0xffff)
1155 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1156
1157 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1158 if (lppd->Flags & PD_NOSELECTION)
1160 else
1161 if (lppd->Flags & PD_SELECTION)
1162 CheckRadioButton(hDlg, rad1, rad3, rad2);
1163 if (lppd->Flags & PD_NOPAGENUMS) {
1169 } else {
1170 if (lppd->Flags & PD_PAGENUMS)
1171 CheckRadioButton(hDlg, rad1, rad3, rad3);
1172 }
1173
1174 /* Collate pages */
1175 if (lppd->Flags & PD_COLLATE) {
1177 (LPARAM)PrintStructures->hCollateIcon);
1178 CheckDlgButton(hDlg, chx2, 1);
1179 } else {
1181 (LPARAM)PrintStructures->hNoCollateIcon);
1182 CheckDlgButton(hDlg, chx2, 0);
1183 }
1184
1186 /* if printer doesn't support it: no Collate */
1187 if (!(lpdm->dmFields & DM_COLLATE)) {
1190 }
1191 }
1192
1193 /* nCopies */
1194 {
1195 INT copies;
1196 if (lppd->hDevMode == 0)
1197 copies = lppd->nCopies;
1198 else
1199 copies = lpdm->u1.s1.dmCopies;
1200 if(copies == 0) copies = 1;
1201 else if(copies < 0) copies = MAX_COPIES;
1202 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1203 }
1204
1206 /* if printer doesn't support it: no nCopies */
1207 if (!(lpdm->dmFields & DM_COPIES)) {
1210 }
1211 }
1212
1213 /* print to file */
1214 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1215 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1217 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1219
1220 /* Fill print quality combo, PrintDlg16 */
1221 if(GetDlgItem(hDlg, cmb1))
1222 {
1223 DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1224 PrintStructures->lpPrinterInfo->pPortName,
1225 DC_ENUMRESOLUTIONS, NULL, lpdm);
1226
1227 if(numResolutions != -1)
1228 {
1229 HWND hQuality = GetDlgItem(hDlg, cmb1);
1230 LONG* Resolutions;
1231 char buf[255];
1232 DWORD i;
1233 int dpiX, dpiY;
1234 HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
1235 PrintStructures->lpPrinterInfo->pPrinterName,
1236 0, lpdm);
1237
1238 Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
1240 PrintStructures->lpPrinterInfo->pPortName,
1241 DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
1242
1243 dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
1244 dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
1245 DeleteDC(hPrinterDC);
1246
1247 SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
1248 for(i = 0; i < (numResolutions * 2); i += 2)
1249 {
1250 BOOL IsDefault = FALSE;
1251 LRESULT Index;
1252
1253 if(Resolutions[i] == Resolutions[i+1])
1254 {
1255 if(dpiX == Resolutions[i])
1256 IsDefault = TRUE;
1257 sprintf(buf, "%d dpi", Resolutions[i]);
1258 } else
1259 {
1260 if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1261 IsDefault = TRUE;
1262 sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
1263 }
1264
1265 Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1266
1267 if(IsDefault)
1268 SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1269
1270 SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
1271 }
1272 HeapFree(GetProcessHeap(), 0, Resolutions);
1273 }
1274 }
1275 } else { /* PD_PRINTSETUP */
1276 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1277
1279 PrintStructures->lpPrinterInfo->pPrinterName,
1280 PrintStructures->lpPrinterInfo->pPortName,
1281 lpdm);
1283 PrintStructures->lpPrinterInfo->pPrinterName,
1284 PrintStructures->lpPrinterInfo->pPortName,
1285 lpdm);
1286 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1288 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1289 PrintStructures->hLandscapeIcon));
1290
1291 }
1292
1293 /* help button */
1294 if ((lppd->Flags & PD_SHOWHELP)==0) {
1295 /* hide if PD_SHOWHELP not specified */
1297 }
1298 return TRUE;
1299}
1300
1302 PRINT_PTRW *PrintStructures)
1303{
1304 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1305 LPDEVMODEW lpdm = NULL;
1306 LONG dmSize;
1307 DWORD needed;
1308 HANDLE hprn;
1309
1310 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1311 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1312 if(!OpenPrinterW(name, &hprn, NULL)) {
1313 ERR("Can't open printer %s\n", debugstr_w(name));
1314 return FALSE;
1315 }
1316 GetPrinterW(hprn, 2, NULL, 0, &needed);
1317 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1318 GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1319 &needed);
1320 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1321 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1322 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1323 needed, &needed)) {
1324 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1325 return FALSE;
1326 }
1327 ClosePrinter(hprn);
1328
1329 PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1330
1331 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1332 PrintStructures->lpDevMode = NULL;
1333
1334 dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1335 if(dmSize == -1) {
1336 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1337 return FALSE;
1338 }
1339 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1340 dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1342 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1343 !lstrcmpW(lpdm->dmDeviceName,
1344 PrintStructures->lpDevMode->dmDeviceName)) {
1345 /* Supplied devicemode matches current printer so try to use it */
1346 DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1348 }
1349 if(lpdm)
1350 GlobalUnlock(lppd->hDevMode);
1351
1352 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1353
1354 if(!(lppd->Flags & PD_PRINTSETUP)) {
1355 /* Print range (All/Range/Selection) */
1356 if(lppd->nFromPage != 0xffff)
1357 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1358 if(lppd->nToPage != 0xffff)
1359 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1360
1361 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1362 if (lppd->Flags & PD_NOSELECTION)
1364 else
1365 if (lppd->Flags & PD_SELECTION)
1366 CheckRadioButton(hDlg, rad1, rad3, rad2);
1367 if (lppd->Flags & PD_NOPAGENUMS) {
1373 } else {
1374 if (lppd->Flags & PD_PAGENUMS)
1375 CheckRadioButton(hDlg, rad1, rad3, rad3);
1376 }
1377
1378 /* Collate pages */
1379 if (lppd->Flags & PD_COLLATE) {
1381 (LPARAM)PrintStructures->hCollateIcon);
1382 CheckDlgButton(hDlg, chx2, 1);
1383 } else {
1385 (LPARAM)PrintStructures->hNoCollateIcon);
1386 CheckDlgButton(hDlg, chx2, 0);
1387 }
1388
1390 /* if printer doesn't support it: no Collate */
1391 if (!(lpdm->dmFields & DM_COLLATE)) {
1394 }
1395 }
1396
1397 /* nCopies */
1398 {
1399 INT copies;
1400 if (lppd->hDevMode == 0)
1401 copies = lppd->nCopies;
1402 else
1403 copies = lpdm->u1.s1.dmCopies;
1404 if(copies == 0) copies = 1;
1405 else if(copies < 0) copies = MAX_COPIES;
1406 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1407 }
1408
1410 /* if printer doesn't support it: no nCopies */
1411 if (!(lpdm->dmFields & DM_COPIES)) {
1414 }
1415 }
1416
1417 /* print to file */
1418 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1419 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1421 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1423
1424 } else { /* PD_PRINTSETUP */
1425 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1426
1428 PrintStructures->lpPrinterInfo->pPrinterName,
1429 PrintStructures->lpPrinterInfo->pPortName,
1430 lpdm);
1432 PrintStructures->lpPrinterInfo->pPrinterName,
1433 PrintStructures->lpPrinterInfo->pPortName,
1434 lpdm);
1435 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1437 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1438 PrintStructures->hLandscapeIcon));
1439
1440 }
1441
1442 /* help button */
1443 if ((lppd->Flags & PD_SHOWHELP)==0) {
1444 /* hide if PD_SHOWHELP not specified */
1446 }
1447 return TRUE;
1448}
1449
1450 /***********************************************************************
1451 * check_printer_setup [internal]
1452 */
1454{
1455 DWORD needed,num;
1456 WCHAR resourcestr[256],resultstr[256];
1457
1458 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1459 if(needed == 0)
1460 {
1462 }
1463 if(needed > 0)
1464 return TRUE;
1465 else
1466 {
1469 MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1470 return FALSE;
1471 }
1472}
1473
1474/***********************************************************************
1475 * PRINTDLG_WMInitDialog [internal]
1476 */
1478 PRINT_PTRA* PrintStructures)
1479{
1480 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1481 DEVNAMES *pdn;
1482 DEVMODEA *pdm;
1483 char *name = NULL;
1484 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1485
1486 /* load Collate ICONs */
1487 /* We load these with LoadImage because they are not a standard
1488 size and we don't want them rescaled */
1489 PrintStructures->hCollateIcon =
1490 LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1491 PrintStructures->hNoCollateIcon =
1492 LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1493
1494 /* These can be done with LoadIcon */
1495 PrintStructures->hPortraitIcon =
1496 LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1497 PrintStructures->hLandscapeIcon =
1498 LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1499
1500 /* display the collate/no_collate icon */
1502 (LPARAM)PrintStructures->hNoCollateIcon);
1503
1504 if(PrintStructures->hCollateIcon == 0 ||
1505 PrintStructures->hNoCollateIcon == 0 ||
1506 PrintStructures->hPortraitIcon == 0 ||
1507 PrintStructures->hLandscapeIcon == 0) {
1508 ERR("no icon in resource file\n");
1510 EndDialog(hDlg, FALSE);
1511 }
1512
1513 /*
1514 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1515 * must be registered and the Help button must be shown.
1516 */
1517 if (lppd->Flags & PD_SHOWHELP) {
1518 if((PrintStructures->HelpMessageID =
1521 return FALSE;
1522 }
1523 } else
1524 PrintStructures->HelpMessageID = 0;
1525
1526 if(!(lppd->Flags &PD_PRINTSETUP)) {
1527 PrintStructures->hwndUpDown =
1530 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1532 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1533 }
1534
1535 /* FIXME: I allow more freedom than either Win95 or WinNT,
1536 * which do not agree on what errors should be thrown or not
1537 * in case nToPage or nFromPage is out-of-range.
1538 */
1539 if (lppd->nMaxPage < lppd->nMinPage)
1540 lppd->nMaxPage = lppd->nMinPage;
1541 if (lppd->nMinPage == lppd->nMaxPage)
1542 lppd->Flags |= PD_NOPAGENUMS;
1543 if (lppd->nToPage < lppd->nMinPage)
1544 lppd->nToPage = lppd->nMinPage;
1545 if (lppd->nToPage > lppd->nMaxPage)
1546 lppd->nToPage = lppd->nMaxPage;
1547 if (lppd->nFromPage < lppd->nMinPage)
1548 lppd->nFromPage = lppd->nMinPage;
1549 if (lppd->nFromPage > lppd->nMaxPage)
1550 lppd->nFromPage = lppd->nMaxPage;
1551
1552 /* if we have the combo box, fill it */
1553 if (GetDlgItem(hDlg,comboID)) {
1554 /* Fill Combobox
1555 */
1556 pdn = GlobalLock(lppd->hDevNames);
1557 pdm = GlobalLock(lppd->hDevMode);
1558 if(pdn)
1559 name = (char*)pdn + pdn->wDeviceOffset;
1560 else if(pdm)
1561 name = (char*)pdm->dmDeviceName;
1562 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1563 if(pdm) GlobalUnlock(lppd->hDevMode);
1564 if(pdn) GlobalUnlock(lppd->hDevNames);
1565
1566 /* Now find selected printer and update rest of dlg */
1567 name = HeapAlloc(GetProcessHeap(),0,256);
1568 if (GetDlgItemTextA(hDlg, comboID, name, 255))
1569 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1571 } else {
1572 /* else use default printer */
1573 char name[200];
1576
1577 if (ret)
1578 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1579 else
1580 FIXME("No default printer found, expect problems!\n");
1581 }
1582 return TRUE;
1583}
1584
1586 PRINT_PTRW* PrintStructures)
1587{
1588 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1589 DEVNAMES *pdn;
1590 DEVMODEW *pdm;
1591 WCHAR *name = NULL;
1592 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1593
1594 /* load Collate ICONs */
1595 /* We load these with LoadImage because they are not a standard
1596 size and we don't want them rescaled */
1597 PrintStructures->hCollateIcon =
1599 PrintStructures->hNoCollateIcon =
1601
1602 /* These can be done with LoadIcon */
1603 PrintStructures->hPortraitIcon =
1605 PrintStructures->hLandscapeIcon =
1607
1608 /* display the collate/no_collate icon */
1610 (LPARAM)PrintStructures->hNoCollateIcon);
1611
1612 if(PrintStructures->hCollateIcon == 0 ||
1613 PrintStructures->hNoCollateIcon == 0 ||
1614 PrintStructures->hPortraitIcon == 0 ||
1615 PrintStructures->hLandscapeIcon == 0) {
1616 ERR("no icon in resource file\n");
1618 EndDialog(hDlg, FALSE);
1619 }
1620
1621 /*
1622 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1623 * must be registered and the Help button must be shown.
1624 */
1625 if (lppd->Flags & PD_SHOWHELP) {
1626 if((PrintStructures->HelpMessageID =
1629 return FALSE;
1630 }
1631 } else
1632 PrintStructures->HelpMessageID = 0;
1633
1634 if(!(lppd->Flags &PD_PRINTSETUP)) {
1635 PrintStructures->hwndUpDown =
1638 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1640 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1641 }
1642
1643 /* FIXME: I allow more freedom than either Win95 or WinNT,
1644 * which do not agree to what errors should be thrown or not
1645 * in case nToPage or nFromPage is out-of-range.
1646 */
1647 if (lppd->nMaxPage < lppd->nMinPage)
1648 lppd->nMaxPage = lppd->nMinPage;
1649 if (lppd->nMinPage == lppd->nMaxPage)
1650 lppd->Flags |= PD_NOPAGENUMS;
1651 if (lppd->nToPage < lppd->nMinPage)
1652 lppd->nToPage = lppd->nMinPage;
1653 if (lppd->nToPage > lppd->nMaxPage)
1654 lppd->nToPage = lppd->nMaxPage;
1655 if (lppd->nFromPage < lppd->nMinPage)
1656 lppd->nFromPage = lppd->nMinPage;
1657 if (lppd->nFromPage > lppd->nMaxPage)
1658 lppd->nFromPage = lppd->nMaxPage;
1659
1660 /* if we have the combo box, fill it */
1661 if (GetDlgItem(hDlg,comboID)) {
1662 /* Fill Combobox
1663 */
1664 pdn = GlobalLock(lppd->hDevNames);
1665 pdm = GlobalLock(lppd->hDevMode);
1666 if(pdn)
1667 name = (WCHAR*)pdn + pdn->wDeviceOffset;
1668 else if(pdm)
1669 name = pdm->dmDeviceName;
1670 PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1671 if(pdm) GlobalUnlock(lppd->hDevMode);
1672 if(pdn) GlobalUnlock(lppd->hDevNames);
1673
1674 /* Now find selected printer and update rest of dlg */
1675 /* ansi is ok here */
1676 name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1677 if (GetDlgItemTextW(hDlg, comboID, name, 255))
1678 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1680 } else {
1681 /* else use default printer */
1682 WCHAR name[200];
1685
1686 if (ret)
1687 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1688 else
1689 FIXME("No default printer found, expect problems!\n");
1690 }
1691 return TRUE;
1692}
1693
1694/***********************************************************************
1695 * PRINTDLG_WMCommand [internal]
1696 */
1698 PRINT_PTRA* PrintStructures)
1699{
1700 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1701 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1702 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1703
1704 switch (LOWORD(wParam)) {
1705 case IDOK:
1706 TRACE(" OK button was hit\n");
1707 if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1708 FIXME("Update printdlg was not successful!\n");
1709 return(FALSE);
1710 }
1711 EndDialog(hDlg, TRUE);
1712 return(TRUE);
1713
1714 case IDCANCEL:
1715 TRACE(" CANCEL button was hit\n");
1716 EndDialog(hDlg, FALSE);
1717 return(FALSE);
1718
1719 case pshHelp:
1720 TRACE(" HELP button was hit\n");
1721 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1722 (WPARAM) hDlg, (LPARAM) lppd);
1723 break;
1724
1725 case chx2: /* collate pages checkbox */
1726 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1728 (LPARAM)PrintStructures->hCollateIcon);
1729 else
1731 (LPARAM)PrintStructures->hNoCollateIcon);
1732 break;
1733 case edt1: /* from page nr editbox */
1734 case edt2: /* to page nr editbox */
1735 if (HIWORD(wParam)==EN_CHANGE) {
1736 WORD nToPage;
1737 WORD nFromPage;
1738 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1739 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1740 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1741 CheckRadioButton(hDlg, rad1, rad3, rad3);
1742 }
1743 break;
1744
1745 case edt3:
1746 if(HIWORD(wParam) == EN_CHANGE) {
1747 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1748 if(copies <= 1)
1750 else
1752 }
1753 break;
1754
1755 case psh2: /* Properties button */
1756 {
1757 HANDLE hPrinter;
1758 char PrinterName[256];
1759
1760 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1761 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1762 FIXME(" Call to OpenPrinter did not succeed!\n");
1763 break;
1764 }
1765 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1766 PrintStructures->lpDevMode,
1767 PrintStructures->lpDevMode,
1769 ClosePrinter(hPrinter);
1770 break;
1771 }
1772
1773 case rad1: /* Paperorientation */
1774 if (lppd->Flags & PD_PRINTSETUP)
1775 {
1776 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1778 (LPARAM)(PrintStructures->hPortraitIcon));
1779 }
1780 break;
1781
1782 case rad2: /* Paperorientation */
1783 if (lppd->Flags & PD_PRINTSETUP)
1784 {
1785 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1787 (LPARAM)(PrintStructures->hLandscapeIcon));
1788 }
1789 break;
1790
1791 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1792 if (PrinterComboID != LOWORD(wParam)) {
1793 break;
1794 }
1795 /* FALLTHROUGH */
1796 case cmb4: /* Printer combobox */
1797 if (HIWORD(wParam)==CBN_SELCHANGE) {
1798 char *PrinterName;
1801 PrinterName = HeapAlloc(GetProcessHeap(),0,length+1);
1802 SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1803 PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1804 HeapFree(GetProcessHeap(),0,PrinterName);
1805 }
1806 break;
1807
1808 case cmb2: /* Papersize */
1809 {
1810 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1811 if(Sel != CB_ERR) {
1812 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1814 Sel, 0);
1815 GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME);
1816 }
1817 }
1818 break;
1819
1820 case cmb3: /* Bin */
1821 {
1822 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1823 if(Sel != CB_ERR)
1824 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1825 CB_GETITEMDATA, Sel,
1826 0);
1827 }
1828 break;
1829 }
1830 if(lppd->Flags & PD_PRINTSETUP) {
1831 switch (LOWORD(wParam)) {
1832 case rad1: /* orientation */
1833 case rad2:
1834 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1835 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1836 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1838 (LPARAM)PrintStructures->hPortraitIcon);
1840 (LPARAM)PrintStructures->hPortraitIcon);
1841 }
1842 } else {
1843 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1844 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1846 (LPARAM)PrintStructures->hLandscapeIcon);
1848 (LPARAM)PrintStructures->hLandscapeIcon);
1849 }
1850 }
1851 break;
1852 }
1853 }
1854 return FALSE;
1855}
1856
1858 PRINT_PTRW* PrintStructures)
1859{
1860 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1861 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1862 LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1863
1864 switch (LOWORD(wParam)) {
1865 case IDOK:
1866 TRACE(" OK button was hit\n");
1867 if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1868 FIXME("Update printdlg was not successful!\n");
1869 return(FALSE);
1870 }
1871 EndDialog(hDlg, TRUE);
1872 return(TRUE);
1873
1874 case IDCANCEL:
1875 TRACE(" CANCEL button was hit\n");
1876 EndDialog(hDlg, FALSE);
1877 return(FALSE);
1878
1879 case pshHelp:
1880 TRACE(" HELP button was hit\n");
1881 SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1882 (WPARAM) hDlg, (LPARAM) lppd);
1883 break;
1884
1885 case chx2: /* collate pages checkbox */
1886 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1888 (LPARAM)PrintStructures->hCollateIcon);
1889 else
1891 (LPARAM)PrintStructures->hNoCollateIcon);
1892 break;
1893 case edt1: /* from page nr editbox */
1894 case edt2: /* to page nr editbox */
1895 if (HIWORD(wParam)==EN_CHANGE) {
1896 WORD nToPage;
1897 WORD nFromPage;
1898 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1899 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1900 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1901 CheckRadioButton(hDlg, rad1, rad3, rad3);
1902 }
1903 break;
1904
1905 case edt3:
1906 if(HIWORD(wParam) == EN_CHANGE) {
1907 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1908 if(copies <= 1)
1910 else
1912 }
1913 break;
1914
1915 case psh2: /* Properties button */
1916 {
1917 HANDLE hPrinter;
1918 WCHAR PrinterName[256];
1919
1920 if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1921 if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1922 FIXME(" Call to OpenPrinter did not succeed!\n");
1923 break;
1924 }
1925 DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1926 PrintStructures->lpDevMode,
1927 PrintStructures->lpDevMode,
1929 ClosePrinter(hPrinter);
1930 break;
1931 }
1932
1933 case rad1: /* Paperorientation */
1934 if (lppd->Flags & PD_PRINTSETUP)
1935 {
1936 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1938 (LPARAM)(PrintStructures->hPortraitIcon));
1939 }
1940 break;
1941
1942 case rad2: /* Paperorientation */
1943 if (lppd->Flags & PD_PRINTSETUP)
1944 {
1945 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1947 (LPARAM)(PrintStructures->hLandscapeIcon));
1948 }
1949 break;
1950
1951 case cmb1: /* Printer Combobox in PRINT SETUP */
1952 /* FALLTHROUGH */
1953 case cmb4: /* Printer combobox */
1954 if (HIWORD(wParam)==CBN_SELCHANGE) {
1955 WCHAR *PrinterName;
1958
1959 PrinterName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
1960 SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1961 PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1962 HeapFree(GetProcessHeap(),0,PrinterName);
1963 }
1964 break;
1965
1966 case cmb2: /* Papersize */
1967 {
1968 DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1969 if(Sel != CB_ERR) {
1970 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1972 Sel, 0);
1974 }
1975 }
1976 break;
1977
1978 case cmb3: /* Bin */
1979 {
1980 DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1981 if(Sel != CB_ERR)
1982 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1983 CB_GETITEMDATA, Sel,
1984 0);
1985 }
1986 break;
1987 }
1988 if(lppd->Flags & PD_PRINTSETUP) {
1989 switch (LOWORD(wParam)) {
1990 case rad1: /* orientation */
1991 case rad2:
1992 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1993 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1994 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1996 (LPARAM)PrintStructures->hPortraitIcon);
1998 (LPARAM)PrintStructures->hPortraitIcon);
1999 }
2000 } else {
2001 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
2002 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2004 (LPARAM)PrintStructures->hLandscapeIcon);
2006 (LPARAM)PrintStructures->hLandscapeIcon);
2007 }
2008 }
2009 break;
2010 }
2011 }
2012 return FALSE;
2013}
2014
2015/***********************************************************************
2016 * PrintDlgProcA [internal]
2017 */
2019 LPARAM lParam)
2020{
2021 PRINT_PTRA* PrintStructures;
2022 INT_PTR res = FALSE;
2023
2024 if (uMsg!=WM_INITDIALOG) {
2025 PrintStructures = GetPropW(hDlg, printdlg_prop);
2026 if (!PrintStructures)
2027 return FALSE;
2028 } else {
2029 PrintStructures = (PRINT_PTRA*) lParam;
2030 SetPropW(hDlg, printdlg_prop, PrintStructures);
2031 if(!check_printer_setup(hDlg))
2032 {
2033 EndDialog(hDlg,FALSE);
2034 return FALSE;
2035 }
2036 res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
2037
2038 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2039 res = PrintStructures->lpPrintDlg->lpfnPrintHook(
2040 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
2041 );
2042 return res;
2043 }
2044
2045 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2046 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
2047 lParam);
2048 if(res) return res;
2049 }
2050
2051 switch (uMsg) {
2052 case WM_COMMAND:
2053 return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
2054
2055 case WM_DESTROY:
2056 DestroyIcon(PrintStructures->hCollateIcon);
2057 DestroyIcon(PrintStructures->hNoCollateIcon);
2058 DestroyIcon(PrintStructures->hPortraitIcon);
2059 DestroyIcon(PrintStructures->hLandscapeIcon);
2060 if(PrintStructures->hwndUpDown)
2061 DestroyWindow(PrintStructures->hwndUpDown);
2062 return FALSE;
2063 }
2064 return res;
2065}
2066
2068 LPARAM lParam)
2069{
2070 PRINT_PTRW* PrintStructures;
2071 INT_PTR res = FALSE;
2072
2073 if (uMsg!=WM_INITDIALOG) {
2074 PrintStructures = GetPropW(hDlg, printdlg_prop);
2075 if (!PrintStructures)
2076 return FALSE;
2077 } else {
2078 PrintStructures = (PRINT_PTRW*) lParam;
2079 SetPropW(hDlg, printdlg_prop, PrintStructures);
2080 if(!check_printer_setup(hDlg))
2081 {
2082 EndDialog(hDlg,FALSE);
2083 return FALSE;
2084 }
2085 res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
2086
2087 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2088 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
2089 return res;
2090 }
2091
2092 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2093 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
2094 if(res) return res;
2095 }
2096
2097 switch (uMsg) {
2098 case WM_COMMAND:
2099 return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
2100
2101 case WM_DESTROY:
2102 DestroyIcon(PrintStructures->hCollateIcon);
2103 DestroyIcon(PrintStructures->hNoCollateIcon);
2104 DestroyIcon(PrintStructures->hPortraitIcon);
2105 DestroyIcon(PrintStructures->hLandscapeIcon);
2106 if(PrintStructures->hwndUpDown)
2107 DestroyWindow(PrintStructures->hwndUpDown);
2108 return FALSE;
2109 }
2110 return res;
2111}
2112
2113/************************************************************
2114 *
2115 * PRINTDLG_GetDlgTemplate
2116 *
2117 */
2119{
2120 HRSRC hResInfo;
2121 HGLOBAL hDlgTmpl;
2122
2123 if (lppd->Flags & PD_PRINTSETUP) {
2125 hDlgTmpl = lppd->hSetupTemplate;
2126 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2127 hResInfo = FindResourceA(lppd->hInstance,
2129 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2130 } else {
2131 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
2132 (LPSTR)RT_DIALOG);
2133 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2134 }
2135 } else {
2137 hDlgTmpl = lppd->hPrintTemplate;
2138 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2139 hResInfo = FindResourceA(lppd->hInstance,
2140 lppd->lpPrintTemplateName,
2141 (LPSTR)RT_DIALOG);
2142 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2143 } else {
2144 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
2145 (LPSTR)RT_DIALOG);
2146 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2147 }
2148 }
2149 return hDlgTmpl;
2150}
2151
2153{
2154 HRSRC hResInfo;
2155 HGLOBAL hDlgTmpl;
2156 static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
2157 static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
2158
2159 if (lppd->Flags & PD_PRINTSETUP) {
2161 hDlgTmpl = lppd->hSetupTemplate;
2162 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2163 hResInfo = FindResourceW(lppd->hInstance,
2165 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2166 } else {
2167 hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
2168 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2169 }
2170 } else {
2172 hDlgTmpl = lppd->hPrintTemplate;
2173 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2174 hResInfo = FindResourceW(lppd->hInstance,
2175 lppd->lpPrintTemplateName,
2176 (LPWSTR)RT_DIALOG);
2177 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2178 } else {
2179 hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
2180 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2181 }
2182 }
2183 return hDlgTmpl;
2184}
2185
2186/***********************************************************************
2187 *
2188 * PRINTDLG_CreateDC
2189 *
2190 */
2192{
2193 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2194 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
2195
2196 if(lppd->Flags & PD_RETURNDC) {
2197 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
2198 (char*)pdn + pdn->wDeviceOffset,
2199 (char*)pdn + pdn->wOutputOffset,
2200 pdm );
2201 } else if(lppd->Flags & PD_RETURNIC) {
2202 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
2203 (char*)pdn + pdn->wDeviceOffset,
2204 (char*)pdn + pdn->wOutputOffset,
2205 pdm );
2206 }
2207 GlobalUnlock(lppd->hDevNames);
2208 GlobalUnlock(lppd->hDevMode);
2209 return lppd->hDC != NULL;
2210}
2211
2213{
2214 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2215 DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
2216
2217 if(lppd->Flags & PD_RETURNDC) {
2218 lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
2219 (WCHAR*)pdn + pdn->wDeviceOffset,
2220 (WCHAR*)pdn + pdn->wOutputOffset,
2221 pdm );
2222 } else if(lppd->Flags & PD_RETURNIC) {
2223 lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
2224 (WCHAR*)pdn + pdn->wDeviceOffset,
2225 (WCHAR*)pdn + pdn->wOutputOffset,
2226 pdm );
2227 }
2228 GlobalUnlock(lppd->hDevNames);
2229 GlobalUnlock(lppd->hDevMode);
2230 return lppd->hDC != NULL;
2231}
2232
2233/***********************************************************************
2234 * PrintDlgA (COMDLG32.@)
2235 *
2236 * Displays the PRINT dialog box, which enables the user to specify
2237 * specific properties of the print job.
2238 *
2239 * PARAMS
2240 * lppd [IO] ptr to PRINTDLG32 struct
2241 *
2242 * RETURNS
2243 * nonzero if the user pressed the OK button
2244 * zero if the user cancelled the window or an error occurred
2245 *
2246 * BUGS
2247 * PrintDlg:
2248 * * The Collate Icons do not display, even though they are in the code.
2249 * * The Properties Button(s) should call DocumentPropertiesA().
2250 */
2251
2253{
2254 BOOL bRet = FALSE;
2255 LPVOID ptr;
2257
2258 if (!lppd)
2259 {
2261 return FALSE;
2262 }
2263
2264 if(TRACE_ON(commdlg)) {
2265 char flagstr[1000] = "";
2266 const struct pd_flags *pflag = pd_flags;
2267 for( ; pflag->name; pflag++) {
2268 if(lppd->Flags & pflag->flag)
2269 strcat(flagstr, pflag->name);
2270 }
2271 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2272 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2273 "flags %08x (%s)\n",
2274 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2275 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2276 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2277 }
2278
2279 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2280 WARN("structure size failure!!!\n");
2282 return FALSE;
2283 }
2284
2285 if(lppd->Flags & PD_RETURNDEFAULT) {
2287 DRIVER_INFO_3A *dbuf;
2288 HANDLE hprn;
2289 DWORD needed;
2290
2291 if(lppd->hDevMode || lppd->hDevNames) {
2292 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2294 return FALSE;
2295 }
2296 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2297 WARN("Can't find default printer\n");
2299 return FALSE;
2300 }
2301
2302 GetPrinterA(hprn, 2, NULL, 0, &needed);
2303 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2304 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2305
2306 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2307 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2308 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2309 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2310 GetLastError(),pbuf->pPrinterName);
2311 HeapFree(GetProcessHeap(), 0, dbuf);
2314 return FALSE;
2315 }
2316 ClosePrinter(hprn);
2317
2319 dbuf->pDriverPath,
2320 pbuf->pPrinterName,
2321 pbuf->pPortName);
2322 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2323 pbuf->pDevMode->dmDriverExtra);
2324 ptr = GlobalLock(lppd->hDevMode);
2325 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2326 pbuf->pDevMode->dmDriverExtra);
2327 GlobalUnlock(lppd->hDevMode);
2329 HeapFree(GetProcessHeap(), 0, dbuf);
2330 bRet = TRUE;
2331 } else {
2332 HGLOBAL hDlgTmpl;
2333 PRINT_PTRA *PrintStructures;
2334
2335 /* load Dialog resources,
2336 * depending on Flags indicates Print32 or Print32_setup dialog
2337 */
2338 hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2339 if (!hDlgTmpl) {
2341 return FALSE;
2342 }
2343 ptr = LockResource( hDlgTmpl );
2344 if (!ptr) {
2346 return FALSE;
2347 }
2348
2349 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2350 sizeof(PRINT_PTRA));
2351 PrintStructures->lpPrintDlg = lppd;
2352
2353 /* and create & process the dialog .
2354 * -1 is failure, 0 is broken hwnd, everything else is ok.
2355 */
2358 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2360 (LPARAM)PrintStructures));
2361
2362 if(bRet) {
2363 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2364 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2365 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2366
2367 if (lppd->hDevMode == 0) {
2368 TRACE(" No hDevMode yet... Need to create my own\n");
2370 lpdm->dmSize + lpdm->dmDriverExtra);
2371 } else {
2372 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2373 lpdm->dmSize + lpdm->dmDriverExtra,
2375 }
2376 lpdmReturn = GlobalLock(lppd->hDevMode);
2377 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2378
2380 di->pDriverPath,
2381 pi->pPrinterName,
2382 pi->pPortName
2383 );
2384 GlobalUnlock(lppd->hDevMode);
2385 }
2386 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2387 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2388 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2389 HeapFree(GetProcessHeap(), 0, PrintStructures);
2390 }
2391 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2392 bRet = PRINTDLG_CreateDCA(lppd);
2393
2394 TRACE("exit! (%d)\n", bRet);
2395 return bRet;
2396}
2397
2398/***********************************************************************
2399 * PrintDlgW (COMDLG32.@)
2400 *
2401 * See PrintDlgA.
2402 */
2404{
2405 BOOL bRet = FALSE;
2406 LPVOID ptr;
2408
2409 if (!lppd)
2410 {
2412 return FALSE;
2413 }
2414
2415 if(TRACE_ON(commdlg)) {
2416 char flagstr[1000] = "";
2417 const struct pd_flags *pflag = pd_flags;
2418 for( ; pflag->name; pflag++) {
2419 if(lppd->Flags & pflag->flag)
2420 strcat(flagstr, pflag->name);
2421 }
2422 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2423 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2424 "flags %08x (%s)\n",
2425 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2426 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2427 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2428 }
2429
2430 if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2431 WARN("structure size failure!!!\n");
2433 return FALSE;
2434 }
2435
2436 if(lppd->Flags & PD_RETURNDEFAULT) {
2438 DRIVER_INFO_3W *dbuf;
2439 HANDLE hprn;
2440 DWORD needed;
2441
2442 if(lppd->hDevMode || lppd->hDevNames) {
2443 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2445 return FALSE;
2446 }
2447 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2448 WARN("Can't find default printer\n");
2450 return FALSE;
2451 }
2452
2453 GetPrinterW(hprn, 2, NULL, 0, &needed);
2454 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2455 GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2456
2457 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2458 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2459 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2460 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2461 GetLastError(),debugstr_w(pbuf->pPrinterName));
2462 HeapFree(GetProcessHeap(), 0, dbuf);
2465 return FALSE;
2466 }
2467 ClosePrinter(hprn);
2468
2470 dbuf->pDriverPath,
2471 pbuf->pPrinterName,
2472 pbuf->pPortName);
2473 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2474 pbuf->pDevMode->dmDriverExtra);
2475 ptr = GlobalLock(lppd->hDevMode);
2476 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2477 pbuf->pDevMode->dmDriverExtra);
2478 GlobalUnlock(lppd->hDevMode);
2480 HeapFree(GetProcessHeap(), 0, dbuf);
2481 bRet = TRUE;
2482 } else {
2483 HGLOBAL hDlgTmpl;
2484 PRINT_PTRW *PrintStructures;
2485
2486 /* load Dialog resources,
2487 * depending on Flags indicates Print32 or Print32_setup dialog
2488 */
2489 hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2490 if (!hDlgTmpl) {
2492 return FALSE;
2493 }
2494 ptr = LockResource( hDlgTmpl );
2495 if (!ptr) {
2497 return FALSE;
2498 }
2499
2500 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2501 sizeof(PRINT_PTRW));
2502 PrintStructures->lpPrintDlg = lppd;
2503
2504 /* and create & process the dialog .
2505 * -1 is failure, 0 is broken hwnd, everything else is ok.
2506 */
2509 bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2511 (LPARAM)PrintStructures));
2512
2513 if(bRet) {
2514 DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2515 PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2516 DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2517
2518 if (lppd->hDevMode == 0) {
2519 TRACE(" No hDevMode yet... Need to create my own\n");
2521 lpdm->dmSize + lpdm->dmDriverExtra);
2522 } else {
2523 WORD locks;
2524 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2525 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2526 while(locks--) {
2527 GlobalUnlock(lppd->hDevMode);
2528 TRACE("Now got %d locks\n", locks);
2529 }
2530 }
2531 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2532 lpdm->dmSize + lpdm->dmDriverExtra,
2534 }
2535 lpdmReturn = GlobalLock(lppd->hDevMode);
2536 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2537
2538 if (lppd->hDevNames != 0) {
2539 WORD locks;
2540 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2541 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2542 while(locks--)
2543 GlobalUnlock(lppd->hDevNames);
2544 }
2545 }
2547 di->pDriverPath,
2548 pi->pPrinterName,
2549 pi->pPortName
2550 );
2551 GlobalUnlock(lppd->hDevMode);
2552 }
2553 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2554 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2555 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2556 HeapFree(GetProcessHeap(), 0, PrintStructures);
2557 }
2558 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2559 bRet = PRINTDLG_CreateDCW(lppd);
2560
2561 TRACE("exit! (%d)\n", bRet);
2562 return bRet;
2563}
2564
2565/***********************************************************************
2566 *
2567 * PageSetupDlg
2568 * rad1 - portrait
2569 * rad2 - landscape
2570 * cmb1 - printer select (not in standard dialog template)
2571 * cmb2 - paper size
2572 * cmb3 - source (tray?)
2573 * edt4 - border left
2574 * edt5 - border top
2575 * edt6 - border right
2576 * edt7 - border bottom
2577 * psh3 - "Printer..."
2578 */
2579
2580typedef struct
2581{
2583 union
2584 {
2587 } u;
2588 HWND hDlg; /* Page Setup dialog handle */
2589 RECT rtDrawRect; /* Drawing rect for page */
2591
2593{
2594 return data->u.dlgw->Flags;
2595}
2596
2597static inline BOOL is_metric(const pagesetup_data *data)
2598{
2600}
2601
2603{
2604 if (is_metric(data))
2605 return 10 * size;
2606 else
2607 return 10 * size * 100 / 254;
2608}
2609
2611{
2612 if (is_metric(data))
2613 return size * 254 / 100;
2614 else
2615 return size;
2616}
2617
2619{
2620 static WCHAR sep;
2621
2622 if(!sep)
2623 {
2624 WCHAR buf[] = {'.', 0};
2626 sep = buf[0];
2627 }
2628 return sep;
2629}
2630
2631static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
2632{
2633 static const WCHAR integer_fmt[] = {'%','d',0};
2634 static const WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
2635 static const WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
2636
2637 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2638
2639 if (is_metric(data))
2640 {
2641 if(size % 100)
2642 wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
2643 else
2644 wsprintfW(strout, integer_fmt, size / 100);
2645 }
2646 else
2647 {
2648 if(size % 1000)
2649 wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
2650 else
2651 wsprintfW(strout, integer_fmt, size / 1000);
2652
2653 }
2654}
2655
2656static inline BOOL is_default_metric(void)
2657{
2658 DWORD system;
2659 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2660 (LPWSTR)&system, sizeof(system));
2661 return system == 0;
2662}
2663
2664/**********************************************
2665 * rotate_rect
2666 * Cyclically permute the four members of rc
2667 * If sense is TRUE l -> t -> r -> b
2668 * otherwise l <- t <- r <- b
2669 */
2670static inline void rotate_rect(RECT *rc, BOOL sense)
2671{
2672 INT tmp;
2673 if(sense)
2674 {
2675 tmp = rc->bottom;
2676 rc->bottom = rc->right;
2677 rc->right = rc->top;
2678 rc->top = rc->left;
2679 rc->left = tmp;
2680 }
2681 else
2682 {
2683 tmp = rc->left;
2684 rc->left = rc->top;
2685 rc->top = rc->right;
2686 rc->right = rc->bottom;
2687 rc->bottom = tmp;
2688 }
2689}
2690
2692{
2693 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2694
2695 assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2696
2697 if(data->unicode)
2698 dm->u1.s1.dmOrientation = orient;
2699 else
2700 {
2701 DEVMODEA *dmA = (DEVMODEA *)dm;
2702 dmA->u1.s1.dmOrientation = orient;
2703 }
2704 GlobalUnlock(data->u.dlgw->hDevMode);
2705}
2706
2708{
2709 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2710 WORD orient;
2711
2712 if(data->unicode)
2713 orient = dm->u1.s1.dmOrientation;
2714 else
2715 {
2716 DEVMODEA *dmA = (DEVMODEA *)dm;
2717 orient = dmA->u1.s1.dmOrientation;
2718 }
2719 GlobalUnlock(data->u.dlgw->hDevMode);
2720 return orient;
2721}
2722
2724{
2725 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2726
2727 if(data->unicode)
2728 dm->u1.s1.dmPaperSize = paper;
2729 else
2730 {
2731 DEVMODEA *dmA = (DEVMODEA *)dm;
2732 dmA->u1.s1.dmPaperSize = paper;
2733 }
2734 GlobalUnlock(data->u.dlgw->hDevMode);
2735}
2736
2738{
2739 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2740 WORD paper;
2741
2742 if(data->unicode)
2743 paper = dm->u1.s1.dmPaperSize;
2744 else
2745 {
2746 DEVMODEA *dmA = (DEVMODEA *)dm;
2747 paper = dmA->u1.s1.dmPaperSize;
2748 }
2749 GlobalUnlock(data->u.dlgw->hDevMode);
2750 return paper;
2751}
2752
2754{
2755 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2756
2757 if(data->unicode)
2758 dm->u1.s1.dmDefaultSource = source;
2759 else
2760 {
2761 DEVMODEA *dmA = (DEVMODEA *)dm;
2762 dmA->u1.s1.dmDefaultSource = source;
2763 }
2764 GlobalUnlock(data->u.dlgw->hDevMode);
2765}
2766
2767typedef enum
2768{
2773
2774
2776{
2777 switch(which)
2778 {
2779 case devnames_driver_name: return dn->wDriverOffset;
2780 case devnames_device_name: return dn->wDeviceOffset;
2781 case devnames_output_name: return dn->wOutputOffset;
2782 }
2783 ERR("Shouldn't be here\n");
2784 return 0;
2785}
2786
2788{
2789 DEVNAMES *dn;
2790 WCHAR *name;
2791
2792 dn = GlobalLock(data->u.dlgw->hDevNames);
2793 if(data->unicode)
2794 name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
2795 else
2796 {
2797 int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
2798 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2799 MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
2800 }
2801 GlobalUnlock(data->u.dlgw->hDevNames);
2802 return name;
2803}
2804
2806{
2808}
2809
2811{
2813}
2814
2816{
2818}
2819
2821{
2823}
2824
2826{
2827 DEVNAMES *dn;
2828 WCHAR def[256];
2829 DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
2830
2831 if(data->unicode)
2832 {
2833 drv_len = (lstrlenW(drv) + 1) * sizeof(WCHAR);
2834 dev_len = (lstrlenW(devname) + 1) * sizeof(WCHAR);
2835 port_len = (lstrlenW(port) + 1) * sizeof(WCHAR);
2836 }
2837 else
2838 {
2839 drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
2840 dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
2841 port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
2842 }
2843 len += drv_len + dev_len + port_len;
2844
2845 if(data->u.dlgw->hDevNames)
2846 data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
2847 else
2848 data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
2849
2850 dn = GlobalLock(data->u.dlgw->hDevNames);
2851
2852 if(data->unicode)
2853 {
2854 WCHAR *ptr = (WCHAR *)(dn + 1);
2855 len = sizeof(DEVNAMES) / sizeof(WCHAR);
2856 dn->wDriverOffset = len;
2857 lstrcpyW(ptr, drv);
2858 ptr += drv_len / sizeof(WCHAR);
2859 len += drv_len / sizeof(WCHAR);
2860 dn->wDeviceOffset = len;
2861 lstrcpyW(ptr, devname);
2862 ptr += dev_len / sizeof(WCHAR);
2863 len += dev_len / sizeof(WCHAR);
2864 dn->wOutputOffset = len;
2865 lstrcpyW(ptr, port);
2866 }
2867 else
2868 {
2869 char *ptr = (char *)(dn + 1);
2870 len = sizeof(DEVNAMES);
2871 dn->wDriverOffset = len;
2872 WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
2873 ptr += drv_len;
2874 len += drv_len;
2875 dn->wDeviceOffset = len;
2876 WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
2877 ptr += dev_len;
2878 len += dev_len;
2879 dn->wOutputOffset = len;
2880 WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
2881 }
2882
2883 dn->wDefault = 0;
2884 len = ARRAY_SIZE(def);
2885 GetDefaultPrinterW(def, &len);
2886 if(!lstrcmpW(def, devname))
2887 dn->wDefault = 1;
2888
2889 GlobalUnlock(data->u.dlgw->hDevNames);
2890}
2891
2893{
2894 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2895 DEVMODEW *ret;
2896
2897 if(data->unicode)
2898 {
2899 /* We make a copy even in the unicode case because the ptr
2900 may get passed back to us in pagesetup_set_devmode. */
2901 ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
2902 memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
2903 }
2904 else
2906
2907 GlobalUnlock(data->u.dlgw->hDevMode);
2908 return ret;
2909}
2910
2912{
2913 HeapFree(GetProcessHeap(), 0, dm);
2914}
2915
2917{
2918 DEVMODEA *dmA = NULL;
2919 void *src, *dst;
2920 DWORD size;
2921
2922 if(data->unicode)
2923 {
2924 size = dm->dmSize + dm->dmDriverExtra;
2925 src = dm;
2926 }
2927 else
2928 {
2929 dmA = convert_to_devmodeA(dm);
2930 size = dmA->dmSize + dmA->dmDriverExtra;
2931 src = dmA;
2932 }
2933
2934 if(data->u.dlgw->hDevMode)
2935 data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
2937 else
2938 data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
2939
2940 dst = GlobalLock(data->u.dlgw->hDevMode);
2941 memcpy(dst, src, size);
2942 GlobalUnlock(data->u.dlgw->hDevMode);
2943 HeapFree(GetProcessHeap(), 0, dmA);
2944}
2945
2947{
2948 return &data->u.dlgw->ptPaperSize;
2949}
2950
2952{
2953 return &data->u.dlgw->rtMargin;
2954}
2955
2956typedef enum
2957{
2961
2963{
2964 switch(which)
2965 {
2966 case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
2967 case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
2968 }
2969 return NULL;
2970}
2971
2972/* This should only be used in calls to hook procs so we return the ptr
2973 already cast to LPARAM */
2975{
2976 return (LPARAM)data->u.dlgw;
2977}
2978
2979static inline void swap_point(POINT *pt)
2980{
2981 LONG tmp = pt->x;
2982 pt->x = pt->y;
2983 pt->y = tmp;
2984}
2985
2987{
2988 DEVMODEW *dm;
2989 LPWSTR devname, portname;
2990 int i, num;
2991 WORD *words = NULL, paperword;
2992 POINT *points = NULL;
2993 BOOL retval = FALSE;
2994
2996 devname = pagesetup_get_devname(data);
2997 portname = pagesetup_get_portname(data);
2998
2999 num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
3000 if (num <= 0)
3001 {
3002 FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
3003 goto end;
3004 }
3005
3006 words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
3007 points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
3008
3009 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
3010 {
3011 FIXME("Number of returned words is not %d\n", num);
3012 goto end;
3013 }
3014
3015 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
3016 {
3017 FIXME("Number of returned sizes is not %d\n", num);
3018 goto end;
3019 }
3020
3021 paperword = pagesetup_get_papersize(data);
3022
3023 for (i = 0; i < num; i++)
3024 if (words[i] == paperword)
3025 break;
3026
3027 if (i == num)
3028 {
3029 FIXME("Papersize %d not found in list?\n", paperword);
3030 goto end;
3031 }
3032
3033 /* this is _10ths_ of a millimeter */
3036
3039
3040 retval = TRUE;
3041
3042end:
3043 HeapFree(GetProcessHeap(), 0, words);
3048
3049 return retval;
3050}
3051
3052/**********************************************************************************************
3053 * pagesetup_change_printer
3054 *
3055 * Redefines hDevMode and hDevNames HANDLES and initialises it.
3056 *
3057 */
3059{
3060 HANDLE hprn;
3061 DWORD needed;
3062 PRINTER_INFO_2W *prn_info = NULL;
3063 DRIVER_INFO_3W *drv_info = NULL;
3064 DEVMODEW *dm = NULL;
3065 BOOL retval = FALSE;
3066
3067 if(!OpenPrinterW(name, &hprn, NULL))
3068 {
3069 ERR("Can't open printer %s\n", debugstr_w(name));
3070 goto end;
3071 }
3072
3073 GetPrinterW(hprn, 2, NULL, 0, &needed);
3074 prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
3075 GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
3076 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
3077 drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
3078 if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
3079 {
3080 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
3081 goto end;
3082 }
3083 ClosePrinter(hprn);
3084
3085 needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
3086 if(needed == -1)
3087 {
3088 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
3089 goto end;
3090 }
3091
3092 dm = HeapAlloc(GetProcessHeap(), 0, needed);
3094
3097 prn_info->pPortName);
3098
3099 retval = TRUE;
3100end:
3101 HeapFree(GetProcessHeap(), 0, dm);
3102 HeapFree(GetProcessHeap(), 0, prn_info);
3103 HeapFree(GetProcessHeap(), 0, drv_info);
3104 return retval;
3105}
3106
3107/****************************************************************************************
3108 * pagesetup_init_combos
3109 *
3110 * Fills Printers, Paper and Source combos
3111 *
3112 */
3114{
3115 DEVMODEW *dm;
3116 LPWSTR devname, portname;
3117
3119 devname = pagesetup_get_devname(data);
3120 portname = pagesetup_get_portname(data);
3121
3122 PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
3123 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
3124 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
3125
3129}
3130
3131
3132/****************************************************************************************
3133 * pagesetup_change_printer_dialog
3134 *
3135 * Pops up another dialog that lets the user pick another printer.
3136 *
3137 * For now we display the PrintDlg, this should display a striped down version of it.
3138 */
3140{
3141 PRINTDLGW prnt;
3142 LPWSTR drvname, devname, portname;
3143 DEVMODEW *tmp_dm, *dm;
3144
3145 memset(&prnt, 0, sizeof(prnt));
3146 prnt.lStructSize = sizeof(prnt);
3147 prnt.Flags = 0;
3148 prnt.hwndOwner = hDlg;
3149
3150 drvname = pagesetup_get_drvname(data);
3151 devname = pagesetup_get_devname(data);
3152 portname = pagesetup_get_portname(data);
3153 prnt.hDevNames = 0;
3154 PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
3158
3159 tmp_dm = pagesetup_get_devmode(data);
3160 prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3161 dm = GlobalLock(prnt.hDevMode);
3162 memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3163 GlobalUnlock(prnt.hDevMode);
3165
3166 if (PrintDlgW(&prnt))
3167 {
3168 DEVMODEW *dm = GlobalLock(prnt.hDevMode);
3169 DEVNAMES *dn = GlobalLock(prnt.hDevNames);
3170
3172 (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
3174 GlobalUnlock(prnt.hDevNames);
3175 GlobalUnlock(prnt.hDevMode);
3177 }
3178
3179 GlobalFree(prnt.hDevMode);
3180 GlobalFree(prnt.hDevNames);
3181
3182}
3183
3184/******************************************************************************************
3185 * pagesetup_change_preview
3186 *
3187 * Changes paper preview size / position
3188 *
3189 */
3191{
3192 LONG width, height, x, y;
3193 RECT tmp;
3194 const int shadow = 4;
3195
3197 {
3198 width = data->rtDrawRect.right - data->rtDrawRect.left;
3200 }
3201 else
3202 {
3203 height = data->rtDrawRect.bottom - data->rtDrawRect.top;
3205 }
3206 x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
3207 y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
3208 TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3209 wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
3210
3211 MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
3212 MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
3214
3215 tmp = data->rtDrawRect;
3216 tmp.right += shadow;
3217 tmp.bottom += shadow;
3218 InvalidateRect(data->hDlg, &tmp, TRUE);
3219}
3220
3221static inline LONG *element_from_margin_id(RECT *rc, WORD id)
3222{
3223 switch(id)
3224 {
3225 case edt4: return &rc->left;
3226 case edt5: return &rc->top;
3227 case edt6: return &rc->right;
3228 case edt7: return &rc->bottom;
3229 }
3230 return NULL;
3231}
3232
3233static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
3234{
3235 WCHAR str[100];
3236 WORD idx;
3237
3238 for(idx = edt4; idx <= edt7; idx++)
3239 {
3240 if(id == 0 || id == idx)
3241 {
3243 SetDlgItemTextW(hDlg, idx, str);
3244 }
3245 }
3246}
3247
3249{
3250 switch (msg)
3251 {
3252 case EN_CHANGE:
3253 {
3254 WCHAR buf[10];
3255 LONG val = 0;
3257
3258 if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0)
3259 {
3260 WCHAR *end;
3261 WCHAR decimal = get_decimal_sep();
3262
3263 val = wcstol(buf, &end, 10);
3264 if(end != buf || *end == decimal)
3265 {
3266 int mult = is_metric(data) ? 100 : 1000;
3267 val *= mult;
3268 if(*end == decimal)
3269 {
3270 while(mult > 1)
3271 {
3272 end++;
3273 mult /= 10;
3274 if(iswdigit(*end))
3275 val += (*end - '0') * mult;
3276 else
3277 break;
3278 }
3279 }
3280 }
3281 }
3282 *value = val;
3283 return;
3284 }
3285
3286 case EN_KILLFOCUS:
3287 update_margin_edits(hDlg, data, id);
3288 return;
3289 }
3290}
3291
3293{
3294 WCHAR title[256];
3295
3298 SetDlgItemTextW(hDlg, grp4, title);
3299}
3300
3302{
3304 CheckRadioButton(hDlg, rad1, rad2, rad2);
3305 else
3306 CheckRadioButton(hDlg, rad1, rad2, rad1);
3307}
3308
3309/****************************************************************************************
3310 * pagesetup_printer_properties
3311 *
3312 * Handle invocation of the 'Properties' button (not present in the default template).
3313 */
3315{
3316 HANDLE hprn;
3317 LPWSTR devname;
3318 DEVMODEW *dm;
3319 LRESULT count;
3320 int i;
3321
3322 devname = pagesetup_get_devname(data);
3323
3324 if (!OpenPrinterW(devname, &hprn, NULL))
3325 {
3326 FIXME("Call to OpenPrinter did not succeed!\n");
3328 return;
3329 }
3330
3332 DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3336 ClosePrinter(hprn);
3337
3338 /* Changing paper */
3341
3342 /* Changing paper preview */
3344
3345 /* Selecting paper in combo */
3346 count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3347 if(count != CB_ERR)
3348 {
3349 WORD paperword = pagesetup_get_papersize(data);
3350 for(i = 0; i < count; i++)
3351 {
3352 if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3354 break;
3355 }
3356 }
3357 }
3358}
3359
3360/********************************************************************************
3361 * pagesetup_wm_command
3362 * process WM_COMMAND message for PageSetupDlg
3363 *
3364 * PARAMS
3365 * hDlg [in] Main dialog HANDLE
3366 * wParam [in] WM_COMMAND wParam
3367 * lParam [in] WM_COMMAND lParam
3368 * pda [in/out] ptr to PageSetupDataA
3369 */
3370
3372{
3373 WORD msg = HIWORD(wParam);
3374 WORD id = LOWORD(wParam);
3375
3376 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3378 switch (id) {
3379 case IDOK:
3380 EndDialog(hDlg, TRUE);
3381 return TRUE ;
3382
3383 case IDCANCEL:
3384 EndDialog(hDlg, FALSE);
3385 return FALSE ;
3386
3387 case psh3: /* Printer... */
3389 return TRUE;
3390
3391 case rad1: /* Portrait */
3392 case rad2: /* Landscape */
3395 {
3399 update_margin_edits(hDlg, data, 0);
3401 }
3402 break;
3403 case cmb1: /* Printer combo */
3404 if(msg == CBN_SELCHANGE)
3405 {
3406 WCHAR *name;
3407 INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0);
3409 name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
3414 }
3415 break;
3416 case cmb2: /* Paper combo */
3417 if(msg == CBN_SELCHANGE)
3418 {
3419 DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
3420 SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3421 if (paperword != CB_ERR)
3422 {
3423 pagesetup_set_papersize(data, paperword);
3426 } else
3427 FIXME("could not get dialog text for papersize cmbbox?\n");
3428 }
3429 break;
3430 case cmb3: /* Paper Source */
3431 if(msg == CBN_SELCHANGE)
3432 {
3434 SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3436 }
3437 break;
3438 case psh2: /* Printer Properties button */
3440 break;
3441 case edt4:
3442 case edt5:
3443 case edt6:
3444 case edt7:
3445 margin_edit_notification(hDlg, data, msg, id);
3446 break;
3447 }
3449 return FALSE;
3450}
3451
3452/***********************************************************************
3453 * default_page_paint_hook
3454 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3455 * whenever the sample page is redrawn.
3456 */
3458 const pagesetup_data *data)
3459{
3461 HDC hdc = (HDC) wParam;
3462 HPEN hpen, holdpen;
3463 LOGFONTW lf;
3464 HFONT hfont, holdfont;
3465 INT oldbkmode;
3466 TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3467 /* Call user paint hook if enable */
3469 if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
3470 return TRUE;
3471
3472 switch (uMsg) {
3473 /* LPPAGESETUPDLG in lParam */
3475 /* Inform about the sample page rectangle */
3477 /* Inform about the margin rectangle */
3479 return FALSE;
3480
3481 /* Draw dashed rectangle showing margins */
3482 case WM_PSD_MARGINRECT:
3484 holdpen = SelectObject(hdc, hpen);
3486 DeleteObject(SelectObject(hdc, holdpen));
3487 return TRUE;
3488 /* Draw the fake document */
3490 /* select a nice scalable font, because we want the text really small */
3492 lf.lfHeight = 6; /* value chosen based on visual effect */
3494 holdfont = SelectObject(hdc, hfont);
3495
3496 /* if text not loaded, then do so now */
3497 if (wszFakeDocumentText[0] == '\0')
3502
3503 oldbkmode = SetBkMode(hdc, TRANSPARENT);
3505 SetBkMode(hdc, oldbkmode);
3506
3507 DeleteObject(SelectObject(hdc, holdfont));
3508 return TRUE;
3509
3510 /* Envelope stamp */
3512 /* Return address */
3514 FIXME("envelope/stamp is not implemented\n");
3515 return FALSE;
3516 default:
3517 FIXME("Unknown message %x\n",uMsg);
3518 return FALSE;
3519 }
3520 return TRUE;
3521}
3522
3523/***********************************************************************
3524 * PagePaintProc
3525 * The main paint procedure for the PageSetupDlg function.
3526 * The Page Setup dialog box includes an image of a sample page that shows how
3527 * the user's selections affect the appearance of the printed output.
3528 * The image consists of a rectangle that represents the selected paper
3529 * or envelope type, with a dotted-line rectangle representing
3530 * the current margins, and partial (Greek text) characters
3531 * to show how text looks on the printed page.
3532 *
3533 * The following messages in the order sends to user hook procedure:
3534 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3535 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3536 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3537 * WM_PSD_MARGINRECT Draw the margin rectangle
3538 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3539 * If any of first three messages returns TRUE, painting done.
3540 *
3541 * PARAMS:
3542 * hWnd [in] Handle to the Page Setup dialog box
3543 * uMsg [in] Received message
3544 *
3545 * TODO:
3546 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3547 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3548 *
3549 * RETURNS:
3550 * FALSE if all done correctly
3551 *
3552 */
3553
3554
3555static LRESULT CALLBACK
3557{
3558 PAINTSTRUCT ps;
3559 RECT rcClient, rcMargin;
3560 HPEN hpen, holdpen;
3561 HDC hdc;
3562 HBRUSH hbrush, holdbrush;
3564 int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
3565 double scalx, scaly;
3566
3567 if (uMsg != WM_PAINT)
3569
3570 /* Processing WM_PAINT message */
3572 if (!data) {
3573 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3574 return FALSE;
3575 }
3576 if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
3578 return FALSE;
3579
3580 hdc = BeginPaint(hWnd, &ps);
3581 GetClientRect(hWnd, &rcClient);
3582
3583 scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
3584 scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
3585 rcMargin = rcClient;
3586
3587 rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
3588 rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
3589 rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
3590 rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
3591
3592 /* if the space is too small then we make sure to not draw anything */
3593 rcMargin.left = min(rcMargin.left, rcMargin.right);
3594 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3595
3598 {
3599 /* fill background */
3601 FillRect(hdc, &rcClient, hbrush);
3602 holdbrush = SelectObject(hdc, hbrush);
3603
3605 holdpen = SelectObject(hdc, hpen);
3606
3607 /* paint left edge */
3608 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3609 LineTo(hdc, rcClient.left, rcClient.bottom-1);
3610
3611 /* paint top edge */
3612 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3613 LineTo(hdc, rcClient.right, rcClient.top);
3614
3617
3618 /* paint right edge */
3619 MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3620 LineTo(hdc, rcClient.right-1, rcClient.bottom);
3621
3622 /* paint bottom edge */
3623 MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3624 LineTo(hdc, rcClient.right, rcClient.bottom-1);
3625
3626 DeleteObject(SelectObject(hdc, holdpen));
3627 DeleteObject(SelectObject(hdc, holdbrush));
3628
3630
3631 /* give text a bit of a space from the frame */
3632 InflateRect(&rcMargin, -2, -2);
3633
3634 /* if the space is too small then we make sure to not draw anything */
3635 rcMargin.left = min(rcMargin.left, rcMargin.right);
3636 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3637
3639 }
3640
3641 EndPaint(hWnd, &ps);
3642 return FALSE;
3643}
3644
3645/*******************************************************
3646 * The margin edit controls are subclassed to filter
3647 * anything other than numbers and the decimal separator.
3648 */
3650{
3651 if (msg == WM_CHAR)
3652 {
3653 WCHAR decimal = get_decimal_sep();
3654 WCHAR wc = (WCHAR)wparam;
3655 if(!iswdigit(wc) && wc != decimal && wc != VK_BACK) return 0;
3656 }
3658}
3659
3661{
3662 int id;
3664
3665 for(id = edt4; id <= edt7; id++)
3666 {
3671 }
3672}
3673
3674/***********************************************************************
3675 * pagesetup_dlg_proc
3676 *
3677 * Message handler for PageSetupDlg
3678 */
3680{
3682 INT_PTR res = FALSE;
3683 HWND hDrawWnd;
3684
3685 if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3687 data->hDlg = hDlg;
3688
3689 hDrawWnd = GetDlgItem(hDlg, rct1);
3690 TRACE("set property to %p\n", data);
3692 SetPropW(hDrawWnd, pagesetupdlg_prop, data);
3693 GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3694 MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
3696 hDrawWnd,
3699
3700 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3701 res = TRUE;
3703 {
3704 if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
3706 FIXME("Setup page hook failed?\n");
3707 }
3708
3709 /* if printer button disabled */
3712 /* if margin edit boxes disabled */
3714 {
3719 }
3720
3721 /* Set orientation radiobuttons properly */
3723
3724 /* if orientation disabled */
3726 {
3729 }
3730
3731 /* We fill them out enabled or not */
3733 {
3734 /* default is 1 inch */
3737 }
3738 update_margin_edits(hDlg, data, 0);
3741
3742 /* if paper disabled */
3744 {
3747 }