Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comdlg32/printdlg.c
4388 views
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
#include "windef.h"
33
#include "winbase.h"
34
#include "wingdi.h"
35
#include "winuser.h"
36
#include "winspool.h"
37
#include "winerror.h"
38
#include "objbase.h"
39
#include "commdlg.h"
40
41
#include "wine/debug.h"
42
43
#include "dlgs.h"
44
#include "cderr.h"
45
#include "cdlg.h"
46
47
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
48
49
/* Yes these constants are the same, but we're just copying win98 */
50
#define UPDOWN_ID 0x270f
51
#define MAX_COPIES 9999
52
53
/* This PRINTDLGA internal structure stores
54
* pointers to several throughout useful structures.
55
*/
56
57
typedef struct
58
{
59
LPPRINTDLGA lpPrintDlg;
60
LPPRINTER_INFO_2A lpPrinterInfo;
61
LPDRIVER_INFO_3A lpDriverInfo;
62
UINT HelpMessageID;
63
HICON hCollateIcon; /* PrintDlg only */
64
HICON hNoCollateIcon; /* PrintDlg only */
65
HICON hPortraitIcon; /* PrintSetupDlg only */
66
HICON hLandscapeIcon; /* PrintSetupDlg only */
67
HWND hwndUpDown;
68
} PRINT_PTRA;
69
70
typedef struct
71
{
72
LPPRINTDLGW lpPrintDlg;
73
LPPRINTER_INFO_2W lpPrinterInfo;
74
LPDRIVER_INFO_3W lpDriverInfo;
75
UINT HelpMessageID;
76
HICON hCollateIcon; /* PrintDlg only */
77
HICON hNoCollateIcon; /* PrintDlg only */
78
HICON hPortraitIcon; /* PrintSetupDlg only */
79
HICON hLandscapeIcon; /* PrintSetupDlg only */
80
HWND hwndUpDown;
81
} PRINT_PTRW;
82
83
/* Debugging info */
84
struct pd_flags
85
{
86
DWORD flag;
87
LPCSTR name;
88
};
89
90
static const struct pd_flags psd_flags[] = {
91
{PSD_MINMARGINS,"PSD_MINMARGINS"},
92
{PSD_MARGINS,"PSD_MARGINS"},
93
{PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
94
{PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
95
{PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
96
{PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
97
{PSD_NOWARNING,"PSD_NOWARNING"},
98
{PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
99
{PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
100
{PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
101
{PSD_SHOWHELP,"PSD_SHOWHELP"},
102
{PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
103
{PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
104
{PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
105
{PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
106
{PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
107
{-1, NULL}
108
};
109
110
static const struct pd_flags pd_flags[] = {
111
{PD_SELECTION, "PD_SELECTION "},
112
{PD_PAGENUMS, "PD_PAGENUMS "},
113
{PD_NOSELECTION, "PD_NOSELECTION "},
114
{PD_NOPAGENUMS, "PD_NOPAGENUMS "},
115
{PD_COLLATE, "PD_COLLATE "},
116
{PD_PRINTTOFILE, "PD_PRINTTOFILE "},
117
{PD_PRINTSETUP, "PD_PRINTSETUP "},
118
{PD_NOWARNING, "PD_NOWARNING "},
119
{PD_RETURNDC, "PD_RETURNDC "},
120
{PD_RETURNIC, "PD_RETURNIC "},
121
{PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
122
{PD_SHOWHELP, "PD_SHOWHELP "},
123
{PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
124
{PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
125
{PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
126
{PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
127
{PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
128
{PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
129
{PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
130
{PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
131
{PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
132
{PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
133
{-1, NULL}
134
};
135
/* address of wndproc for subclassed Static control */
136
static WNDPROC lpfnStaticWndProc;
137
static WNDPROC edit_wndproc;
138
/* the text of the fake document to render for the Page Setup dialog */
139
static WCHAR wszFakeDocumentText[1024];
140
static const WCHAR printdlg_prop[] = L"__WINE_PRINTDLGDATA";
141
static const WCHAR pagesetupdlg_prop[] = L"__WINE_PAGESETUPDLGDATA";
142
143
144
/***********************************************************************
145
* get_driver_info [internal]
146
*
147
* get DRIVER_INFO_3W for the current printer handle,
148
* alloc the buffer, when needed
149
*/
150
static DRIVER_INFO_3W * get_driver_infoW(HANDLE hprn)
151
{
152
DRIVER_INFO_3W *di3 = NULL;
153
DWORD needed = 0;
154
BOOL res;
155
156
res = GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
157
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
158
di3 = malloc(needed);
159
res = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
160
}
161
162
if (res)
163
return di3;
164
165
TRACE("GetPrinterDriverW failed with %lu\n", GetLastError());
166
free(di3);
167
return NULL;
168
}
169
170
static DRIVER_INFO_3A * get_driver_infoA(HANDLE hprn)
171
{
172
DRIVER_INFO_3A *di3 = NULL;
173
DWORD needed = 0;
174
BOOL res;
175
176
res = GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
177
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
178
di3 = malloc(needed);
179
res = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
180
}
181
182
if (res)
183
return di3;
184
185
TRACE("GetPrinterDriverA failed with %lu\n", GetLastError());
186
free(di3);
187
return NULL;
188
}
189
190
191
/***********************************************************************
192
* get_printer_info [internal]
193
*
194
* get PRINTER_INFO_2W for the current printer handle,
195
* alloc the buffer, when needed
196
*/
197
static PRINTER_INFO_2W * get_printer_infoW(HANDLE hprn)
198
{
199
PRINTER_INFO_2W *pi2 = NULL;
200
DWORD needed = 0;
201
BOOL res;
202
203
res = GetPrinterW(hprn, 2, NULL, 0, &needed);
204
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
205
pi2 = malloc(needed);
206
res = GetPrinterW(hprn, 2, (LPBYTE)pi2, needed, &needed);
207
}
208
209
if (res)
210
return pi2;
211
212
TRACE("GetPrinterW failed with %lu\n", GetLastError());
213
free(pi2);
214
return NULL;
215
}
216
217
static PRINTER_INFO_2A * get_printer_infoA(HANDLE hprn)
218
{
219
PRINTER_INFO_2A *pi2 = NULL;
220
DWORD needed = 0;
221
BOOL res;
222
223
res = GetPrinterA(hprn, 2, NULL, 0, &needed);
224
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
225
pi2 = malloc(needed);
226
res = GetPrinterA(hprn, 2, (LPBYTE)pi2, needed, &needed);
227
}
228
229
if (res)
230
return pi2;
231
232
TRACE("GetPrinterA failed with %lu\n", GetLastError());
233
free(pi2);
234
return NULL;
235
}
236
237
238
/***********************************************************************
239
* update_devmode_handle [internal]
240
*
241
* update a devmode handle for the given DEVMODE, alloc the buffer, when needed
242
*/
243
static HGLOBAL update_devmode_handleW(HGLOBAL hdm, DEVMODEW *dm)
244
{
245
SIZE_T size = GlobalSize(hdm);
246
LPVOID ptr;
247
248
/* Increase / alloc the global memory block, when needed */
249
if ((dm->dmSize + dm->dmDriverExtra) > size) {
250
if (hdm)
251
hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, GMEM_MOVEABLE);
252
else
253
hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
254
}
255
256
if (hdm) {
257
ptr = GlobalLock(hdm);
258
if (ptr) {
259
memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
260
GlobalUnlock(hdm);
261
}
262
else
263
{
264
GlobalFree(hdm);
265
hdm = NULL;
266
}
267
}
268
return hdm;
269
}
270
271
static HGLOBAL update_devmode_handleA(HGLOBAL hdm, DEVMODEA *dm)
272
{
273
SIZE_T size = GlobalSize(hdm);
274
LPVOID ptr;
275
276
/* Increase / alloc the global memory block, when needed */
277
if ((dm->dmSize + dm->dmDriverExtra) > size) {
278
if (hdm)
279
hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, GMEM_MOVEABLE);
280
else
281
hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
282
}
283
284
if (hdm) {
285
ptr = GlobalLock(hdm);
286
if (ptr) {
287
memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
288
GlobalUnlock(hdm);
289
}
290
else
291
{
292
GlobalFree(hdm);
293
hdm = NULL;
294
}
295
}
296
return hdm;
297
}
298
299
/***********************************************************
300
* convert_to_devmodeA
301
*
302
* Creates an ansi copy of supplied devmode
303
*/
304
static DEVMODEA *convert_to_devmodeA(const DEVMODEW *dmW)
305
{
306
DEVMODEA *dmA;
307
DWORD size;
308
309
if (!dmW) return NULL;
310
size = dmW->dmSize - CCHDEVICENAME -
311
((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
312
313
dmA = malloc(size + dmW->dmDriverExtra);
314
if (!dmA) return NULL;
315
316
WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1,
317
(LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
318
319
if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
320
{
321
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
322
dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
323
}
324
else
325
{
326
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
327
FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
328
WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1,
329
(LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
330
331
memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
332
}
333
334
dmA->dmSize = size;
335
memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
336
return dmA;
337
}
338
339
/***********************************************************************
340
* PRINTDLG_OpenDefaultPrinter
341
*
342
* Returns a winspool printer handle to the default printer in *hprn
343
* Caller must call ClosePrinter on the handle
344
*
345
* Returns TRUE on success else FALSE
346
*/
347
static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
348
{
349
WCHAR buf[260];
350
DWORD dwBufLen = ARRAY_SIZE(buf);
351
BOOL res;
352
if(!GetDefaultPrinterW(buf, &dwBufLen))
353
return FALSE;
354
res = OpenPrinterW(buf, hprn, NULL);
355
if (!res)
356
WARN("Could not open printer %s\n", debugstr_w(buf));
357
return res;
358
}
359
360
/***********************************************************************
361
* PRINTDLG_SetUpPrinterListCombo
362
*
363
* Initializes printer list combox.
364
* hDlg: HWND of dialog
365
* id: Control id of combo
366
* name: Name of printer to select
367
*
368
* Initializes combo with list of available printers. Selects printer 'name'
369
* If name is NULL or does not exist select the default printer.
370
*
371
* Returns number of printers added to list.
372
*/
373
static INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
374
{
375
DWORD needed, num;
376
INT i;
377
LPPRINTER_INFO_2A pi;
378
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
379
pi = malloc(needed);
380
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
381
&num);
382
383
SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
384
385
for(i = 0; i < num; i++) {
386
SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
387
(LPARAM)pi[i].pPrinterName );
388
}
389
free(pi);
390
if(!name ||
391
(i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
392
(LPARAM)name)) == CB_ERR) {
393
394
char buf[260];
395
DWORD dwBufLen = ARRAY_SIZE(buf);
396
if (name != NULL)
397
WARN("Can't find %s in printer list so trying to find default\n",
398
debugstr_a(name));
399
if(!GetDefaultPrinterA(buf, &dwBufLen))
400
return num;
401
i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
402
if(i == CB_ERR)
403
FIXME("Can't find default printer in printer list\n");
404
}
405
SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
406
return num;
407
}
408
409
static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
410
{
411
DWORD needed, num;
412
INT i;
413
LPPRINTER_INFO_2W pi;
414
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
415
pi = malloc(needed);
416
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
417
&num);
418
419
for(i = 0; i < num; i++) {
420
SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
421
(LPARAM)pi[i].pPrinterName );
422
}
423
free(pi);
424
if(!name ||
425
(i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
426
(LPARAM)name)) == CB_ERR) {
427
WCHAR buf[260];
428
DWORD dwBufLen = ARRAY_SIZE(buf);
429
if (name != NULL)
430
WARN("Can't find %s in printer list so trying to find default\n",
431
debugstr_w(name));
432
if(!GetDefaultPrinterW(buf, &dwBufLen))
433
return num;
434
i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
435
if(i == CB_ERR)
436
TRACE("Can't find default printer in printer list\n");
437
}
438
SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
439
return num;
440
}
441
442
/***********************************************************************
443
* PRINTDLG_CreateDevNames [internal]
444
*
445
*
446
* creates a DevNames structure.
447
*
448
* (NB. when we handle unicode the offsets will be in wchars).
449
*/
450
static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
451
const char* DeviceName, const char* OutputPort)
452
{
453
long size;
454
char* pDevNamesSpace;
455
char* pTempPtr;
456
LPDEVNAMES lpDevNames;
457
char buf[260];
458
DWORD dwBufLen = ARRAY_SIZE(buf);
459
const char *p;
460
461
p = strrchr( DeviceDriverName, '\\' );
462
if (p) DeviceDriverName = p + 1;
463
464
size = strlen(DeviceDriverName) + 1
465
+ strlen(DeviceName) + 1
466
+ strlen(OutputPort) + 1
467
+ sizeof(DEVNAMES);
468
469
if(*hmem)
470
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
471
else
472
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
473
if (*hmem == 0)
474
return FALSE;
475
476
pDevNamesSpace = GlobalLock(*hmem);
477
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
478
479
pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
480
strcpy(pTempPtr, DeviceDriverName);
481
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
482
483
pTempPtr += strlen(DeviceDriverName) + 1;
484
strcpy(pTempPtr, DeviceName);
485
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
486
487
pTempPtr += strlen(DeviceName) + 1;
488
strcpy(pTempPtr, OutputPort);
489
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
490
491
GetDefaultPrinterA(buf, &dwBufLen);
492
lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
493
GlobalUnlock(*hmem);
494
return TRUE;
495
}
496
497
static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
498
LPCWSTR DeviceName, LPCWSTR OutputPort)
499
{
500
long size;
501
LPWSTR pDevNamesSpace;
502
LPWSTR pTempPtr;
503
LPDEVNAMES lpDevNames;
504
WCHAR bufW[260];
505
DWORD dwBufLen = ARRAY_SIZE(bufW);
506
const WCHAR *p;
507
508
p = wcsrchr( DeviceDriverName, '\\' );
509
if (p) DeviceDriverName = p + 1;
510
511
size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
512
+ sizeof(WCHAR)*lstrlenW(DeviceName) + 2
513
+ sizeof(WCHAR)*lstrlenW(OutputPort) + 2
514
+ sizeof(DEVNAMES);
515
516
if(*hmem)
517
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
518
else
519
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
520
if (*hmem == 0)
521
return FALSE;
522
523
pDevNamesSpace = GlobalLock(*hmem);
524
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
525
526
pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
527
lstrcpyW(pTempPtr, DeviceDriverName);
528
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
529
530
pTempPtr += lstrlenW(DeviceDriverName) + 1;
531
lstrcpyW(pTempPtr, DeviceName);
532
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
533
534
pTempPtr += lstrlenW(DeviceName) + 1;
535
lstrcpyW(pTempPtr, OutputPort);
536
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
537
538
GetDefaultPrinterW(bufW, &dwBufLen);
539
lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
540
GlobalUnlock(*hmem);
541
return TRUE;
542
}
543
544
/***********************************************************************
545
* PRINTDLG_UpdatePrintDlg [internal]
546
*
547
*
548
* updates the PrintDlg structure for return values.
549
*
550
* RETURNS
551
* FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
552
* TRUE if successful.
553
*/
554
static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
555
PRINT_PTRA* PrintStructures)
556
{
557
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
558
PDEVMODEA lpdm = GlobalLock(lppd->hDevMode);
559
LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
560
561
562
if(!lpdm) {
563
FIXME("No lpdm ptr?\n");
564
return FALSE;
565
}
566
567
568
if(!(lppd->Flags & PD_PRINTSETUP)) {
569
/* check whether nFromPage and nToPage are within range defined by
570
* nMinPage and nMaxPage
571
*/
572
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
573
WORD nToPage;
574
WORD nFromPage;
575
BOOL translated;
576
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
577
nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
578
579
/* if no ToPage value is entered, use the FromPage value */
580
if(!translated) nToPage = nFromPage;
581
582
if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
583
nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
584
WCHAR resourcestr[256];
585
WCHAR resultstr[256];
586
LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, resourcestr, 255);
587
wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
588
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
589
MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
590
GlobalUnlock(lppd->hDevMode);
591
return FALSE;
592
}
593
lppd->nFromPage = nFromPage;
594
lppd->nToPage = nToPage;
595
lppd->Flags |= PD_PAGENUMS;
596
}
597
else
598
lppd->Flags &= ~PD_PAGENUMS;
599
600
if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
601
lppd->Flags |= PD_SELECTION;
602
else
603
lppd->Flags &= ~PD_SELECTION;
604
605
if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
606
static char file[] = "FILE:";
607
lppd->Flags |= PD_PRINTTOFILE;
608
pi->pPortName = file;
609
}
610
611
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
612
FIXME("Collate lppd not yet implemented as output\n");
613
}
614
615
/* set PD_Collate and nCopies */
616
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
617
/* The application doesn't support multiple copies or collate...
618
*/
619
lppd->Flags &= ~PD_COLLATE;
620
lppd->nCopies = 1;
621
/* if the printer driver supports it... store info there
622
* otherwise no collate & multiple copies !
623
*/
624
if (lpdm->dmFields & DM_COLLATE)
625
lpdm->dmCollate =
626
(IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
627
if (lpdm->dmFields & DM_COPIES)
628
lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
629
} else {
630
/* Application is responsible for multiple copies */
631
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
632
lppd->Flags |= PD_COLLATE;
633
else
634
lppd->Flags &= ~PD_COLLATE;
635
lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
636
/* multiple copies already included in the document. Driver must print only one copy */
637
lpdm->dmCopies = 1;
638
}
639
640
/* Print quality, PrintDlg16 */
641
if(GetDlgItem(hDlg, cmb1))
642
{
643
HWND hQuality = GetDlgItem(hDlg, cmb1);
644
int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
645
646
if(Sel != CB_ERR)
647
{
648
LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
649
lpdm->dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
650
lpdm->dmPrintQuality = LOWORD(dpi);
651
lpdm->dmYResolution = HIWORD(dpi);
652
}
653
}
654
}
655
GlobalUnlock(lppd->hDevMode);
656
return TRUE;
657
}
658
659
static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
660
PRINT_PTRW* PrintStructures)
661
{
662
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
663
PDEVMODEW lpdm = GlobalLock(lppd->hDevMode);
664
LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
665
666
667
if(!lpdm) {
668
FIXME("No lpdm ptr?\n");
669
return FALSE;
670
}
671
672
673
if(!(lppd->Flags & PD_PRINTSETUP)) {
674
/* check whether nFromPage and nToPage are within range defined by
675
* nMinPage and nMaxPage
676
*/
677
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
678
WORD nToPage;
679
WORD nFromPage;
680
BOOL translated;
681
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
682
nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
683
684
/* if no ToPage value is entered, use the FromPage value */
685
if(!translated) nToPage = nFromPage;
686
687
if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
688
nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
689
WCHAR resourcestr[256];
690
WCHAR resultstr[256];
691
DWORD_PTR args[2];
692
LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
693
resourcestr, 255);
694
args[0] = lppd->nMinPage;
695
args[1] = lppd->nMaxPage;
696
FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
697
resourcestr, 0, 0, resultstr, ARRAY_SIZE(resultstr), (va_list *)args);
698
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
699
resourcestr, 255);
700
MessageBoxW(hDlg, resultstr, resourcestr,
701
MB_OK | MB_ICONWARNING);
702
GlobalUnlock(lppd->hDevMode);
703
return FALSE;
704
}
705
lppd->nFromPage = nFromPage;
706
lppd->nToPage = nToPage;
707
lppd->Flags |= PD_PAGENUMS;
708
}
709
else
710
lppd->Flags &= ~PD_PAGENUMS;
711
712
if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
713
lppd->Flags |= PD_SELECTION;
714
else
715
lppd->Flags &= ~PD_SELECTION;
716
717
if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
718
static WCHAR file[] = L"FILE:";
719
lppd->Flags |= PD_PRINTTOFILE;
720
pi->pPortName = file;
721
}
722
723
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
724
FIXME("Collate lppd not yet implemented as output\n");
725
}
726
727
/* set PD_Collate and nCopies */
728
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
729
/* The application doesn't support multiple copies or collate...
730
*/
731
lppd->Flags &= ~PD_COLLATE;
732
lppd->nCopies = 1;
733
/* if the printer driver supports it... store info there
734
* otherwise no collate & multiple copies !
735
*/
736
if (lpdm->dmFields & DM_COLLATE)
737
lpdm->dmCollate =
738
(IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
739
if (lpdm->dmFields & DM_COPIES)
740
lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
741
} else {
742
/* Application is responsible for multiple copies */
743
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
744
lppd->Flags |= PD_COLLATE;
745
else
746
lppd->Flags &= ~PD_COLLATE;
747
lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
748
/* multiple copies already included in the document. Driver must print only one copy */
749
lpdm->dmCopies = 1;
750
}
751
}
752
GlobalUnlock(lppd->hDevMode);
753
return TRUE;
754
}
755
756
/************************************************************************
757
* PRINTDLG_SetUpPaperComboBox
758
*
759
* Initialize either the papersize or inputslot combos of the Printer Setup
760
* dialog. We store the associated word (eg DMPAPER_A4) as the item data.
761
* We also try to re-select the old selection.
762
*/
763
static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
764
int nIDComboBox,
765
char* PrinterName,
766
char* PortName,
767
LPDEVMODEA dm)
768
{
769
int i;
770
int NrOfEntries;
771
char* Names;
772
WORD* Words;
773
DWORD Sel, old_Sel;
774
WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
775
int NamesSize;
776
int fwCapability_Names;
777
int fwCapability_Words;
778
779
TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
780
781
/* query the dialog box for the current selected value */
782
Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
783
if(Sel != CB_ERR) {
784
/* we enter here only if a different printer is selected after
785
* the Print Setup dialog is opened. The current settings are
786
* stored into the newly selected printer.
787
*/
788
oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
789
Sel, 0);
790
if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
791
oldWord = 0; /* There's no point in trying to keep custom
792
paper / bin sizes across printers */
793
}
794
795
if (dm)
796
newWord = (nIDComboBox == cmb2) ? dm->dmPaperSize : dm->dmDefaultSource;
797
798
if (nIDComboBox == cmb2) {
799
NamesSize = 64;
800
fwCapability_Names = DC_PAPERNAMES;
801
fwCapability_Words = DC_PAPERS;
802
} else {
803
nIDComboBox = cmb3;
804
NamesSize = 24;
805
fwCapability_Names = DC_BINNAMES;
806
fwCapability_Words = DC_BINS;
807
}
808
809
NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
810
fwCapability_Names, NULL, dm);
811
if (NrOfEntries == 0)
812
WARN("no Name Entries found!\n");
813
else if (NrOfEntries < 0)
814
return FALSE;
815
816
if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
817
!= NrOfEntries) {
818
ERR("Number of caps is different\n");
819
NrOfEntries = 0;
820
}
821
822
Names = malloc(NrOfEntries * sizeof(char) * NamesSize);
823
Words = malloc(NrOfEntries * sizeof(WORD));
824
DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Names, Names, dm);
825
NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
826
fwCapability_Words, (LPSTR)Words, dm);
827
828
/* reset any current content in the combobox */
829
SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
830
831
/* store new content */
832
for (i = 0; i < NrOfEntries; i++) {
833
DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
834
(LPARAM)(&Names[i*NamesSize]) );
835
SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
836
Words[i]);
837
}
838
839
/* Look for old selection or the new default.
840
Can't do this is previous loop since item order will change as more items are added */
841
Sel = 0;
842
old_Sel = NrOfEntries;
843
for (i = 0; i < NrOfEntries; i++) {
844
if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
845
oldWord) {
846
old_Sel = i;
847
break;
848
}
849
if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
850
Sel = i;
851
}
852
853
if(old_Sel < NrOfEntries)
854
{
855
if (dm)
856
{
857
if(nIDComboBox == cmb2)
858
dm->dmPaperSize = oldWord;
859
else
860
dm->dmDefaultSource = oldWord;
861
}
862
Sel = old_Sel;
863
}
864
865
SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
866
867
free(Words);
868
free(Names);
869
return TRUE;
870
}
871
872
static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
873
int nIDComboBox,
874
const WCHAR* PrinterName,
875
const WCHAR* PortName,
876
LPDEVMODEW dm)
877
{
878
int i;
879
int NrOfEntries;
880
WCHAR* Names;
881
WORD* Words;
882
DWORD Sel, old_Sel;
883
WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
884
int NamesSize;
885
int fwCapability_Names;
886
int fwCapability_Words;
887
888
TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
889
890
/* query the dialog box for the current selected value */
891
Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
892
if(Sel != CB_ERR) {
893
/* we enter here only if a different printer is selected after
894
* the Print Setup dialog is opened. The current settings are
895
* stored into the newly selected printer.
896
*/
897
oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
898
Sel, 0);
899
900
if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
901
oldWord = 0; /* There's no point in trying to keep custom
902
paper / bin sizes across printers */
903
}
904
905
if (dm)
906
newWord = (nIDComboBox == cmb2) ? dm->dmPaperSize : dm->dmDefaultSource;
907
908
if (nIDComboBox == cmb2) {
909
NamesSize = 64;
910
fwCapability_Names = DC_PAPERNAMES;
911
fwCapability_Words = DC_PAPERS;
912
} else {
913
nIDComboBox = cmb3;
914
NamesSize = 24;
915
fwCapability_Names = DC_BINNAMES;
916
fwCapability_Words = DC_BINS;
917
}
918
919
NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
920
fwCapability_Names, NULL, dm);
921
if (NrOfEntries == 0)
922
WARN("no Name Entries found!\n");
923
else if (NrOfEntries < 0)
924
return FALSE;
925
926
if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
927
!= NrOfEntries) {
928
ERR("Number of caps is different\n");
929
NrOfEntries = 0;
930
}
931
932
Names = malloc(NrOfEntries * sizeof(WCHAR) * NamesSize);
933
Words = malloc(NrOfEntries * sizeof(WORD));
934
DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Names, Names, dm);
935
NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
936
fwCapability_Words, Words, dm);
937
938
/* reset any current content in the combobox */
939
SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
940
941
/* store new content */
942
for (i = 0; i < NrOfEntries; i++) {
943
DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
944
(LPARAM)(&Names[i*NamesSize]) );
945
SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
946
Words[i]);
947
}
948
949
/* Look for old selection or the new default.
950
Can't do this is previous loop since item order will change as more items are added */
951
Sel = 0;
952
old_Sel = NrOfEntries;
953
for (i = 0; i < NrOfEntries; i++) {
954
if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
955
oldWord) {
956
old_Sel = i;
957
break;
958
}
959
if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
960
Sel = i;
961
}
962
963
if(old_Sel < NrOfEntries)
964
{
965
if (dm)
966
{
967
if(nIDComboBox == cmb2)
968
dm->dmPaperSize = oldWord;
969
else
970
dm->dmDefaultSource = oldWord;
971
}
972
Sel = old_Sel;
973
}
974
975
SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
976
977
free(Words);
978
free(Names);
979
return TRUE;
980
}
981
982
983
/***********************************************************************
984
* PRINTDLG_UpdatePrinterInfoTexts [internal]
985
*/
986
static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, DWORD flags, const PRINTER_INFO_2A *pi)
987
{
988
char StatusMsg[256];
989
char ResourceString[256];
990
char printer_name[256];
991
int i;
992
993
/* Status Message */
994
StatusMsg[0]='\0';
995
996
/* add all status messages */
997
for (i = 0; i < 25; i++) {
998
if (pi->Status & (1<<i)) {
999
LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
1000
ResourceString, 255);
1001
strcat(StatusMsg,ResourceString);
1002
}
1003
}
1004
/* append "ready" */
1005
/* FIXME: status==ready must only be appended if really so.
1006
but how to detect? */
1007
LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
1008
ResourceString, 255);
1009
strcat(StatusMsg,ResourceString);
1010
SetDlgItemTextA(hDlg, stc12, StatusMsg);
1011
1012
/* set all other printer info texts */
1013
if (flags & PD_PRINTSETUP)
1014
{
1015
DWORD dwBufLen = ARRAY_SIZE(printer_name);
1016
GetDefaultPrinterA(printer_name, &dwBufLen);
1017
}
1018
else
1019
{
1020
/* FIXME: Windows decorates the printer name with text like 'System Printer' or 'on <port>'. */
1021
lstrcpynA(printer_name, pi->pPrinterName, ARRAY_SIZE(printer_name));
1022
}
1023
SetDlgItemTextA(hDlg, stc1, printer_name);
1024
SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
1025
1026
if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1027
SetDlgItemTextA(hDlg, stc14, pi->pLocation);
1028
else
1029
SetDlgItemTextA(hDlg, stc14, pi->pPortName);
1030
SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
1031
return;
1032
}
1033
1034
static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, DWORD flags, const PRINTER_INFO_2W *pi)
1035
{
1036
WCHAR StatusMsg[256];
1037
WCHAR ResourceString[256];
1038
WCHAR printer_name[256];
1039
int i;
1040
1041
/* Status Message */
1042
StatusMsg[0]='\0';
1043
1044
/* add all status messages */
1045
for (i = 0; i < 25; i++) {
1046
if (pi->Status & (1<<i)) {
1047
LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
1048
ResourceString, 255);
1049
lstrcatW(StatusMsg,ResourceString);
1050
}
1051
}
1052
/* append "ready" */
1053
/* FIXME: status==ready must only be appended if really so.
1054
but how to detect? */
1055
LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
1056
ResourceString, 255);
1057
lstrcatW(StatusMsg,ResourceString);
1058
SetDlgItemTextW(hDlg, stc12, StatusMsg);
1059
1060
/* set all other printer info texts */
1061
if (flags & PD_PRINTSETUP)
1062
{
1063
DWORD dwBufLen = ARRAY_SIZE(printer_name);
1064
GetDefaultPrinterW(printer_name, &dwBufLen);
1065
}
1066
else
1067
{
1068
/* FIXME: Windows decorates the printer name with text like 'System Printer' or 'on <port>'. */
1069
lstrcpynW(printer_name, pi->pPrinterName, ARRAY_SIZE(printer_name));
1070
}
1071
SetDlgItemTextW(hDlg, stc1, printer_name);
1072
SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
1073
if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1074
SetDlgItemTextW(hDlg, stc14, pi->pLocation);
1075
else
1076
SetDlgItemTextW(hDlg, stc14, pi->pPortName);
1077
SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : L"");
1078
}
1079
1080
1081
/*******************************************************************
1082
*
1083
* PRINTDLG_ChangePrinter
1084
*
1085
*/
1086
static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
1087
{
1088
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1089
LPDEVMODEA lpdm, dm_tmp;
1090
LONG dmSize;
1091
DWORD needed;
1092
HANDLE hprn;
1093
1094
free(PrintStructures->lpPrinterInfo);
1095
free(PrintStructures->lpDriverInfo);
1096
if(!OpenPrinterA(name, &hprn, NULL)) {
1097
ERR("Can't open printer %s\n", name);
1098
return FALSE;
1099
}
1100
GetPrinterA(hprn, 2, NULL, 0, &needed);
1101
PrintStructures->lpPrinterInfo = malloc(needed);
1102
GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1103
&needed);
1104
GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1105
PrintStructures->lpDriverInfo = malloc(needed);
1106
if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1107
needed, &needed)) {
1108
ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
1109
return FALSE;
1110
}
1111
ClosePrinter(hprn);
1112
1113
PRINTDLG_UpdatePrinterInfoTextsA(hDlg, lppd->Flags, PrintStructures->lpPrinterInfo);
1114
1115
dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
1116
if(dmSize == -1) {
1117
ERR("DocumentProperties fails on %s\n", debugstr_a(name));
1118
return FALSE;
1119
}
1120
dm_tmp = malloc(dmSize);
1121
dmSize = DocumentPropertiesA(0, 0, name, dm_tmp, NULL,
1122
DM_OUT_BUFFER);
1123
if(lppd->hDevMode)
1124
{
1125
lpdm = GlobalLock(lppd->hDevMode);
1126
if(!lstrcmpA((LPSTR)lpdm->dmDeviceName, (LPSTR)dm_tmp->dmDeviceName))
1127
/* Supplied devicemode matches current printer so try to use it */
1128
DocumentPropertiesA(0, 0, name, dm_tmp, lpdm, DM_OUT_BUFFER | DM_IN_BUFFER);
1129
GlobalUnlock(lppd->hDevMode);
1130
lppd->hDevMode = GlobalReAlloc(lppd->hDevMode, dm_tmp->dmSize + dm_tmp->dmDriverExtra, GMEM_MOVEABLE);
1131
}else
1132
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dm_tmp->dmSize + dm_tmp->dmDriverExtra);
1133
lpdm = GlobalLock(lppd->hDevMode);
1134
memcpy(lpdm, dm_tmp, dm_tmp->dmSize + dm_tmp->dmDriverExtra);
1135
free(dm_tmp);
1136
1137
if(!(lppd->Flags & PD_PRINTSETUP)) {
1138
/* Print range (All/Range/Selection) */
1139
if(lppd->nFromPage != 0xffff)
1140
SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1141
if(lppd->nToPage != 0xffff)
1142
SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1143
1144
CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1145
if (lppd->Flags & PD_NOSELECTION)
1146
EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1147
else
1148
if (lppd->Flags & PD_SELECTION)
1149
CheckRadioButton(hDlg, rad1, rad3, rad2);
1150
if (lppd->Flags & PD_NOPAGENUMS) {
1151
EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1152
EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1153
EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1154
EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1155
EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1156
} else {
1157
if (lppd->Flags & PD_PAGENUMS)
1158
CheckRadioButton(hDlg, rad1, rad3, rad3);
1159
}
1160
1161
/* Collate pages
1162
*
1163
* FIXME: The ico3 is not displayed for some reason. I don't know why.
1164
*/
1165
if (lppd->Flags & PD_COLLATE) {
1166
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1167
(LPARAM)PrintStructures->hCollateIcon);
1168
CheckDlgButton(hDlg, chx2, 1);
1169
} else {
1170
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1171
(LPARAM)PrintStructures->hNoCollateIcon);
1172
CheckDlgButton(hDlg, chx2, 0);
1173
}
1174
1175
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1176
/* if printer doesn't support it: no Collate */
1177
if (!(lpdm->dmFields & DM_COLLATE)) {
1178
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1179
EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1180
}
1181
}
1182
1183
/* nCopies */
1184
{
1185
INT copies;
1186
if (lppd->hDevMode == 0)
1187
copies = lppd->nCopies;
1188
else
1189
copies = lpdm->dmCopies;
1190
if(copies == 0) copies = 1;
1191
else if(copies < 0) copies = MAX_COPIES;
1192
SetDlgItemInt(hDlg, edt3, copies, FALSE);
1193
}
1194
1195
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1196
/* if printer doesn't support it: no nCopies */
1197
if (!(lpdm->dmFields & DM_COPIES)) {
1198
EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1199
EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1200
}
1201
}
1202
1203
/* print to file */
1204
CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1205
if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1206
EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1207
if (lppd->Flags & PD_HIDEPRINTTOFILE)
1208
ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1209
1210
/* Fill print quality combo, PrintDlg16 */
1211
if(GetDlgItem(hDlg, cmb1))
1212
{
1213
DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1214
PrintStructures->lpPrinterInfo->pPortName,
1215
DC_ENUMRESOLUTIONS, NULL, lpdm);
1216
1217
if(numResolutions != -1)
1218
{
1219
HWND hQuality = GetDlgItem(hDlg, cmb1);
1220
LONG* Resolutions;
1221
char buf[255];
1222
DWORD i;
1223
int dpiX, dpiY;
1224
HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
1225
PrintStructures->lpPrinterInfo->pPrinterName,
1226
0, lpdm);
1227
1228
Resolutions = malloc(numResolutions * sizeof(LONG) * 2);
1229
DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1230
PrintStructures->lpPrinterInfo->pPortName,
1231
DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
1232
1233
dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
1234
dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
1235
DeleteDC(hPrinterDC);
1236
1237
SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
1238
for(i = 0; i < (numResolutions * 2); i += 2)
1239
{
1240
BOOL IsDefault = FALSE;
1241
LRESULT Index;
1242
1243
if(Resolutions[i] == Resolutions[i+1])
1244
{
1245
if(dpiX == Resolutions[i])
1246
IsDefault = TRUE;
1247
sprintf(buf, "%ld dpi", Resolutions[i]);
1248
} else
1249
{
1250
if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1251
IsDefault = TRUE;
1252
sprintf(buf, "%ld dpi x %ld dpi", Resolutions[i], Resolutions[i+1]);
1253
}
1254
1255
Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1256
1257
if(IsDefault)
1258
SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1259
1260
SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(Resolutions[i], Resolutions[i+1]));
1261
}
1262
free(Resolutions);
1263
}
1264
}
1265
} else { /* PD_PRINTSETUP */
1266
BOOL bPortrait = (lpdm->dmOrientation == DMORIENT_PORTRAIT);
1267
1268
PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
1269
PrintStructures->lpPrinterInfo->pPrinterName,
1270
PrintStructures->lpPrinterInfo->pPortName,
1271
lpdm);
1272
PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
1273
PrintStructures->lpPrinterInfo->pPrinterName,
1274
PrintStructures->lpPrinterInfo->pPortName,
1275
lpdm);
1276
CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1277
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1278
(LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1279
PrintStructures->hLandscapeIcon));
1280
1281
}
1282
1283
/* help button */
1284
if ((lppd->Flags & PD_SHOWHELP)==0) {
1285
/* hide if PD_SHOWHELP not specified */
1286
ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1287
}
1288
GlobalUnlock(lppd->hDevMode);
1289
return TRUE;
1290
}
1291
1292
static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1293
PRINT_PTRW *PrintStructures)
1294
{
1295
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1296
LPDEVMODEW lpdm, dm_tmp;
1297
LONG dmSize;
1298
DWORD needed;
1299
HANDLE hprn;
1300
1301
free(PrintStructures->lpPrinterInfo);
1302
free(PrintStructures->lpDriverInfo);
1303
if(!OpenPrinterW(name, &hprn, NULL)) {
1304
ERR("Can't open printer %s\n", debugstr_w(name));
1305
return FALSE;
1306
}
1307
GetPrinterW(hprn, 2, NULL, 0, &needed);
1308
PrintStructures->lpPrinterInfo = malloc(needed);
1309
GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1310
&needed);
1311
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1312
PrintStructures->lpDriverInfo = malloc(needed);
1313
if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1314
needed, &needed)) {
1315
ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1316
return FALSE;
1317
}
1318
ClosePrinter(hprn);
1319
1320
PRINTDLG_UpdatePrinterInfoTextsW(hDlg, lppd->Flags, PrintStructures->lpPrinterInfo);
1321
1322
dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1323
if(dmSize == -1) {
1324
ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1325
return FALSE;
1326
}
1327
dm_tmp = malloc(dmSize);
1328
dmSize = DocumentPropertiesW(0, 0, name, dm_tmp, NULL,
1329
DM_OUT_BUFFER);
1330
if(lppd->hDevMode)
1331
{
1332
lpdm = GlobalLock(lppd->hDevMode);
1333
if(!lstrcmpW(lpdm->dmDeviceName, dm_tmp->dmDeviceName))
1334
/* Supplied devicemode matches current printer so try to use it */
1335
DocumentPropertiesW(0, 0, name, dm_tmp, lpdm, DM_OUT_BUFFER | DM_IN_BUFFER);
1336
GlobalUnlock(lppd->hDevMode);
1337
lppd->hDevMode = GlobalReAlloc(lppd->hDevMode, dm_tmp->dmSize + dm_tmp->dmDriverExtra, GMEM_MOVEABLE);
1338
}else
1339
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dm_tmp->dmSize + dm_tmp->dmDriverExtra);
1340
lpdm = GlobalLock(lppd->hDevMode);
1341
memcpy(lpdm, dm_tmp, dm_tmp->dmSize + dm_tmp->dmDriverExtra);
1342
free(dm_tmp);
1343
1344
if(!(lppd->Flags & PD_PRINTSETUP)) {
1345
/* Print range (All/Range/Selection) */
1346
if(lppd->nFromPage != 0xffff)
1347
SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1348
if(lppd->nToPage != 0xffff)
1349
SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1350
1351
CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1352
if (lppd->Flags & PD_NOSELECTION)
1353
EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1354
else
1355
if (lppd->Flags & PD_SELECTION)
1356
CheckRadioButton(hDlg, rad1, rad3, rad2);
1357
if (lppd->Flags & PD_NOPAGENUMS) {
1358
EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1359
EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1360
EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1361
EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1362
EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1363
} else {
1364
if (lppd->Flags & PD_PAGENUMS)
1365
CheckRadioButton(hDlg, rad1, rad3, rad3);
1366
}
1367
1368
/* Collate pages
1369
*
1370
* FIXME: The ico3 is not displayed for some reason. I don't know why.
1371
*/
1372
if (lppd->Flags & PD_COLLATE) {
1373
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1374
(LPARAM)PrintStructures->hCollateIcon);
1375
CheckDlgButton(hDlg, chx2, 1);
1376
} else {
1377
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1378
(LPARAM)PrintStructures->hNoCollateIcon);
1379
CheckDlgButton(hDlg, chx2, 0);
1380
}
1381
1382
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1383
/* if printer doesn't support it: no Collate */
1384
if (!(lpdm->dmFields & DM_COLLATE)) {
1385
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1386
EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1387
}
1388
}
1389
1390
/* nCopies */
1391
{
1392
INT copies;
1393
if (lppd->hDevMode == 0)
1394
copies = lppd->nCopies;
1395
else
1396
copies = lpdm->dmCopies;
1397
if(copies == 0) copies = 1;
1398
else if(copies < 0) copies = MAX_COPIES;
1399
SetDlgItemInt(hDlg, edt3, copies, FALSE);
1400
}
1401
1402
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1403
/* if printer doesn't support it: no nCopies */
1404
if (!(lpdm->dmFields & DM_COPIES)) {
1405
EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1406
EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1407
}
1408
}
1409
1410
/* print to file */
1411
CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1412
if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1413
EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1414
if (lppd->Flags & PD_HIDEPRINTTOFILE)
1415
ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1416
1417
/* Fill print quality combo, PrintDlg16 */
1418
if (GetDlgItem(hDlg, cmb1))
1419
{
1420
DWORD num_resolutions = DeviceCapabilitiesW(PrintStructures->lpPrinterInfo->pPrinterName,
1421
PrintStructures->lpPrinterInfo->pPortName,
1422
DC_ENUMRESOLUTIONS, NULL, lpdm);
1423
1424
if (num_resolutions != -1)
1425
{
1426
HWND quality = GetDlgItem(hDlg, cmb1);
1427
LONG* resolutions;
1428
WCHAR buf[255];
1429
DWORD i;
1430
int dpiX, dpiY;
1431
HDC printer = CreateDCW(PrintStructures->lpPrinterInfo->pDriverName,
1432
PrintStructures->lpPrinterInfo->pPrinterName,
1433
0, lpdm);
1434
1435
resolutions = malloc(num_resolutions * sizeof(LONG) * 2);
1436
DeviceCapabilitiesW(PrintStructures->lpPrinterInfo->pPrinterName,
1437
PrintStructures->lpPrinterInfo->pPortName,
1438
DC_ENUMRESOLUTIONS, (LPWSTR)resolutions, lpdm);
1439
1440
dpiX = GetDeviceCaps(printer, LOGPIXELSX);
1441
dpiY = GetDeviceCaps(printer, LOGPIXELSY);
1442
DeleteDC(printer);
1443
1444
SendMessageW(quality, CB_RESETCONTENT, 0, 0);
1445
for (i = 0; i < (num_resolutions * 2); i += 2)
1446
{
1447
BOOL is_default = FALSE;
1448
LRESULT index;
1449
1450
if (resolutions[i] == resolutions[i+1])
1451
{
1452
if (dpiX == resolutions[i])
1453
is_default = TRUE;
1454
swprintf(buf, sizeof(buf), L"%ld dpi", resolutions[i]);
1455
} else
1456
{
1457
if (dpiX == resolutions[i] && dpiY == resolutions[i+1])
1458
is_default = TRUE;
1459
swprintf(buf, sizeof(buf), L"%ld dpi x %ld dpi", resolutions[i], resolutions[i+1]);
1460
}
1461
1462
index = SendMessageW(quality, CB_ADDSTRING, 0, (LPARAM)buf);
1463
1464
if (is_default)
1465
SendMessageW(quality, CB_SETCURSEL, index, 0);
1466
1467
SendMessageW(quality, CB_SETITEMDATA, index, MAKELONG(resolutions[i], resolutions[i+1]));
1468
}
1469
free(resolutions);
1470
}
1471
}
1472
} else { /* PD_PRINTSETUP */
1473
BOOL bPortrait = (lpdm->dmOrientation == DMORIENT_PORTRAIT);
1474
1475
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1476
PrintStructures->lpPrinterInfo->pPrinterName,
1477
PrintStructures->lpPrinterInfo->pPortName,
1478
lpdm);
1479
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1480
PrintStructures->lpPrinterInfo->pPrinterName,
1481
PrintStructures->lpPrinterInfo->pPortName,
1482
lpdm);
1483
CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1484
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1485
(LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1486
PrintStructures->hLandscapeIcon));
1487
1488
}
1489
1490
/* help button */
1491
if ((lppd->Flags & PD_SHOWHELP)==0) {
1492
/* hide if PD_SHOWHELP not specified */
1493
ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1494
}
1495
GlobalUnlock(lppd->hDevMode);
1496
return TRUE;
1497
}
1498
1499
/***********************************************************************
1500
* check_printer_setup [internal]
1501
*/
1502
static LRESULT check_printer_setup(HWND hDlg)
1503
{
1504
DWORD needed,num;
1505
WCHAR resourcestr[256],resultstr[256];
1506
1507
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1508
if(needed == 0)
1509
{
1510
EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1511
}
1512
if(needed > 0)
1513
return TRUE;
1514
else
1515
{
1516
LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
1517
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1518
MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1519
return FALSE;
1520
}
1521
}
1522
1523
/***********************************************************************
1524
* PRINTDLG_WMInitDialog [internal]
1525
*/
1526
static LRESULT PRINTDLG_WMInitDialog(HWND hDlg,
1527
PRINT_PTRA* PrintStructures)
1528
{
1529
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1530
DEVNAMES *pdn;
1531
DEVMODEA *pdm;
1532
char *name = NULL;
1533
UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1534
1535
/* load Collate ICONs */
1536
/* We load these with LoadImage because they are not a standard
1537
size and we don't want them rescaled */
1538
PrintStructures->hCollateIcon =
1539
LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1540
PrintStructures->hNoCollateIcon =
1541
LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1542
1543
/* These can be done with LoadIcon */
1544
PrintStructures->hPortraitIcon =
1545
LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1546
PrintStructures->hLandscapeIcon =
1547
LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1548
1549
/* display the collate/no_collate icon */
1550
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1551
(LPARAM)PrintStructures->hNoCollateIcon);
1552
1553
if(PrintStructures->hCollateIcon == 0 ||
1554
PrintStructures->hNoCollateIcon == 0 ||
1555
PrintStructures->hPortraitIcon == 0 ||
1556
PrintStructures->hLandscapeIcon == 0) {
1557
ERR("no icon in resource file\n");
1558
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1559
EndDialog(hDlg, FALSE);
1560
}
1561
1562
/*
1563
* if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1564
* must be registered and the Help button must be shown.
1565
*/
1566
if (lppd->Flags & PD_SHOWHELP) {
1567
if((PrintStructures->HelpMessageID =
1568
RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1569
COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1570
return FALSE;
1571
}
1572
} else
1573
PrintStructures->HelpMessageID = 0;
1574
1575
if(!(lppd->Flags &PD_PRINTSETUP)) {
1576
PrintStructures->hwndUpDown =
1577
CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1578
UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1579
UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1580
hDlg, UPDOWN_ID, COMDLG32_hInstance,
1581
GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1582
}
1583
1584
/* FIXME: I allow more freedom than either Win95 or WinNT,
1585
* which do not agree on what errors should be thrown or not
1586
* in case nToPage or nFromPage is out-of-range.
1587
*/
1588
if (lppd->nMaxPage < lppd->nMinPage)
1589
lppd->nMaxPage = lppd->nMinPage;
1590
if (lppd->nMinPage == lppd->nMaxPage)
1591
lppd->Flags |= PD_NOPAGENUMS;
1592
if (lppd->nToPage < lppd->nMinPage)
1593
lppd->nToPage = lppd->nMinPage;
1594
if (lppd->nToPage > lppd->nMaxPage)
1595
lppd->nToPage = lppd->nMaxPage;
1596
if (lppd->nFromPage < lppd->nMinPage)
1597
lppd->nFromPage = lppd->nMinPage;
1598
if (lppd->nFromPage > lppd->nMaxPage)
1599
lppd->nFromPage = lppd->nMaxPage;
1600
1601
/* if we have the combo box, fill it */
1602
if (GetDlgItem(hDlg,comboID)) {
1603
/* Fill Combobox
1604
*/
1605
pdn = GlobalLock(lppd->hDevNames);
1606
pdm = GlobalLock(lppd->hDevMode);
1607
if(pdn)
1608
name = (char*)pdn + pdn->wDeviceOffset;
1609
else if(pdm)
1610
name = (char*)pdm->dmDeviceName;
1611
PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1612
if(pdm) GlobalUnlock(lppd->hDevMode);
1613
if(pdn) GlobalUnlock(lppd->hDevNames);
1614
1615
/* Now find selected printer and update rest of dlg */
1616
name = malloc(256);
1617
if (GetDlgItemTextA(hDlg, comboID, name, 255))
1618
PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1619
free(name);
1620
} else {
1621
/* else use default printer */
1622
char name[200];
1623
DWORD dwBufLen = ARRAY_SIZE(name);
1624
BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1625
1626
if (ret)
1627
PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1628
else
1629
FIXME("No default printer found, expect problems!\n");
1630
}
1631
return TRUE;
1632
}
1633
1634
static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg,
1635
PRINT_PTRW* PrintStructures)
1636
{
1637
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1638
DEVNAMES *pdn;
1639
DEVMODEW *pdm;
1640
WCHAR *name = NULL;
1641
UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1642
1643
/* load Collate ICONs */
1644
/* We load these with LoadImage because they are not a standard
1645
size and we don't want them rescaled */
1646
PrintStructures->hCollateIcon =
1647
LoadImageW(COMDLG32_hInstance, L"PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1648
PrintStructures->hNoCollateIcon =
1649
LoadImageW(COMDLG32_hInstance, L"PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1650
1651
/* These can be done with LoadIcon */
1652
PrintStructures->hPortraitIcon =
1653
LoadIconW(COMDLG32_hInstance, L"PD32_PORTRAIT");
1654
PrintStructures->hLandscapeIcon =
1655
LoadIconW(COMDLG32_hInstance, L"PD32_LANDSCAPE");
1656
1657
/* display the collate/no_collate icon */
1658
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1659
(LPARAM)PrintStructures->hNoCollateIcon);
1660
1661
if(PrintStructures->hCollateIcon == 0 ||
1662
PrintStructures->hNoCollateIcon == 0 ||
1663
PrintStructures->hPortraitIcon == 0 ||
1664
PrintStructures->hLandscapeIcon == 0) {
1665
ERR("no icon in resource file\n");
1666
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1667
EndDialog(hDlg, FALSE);
1668
}
1669
1670
/*
1671
* if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1672
* must be registered and the Help button must be shown.
1673
*/
1674
if (lppd->Flags & PD_SHOWHELP) {
1675
if((PrintStructures->HelpMessageID =
1676
RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1677
COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1678
return FALSE;
1679
}
1680
} else
1681
PrintStructures->HelpMessageID = 0;
1682
1683
if(!(lppd->Flags &PD_PRINTSETUP)) {
1684
PrintStructures->hwndUpDown =
1685
CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1686
UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1687
UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1688
hDlg, UPDOWN_ID, COMDLG32_hInstance,
1689
GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1690
}
1691
1692
/* FIXME: I allow more freedom than either Win95 or WinNT,
1693
* which do not agree to what errors should be thrown or not
1694
* in case nToPage or nFromPage is out-of-range.
1695
*/
1696
if (lppd->nMaxPage < lppd->nMinPage)
1697
lppd->nMaxPage = lppd->nMinPage;
1698
if (lppd->nMinPage == lppd->nMaxPage)
1699
lppd->Flags |= PD_NOPAGENUMS;
1700
if (lppd->nToPage < lppd->nMinPage)
1701
lppd->nToPage = lppd->nMinPage;
1702
if (lppd->nToPage > lppd->nMaxPage)
1703
lppd->nToPage = lppd->nMaxPage;
1704
if (lppd->nFromPage < lppd->nMinPage)
1705
lppd->nFromPage = lppd->nMinPage;
1706
if (lppd->nFromPage > lppd->nMaxPage)
1707
lppd->nFromPage = lppd->nMaxPage;
1708
1709
/* if we have the combo box, fill it */
1710
if (GetDlgItem(hDlg,comboID)) {
1711
/* Fill Combobox
1712
*/
1713
pdn = GlobalLock(lppd->hDevNames);
1714
pdm = GlobalLock(lppd->hDevMode);
1715
if(pdn)
1716
name = (WCHAR*)pdn + pdn->wDeviceOffset;
1717
else if(pdm)
1718
name = pdm->dmDeviceName;
1719
PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1720
if(pdm) GlobalUnlock(lppd->hDevMode);
1721
if(pdn) GlobalUnlock(lppd->hDevNames);
1722
1723
/* Now find selected printer and update rest of dlg */
1724
/* ansi is ok here */
1725
name = malloc(256 * sizeof(WCHAR));
1726
if (GetDlgItemTextW(hDlg, comboID, name, 255))
1727
PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1728
free(name);
1729
} else {
1730
/* else use default printer */
1731
WCHAR name[200];
1732
DWORD dwBufLen = ARRAY_SIZE(name);
1733
BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1734
1735
if (ret)
1736
PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1737
else
1738
FIXME("No default printer found, expect problems!\n");
1739
}
1740
return TRUE;
1741
}
1742
1743
/***********************************************************************
1744
* PRINTDLG_WMCommand [internal]
1745
*/
1746
static LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1747
PRINT_PTRA* PrintStructures)
1748
{
1749
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1750
UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1751
LPDEVMODEA lpdm = GlobalLock(lppd->hDevMode);
1752
1753
switch (LOWORD(wParam)) {
1754
case IDOK:
1755
TRACE(" OK button was hit\n");
1756
if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1757
FIXME("Update printdlg was not successful!\n");
1758
GlobalUnlock(lppd->hDevMode);
1759
return(FALSE);
1760
}
1761
EndDialog(hDlg, TRUE);
1762
GlobalUnlock(lppd->hDevMode);
1763
return(TRUE);
1764
1765
case IDCANCEL:
1766
TRACE(" CANCEL button was hit\n");
1767
EndDialog(hDlg, FALSE);
1768
GlobalUnlock(lppd->hDevMode);
1769
return(FALSE);
1770
1771
case pshHelp:
1772
TRACE(" HELP button was hit\n");
1773
SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1774
(WPARAM) hDlg, (LPARAM) lppd);
1775
break;
1776
1777
case chx2: /* collate pages checkbox */
1778
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1779
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1780
(LPARAM)PrintStructures->hCollateIcon);
1781
else
1782
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1783
(LPARAM)PrintStructures->hNoCollateIcon);
1784
break;
1785
case edt1: /* from page nr editbox */
1786
case edt2: /* to page nr editbox */
1787
if (HIWORD(wParam)==EN_CHANGE) {
1788
WORD nToPage;
1789
WORD nFromPage;
1790
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1791
nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1792
if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1793
CheckRadioButton(hDlg, rad1, rad3, rad3);
1794
}
1795
break;
1796
1797
case edt3:
1798
if(HIWORD(wParam) == EN_CHANGE) {
1799
INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1800
if(copies <= 1)
1801
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1802
else
1803
EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1804
}
1805
break;
1806
1807
case psh1: /* Setup button */
1808
case psh2: /* Properties button */
1809
{
1810
HANDLE hPrinter;
1811
char PrinterName[256];
1812
1813
GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1814
if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1815
FIXME(" Call to OpenPrinter did not succeed!\n");
1816
break;
1817
}
1818
DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1819
lpdm,
1820
lpdm,
1821
DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1822
ClosePrinter(hPrinter);
1823
break;
1824
}
1825
1826
case rad1: /* Paperorientation */
1827
if (lppd->Flags & PD_PRINTSETUP)
1828
{
1829
lpdm->dmOrientation = DMORIENT_PORTRAIT;
1830
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1831
(LPARAM)(PrintStructures->hPortraitIcon));
1832
}
1833
break;
1834
1835
case rad2: /* Paperorientation */
1836
if (lppd->Flags & PD_PRINTSETUP)
1837
{
1838
lpdm->dmOrientation = DMORIENT_LANDSCAPE;
1839
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1840
(LPARAM)(PrintStructures->hLandscapeIcon));
1841
}
1842
break;
1843
1844
case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1845
if (PrinterComboID != LOWORD(wParam)) {
1846
break;
1847
}
1848
/* FALLTHROUGH */
1849
case cmb4: /* Printer combobox */
1850
if (HIWORD(wParam)==CBN_SELCHANGE) {
1851
char *PrinterName;
1852
INT index = SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
1853
INT length = SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
1854
PrinterName = malloc(length + 1);
1855
SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1856
PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1857
free(PrinterName);
1858
}
1859
break;
1860
1861
case cmb2: /* Papersize */
1862
{
1863
DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1864
if(Sel != CB_ERR) {
1865
lpdm->dmPaperSize = SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, Sel, 0);
1866
GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME);
1867
}
1868
}
1869
break;
1870
1871
case cmb3: /* Bin */
1872
{
1873
DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1874
if(Sel != CB_ERR)
1875
lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3, CB_GETITEMDATA, Sel, 0);
1876
}
1877
break;
1878
}
1879
if(lppd->Flags & PD_PRINTSETUP) {
1880
switch (LOWORD(wParam)) {
1881
case rad1: /* orientation */
1882
case rad2:
1883
if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1884
if(lpdm->dmOrientation != DMORIENT_PORTRAIT) {
1885
lpdm->dmOrientation = DMORIENT_PORTRAIT;
1886
SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
1887
(LPARAM)PrintStructures->hPortraitIcon);
1888
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1889
(LPARAM)PrintStructures->hPortraitIcon);
1890
}
1891
} else {
1892
if(lpdm->dmOrientation != DMORIENT_LANDSCAPE) {
1893
lpdm->dmOrientation = DMORIENT_LANDSCAPE;
1894
SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
1895
(LPARAM)PrintStructures->hLandscapeIcon);
1896
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1897
(LPARAM)PrintStructures->hLandscapeIcon);
1898
}
1899
}
1900
break;
1901
}
1902
}
1903
GlobalUnlock(lppd->hDevMode);
1904
return FALSE;
1905
}
1906
1907
static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1908
PRINT_PTRW* PrintStructures)
1909
{
1910
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1911
UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1912
LPDEVMODEW lpdm = GlobalLock(lppd->hDevMode);
1913
1914
switch (LOWORD(wParam)) {
1915
case IDOK:
1916
TRACE(" OK button was hit\n");
1917
if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1918
FIXME("Update printdlg was not successful!\n");
1919
GlobalUnlock(lppd->hDevMode);
1920
return(FALSE);
1921
}
1922
EndDialog(hDlg, TRUE);
1923
GlobalUnlock(lppd->hDevMode);
1924
return(TRUE);
1925
1926
case IDCANCEL:
1927
TRACE(" CANCEL button was hit\n");
1928
EndDialog(hDlg, FALSE);
1929
GlobalUnlock(lppd->hDevMode);
1930
return(FALSE);
1931
1932
case pshHelp:
1933
TRACE(" HELP button was hit\n");
1934
SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1935
(WPARAM) hDlg, (LPARAM) lppd);
1936
break;
1937
1938
case chx2: /* collate pages checkbox */
1939
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1940
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1941
(LPARAM)PrintStructures->hCollateIcon);
1942
else
1943
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1944
(LPARAM)PrintStructures->hNoCollateIcon);
1945
break;
1946
case edt1: /* from page nr editbox */
1947
case edt2: /* to page nr editbox */
1948
if (HIWORD(wParam)==EN_CHANGE) {
1949
WORD nToPage;
1950
WORD nFromPage;
1951
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1952
nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1953
if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1954
CheckRadioButton(hDlg, rad1, rad3, rad3);
1955
}
1956
break;
1957
1958
case edt3:
1959
if(HIWORD(wParam) == EN_CHANGE) {
1960
INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1961
if(copies <= 1)
1962
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1963
else
1964
EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1965
}
1966
break;
1967
1968
case psh1: /* Setup button */
1969
case psh2: /* Properties button */
1970
{
1971
HANDLE hPrinter;
1972
WCHAR PrinterName[256];
1973
1974
if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1975
if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1976
FIXME(" Call to OpenPrinter did not succeed!\n");
1977
break;
1978
}
1979
DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1980
lpdm,
1981
lpdm,
1982
DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1983
ClosePrinter(hPrinter);
1984
break;
1985
}
1986
1987
case rad1: /* Paperorientation */
1988
if (lppd->Flags & PD_PRINTSETUP)
1989
{
1990
lpdm->dmOrientation = DMORIENT_PORTRAIT;
1991
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1992
(LPARAM)(PrintStructures->hPortraitIcon));
1993
}
1994
break;
1995
1996
case rad2: /* Paperorientation */
1997
if (lppd->Flags & PD_PRINTSETUP)
1998
{
1999
lpdm->dmOrientation = DMORIENT_LANDSCAPE;
2000
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
2001
(LPARAM)(PrintStructures->hLandscapeIcon));
2002
}
2003
break;
2004
2005
case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
2006
if (PrinterComboID != LOWORD(wParam)) {
2007
break;
2008
}
2009
/* FALLTHROUGH */
2010
case cmb4: /* Printer combobox */
2011
if (HIWORD(wParam)==CBN_SELCHANGE) {
2012
WCHAR *PrinterName;
2013
INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
2014
INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
2015
2016
PrinterName = malloc(sizeof(WCHAR) * (length + 1));
2017
SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
2018
PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
2019
free(PrinterName);
2020
}
2021
break;
2022
2023
case cmb2: /* Papersize */
2024
{
2025
DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
2026
if(Sel != CB_ERR) {
2027
lpdm->dmPaperSize = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, Sel, 0);
2028
GetDlgItemTextW(hDlg, cmb2, lpdm->dmFormName, CCHFORMNAME);
2029
}
2030
}
2031
break;
2032
2033
case cmb3: /* Bin */
2034
{
2035
DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
2036
if(Sel != CB_ERR)
2037
lpdm->dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA, Sel, 0);
2038
}
2039
break;
2040
}
2041
if(lppd->Flags & PD_PRINTSETUP) {
2042
switch (LOWORD(wParam)) {
2043
case rad1: /* orientation */
2044
case rad2:
2045
if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
2046
if(lpdm->dmOrientation != DMORIENT_PORTRAIT) {
2047
lpdm->dmOrientation = DMORIENT_PORTRAIT;
2048
SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
2049
(LPARAM)PrintStructures->hPortraitIcon);
2050
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
2051
(LPARAM)PrintStructures->hPortraitIcon);
2052
}
2053
} else {
2054
if(lpdm->dmOrientation != DMORIENT_LANDSCAPE) {
2055
lpdm->dmOrientation = DMORIENT_LANDSCAPE;
2056
SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
2057
(LPARAM)PrintStructures->hLandscapeIcon);
2058
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
2059
(LPARAM)PrintStructures->hLandscapeIcon);
2060
}
2061
}
2062
break;
2063
}
2064
}
2065
GlobalUnlock(lppd->hDevMode);
2066
return FALSE;
2067
}
2068
2069
/***********************************************************************
2070
* PrintDlgProcA [internal]
2071
*/
2072
static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
2073
LPARAM lParam)
2074
{
2075
PRINT_PTRA* PrintStructures;
2076
INT_PTR res = FALSE;
2077
2078
if (uMsg!=WM_INITDIALOG) {
2079
PrintStructures = GetPropW(hDlg, printdlg_prop);
2080
if (!PrintStructures)
2081
return FALSE;
2082
} else {
2083
PrintStructures = (PRINT_PTRA*) lParam;
2084
SetPropW(hDlg, printdlg_prop, PrintStructures);
2085
if(!check_printer_setup(hDlg))
2086
{
2087
EndDialog(hDlg,FALSE);
2088
return FALSE;
2089
}
2090
res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
2091
2092
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2093
res = PrintStructures->lpPrintDlg->lpfnPrintHook(
2094
hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
2095
);
2096
return res;
2097
}
2098
2099
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2100
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
2101
lParam);
2102
if(res) return res;
2103
}
2104
2105
switch (uMsg) {
2106
case WM_COMMAND:
2107
return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
2108
2109
case WM_DESTROY:
2110
DestroyIcon(PrintStructures->hCollateIcon);
2111
DestroyIcon(PrintStructures->hNoCollateIcon);
2112
DestroyIcon(PrintStructures->hPortraitIcon);
2113
DestroyIcon(PrintStructures->hLandscapeIcon);
2114
if(PrintStructures->hwndUpDown)
2115
DestroyWindow(PrintStructures->hwndUpDown);
2116
return FALSE;
2117
}
2118
return res;
2119
}
2120
2121
static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
2122
LPARAM lParam)
2123
{
2124
PRINT_PTRW* PrintStructures;
2125
INT_PTR res = FALSE;
2126
2127
if (uMsg!=WM_INITDIALOG) {
2128
PrintStructures = GetPropW(hDlg, printdlg_prop);
2129
if (!PrintStructures)
2130
return FALSE;
2131
} else {
2132
PrintStructures = (PRINT_PTRW*) lParam;
2133
SetPropW(hDlg, printdlg_prop, PrintStructures);
2134
if(!check_printer_setup(hDlg))
2135
{
2136
EndDialog(hDlg,FALSE);
2137
return FALSE;
2138
}
2139
res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
2140
2141
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2142
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
2143
return res;
2144
}
2145
2146
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2147
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
2148
if(res) return res;
2149
}
2150
2151
switch (uMsg) {
2152
case WM_COMMAND:
2153
return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
2154
2155
case WM_DESTROY:
2156
DestroyIcon(PrintStructures->hCollateIcon);
2157
DestroyIcon(PrintStructures->hNoCollateIcon);
2158
DestroyIcon(PrintStructures->hPortraitIcon);
2159
DestroyIcon(PrintStructures->hLandscapeIcon);
2160
if(PrintStructures->hwndUpDown)
2161
DestroyWindow(PrintStructures->hwndUpDown);
2162
return FALSE;
2163
}
2164
return res;
2165
}
2166
2167
/************************************************************
2168
*
2169
* PRINTDLG_GetDlgTemplate
2170
*
2171
*/
2172
static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
2173
{
2174
HRSRC hResInfo;
2175
HGLOBAL hDlgTmpl;
2176
2177
if (lppd->Flags & PD_PRINTSETUP) {
2178
if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2179
hDlgTmpl = lppd->hSetupTemplate;
2180
} else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2181
hResInfo = FindResourceA(lppd->hInstance,
2182
lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
2183
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2184
} else {
2185
hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
2186
(LPSTR)RT_DIALOG);
2187
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2188
}
2189
} else {
2190
if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2191
hDlgTmpl = lppd->hPrintTemplate;
2192
} else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2193
hResInfo = FindResourceA(lppd->hInstance,
2194
lppd->lpPrintTemplateName,
2195
(LPSTR)RT_DIALOG);
2196
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2197
} else {
2198
hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
2199
(LPSTR)RT_DIALOG);
2200
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2201
}
2202
}
2203
return hDlgTmpl;
2204
}
2205
2206
static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
2207
{
2208
HRSRC hResInfo;
2209
HGLOBAL hDlgTmpl;
2210
2211
if (lppd->Flags & PD_PRINTSETUP) {
2212
if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2213
hDlgTmpl = lppd->hSetupTemplate;
2214
} else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2215
hResInfo = FindResourceW(lppd->hInstance,
2216
lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
2217
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2218
} else {
2219
hResInfo = FindResourceW(COMDLG32_hInstance, L"PRINT32_SETUP", (LPWSTR)RT_DIALOG);
2220
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2221
}
2222
} else {
2223
if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2224
hDlgTmpl = lppd->hPrintTemplate;
2225
} else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2226
hResInfo = FindResourceW(lppd->hInstance,
2227
lppd->lpPrintTemplateName,
2228
(LPWSTR)RT_DIALOG);
2229
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2230
} else {
2231
hResInfo = FindResourceW(COMDLG32_hInstance, L"PRINT32", (LPWSTR)RT_DIALOG);
2232
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2233
}
2234
}
2235
return hDlgTmpl;
2236
}
2237
2238
/***********************************************************************
2239
*
2240
* PRINTDLG_CreateDC
2241
*
2242
*/
2243
static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
2244
{
2245
DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2246
DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
2247
2248
if(lppd->Flags & PD_RETURNDC) {
2249
lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
2250
(char*)pdn + pdn->wDeviceOffset,
2251
(char*)pdn + pdn->wOutputOffset,
2252
pdm );
2253
} else if(lppd->Flags & PD_RETURNIC) {
2254
lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
2255
(char*)pdn + pdn->wDeviceOffset,
2256
(char*)pdn + pdn->wOutputOffset,
2257
pdm );
2258
}
2259
GlobalUnlock(lppd->hDevNames);
2260
GlobalUnlock(lppd->hDevMode);
2261
return lppd->hDC != NULL;
2262
}
2263
2264
static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
2265
{
2266
DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2267
DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
2268
2269
if(lppd->Flags & PD_RETURNDC) {
2270
lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
2271
(WCHAR*)pdn + pdn->wDeviceOffset,
2272
(WCHAR*)pdn + pdn->wOutputOffset,
2273
pdm );
2274
} else if(lppd->Flags & PD_RETURNIC) {
2275
lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
2276
(WCHAR*)pdn + pdn->wDeviceOffset,
2277
(WCHAR*)pdn + pdn->wOutputOffset,
2278
pdm );
2279
}
2280
GlobalUnlock(lppd->hDevNames);
2281
GlobalUnlock(lppd->hDevMode);
2282
return lppd->hDC != NULL;
2283
}
2284
2285
/***********************************************************************
2286
* PrintDlgA (COMDLG32.@)
2287
*
2288
* Displays the PRINT dialog box, which enables the user to specify
2289
* specific properties of the print job.
2290
*
2291
* PARAMS
2292
* lppd [IO] ptr to PRINTDLG32 struct
2293
*
2294
* RETURNS
2295
* nonzero if the user pressed the OK button
2296
* zero if the user cancelled the window or an error occurred
2297
*
2298
* BUGS
2299
* PrintDlg:
2300
* * The Collate Icons do not display, even though they are in the code.
2301
* * The Properties Button(s) should call DocumentPropertiesA().
2302
*/
2303
2304
BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
2305
{
2306
BOOL bRet = FALSE;
2307
LPVOID ptr;
2308
HINSTANCE hInst;
2309
2310
if (!lppd)
2311
{
2312
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2313
return FALSE;
2314
}
2315
2316
if(TRACE_ON(commdlg)) {
2317
char flagstr[1000] = "";
2318
const struct pd_flags *pflag = pd_flags;
2319
for( ; pflag->name; pflag++) {
2320
if(lppd->Flags & pflag->flag)
2321
strcat(flagstr, pflag->name);
2322
}
2323
TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2324
"pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2325
"flags %08lx (%s)\n",
2326
lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2327
lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2328
lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2329
}
2330
2331
if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2332
WARN("structure size failure!!!\n");
2333
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2334
return FALSE;
2335
}
2336
2337
if(lppd->Flags & PD_RETURNDEFAULT) {
2338
PRINTER_INFO_2A *pbuf;
2339
DRIVER_INFO_3A *dbuf;
2340
HANDLE hprn;
2341
DWORD needed;
2342
2343
if(lppd->hDevMode || lppd->hDevNames) {
2344
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2345
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2346
return FALSE;
2347
}
2348
if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2349
WARN("Can't find default printer\n");
2350
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2351
return FALSE;
2352
}
2353
2354
GetPrinterA(hprn, 2, NULL, 0, &needed);
2355
pbuf = malloc(needed);
2356
GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2357
2358
GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2359
dbuf = malloc(needed);
2360
if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2361
ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",
2362
GetLastError(),pbuf->pPrinterName);
2363
free(dbuf);
2364
free(pbuf);
2365
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2366
return FALSE;
2367
}
2368
ClosePrinter(hprn);
2369
2370
PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2371
dbuf->pDriverPath,
2372
pbuf->pPrinterName,
2373
pbuf->pPortName);
2374
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2375
pbuf->pDevMode->dmDriverExtra);
2376
ptr = GlobalLock(lppd->hDevMode);
2377
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2378
pbuf->pDevMode->dmDriverExtra);
2379
GlobalUnlock(lppd->hDevMode);
2380
free(pbuf);
2381
free(dbuf);
2382
bRet = TRUE;
2383
} else {
2384
HGLOBAL hDlgTmpl;
2385
PRINT_PTRA *PrintStructures;
2386
2387
/* load Dialog resources,
2388
* depending on Flags indicates Print32 or Print32_setup dialog
2389
*/
2390
hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2391
if (!hDlgTmpl) {
2392
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2393
return FALSE;
2394
}
2395
ptr = LockResource( hDlgTmpl );
2396
if (!ptr) {
2397
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2398
return FALSE;
2399
}
2400
2401
PrintStructures = calloc(1, sizeof(PRINT_PTRA));
2402
PrintStructures->lpPrintDlg = lppd;
2403
2404
/* and create & process the dialog .
2405
* -1 is failure, 0 is broken hwnd, everything else is ok.
2406
*/
2407
hInst = COMDLG32_hInstance;
2408
if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2409
bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2410
PrintDlgProcA,
2411
(LPARAM)PrintStructures));
2412
2413
if(bRet) {
2414
PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2415
DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2416
2417
PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2418
di->pDriverPath,
2419
pi->pPrinterName,
2420
pi->pPortName
2421
);
2422
GlobalUnlock(lppd->hDevMode);
2423
}
2424
free(PrintStructures->lpPrinterInfo);
2425
free(PrintStructures->lpDriverInfo);
2426
free(PrintStructures);
2427
}
2428
if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2429
bRet = PRINTDLG_CreateDCA(lppd);
2430
2431
TRACE("exit! (%d)\n", bRet);
2432
return bRet;
2433
}
2434
2435
/***********************************************************************
2436
* PrintDlgW (COMDLG32.@)
2437
*
2438
* See PrintDlgA.
2439
*/
2440
BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
2441
{
2442
BOOL bRet = FALSE;
2443
LPVOID ptr;
2444
HINSTANCE hInst;
2445
2446
if (!lppd)
2447
{
2448
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2449
return FALSE;
2450
}
2451
2452
if(TRACE_ON(commdlg)) {
2453
char flagstr[1000] = "";
2454
const struct pd_flags *pflag = pd_flags;
2455
for( ; pflag->name; pflag++) {
2456
if(lppd->Flags & pflag->flag)
2457
strcat(flagstr, pflag->name);
2458
}
2459
TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2460
"pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2461
"flags %08lx (%s)\n",
2462
lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2463
lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2464
lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2465
}
2466
2467
if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2468
WARN("structure size failure!!!\n");
2469
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2470
return FALSE;
2471
}
2472
2473
if(lppd->Flags & PD_RETURNDEFAULT) {
2474
PRINTER_INFO_2W *pbuf;
2475
DRIVER_INFO_3W *dbuf;
2476
HANDLE hprn;
2477
DWORD needed;
2478
2479
if(lppd->hDevMode || lppd->hDevNames) {
2480
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2481
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2482
return FALSE;
2483
}
2484
if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2485
WARN("Can't find default printer\n");
2486
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2487
return FALSE;
2488
}
2489
2490
GetPrinterW(hprn, 2, NULL, 0, &needed);
2491
pbuf = malloc(needed);
2492
GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2493
2494
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2495
dbuf = malloc(needed);
2496
if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2497
ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",
2498
GetLastError(),debugstr_w(pbuf->pPrinterName));
2499
free(dbuf);
2500
free(pbuf);
2501
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2502
return FALSE;
2503
}
2504
ClosePrinter(hprn);
2505
2506
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2507
dbuf->pDriverPath,
2508
pbuf->pPrinterName,
2509
pbuf->pPortName);
2510
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2511
pbuf->pDevMode->dmDriverExtra);
2512
ptr = GlobalLock(lppd->hDevMode);
2513
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2514
pbuf->pDevMode->dmDriverExtra);
2515
GlobalUnlock(lppd->hDevMode);
2516
free(pbuf);
2517
free(dbuf);
2518
bRet = TRUE;
2519
} else {
2520
HGLOBAL hDlgTmpl;
2521
PRINT_PTRW *PrintStructures;
2522
2523
/* load Dialog resources,
2524
* depending on Flags indicates Print32 or Print32_setup dialog
2525
*/
2526
hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2527
if (!hDlgTmpl) {
2528
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2529
return FALSE;
2530
}
2531
ptr = LockResource( hDlgTmpl );
2532
if (!ptr) {
2533
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2534
return FALSE;
2535
}
2536
2537
PrintStructures = calloc(1, sizeof(PRINT_PTRW));
2538
PrintStructures->lpPrintDlg = lppd;
2539
2540
/* and create & process the dialog .
2541
* -1 is failure, 0 is broken hwnd, everything else is ok.
2542
*/
2543
hInst = COMDLG32_hInstance;
2544
if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2545
bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2546
PrintDlgProcW,
2547
(LPARAM)PrintStructures));
2548
2549
if(bRet) {
2550
PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2551
DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2552
2553
if (lppd->hDevNames != 0) {
2554
WORD locks;
2555
if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2556
WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2557
while(locks--)
2558
GlobalUnlock(lppd->hDevNames);
2559
}
2560
}
2561
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2562
di->pDriverPath,
2563
pi->pPrinterName,
2564
pi->pPortName
2565
);
2566
GlobalUnlock(lppd->hDevMode);
2567
}
2568
free(PrintStructures->lpPrinterInfo);
2569
free(PrintStructures->lpDriverInfo);
2570
free(PrintStructures);
2571
}
2572
if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2573
bRet = PRINTDLG_CreateDCW(lppd);
2574
2575
TRACE("exit! (%d)\n", bRet);
2576
return bRet;
2577
}
2578
2579
/***********************************************************************
2580
*
2581
* PageSetupDlg
2582
* rad1 - portrait
2583
* rad2 - landscape
2584
* cmb1 - printer select (not in standard dialog template)
2585
* cmb2 - paper size
2586
* cmb3 - source (tray?)
2587
* edt4 - border left
2588
* edt5 - border top
2589
* edt6 - border right
2590
* edt7 - border bottom
2591
* psh3 - "Printer..."
2592
*/
2593
2594
typedef struct
2595
{
2596
BOOL unicode;
2597
union
2598
{
2599
LPPAGESETUPDLGA dlga;
2600
LPPAGESETUPDLGW dlgw;
2601
} u;
2602
HWND hDlg; /* Page Setup dialog handle */
2603
RECT rtDrawRect; /* Drawing rect for page */
2604
} pagesetup_data;
2605
2606
static inline DWORD pagesetup_get_flags(const pagesetup_data *data)
2607
{
2608
return data->u.dlgw->Flags;
2609
}
2610
2611
static inline BOOL is_metric(const pagesetup_data *data)
2612
{
2613
return pagesetup_get_flags(data) & PSD_INHUNDREDTHSOFMILLIMETERS;
2614
}
2615
2616
static inline LONG tenths_mm_to_size(const pagesetup_data *data, LONG size)
2617
{
2618
if (is_metric(data))
2619
return 10 * size;
2620
else
2621
return 10 * size * 100 / 254;
2622
}
2623
2624
static inline LONG thousandths_inch_to_size(const pagesetup_data *data, LONG size)
2625
{
2626
if (is_metric(data))
2627
return size * 254 / 100;
2628
else
2629
return size;
2630
}
2631
2632
static WCHAR get_decimal_sep(void)
2633
{
2634
static WCHAR sep;
2635
2636
if(!sep)
2637
{
2638
WCHAR buf[] = L".";
2639
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, ARRAY_SIZE(buf));
2640
sep = buf[0];
2641
}
2642
return sep;
2643
}
2644
2645
static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
2646
{
2647
/* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2648
2649
if (is_metric(data))
2650
{
2651
if(size % 100)
2652
wsprintfW(strout, L"%d%c%02d", size / 100, get_decimal_sep(), size % 100);
2653
else
2654
wsprintfW(strout, L"%d", size / 100);
2655
}
2656
else
2657
{
2658
if(size % 1000)
2659
wsprintfW(strout, L"%d%c%03d", size / 1000, get_decimal_sep(), size % 1000);
2660
else
2661
wsprintfW(strout, L"%d", size / 1000);
2662
2663
}
2664
}
2665
2666
static inline BOOL is_default_metric(void)
2667
{
2668
DWORD system;
2669
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2670
(LPWSTR)&system, sizeof(system));
2671
return system == 0;
2672
}
2673
2674
/**********************************************
2675
* rotate_rect
2676
* Cyclically permute the four members of rc
2677
* If sense is TRUE l -> t -> r -> b
2678
* otherwise l <- t <- r <- b
2679
*/
2680
static inline void rotate_rect(RECT *rc, BOOL sense)
2681
{
2682
INT tmp;
2683
if(sense)
2684
{
2685
tmp = rc->bottom;
2686
rc->bottom = rc->right;
2687
rc->right = rc->top;
2688
rc->top = rc->left;
2689
rc->left = tmp;
2690
}
2691
else
2692
{
2693
tmp = rc->left;
2694
rc->left = rc->top;
2695
rc->top = rc->right;
2696
rc->right = rc->bottom;
2697
rc->bottom = tmp;
2698
}
2699
}
2700
2701
static void pagesetup_set_orientation(pagesetup_data *data, WORD orient)
2702
{
2703
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2704
2705
assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2706
2707
if(data->unicode)
2708
dm->dmOrientation = orient;
2709
else
2710
{
2711
DEVMODEA *dmA = (DEVMODEA *)dm;
2712
dmA->dmOrientation = orient;
2713
}
2714
GlobalUnlock(data->u.dlgw->hDevMode);
2715
}
2716
2717
static WORD pagesetup_get_orientation(const pagesetup_data *data)
2718
{
2719
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2720
WORD orient;
2721
2722
if(data->unicode)
2723
orient = dm->dmOrientation;
2724
else
2725
{
2726
DEVMODEA *dmA = (DEVMODEA *)dm;
2727
orient = dmA->dmOrientation;
2728
}
2729
GlobalUnlock(data->u.dlgw->hDevMode);
2730
return orient;
2731
}
2732
2733
static void pagesetup_set_papersize(pagesetup_data *data, WORD paper)
2734
{
2735
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2736
2737
if(data->unicode)
2738
dm->dmPaperSize = paper;
2739
else
2740
{
2741
DEVMODEA *dmA = (DEVMODEA *)dm;
2742
dmA->dmPaperSize = paper;
2743
}
2744
GlobalUnlock(data->u.dlgw->hDevMode);
2745
}
2746
2747
static WORD pagesetup_get_papersize(const pagesetup_data *data)
2748
{
2749
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2750
WORD paper;
2751
2752
if(data->unicode)
2753
paper = dm->dmPaperSize;
2754
else
2755
{
2756
DEVMODEA *dmA = (DEVMODEA *)dm;
2757
paper = dmA->dmPaperSize;
2758
}
2759
GlobalUnlock(data->u.dlgw->hDevMode);
2760
return paper;
2761
}
2762
2763
static void pagesetup_set_defaultsource(pagesetup_data *data, WORD source)
2764
{
2765
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2766
2767
if(data->unicode)
2768
dm->dmDefaultSource = source;
2769
else
2770
{
2771
DEVMODEA *dmA = (DEVMODEA *)dm;
2772
dmA->dmDefaultSource = source;
2773
}
2774
GlobalUnlock(data->u.dlgw->hDevMode);
2775
}
2776
2777
typedef enum
2778
{
2779
devnames_driver_name,
2780
devnames_device_name,
2781
devnames_output_name
2782
} devnames_name;
2783
2784
2785
static inline WORD get_devname_offset(const DEVNAMES *dn, devnames_name which)
2786
{
2787
switch(which)
2788
{
2789
case devnames_driver_name: return dn->wDriverOffset;
2790
case devnames_device_name: return dn->wDeviceOffset;
2791
case devnames_output_name: return dn->wOutputOffset;
2792
}
2793
ERR("Shouldn't be here\n");
2794
return 0;
2795
}
2796
2797
static WCHAR *pagesetup_get_a_devname(const pagesetup_data *data, devnames_name which)
2798
{
2799
DEVNAMES *dn;
2800
WCHAR *name;
2801
2802
dn = GlobalLock(data->u.dlgw->hDevNames);
2803
if(data->unicode)
2804
name = wcsdup((WCHAR *)dn + get_devname_offset(dn, which));
2805
else
2806
{
2807
int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
2808
name = malloc(len * sizeof(WCHAR));
2809
MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
2810
}
2811
GlobalUnlock(data->u.dlgw->hDevNames);
2812
return name;
2813
}
2814
2815
static WCHAR *pagesetup_get_drvname(const pagesetup_data *data)
2816
{
2817
return pagesetup_get_a_devname(data, devnames_driver_name);
2818
}
2819
2820
static WCHAR *pagesetup_get_devname(const pagesetup_data *data)
2821
{
2822
return pagesetup_get_a_devname(data, devnames_device_name);
2823
}
2824
2825
static WCHAR *pagesetup_get_portname(const pagesetup_data *data)
2826
{
2827
return pagesetup_get_a_devname(data, devnames_output_name);
2828
}
2829
2830
static void pagesetup_release_a_devname(const pagesetup_data *data, WCHAR *name)
2831
{
2832
free(name);
2833
}
2834
2835
static void pagesetup_set_devnames(pagesetup_data *data, LPCWSTR drv, LPCWSTR devname, LPCWSTR port)
2836
{
2837
DEVNAMES *dn;
2838
WCHAR def[256];
2839
DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
2840
2841
if(data->unicode)
2842
{
2843
drv_len = (lstrlenW(drv) + 1) * sizeof(WCHAR);
2844
dev_len = (lstrlenW(devname) + 1) * sizeof(WCHAR);
2845
port_len = (lstrlenW(port) + 1) * sizeof(WCHAR);
2846
}
2847
else
2848
{
2849
drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
2850
dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
2851
port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
2852
}
2853
len += drv_len + dev_len + port_len;
2854
2855
if(data->u.dlgw->hDevNames)
2856
data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
2857
else
2858
data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
2859
2860
dn = GlobalLock(data->u.dlgw->hDevNames);
2861
2862
if(data->unicode)
2863
{
2864
WCHAR *ptr = (WCHAR *)(dn + 1);
2865
len = sizeof(DEVNAMES) / sizeof(WCHAR);
2866
dn->wDriverOffset = len;
2867
lstrcpyW(ptr, drv);
2868
ptr += drv_len / sizeof(WCHAR);
2869
len += drv_len / sizeof(WCHAR);
2870
dn->wDeviceOffset = len;
2871
lstrcpyW(ptr, devname);
2872
ptr += dev_len / sizeof(WCHAR);
2873
len += dev_len / sizeof(WCHAR);
2874
dn->wOutputOffset = len;
2875
lstrcpyW(ptr, port);
2876
}
2877
else
2878
{
2879
char *ptr = (char *)(dn + 1);
2880
len = sizeof(DEVNAMES);
2881
dn->wDriverOffset = len;
2882
WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
2883
ptr += drv_len;
2884
len += drv_len;
2885
dn->wDeviceOffset = len;
2886
WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
2887
ptr += dev_len;
2888
len += dev_len;
2889
dn->wOutputOffset = len;
2890
WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
2891
}
2892
2893
dn->wDefault = 0;
2894
len = ARRAY_SIZE(def);
2895
GetDefaultPrinterW(def, &len);
2896
if(!lstrcmpW(def, devname))
2897
dn->wDefault = 1;
2898
2899
GlobalUnlock(data->u.dlgw->hDevNames);
2900
}
2901
2902
static DEVMODEW *pagesetup_get_devmode(const pagesetup_data *data)
2903
{
2904
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2905
DEVMODEW *ret;
2906
2907
if(data->unicode)
2908
{
2909
/* We make a copy even in the unicode case because the ptr
2910
may get passed back to us in pagesetup_set_devmode. */
2911
ret = malloc(dm->dmSize + dm->dmDriverExtra);
2912
memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
2913
}
2914
else
2915
ret = GdiConvertToDevmodeW((DEVMODEA *)dm);
2916
2917
GlobalUnlock(data->u.dlgw->hDevMode);
2918
return ret;
2919
}
2920
2921
static void pagesetup_release_devmode(const pagesetup_data *data, DEVMODEW *dm)
2922
{
2923
free(dm);
2924
}
2925
2926
static void pagesetup_set_devmode(pagesetup_data *data, DEVMODEW *dm)
2927
{
2928
DEVMODEA *dmA = NULL;
2929
void *src, *dst;
2930
DWORD size;
2931
2932
if(data->unicode)
2933
{
2934
size = dm->dmSize + dm->dmDriverExtra;
2935
src = dm;
2936
}
2937
else
2938
{
2939
dmA = convert_to_devmodeA(dm);
2940
size = dmA->dmSize + dmA->dmDriverExtra;
2941
src = dmA;
2942
}
2943
2944
if(data->u.dlgw->hDevMode)
2945
data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
2946
GMEM_MOVEABLE);
2947
else
2948
data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
2949
2950
dst = GlobalLock(data->u.dlgw->hDevMode);
2951
memcpy(dst, src, size);
2952
GlobalUnlock(data->u.dlgw->hDevMode);
2953
free(dmA);
2954
}
2955
2956
static inline POINT *pagesetup_get_papersize_pt(const pagesetup_data *data)
2957
{
2958
return &data->u.dlgw->ptPaperSize;
2959
}
2960
2961
static inline RECT *pagesetup_get_margin_rect(const pagesetup_data *data)
2962
{
2963
return &data->u.dlgw->rtMargin;
2964
}
2965
2966
typedef enum
2967
{
2968
page_setup_hook,
2969
page_paint_hook
2970
} hook_type;
2971
2972
static inline LPPAGESETUPHOOK pagesetup_get_hook(const pagesetup_data *data, hook_type which)
2973
{
2974
switch(which)
2975
{
2976
case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
2977
case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
2978
}
2979
return NULL;
2980
}
2981
2982
/* This should only be used in calls to hook procs so we return the ptr
2983
already cast to LPARAM */
2984
static inline LPARAM pagesetup_get_dlg_struct(const pagesetup_data *data)
2985
{
2986
return (LPARAM)data->u.dlgw;
2987
}
2988
2989
static inline void swap_point(POINT *pt)
2990
{
2991
LONG tmp = pt->x;
2992
pt->x = pt->y;
2993
pt->y = tmp;
2994
}
2995
2996
static BOOL pagesetup_update_papersize(pagesetup_data *data)
2997
{
2998
DEVMODEW *dm;
2999
LPWSTR devname, portname;
3000
int i, num;
3001
WORD *words = NULL, paperword;
3002
POINT *points = NULL;
3003
BOOL retval = FALSE;
3004
3005
dm = pagesetup_get_devmode(data);
3006
devname = pagesetup_get_devname(data);
3007
portname = pagesetup_get_portname(data);
3008
3009
num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
3010
if (num <= 0)
3011
{
3012
FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
3013
goto end;
3014
}
3015
3016
words = malloc(num * sizeof(WORD));
3017
points = malloc(num * sizeof(POINT));
3018
3019
if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
3020
{
3021
FIXME("Number of returned words is not %d\n", num);
3022
goto end;
3023
}
3024
3025
if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
3026
{
3027
FIXME("Number of returned sizes is not %d\n", num);
3028
goto end;
3029
}
3030
3031
paperword = pagesetup_get_papersize(data);
3032
3033
for (i = 0; i < num; i++)
3034
if (words[i] == paperword)
3035
break;
3036
3037
if (i == num)
3038
{
3039
FIXME("Papersize %d not found in list?\n", paperword);
3040
goto end;
3041
}
3042
3043
/* this is _10ths_ of a millimeter */
3044
pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x);
3045
pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y);
3046
3047
if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3048
swap_point(pagesetup_get_papersize_pt(data));
3049
3050
retval = TRUE;
3051
3052
end:
3053
free(words);
3054
free(points);
3055
pagesetup_release_a_devname(data, portname);
3056
pagesetup_release_a_devname(data, devname);
3057
pagesetup_release_devmode(data, dm);
3058
3059
return retval;
3060
}
3061
3062
/**********************************************************************************************
3063
* pagesetup_change_printer
3064
*
3065
* Redefines hDevMode and hDevNames HANDLES and initialises it.
3066
*
3067
*/
3068
static BOOL pagesetup_change_printer(LPWSTR name, pagesetup_data *data)
3069
{
3070
HANDLE hprn;
3071
DWORD needed;
3072
PRINTER_INFO_2W *prn_info = NULL;
3073
DRIVER_INFO_3W *drv_info = NULL;
3074
DEVMODEW *dm = NULL;
3075
BOOL retval = FALSE;
3076
3077
if(!OpenPrinterW(name, &hprn, NULL))
3078
{
3079
ERR("Can't open printer %s\n", debugstr_w(name));
3080
goto end;
3081
}
3082
3083
GetPrinterW(hprn, 2, NULL, 0, &needed);
3084
prn_info = malloc(needed);
3085
GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
3086
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
3087
drv_info = malloc(needed);
3088
if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
3089
{
3090
ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
3091
goto end;
3092
}
3093
ClosePrinter(hprn);
3094
3095
needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
3096
if(needed == -1)
3097
{
3098
ERR("DocumentProperties fails on %s\n", debugstr_w(name));
3099
goto end;
3100
}
3101
3102
dm = malloc(needed);
3103
DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER);
3104
3105
pagesetup_set_devmode(data, dm);
3106
pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
3107
prn_info->pPortName);
3108
3109
retval = TRUE;
3110
end:
3111
free(dm);
3112
free(prn_info);
3113
free(drv_info);
3114
return retval;
3115
}
3116
3117
/****************************************************************************************
3118
* pagesetup_init_combos
3119
*
3120
* Fills Printers, Paper and Source combos
3121
*
3122
*/
3123
static void pagesetup_init_combos(HWND hDlg, pagesetup_data *data)
3124
{
3125
DEVMODEW *dm;
3126
LPWSTR devname, portname;
3127
3128
dm = pagesetup_get_devmode(data);
3129
devname = pagesetup_get_devname(data);
3130
portname = pagesetup_get_portname(data);
3131
3132
PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
3133
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
3134
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
3135
3136
pagesetup_release_a_devname(data, portname);
3137
pagesetup_release_a_devname(data, devname);
3138
pagesetup_release_devmode(data, dm);
3139
}
3140
3141
3142
/****************************************************************************************
3143
* pagesetup_change_printer_dialog
3144
*
3145
* Pops up another dialog that lets the user pick another printer.
3146
*
3147
* For now we display the PrintDlg, this should display a striped down version of it.
3148
*/
3149
static void pagesetup_change_printer_dialog(HWND hDlg, pagesetup_data *data)
3150
{
3151
PRINTDLGW prnt;
3152
LPWSTR drvname, devname, portname;
3153
DEVMODEW *tmp_dm, *dm;
3154
3155
memset(&prnt, 0, sizeof(prnt));
3156
prnt.lStructSize = sizeof(prnt);
3157
prnt.Flags = 0;
3158
prnt.hwndOwner = hDlg;
3159
3160
drvname = pagesetup_get_drvname(data);
3161
devname = pagesetup_get_devname(data);
3162
portname = pagesetup_get_portname(data);
3163
prnt.hDevNames = 0;
3164
PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
3165
pagesetup_release_a_devname(data, portname);
3166
pagesetup_release_a_devname(data, devname);
3167
pagesetup_release_a_devname(data, drvname);
3168
3169
tmp_dm = pagesetup_get_devmode(data);
3170
prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3171
dm = GlobalLock(prnt.hDevMode);
3172
memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3173
GlobalUnlock(prnt.hDevMode);
3174
pagesetup_release_devmode(data, tmp_dm);
3175
3176
if (PrintDlgW(&prnt))
3177
{
3178
DEVMODEW *dm = GlobalLock(prnt.hDevMode);
3179
DEVNAMES *dn = GlobalLock(prnt.hDevNames);
3180
3181
pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset,
3182
(WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
3183
pagesetup_set_devmode(data, dm);
3184
GlobalUnlock(prnt.hDevNames);
3185
GlobalUnlock(prnt.hDevMode);
3186
pagesetup_init_combos(hDlg, data);
3187
}
3188
3189
GlobalFree(prnt.hDevMode);
3190
GlobalFree(prnt.hDevNames);
3191
3192
}
3193
3194
/******************************************************************************************
3195
* pagesetup_change_preview
3196
*
3197
* Changes paper preview size / position
3198
*
3199
*/
3200
static void pagesetup_change_preview(const pagesetup_data *data)
3201
{
3202
LONG width, height, x, y;
3203
RECT tmp;
3204
const int shadow = 4;
3205
3206
if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3207
{
3208
width = data->rtDrawRect.right - data->rtDrawRect.left;
3209
height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x;
3210
}
3211
else
3212
{
3213
height = data->rtDrawRect.bottom - data->rtDrawRect.top;
3214
width = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y;
3215
}
3216
x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
3217
y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
3218
TRACE("draw rect %s x=%ld, y=%ld, w=%ld, h=%ld\n",
3219
wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
3220
3221
MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
3222
MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
3223
MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
3224
3225
tmp = data->rtDrawRect;
3226
tmp.right += shadow;
3227
tmp.bottom += shadow;
3228
InvalidateRect(data->hDlg, &tmp, TRUE);
3229
}
3230
3231
static inline LONG *element_from_margin_id(RECT *rc, WORD id)
3232
{
3233
switch(id)
3234
{
3235
case edt4: return &rc->left;
3236
case edt5: return &rc->top;
3237
case edt6: return &rc->right;
3238
case edt7: return &rc->bottom;
3239
}
3240
return NULL;
3241
}
3242
3243
static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
3244
{
3245
WCHAR str[100];
3246
WORD idx;
3247
3248
for(idx = edt4; idx <= edt7; idx++)
3249
{
3250
if(id == 0 || id == idx)
3251
{
3252
size2str(data, *element_from_margin_id(pagesetup_get_margin_rect(data), idx), str);
3253
SetDlgItemTextW(hDlg, idx, str);
3254
}
3255
}
3256
}
3257
3258
static void margin_edit_notification(HWND hDlg, const pagesetup_data *data, WORD msg, WORD id)
3259
{
3260
switch (msg)
3261
{
3262
case EN_CHANGE:
3263
{
3264
WCHAR buf[10];
3265
LONG val = 0;
3266
LONG *value = element_from_margin_id(pagesetup_get_margin_rect(data), id);
3267
3268
if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0)
3269
{
3270
WCHAR *end;
3271
WCHAR decimal = get_decimal_sep();
3272
3273
val = wcstol(buf, &end, 10);
3274
if(end != buf || *end == decimal)
3275
{
3276
int mult = is_metric(data) ? 100 : 1000;
3277
val *= mult;
3278
if(*end == decimal)
3279
{
3280
while(mult > 1)
3281
{
3282
end++;
3283
mult /= 10;
3284
if(iswdigit(*end))
3285
val += (*end - '0') * mult;
3286
else
3287
break;
3288
}
3289
}
3290
}
3291
}
3292
*value = val;
3293
return;
3294
}
3295
3296
case EN_KILLFOCUS:
3297
update_margin_edits(hDlg, data, id);
3298
return;
3299
}
3300
}
3301
3302
static void set_margin_groupbox_title(HWND hDlg, const pagesetup_data *data)
3303
{
3304
WCHAR title[256];
3305
3306
if(LoadStringW(COMDLG32_hInstance, is_metric(data) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES,
3307
title, ARRAY_SIZE(title)))
3308
SetDlgItemTextW(hDlg, grp4, title);
3309
}
3310
3311
static void pagesetup_update_orientation_buttons(HWND hDlg, const pagesetup_data *data)
3312
{
3313
if (pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3314
CheckRadioButton(hDlg, rad1, rad2, rad2);
3315
else
3316
CheckRadioButton(hDlg, rad1, rad2, rad1);
3317
}
3318
3319
/****************************************************************************************
3320
* pagesetup_printer_properties
3321
*
3322
* Handle invocation of the 'Properties' button (not present in the default template).
3323
*/
3324
static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data)
3325
{
3326
HANDLE hprn;
3327
LPWSTR devname;
3328
DEVMODEW *dm;
3329
LRESULT count;
3330
int i;
3331
3332
devname = pagesetup_get_devname(data);
3333
3334
if (!OpenPrinterW(devname, &hprn, NULL))
3335
{
3336
FIXME("Call to OpenPrinter did not succeed!\n");
3337
pagesetup_release_a_devname(data, devname);
3338
return;
3339
}
3340
3341
dm = pagesetup_get_devmode(data);
3342
DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3343
pagesetup_set_devmode(data, dm);
3344
pagesetup_release_devmode(data, dm);
3345
pagesetup_release_a_devname(data, devname);
3346
ClosePrinter(hprn);
3347
3348
/* Changing paper */
3349
pagesetup_update_papersize(data);
3350
pagesetup_update_orientation_buttons(hDlg, data);
3351
3352
/* Changing paper preview */
3353
pagesetup_change_preview(data);
3354
3355
/* Selecting paper in combo */
3356
count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3357
if(count != CB_ERR)
3358
{
3359
WORD paperword = pagesetup_get_papersize(data);
3360
for(i = 0; i < count; i++)
3361
{
3362
if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3363
SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
3364
break;
3365
}
3366
}
3367
}
3368
}
3369
3370
/********************************************************************************
3371
* pagesetup_wm_command
3372
* process WM_COMMAND message for PageSetupDlg
3373
*
3374
* PARAMS
3375
* hDlg [in] Main dialog HANDLE
3376
* wParam [in] WM_COMMAND wParam
3377
* lParam [in] WM_COMMAND lParam
3378
* pda [in/out] ptr to PageSetupDataA
3379
*/
3380
3381
static BOOL pagesetup_wm_command(HWND hDlg, WPARAM wParam, LPARAM lParam, pagesetup_data *data)
3382
{
3383
WORD msg = HIWORD(wParam);
3384
WORD id = LOWORD(wParam);
3385
3386
TRACE("loword (lparam) %d, wparam 0x%Ix, lparam %08Ix\n",
3387
LOWORD(lParam),wParam,lParam);
3388
switch (id) {
3389
case IDOK:
3390
EndDialog(hDlg, TRUE);
3391
return TRUE ;
3392
3393
case IDCANCEL:
3394
EndDialog(hDlg, FALSE);
3395
return FALSE ;
3396
3397
case psh3: /* Printer... */
3398
pagesetup_change_printer_dialog(hDlg, data);
3399
return TRUE;
3400
3401
case rad1: /* Portrait */
3402
case rad2: /* Landscape */
3403
if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) ||
3404
(id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT))
3405
{
3406
pagesetup_set_orientation(data, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
3407
pagesetup_update_papersize(data);
3408
rotate_rect(pagesetup_get_margin_rect(data), (id == rad2));
3409
update_margin_edits(hDlg, data, 0);
3410
pagesetup_change_preview(data);
3411
}
3412
break;
3413
case cmb1: /* Printer combo */
3414
if(msg == CBN_SELCHANGE)
3415
{
3416
WCHAR *name;
3417
INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0);
3418
INT length = SendDlgItemMessageW(hDlg, id, CB_GETLBTEXTLEN, index, 0);
3419
name = malloc(sizeof(WCHAR) * (length + 1));
3420
SendDlgItemMessageW(hDlg, id, CB_GETLBTEXT, index, (LPARAM)name);
3421
pagesetup_change_printer(name, data);
3422
pagesetup_init_combos(hDlg, data);
3423
free(name);
3424
}
3425
break;
3426
case cmb2: /* Paper combo */
3427
if(msg == CBN_SELCHANGE)
3428
{
3429
DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
3430
SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3431
if (paperword != CB_ERR)
3432
{
3433
pagesetup_set_papersize(data, paperword);
3434
pagesetup_update_papersize(data);
3435
pagesetup_change_preview(data);
3436
} else
3437
FIXME("could not get dialog text for papersize cmbbox?\n");
3438
}
3439
break;
3440
case cmb3: /* Paper Source */
3441
if(msg == CBN_SELCHANGE)
3442
{
3443
WORD source = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA,
3444
SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3445
pagesetup_set_defaultsource(data, source);
3446
}
3447
break;
3448
case psh2: /* Printer Properties button */
3449
pagesetup_printer_properties(hDlg, data);
3450
break;
3451
case edt4:
3452
case edt5:
3453
case edt6:
3454
case edt7:
3455
margin_edit_notification(hDlg, data, msg, id);
3456
break;
3457
}
3458
InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
3459
return FALSE;
3460
}
3461
3462
/***********************************************************************
3463
* default_page_paint_hook
3464
* Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3465
* whenever the sample page is redrawn.
3466
*/
3467
static UINT_PTR default_page_paint_hook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
3468
const pagesetup_data *data)
3469
{
3470
LPRECT lprc = (LPRECT) lParam;
3471
HDC hdc = (HDC) wParam;
3472
HPEN hpen, holdpen;
3473
LOGFONTW lf;
3474
HFONT hfont, holdfont;
3475
INT oldbkmode;
3476
TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3477
/* Call user paint hook if enable */
3478
if (pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK)
3479
if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
3480
return TRUE;
3481
3482
switch (uMsg) {
3483
/* LPPAGESETUPDLG in lParam */
3484
case WM_PSD_PAGESETUPDLG:
3485
/* Inform about the sample page rectangle */
3486
case WM_PSD_FULLPAGERECT:
3487
/* Inform about the margin rectangle */
3488
case WM_PSD_MINMARGINRECT:
3489
return FALSE;
3490
3491
/* Draw dashed rectangle showing margins */
3492
case WM_PSD_MARGINRECT:
3493
hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
3494
holdpen = SelectObject(hdc, hpen);
3495
Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
3496
DeleteObject(SelectObject(hdc, holdpen));
3497
return TRUE;
3498
/* Draw the fake document */
3499
case WM_PSD_GREEKTEXTRECT:
3500
/* select a nice scalable font, because we want the text really small */
3501
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3502
lf.lfHeight = 6; /* value chosen based on visual effect */
3503
hfont = CreateFontIndirectW(&lf);
3504
holdfont = SelectObject(hdc, hfont);
3505
3506
/* if text not loaded, then do so now */
3507
if (wszFakeDocumentText[0] == '\0')
3508
LoadStringW(COMDLG32_hInstance,
3509
IDS_FAKEDOCTEXT,
3510
wszFakeDocumentText,
3511
ARRAY_SIZE(wszFakeDocumentText));
3512
3513
oldbkmode = SetBkMode(hdc, TRANSPARENT);
3514
DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
3515
SetBkMode(hdc, oldbkmode);
3516
3517
DeleteObject(SelectObject(hdc, holdfont));
3518
return TRUE;
3519
3520
/* Envelope stamp */
3521
case WM_PSD_ENVSTAMPRECT:
3522
/* Return address */
3523
case WM_PSD_YAFULLPAGERECT:
3524
FIXME("envelope/stamp is not implemented\n");
3525
return FALSE;
3526
default:
3527
FIXME("Unknown message %x\n",uMsg);
3528
return FALSE;
3529
}
3530
return TRUE;
3531
}
3532
3533
/***********************************************************************
3534
* PagePaintProc
3535
* The main paint procedure for the PageSetupDlg function.
3536
* The Page Setup dialog box includes an image of a sample page that shows how
3537
* the user's selections affect the appearance of the printed output.
3538
* The image consists of a rectangle that represents the selected paper
3539
* or envelope type, with a dotted-line rectangle representing
3540
* the current margins, and partial (Greek text) characters
3541
* to show how text looks on the printed page.
3542
*
3543
* The following messages in the order sends to user hook procedure:
3544
* WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3545
* WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3546
* WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3547
* WM_PSD_MARGINRECT Draw the margin rectangle
3548
* WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3549
* If any of first three messages returns TRUE, painting done.
3550
*
3551
* PARAMS:
3552
* hWnd [in] Handle to the Page Setup dialog box
3553
* uMsg [in] Received message
3554
*
3555
* TODO:
3556
* WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3557
* WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3558
*
3559
* RETURNS:
3560
* FALSE if all done correctly
3561
*
3562
*/
3563
3564
3565
static LRESULT CALLBACK
3566
PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3567
{
3568
PAINTSTRUCT ps;
3569
RECT rcClient, rcMargin;
3570
HPEN hpen, holdpen;
3571
HDC hdc;
3572
HBRUSH hbrush, holdbrush;
3573
pagesetup_data *data;
3574
int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
3575
double scalx, scaly;
3576
3577
if (uMsg != WM_PAINT)
3578
return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3579
3580
/* Processing WM_PAINT message */
3581
data = GetPropW(hWnd, pagesetupdlg_prop);
3582
if (!data) {
3583
WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3584
return FALSE;
3585
}
3586
if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
3587
pagesetup_get_dlg_struct(data), data))
3588
return FALSE;
3589
3590
hdc = BeginPaint(hWnd, &ps);
3591
GetClientRect(hWnd, &rcClient);
3592
3593
scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
3594
scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
3595
rcMargin = rcClient;
3596
3597
rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
3598
rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
3599
rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
3600
rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
3601
3602
/* if the space is too small then we make sure to not draw anything */
3603
rcMargin.left = min(rcMargin.left, rcMargin.right);
3604
rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3605
3606
if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) &&
3607
!default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) )
3608
{
3609
/* fill background */
3610
hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3611
FillRect(hdc, &rcClient, hbrush);
3612
holdbrush = SelectObject(hdc, hbrush);
3613
3614
hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3615
holdpen = SelectObject(hdc, hpen);
3616
3617
/* paint left edge */
3618
MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3619
LineTo(hdc, rcClient.left, rcClient.bottom-1);
3620
3621
/* paint top edge */
3622
MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3623
LineTo(hdc, rcClient.right, rcClient.top);
3624
3625
hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3626
DeleteObject(SelectObject(hdc, hpen));
3627
3628
/* paint right edge */
3629
MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3630
LineTo(hdc, rcClient.right-1, rcClient.bottom);
3631
3632
/* paint bottom edge */
3633
MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3634
LineTo(hdc, rcClient.right, rcClient.bottom-1);
3635
3636
DeleteObject(SelectObject(hdc, holdpen));
3637
DeleteObject(SelectObject(hdc, holdbrush));
3638
3639
default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3640
3641
/* give text a bit of a space from the frame */
3642
InflateRect(&rcMargin, -2, -2);
3643
3644
/* if the space is too small then we make sure to not draw anything */
3645
rcMargin.left = min(rcMargin.left, rcMargin.right);
3646
rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3647
3648
default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3649
}
3650
3651
EndPaint(hWnd, &ps);
3652
return FALSE;
3653
}
3654
3655
/*******************************************************
3656
* The margin edit controls are subclassed to filter
3657
* anything other than numbers and the decimal separator.
3658
*/
3659
static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3660
{
3661
if (msg == WM_CHAR)
3662
{
3663
WCHAR decimal = get_decimal_sep();
3664
WCHAR wc = (WCHAR)wparam;
3665
if(!iswdigit(wc) && wc != decimal && wc != VK_BACK) return 0;
3666
}
3667
return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
3668
}
3669
3670
static void subclass_margin_edits(HWND hDlg)
3671
{
3672
int id;
3673
WNDPROC old_proc;
3674
3675
for(id = edt4; id <= edt7; id++)
3676
{
3677
old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
3678
GWLP_WNDPROC,
3679
(ULONG_PTR)pagesetup_margin_editproc);
3680
InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL);
3681
}
3682
}
3683
3684
/***********************************************************************
3685
* pagesetup_dlg_proc
3686
*
3687
* Message handler for PageSetupDlg
3688
*/
3689
static INT_PTR CALLBACK pagesetup_dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3690
{
3691
pagesetup_data *data;
3692
INT_PTR res = FALSE;
3693
HWND hDrawWnd;
3694
3695
if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3696
data = (pagesetup_data *)lParam;
3697
data->hDlg = hDlg;
3698
3699
hDrawWnd = GetDlgItem(hDlg, rct1);
3700
TRACE("set property to %p\n", data);
3701
SetPropW(hDlg, pagesetupdlg_prop, data);
3702
SetPropW(hDrawWnd, pagesetupdlg_prop, data);
3703
GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3704
MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
3705
lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3706
hDrawWnd,
3707
GWLP_WNDPROC,
3708
(ULONG_PTR)PRINTDLG_PagePaintProc);
3709
3710
/* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3711
res = TRUE;
3712
if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
3713
{
3714
if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
3715
pagesetup_get_dlg_struct(data)))
3716
FIXME("Setup page hook failed?\n");
3717
}
3718
3719
/* if printer button disabled */
3720
if (pagesetup_get_flags(data) & PSD_DISABLEPRINTER)
3721
EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3722
/* if margin edit boxes disabled */
3723
if (pagesetup_get_flags(data) & PSD_DISABLEMARGINS)
3724
{
3725
EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3726
EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3727
EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3728
EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3729
}
3730
3731
/* Set orientation radiobuttons properly */
3732
pagesetup_update_orientation_buttons(hDlg, data);
3733
3734
/* if orientation disabled */
3735
if (pagesetup_get_flags(data) & PSD_DISABLEORIENTATION)
3736
{
3737
EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3738
EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3739
}
3740
3741
/* We fill them out enabled or not */
3742
if (!(pagesetup_get_flags(data) & PSD_MARGINS))
3743
{
3744
/* default is 1 inch */
3745
LONG size = thousandths_inch_to_size(data, 1000);
3746
SetRect(pagesetup_get_margin_rect(data), size, size, size, size);
3747
}
3748
update_margin_edits(hDlg, data, 0);
3749
subclass_margin_edits(hDlg);
3750
set_margin_groupbox_title(hDlg, data);
3751
3752
/* if paper disabled */
3753
if (pagesetup_get_flags(data) & PSD_DISABLEPAPER)
3754
{
3755
EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3756
EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3757
}
3758
3759
/* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3760
pagesetup_init_combos(hDlg, data);
3761
pagesetup_update_papersize(data);
3762
pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
3763
3764
/* Drawing paper prev */
3765
pagesetup_change_preview(data);
3766
return TRUE;
3767
} else {
3768
data = GetPropW(hDlg, pagesetupdlg_prop);
3769
if (!data)
3770
{
3771
WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3772
return FALSE;
3773
}
3774
if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
3775
{
3776
res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam);
3777
if (res) return res;
3778
}
3779
}
3780
switch (uMsg) {
3781
case WM_COMMAND:
3782
return pagesetup_wm_command(hDlg, wParam, lParam, data);
3783
}
3784
return FALSE;
3785
}
3786
3787
static WCHAR *get_default_printer(void)
3788
{
3789
WCHAR *name = NULL;
3790
DWORD len = 0;
3791
3792
GetDefaultPrinterW(NULL, &len);
3793
if(len)
3794
{
3795
name = malloc(len * sizeof(WCHAR));
3796
GetDefaultPrinterW(name, &len);
3797
}
3798
return name;
3799
}
3800
3801
static void pagesetup_dump_dlg_struct(const pagesetup_data *data)
3802
{
3803
if(TRACE_ON(commdlg))
3804
{
3805
char flagstr[1000] = "";
3806
const struct pd_flags *pflag = psd_flags;
3807
for( ; pflag->name; pflag++)
3808
{
3809
if(pagesetup_get_flags(data) & pflag->flag)
3810
{
3811
strcat(flagstr, pflag->name);
3812
strcat(flagstr, "|");
3813
}
3814
}
3815
TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3816
"hinst %p, flags %08lx (%s)\n",
3817
data->unicode ? "unicode" : "ansi",
3818
data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
3819
data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
3820
pagesetup_get_flags(data), flagstr);
3821
}
3822
}
3823
3824
static void *pagesetup_get_template(pagesetup_data *data)
3825
{
3826
HRSRC res;
3827
HGLOBAL tmpl_handle;
3828
3829
if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE)
3830
{
3831
tmpl_handle = data->u.dlgw->hPageSetupTemplate;
3832
}
3833
else if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATE)
3834
{
3835
if(data->unicode)
3836
res = FindResourceW(data->u.dlgw->hInstance,
3837
data->u.dlgw->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
3838
else
3839
res = FindResourceA(data->u.dlga->hInstance,
3840
data->u.dlga->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
3841
tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
3842
}
3843
else
3844
{
3845
res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD),
3846
(LPWSTR)RT_DIALOG);
3847
tmpl_handle = LoadResource(COMDLG32_hInstance, res);
3848
}
3849
return LockResource(tmpl_handle);
3850
}
3851
3852
static BOOL pagesetup_common(pagesetup_data *data)
3853
{
3854
BOOL ret;
3855
void *tmpl;
3856
3857
if(!pagesetup_get_dlg_struct(data))
3858
{
3859
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3860
return FALSE;
3861
}
3862
3863
pagesetup_dump_dlg_struct(data);
3864
3865
if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
3866
{
3867
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3868
return FALSE;
3869
}
3870
3871
if ((pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) &&
3872
(pagesetup_get_hook(data, page_paint_hook) == NULL))
3873
{
3874
COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3875
return FALSE;
3876
}
3877
3878
if(!(pagesetup_get_flags(data) & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
3879
data->u.dlgw->Flags |= is_default_metric() ?
3880
PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES;
3881
3882
if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
3883
{
3884
WCHAR *def = get_default_printer();
3885
if(!def)
3886
{
3887
if (!(pagesetup_get_flags(data) & PSD_NOWARNING))
3888
{
3889
WCHAR errstr[256];
3890
LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3891
MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3892
}
3893
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
3894
return FALSE;
3895
}
3896
pagesetup_change_printer(def, data);
3897
free(def);
3898
}
3899
3900
if (pagesetup_get_flags(data) & PSD_RETURNDEFAULT)
3901
{
3902
pagesetup_update_papersize(data);
3903
return TRUE;
3904
}
3905
3906
tmpl = pagesetup_get_template(data);
3907
3908
ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
3909
data->u.dlgw->hwndOwner,
3910
pagesetup_dlg_proc, (LPARAM)data) > 0;
3911
return ret;
3912
}
3913
3914
/***********************************************************************
3915
* PageSetupDlgA (COMDLG32.@)
3916
*
3917
* Displays the PAGE SETUP dialog box, which enables the user to specify
3918
* specific properties of a printed page such as
3919
* size, source, orientation and the width of the page margins.
3920
*
3921
* PARAMS
3922
* setupdlg [IO] PAGESETUPDLGA struct
3923
*
3924
* RETURNS
3925
* TRUE if the user pressed the OK button
3926
* FALSE if the user cancelled the window or an error occurred
3927
*
3928
* NOTES
3929
* The values of hDevMode and hDevNames are filled on output and can be
3930
* changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3931
*
3932
*/
3933
BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg)
3934
{
3935
pagesetup_data data;
3936
3937
data.unicode = FALSE;
3938
data.u.dlga = setupdlg;
3939
3940
return pagesetup_common(&data);
3941
}
3942
3943
/***********************************************************************
3944
* PageSetupDlgW (COMDLG32.@)
3945
*
3946
* See PageSetupDlgA.
3947
*/
3948
BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg)
3949
{
3950
pagesetup_data data;
3951
3952
data.unicode = TRUE;
3953
data.u.dlgw = setupdlg;
3954
3955
return pagesetup_common(&data);
3956
}
3957
3958
static void pdlgex_to_pdlg(const PRINTDLGEXW *pdlgex, PRINTDLGW *pdlg)
3959
{
3960
pdlg->lStructSize = sizeof(*pdlg);
3961
pdlg->hwndOwner = pdlgex->hwndOwner;
3962
pdlg->hDevMode = pdlgex->hDevMode;
3963
pdlg->hDevNames = pdlgex->hDevNames;
3964
pdlg->hDC = pdlgex->hDC;
3965
pdlg->Flags = pdlgex->Flags;
3966
if ((pdlgex->Flags & PD_NOPAGENUMS) || !pdlgex->nPageRanges || !pdlgex->lpPageRanges)
3967
{
3968
pdlg->nFromPage = 0;
3969
pdlg->nToPage = 65534;
3970
}
3971
else
3972
{
3973
pdlg->nFromPage = pdlgex->lpPageRanges[0].nFromPage;
3974
pdlg->nToPage = pdlgex->lpPageRanges[0].nToPage;
3975
}
3976
pdlg->nMinPage = pdlgex->nMinPage;
3977
pdlg->nMaxPage = pdlgex->nMaxPage;
3978
pdlg->nCopies = pdlgex->nCopies;
3979
pdlg->hInstance = pdlgex->hInstance;
3980
pdlg->lCustData = 0;
3981
pdlg->lpfnPrintHook = NULL;
3982
pdlg->lpfnSetupHook = NULL;
3983
pdlg->lpPrintTemplateName = pdlgex->lpPrintTemplateName;
3984
pdlg->lpSetupTemplateName = NULL;
3985
pdlg->hPrintTemplate = NULL;
3986
pdlg->hSetupTemplate = NULL;
3987
}
3988
3989
/* Only copy fields that are supposed to be changed. */
3990
static void pdlg_to_pdlgex(const PRINTDLGW *pdlg, PRINTDLGEXW *pdlgex)
3991
{
3992
pdlgex->hDevMode = pdlg->hDevMode;
3993
pdlgex->hDevNames = pdlg->hDevNames;
3994
pdlgex->hDC = pdlg->hDC;
3995
if (!(pdlgex->Flags & PD_NOPAGENUMS) && pdlgex->nPageRanges && pdlgex->lpPageRanges)
3996
{
3997
pdlgex->lpPageRanges[0].nFromPage = pdlg->nFromPage;
3998
pdlgex->lpPageRanges[0].nToPage = pdlg->nToPage;
3999
}
4000
pdlgex->nMinPage = pdlg->nMinPage;
4001
pdlgex->nMaxPage = pdlg->nMaxPage;
4002
pdlgex->nCopies = pdlg->nCopies;
4003
}
4004
4005
struct callback_data
4006
{
4007
IPrintDialogCallback *callback;
4008
IObjectWithSite *object;
4009
};
4010
4011
static UINT_PTR CALLBACK pdlgex_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
4012
{
4013
if (msg == WM_INITDIALOG)
4014
{
4015
PRINTDLGW *pd = (PRINTDLGW *)lp;
4016
struct callback_data *cb = (struct callback_data *)pd->lCustData;
4017
4018
if (cb->callback)
4019
{
4020
cb->callback->lpVtbl->SelectionChange(cb->callback);
4021
cb->callback->lpVtbl->InitDone(cb->callback);
4022
}
4023
}
4024
else
4025
{
4026
/* FIXME: store interface pointer somewhere in window properties and call it
4027
HRESULT hres;
4028
cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres);
4029
*/
4030
}
4031
4032
return 0;
4033
}
4034
4035
/***********************************************************************
4036
* PrintDlgExA (COMDLG32.@)
4037
*
4038
* See PrintDlgExW.
4039
*
4040
* BUGS
4041
* Only a Stub
4042
*
4043
*/
4044
HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
4045
{
4046
PRINTER_INFO_2A *pbuf;
4047
DRIVER_INFO_3A *dbuf;
4048
DEVMODEA *dm;
4049
HRESULT hr = S_OK;
4050
HANDLE hprn;
4051
4052
if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
4053
return E_INVALIDARG;
4054
4055
if (!IsWindow(lppd->hwndOwner))
4056
return E_HANDLE;
4057
4058
if (lppd->nStartPage != START_PAGE_GENERAL)
4059
{
4060
if (!lppd->nPropertyPages)
4061
return E_INVALIDARG;
4062
4063
FIXME("custom property sheets (%ld at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4064
}
4065
4066
/* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4067
if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4068
{
4069
return E_INVALIDARG;
4070
}
4071
4072
if (lppd->Flags & PD_RETURNDEFAULT)
4073
{
4074
if (lppd->hDevMode || lppd->hDevNames)
4075
{
4076
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4077
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4078
return E_INVALIDARG;
4079
}
4080
if (!PRINTDLG_OpenDefaultPrinter(&hprn))
4081
{
4082
WARN("Can't find default printer\n");
4083
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
4084
return E_FAIL;
4085
}
4086
4087
pbuf = get_printer_infoA(hprn);
4088
if (!pbuf)
4089
{
4090
ClosePrinter(hprn);
4091
return E_FAIL;
4092
}
4093
4094
dbuf = get_driver_infoA(hprn);
4095
if (!dbuf)
4096
{
4097
free(pbuf);
4098
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4099
ClosePrinter(hprn);
4100
return E_FAIL;
4101
}
4102
dm = pbuf->pDevMode;
4103
}
4104
else
4105
{
4106
PRINTDLGA pdlg;
4107
struct callback_data cb_data = { 0 };
4108
4109
FIXME("(%p) semi-stub\n", lppd);
4110
4111
if (lppd->lpCallback)
4112
{
4113
IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4114
IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4115
}
4116
4117
/*
4118
* PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants.
4119
*/
4120
pdlgex_to_pdlg((const PRINTDLGEXW *)lppd, (PRINTDLGW *)&pdlg);
4121
pdlg.Flags |= PD_ENABLEPRINTHOOK;
4122
pdlg.lpfnPrintHook = pdlgex_hook_proc;
4123
pdlg.lCustData = (LPARAM)&cb_data;
4124
4125
if (PrintDlgA(&pdlg))
4126
{
4127
pdlg_to_pdlgex((const PRINTDLGW *)&pdlg, (PRINTDLGEXW *)lppd);
4128
lppd->dwResultAction = PD_RESULT_PRINT;
4129
}
4130
else
4131
lppd->dwResultAction = PD_RESULT_CANCEL;
4132
4133
if (cb_data.callback)
4134
cb_data.callback->lpVtbl->Release(cb_data.callback);
4135
if (cb_data.object)
4136
cb_data.object->lpVtbl->Release(cb_data.object);
4137
4138
return S_OK;
4139
}
4140
4141
ClosePrinter(hprn);
4142
4143
PRINTDLG_CreateDevNames(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4144
if (!lppd->hDevNames)
4145
hr = E_FAIL;
4146
4147
lppd->hDevMode = update_devmode_handleA(lppd->hDevMode, dm);
4148
if (hr == S_OK && lppd->hDevMode) {
4149
if (lppd->Flags & PD_RETURNDC) {
4150
lppd->hDC = CreateDCA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4151
if (!lppd->hDC)
4152
hr = E_FAIL;
4153
}
4154
else if (lppd->Flags & PD_RETURNIC) {
4155
lppd->hDC = CreateICA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4156
if (!lppd->hDC)
4157
hr = E_FAIL;
4158
}
4159
}
4160
else
4161
hr = E_FAIL;
4162
4163
free(pbuf);
4164
free(dbuf);
4165
4166
return hr;
4167
}
4168
4169
/***********************************************************************
4170
* PrintDlgExW (COMDLG32.@)
4171
*
4172
* Display the property sheet style PRINT dialog box
4173
*
4174
* PARAMS
4175
* lppd [IO] ptr to PRINTDLGEX struct
4176
*
4177
* RETURNS
4178
* Success: S_OK
4179
* Failure: One of the following COM error codes:
4180
* E_OUTOFMEMORY Insufficient memory.
4181
* E_INVALIDARG One or more arguments are invalid.
4182
* E_POINTER Invalid pointer.
4183
* E_HANDLE Invalid handle.
4184
* E_FAIL Unspecified error.
4185
*
4186
* NOTES
4187
* This Dialog enables the user to specify specific properties of the print job.
4188
* The property sheet can also have additional application-specific and
4189
* driver-specific property pages.
4190
*
4191
* BUGS
4192
* Not fully implemented
4193
*
4194
*/
4195
HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
4196
{
4197
PRINTER_INFO_2W *pbuf;
4198
DRIVER_INFO_3W *dbuf;
4199
DEVMODEW *dm;
4200
HRESULT hr = S_OK;
4201
HANDLE hprn;
4202
4203
if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
4204
return E_INVALIDARG;
4205
}
4206
4207
if (!IsWindow(lppd->hwndOwner)) {
4208
return E_HANDLE;
4209
}
4210
4211
if (lppd->nStartPage != START_PAGE_GENERAL)
4212
{
4213
if (!lppd->nPropertyPages)
4214
return E_INVALIDARG;
4215
4216
FIXME("custom property sheets (%ld at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4217
}
4218
4219
/* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4220
if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4221
{
4222
return E_INVALIDARG;
4223
}
4224
4225
if (lppd->Flags & PD_RETURNDEFAULT) {
4226
4227
if (lppd->hDevMode || lppd->hDevNames) {
4228
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4229
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4230
return E_INVALIDARG;
4231
}
4232
if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
4233
WARN("Can't find default printer\n");
4234
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
4235
return E_FAIL;
4236
}
4237
4238
pbuf = get_printer_infoW(hprn);
4239
if (!pbuf)
4240
{
4241
ClosePrinter(hprn);
4242
return E_FAIL;
4243
}
4244
4245
dbuf = get_driver_infoW(hprn);
4246
if (!dbuf)
4247
{
4248
free(pbuf);
4249
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4250
ClosePrinter(hprn);
4251
return E_FAIL;
4252
}
4253
dm = pbuf->pDevMode;
4254
}
4255
else
4256
{
4257
PRINTDLGW pdlg;
4258
struct callback_data cb_data = { 0 };
4259
4260
FIXME("(%p) semi-stub\n", lppd);
4261
4262
if (lppd->lpCallback)
4263
{
4264
IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4265
IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4266
}
4267
4268
pdlgex_to_pdlg(lppd, &pdlg);
4269
pdlg.Flags |= PD_ENABLEPRINTHOOK;
4270
pdlg.lpfnPrintHook = pdlgex_hook_proc;
4271
pdlg.lCustData = (LPARAM)&cb_data;
4272
4273
if (PrintDlgW(&pdlg))
4274
{
4275
pdlg_to_pdlgex(&pdlg, lppd);
4276
lppd->dwResultAction = PD_RESULT_PRINT;
4277
}
4278
else
4279
lppd->dwResultAction = PD_RESULT_CANCEL;
4280
4281
if (cb_data.callback)
4282
cb_data.callback->lpVtbl->Release(cb_data.callback);
4283
if (cb_data.object)
4284
cb_data.object->lpVtbl->Release(cb_data.object);
4285
4286
return S_OK;
4287
}
4288
4289
ClosePrinter(hprn);
4290
4291
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4292
if (!lppd->hDevNames)
4293
hr = E_FAIL;
4294
4295
lppd->hDevMode = update_devmode_handleW(lppd->hDevMode, dm);
4296
if (hr == S_OK && lppd->hDevMode) {
4297
if (lppd->Flags & PD_RETURNDC) {
4298
lppd->hDC = CreateDCW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4299
if (!lppd->hDC)
4300
hr = E_FAIL;
4301
}
4302
else if (lppd->Flags & PD_RETURNIC) {
4303
lppd->hDC = CreateICW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4304
if (!lppd->hDC)
4305
hr = E_FAIL;
4306
}
4307
}
4308
else
4309
hr = E_FAIL;
4310
4311
free(pbuf);
4312
free(dbuf);
4313
4314
return hr;
4315
}
4316
4317