1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied,
8
modified or distributed except as expressly authorized under the terms
9
of the license contained in the file LICENSE in this distribution.
11
Refer to licensing information at http://www.artifex.com or contact
12
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
CA 94903, U.S.A., +1(415)492-9861, for further information.
18
* Microsoft Windows 3.n printer driver for Ghostscript.
19
* Original version by Russell Lang and
20
* L. Peter Deutsch, Aladdin Enterprises.
21
* Modified by rjl 1995-03-29 to use BMP printer code
22
* Modified by Pierre Arnaud 1999-02-18 (see description below)
23
* Modified by lpd 1999-04-03 for compatibility with Borland C++ 4.5.
24
* Modified by Pierre Arnaud 1999-10-03 (accept b&w printing on color printers).
25
* Modified by Pierre Arnaud 1999-11-20 (accept lower resolution)
26
* Bug fixed by Pierre Arnaud 2000-03-09 (win_pr2_put_params error when is_open)
27
* Bug fixed by Pierre Arnaud 2000-03-20 (win_pr2_set_bpp did not set anti_alias)
28
* Bug fixed by Pierre Arnaud 2000-03-22 (win_pr2_set_bpp depth was wrong)
29
* Modified by Pierre Arnaud 2000-12-12 (mainly added support for Tumble)
30
* Bug fixed by Pierre Arnaud 2000-12-18 (-dQueryUser now works from cmd line)
33
/* This driver uses the printer default size and resolution and
34
* ignores page size and resolution set using -gWIDTHxHEIGHT and
35
* -rXxY. You must still set the correct PageSize to get the
36
* correct clipping path.
37
* The code in win_pr2_getdc() does try to set the printer page
38
* size from the PostScript PageSize, but it isn't working
39
* reliably at the moment.
41
* This driver doesn't work with some Windows printer drivers.
42
* The reason is unknown. All printers to which I have access
48
/* Additions by Pierre Arnaud (Pierre.Arnaud@opac.ch)
50
* The driver has been extended in order to provide some run-time
51
* feed-back about the default Windows printer and to give the user
52
* the opportunity to select the printer's properties before the
53
* device gets opened (and any spooling starts).
55
* The driver returns an additional property named "UserSettings".
56
* This is a dictionary which contens are valid only after setting
57
* the QueryUser property (see below). The UserSettings dict contains
60
* DocumentRange [begin end] (int array, can be set)
61
* Defines the range of pages in the document; [1 10] would
62
* describe a document starting at page 1 and ending at page 10.
64
* SelectedRange [begin end] (int array, can be set)
65
* Defines the pages the user wants to print.
67
* MediaSize [width height] (float array, read only)
68
* Current printer's media size.
70
* Copies n (integer, can be set)
71
* User selected number of copies.
73
* PrintCopies n (integer, read only)
74
* Number of copies which must be printed by Ghostscript itself.
75
* This is still experimental.
77
* DocumentName name (string, can be set)
78
* Name to be associated with the print job.
80
* UserChangedSettings (bool, read only)
81
* Set to 'true' if the last QueryUser operation succeeded.
83
* Paper n (integer, can be set)
84
* Windows paper selection (0 = automatic).
86
* Orient n (integer, can be set)
87
* Windows paper orientation (0 = automatic).
89
* Color n (integer, can be set)
90
* Windows color (0 = automatic, 1 = monochrome, 2 = color).
92
* MaxResolution n (integer, can be set)
93
* Maximum resolution in pixels pet inch (0 = no maximum). If
94
* the printer has a higher resolution than the maximum, trim
95
* the used resolution to the best one (dpi_chosen <= dpi_max,
96
* with dpi_chosen = dpi_printer / ratio).
99
/* Supported printer parameters are :
102
* Override what the Window printer driver returns.
105
* Don't display cancel dialog box. Useful for unattended or
106
* console EXE operation.
109
* Query user interactively for the destination printer, before
110
* the device gets opened. This fills in the UserSettings dict
111
* and the OutputFile name properties. The following values are
113
* 1 => show standard Print dialog
114
* 2 => show Print Setup dialog instead
115
* 3 => select default printer
116
* other, does nothing
118
* The /Duplex & /Tumble keys of the setpagedevice dict are supported
119
* if the Windows printer supports duplex printing.
123
#include "gdevpccm.h"
125
#include "windows_.h"
126
#include <shellapi.h>
127
#include "gp_mswin.h"
132
#include "gsicc_manage.h"
134
/* Make sure we cast to the correct structure type. */
135
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
138
#define wdev ((gx_device_win_pr2 *)dev)
140
/* Device procedures */
142
/* See gxdevice.h for the definitions of the procedures. */
143
static dev_proc_open_device(win_pr2_open);
144
static dev_proc_close_device(win_pr2_close);
145
static dev_proc_print_page(win_pr2_print_page);
146
static dev_proc_map_rgb_color(win_pr2_map_rgb_color);
147
static dev_proc_map_color_rgb(win_pr2_map_color_rgb);
148
static dev_proc_get_params(win_pr2_get_params);
149
static dev_proc_put_params(win_pr2_put_params);
151
static int win_pr2_set_bpp(gx_device * dev, int depth);
153
static const gx_device_procs win_pr2_procs =
154
prn_color_params_procs(win_pr2_open, gdev_prn_output_page, win_pr2_close,
155
win_pr2_map_rgb_color, win_pr2_map_color_rgb,
156
win_pr2_get_params, win_pr2_put_params);
158
#define PARENT_WINDOW HWND_DESKTOP
159
BOOL CALLBACK CancelDlgProc(HWND, UINT, WPARAM, LPARAM);
160
BOOL CALLBACK AbortProc2(HDC, int);
162
/* The device descriptor */
163
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
164
struct gx_device_win_pr2_s {
166
gx_prn_device_common;
170
int doc_page_begin; /* first page number in document */
171
int doc_page_end; /* last page number in document */
172
int user_page_begin; /* user's choice: first page to print */
173
int user_page_end; /* user's choice: last page to print */
174
int user_copies; /* user's choice: number of copies */
175
int print_copies; /* number of times GS should print each page */
176
float user_media_size[2]; /* width/height of media selected by user */
177
char doc_name[200]; /* name of document for the spooler */
178
char paper_name[64]; /* name of selected paper format */
179
bool user_icc; /* User specified device icc profile */
180
bool user_changed_settings; /* true if user validated dialog */
181
int user_paper; /* user's choice: paper format */
182
int user_orient; /* user's choice: paper orientation */
183
int user_color; /* user's choice: color format */
184
int max_dpi; /* maximum resolution in DPI */
185
int ratio; /* stretch ratio when printing */
186
int selected_bpp; /* selected bpp, memorised by win_pr2_set_bpp */
187
bool tumble; /* tumble setting (with duplex) */
188
int query_user; /* query user (-dQueryUser) */
190
HANDLE win32_hdevmode; /* handle to device mode information */
191
HANDLE win32_hdevnames; /* handle to device names information */
193
DLGPROC lpfnAbortProc;
194
DLGPROC lpfnCancelProc;
197
bool use_old_spool_name; /* user prefers old \\spool\ name */
198
gx_device_win_pr2* original_device; /* used to detect copies */
201
gx_device_win_pr2 far_data gs_mswinpr2_device =
203
prn_device_std_body(gx_device_win_pr2, win_pr2_procs, "mswinpr2",
204
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72.0, 72.0,
206
0, win_pr2_print_page), /* depth = 0 */
209
0, /* doc_page_begin */
210
0, /* doc_page_end */
211
0, /* user_page_begin */
212
0, /* user_page_end */
214
1, /* print_copies */
215
{ 0.0, 0.0 }, /* user_media_size */
216
{ 0 }, /* doc_name */
217
{ 0 }, /* paper_name */
218
false, /* user_icc */
219
0, /* user_changed_settings */
225
0, /* selected_bpp */
228
NULL, /* win32_hdevmode */
229
NULL, /* win32_hdevnames */
230
NULL, /* lpfnAbortProc */
231
NULL, /* lpfnCancelProc */
232
NULL, /* hDlgModeless */
233
false, /* use_old_spool_name */
234
NULL /* original_device */
237
/********************************************************************************/
239
static int win_pr2_getdc(gx_device_win_pr2 * dev);
240
static int win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
241
static int win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
242
static int win_pr2_print_setup_interaction(gx_device_win_pr2 * dev, int mode);
243
static int win_pr2_write_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
244
static int win_pr2_read_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
245
static void win_pr2_copy_check(gx_device_win_pr2 * dev);
247
/********************************************************************************/
249
/* Open the win_pr2 driver */
251
win_pr2_open(gx_device * dev)
263
win_pr2_copy_check(wdev);
265
/* get a HDC for the printer */
266
if ((wdev->win32_hdevmode) &&
267
(wdev->win32_hdevnames)) {
268
/* The user has already had the opportunity to choose the output */
269
/* file interactively. Just use the specified parameters. */
271
LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
272
LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
274
const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
275
const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
276
const char* output = (char*)(devnames)+(devnames->wOutputOffset);
278
wdev->hdcprn = CreateDC(driver, device, output, devmode);
280
GlobalUnlock(wdev->win32_hdevmode);
281
GlobalUnlock(wdev->win32_hdevnames);
283
if (wdev->hdcprn == NULL) {
284
return gs_error_Fatal;
287
} else if (!win_pr2_getdc(wdev)) {
288
/* couldn't get a printer from -sOutputFile= */
289
/* Prompt with dialog box */
291
LPDEVMODE devmode = NULL;
292
memset(&pd, 0, sizeof(pd));
294
pd.lStructSize = sizeof(pd);
295
pd.hwndOwner = PARENT_WINDOW;
296
pd.Flags = PD_RETURNDC;
297
pd.nMinPage = wdev->doc_page_begin;
298
pd.nMaxPage = wdev->doc_page_end;
299
pd.nFromPage = wdev->user_page_begin;
300
pd.nToPage = wdev->user_page_end;
301
pd.nCopies = wdev->user_copies;
303
if (!PrintDlg(&pd)) {
304
/* device not opened - exit ghostscript */
305
return gs_error_Fatal; /* exit Ghostscript cleanly */
308
devmode = GlobalLock(pd.hDevMode);
309
win_pr2_update_dev(wdev,devmode);
310
GlobalUnlock(pd.hDevMode);
312
if (wdev->win32_hdevmode)
313
GlobalFree(wdev->win32_hdevmode);
314
if (wdev->win32_hdevnames)
315
GlobalFree(wdev->win32_hdevnames);
317
wdev->hdcprn = pd.hDC;
318
wdev->win32_hdevmode = pd.hDevMode;
319
wdev->win32_hdevnames = pd.hDevNames;
324
if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_DIBTODEV)) {
325
errprintf(dev->memory, "Windows printer does not have RC_DIBTODEV\n");
326
DeleteDC(wdev->hdcprn);
327
return gs_error_limitcheck;
329
/* initialise printer, install abort proc */
330
wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
331
SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);
334
* Some versions of the Windows headers include lpszDatatype and fwType,
335
* and some don't. Since we want to set these fields to zero anyway,
336
* we just start by zeroing the whole structure.
338
memset(&docinfo, 0, sizeof(docinfo));
339
docinfo.cbSize = sizeof(docinfo);
340
docinfo.lpszDocName = wdev->doc_name;
341
/*docinfo.lpszOutput = NULL;*/
342
/*docinfo.lpszDatatype = NULL;*/
343
/*docinfo.fwType = 0;*/
345
if (docinfo.lpszDocName[0] == 0) {
346
docinfo.lpszDocName = "Ghostscript output";
349
if (StartDoc(wdev->hdcprn, &docinfo) <= 0) {
350
errprintf(dev->memory,
351
"Printer StartDoc failed (error %08x)\n", GetLastError());
352
DeleteDC(wdev->hdcprn);
353
return gs_error_limitcheck;
356
dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
357
dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
361
if (wdev->max_dpi > 50) {
363
float dpi_x = dev->x_pixels_per_inch;
364
float dpi_y = dev->y_pixels_per_inch;
366
while ((dev->x_pixels_per_inch > wdev->max_dpi)
367
|| (dev->y_pixels_per_inch > wdev->max_dpi)) {
370
dev->x_pixels_per_inch = dpi_x / ratio;
371
dev->y_pixels_per_inch = dpi_y / ratio;
375
size.x = GetDeviceCaps(wdev->hdcprn, PHYSICALWIDTH);
376
size.y = GetDeviceCaps(wdev->hdcprn, PHYSICALHEIGHT);
377
gx_device_set_width_height(dev, (int)(size.x / ratio), (int)(size.y / ratio));
378
offset.x = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETX);
379
offset.y = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETY);
381
/* m[] gives margins in inches */
382
m[0] /*left */ = offset.x / dev->x_pixels_per_inch / ratio;
383
m[3] /*top */ = offset.y / dev->y_pixels_per_inch / ratio;
384
m[2] /*right */ = (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES)) / dev->x_pixels_per_inch / ratio;
385
m[1] /*bottom */ = (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES)) / dev->y_pixels_per_inch / ratio;
386
gx_device_set_margins(dev, m, true);
388
depth = dev->color_info.depth;
390
/* Set parameters that were unknown before opening device */
391
/* Find out if the device supports color */
392
/* We recognize 1, 4 (but use only 3), 8 and 24 bit color devices */
393
depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
395
code1 = win_pr2_set_bpp(dev, depth);
397
/* gdev_prn_open opens a temporary file which we don't want */
398
/* so we specify the name now so we can delete it later */
399
wdev->fname[0] = '\0';
400
pfile = gp_open_scratch_file(dev->memory,
401
gp_scratch_file_name_prefix,
404
code = gdev_prn_open(dev);
405
if ((code < 0) && wdev->fname[0])
408
if (!wdev->nocancel) {
409
/* inform user of progress with dialog box and allow cancel */
410
wdev->lpfnCancelProc = (DLGPROC) CancelDlgProc;
411
wdev->hDlgModeless = CreateDialog(phInstance, "CancelDlgBox",
412
PARENT_WINDOW, wdev->lpfnCancelProc);
413
ShowWindow(wdev->hDlgModeless, SW_HIDE);
415
if (code1 < 0 && code >= 0) {
422
/* Close the win_pr2 driver */
424
win_pr2_close(gx_device * dev)
429
win_pr2_copy_check(wdev);
433
if (!wdev->nocancel) {
434
if (!wdev->hDlgModeless)
437
DestroyWindow(wdev->hDlgModeless);
438
wdev->hDlgModeless = 0;
441
AbortDoc(wdev->hdcprn);
443
EndDoc(wdev->hdcprn);
445
DeleteDC(wdev->hdcprn);
447
if (wdev->win32_hdevmode != NULL) {
448
GlobalFree(wdev->win32_hdevmode);
449
wdev->win32_hdevmode = NULL;
451
if (wdev->win32_hdevnames != NULL) {
452
GlobalFree(wdev->win32_hdevnames);
453
wdev->win32_hdevnames = NULL;
456
code = gdev_prn_close(dev);
458
/* delete unwanted temporary file */
465
/* ------ Internal routines ------ */
468
#define wdev ((gx_device_win_pr2 *)pdev)
470
/********************************************************************************/
472
/* ------ Private definitions ------ */
474
/* new win_pr2_print_page routine */
476
/* Write BMP header to memory, then send bitmap to printer */
477
/* one scan line at a time */
479
win_pr2_print_page(gx_device_printer * pdev, FILE * file)
481
int raster = gdev_prn_raster(pdev);
483
/* BMP scan lines are padded to 32 bits. */
484
ulong bmp_raster = raster + (-raster & 3);
485
ulong bmp_raster_multi;
486
int scan_lines, yslice, lines, i;
488
int depth = pdev->color_info.depth;
491
int code = 0; /* return code */
495
int ratio = ((gx_device_win_pr2 *)pdev)->ratio;
502
scan_lines = dev_print_scan_lines(pdev);
503
width = (int)(pdev->width - ((dev_l_margin(pdev) + dev_r_margin(pdev) -
504
dev_x_offset(pdev)) * pdev->x_pixels_per_inch));
506
yslice = 65535 / bmp_raster; /* max lines in 64k */
507
bmp_raster_multi = bmp_raster * yslice;
508
hrow = GlobalAlloc(0, bmp_raster_multi);
509
row = GlobalLock(hrow);
510
if (row == 0) /* can't allocate row buffer */
511
return_error(gs_error_VMerror);
513
/* Write the info header. */
515
bmi.h.biSize = sizeof(bmi.h);
516
bmi.h.biWidth = pdev->width; /* wdev->mdev.width; */
517
bmi.h.biHeight = yslice;
519
bmi.h.biBitCount = pdev->color_info.depth;
520
bmi.h.biCompression = 0;
521
bmi.h.biSizeImage = 0; /* default */
522
bmi.h.biXPelsPerMeter = 0; /* default */
523
bmi.h.biYPelsPerMeter = 0; /* default */
525
StartPage(wdev->hdcprn);
527
/* Write the palette. */
531
gx_color_value rgb[3];
534
bmi.h.biClrUsed = 1 << depth;
535
bmi.h.biClrImportant = 1 << depth;
536
for (i = 0; i != 1 << depth; i++) {
537
(*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
538
(gx_color_index) i, rgb);
540
pq->rgbRed = gx_color_value_to_byte(rgb[0]);
541
pq->rgbGreen = gx_color_value_to_byte(rgb[1]);
542
pq->rgbBlue = gx_color_value_to_byte(rgb[2]);
547
bmi.h.biClrImportant = 0;
550
if (!wdev->nocancel) {
551
gs_sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
552
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext);
553
ShowWindow(wdev->hDlgModeless, SW_SHOW);
555
for (y = 0; y < scan_lines;) {
556
/* copy slice to row buffer */
557
if (y > scan_lines - yslice)
558
lines = scan_lines - y;
561
for (i = 0; i < lines; i++)
562
gdev_prn_copy_scan_lines(pdev, y + i,
563
row + (bmp_raster * (lines - 1 - i)), raster);
566
StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio,
567
0, 0, pdev->width, lines,
569
(BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY);
571
SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines,
574
(BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS);
578
if (!wdev->nocancel) {
579
/* inform user of progress */
580
gs_sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
581
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext);
583
/* process message loop */
584
while (PeekMessage(&msg, wdev->hDlgModeless, 0, 0, PM_REMOVE)) {
585
if ((wdev->hDlgModeless == 0) || !IsDialogMessage(wdev->hDlgModeless, &msg)) {
586
TranslateMessage(&msg);
587
DispatchMessage(&msg);
590
if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) {
591
/* user pressed cancel button */
596
if ((!wdev->nocancel) && (wdev->hDlgModeless == 0))
597
code = gs_error_Fatal; /* exit Ghostscript cleanly */
599
/* push out the page */
601
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE),
603
EndPage(wdev->hdcprn);
605
ShowWindow(wdev->hDlgModeless, SW_HIDE);
614
/* combined color mappers */
616
/* 24-bit color mappers (taken from gdevmem2.c). */
617
/* Note that Windows expects RGB values in the order B,G,R. */
619
/* Map a r-g-b color to a color index. */
620
static gx_color_index
621
win_pr2_map_rgb_color(gx_device * dev, const gx_color_value cv[])
623
gx_color_value r = cv[0];
624
gx_color_value g = cv[1];
625
gx_color_value b = cv[2];
626
switch (dev->color_info.depth) {
628
return gdev_prn_map_rgb_color(dev, cv);
630
/* use only 8 colors */
631
return (r > (gx_max_color_value / 2 + 1) ? 4 : 0) +
632
(g > (gx_max_color_value / 2 + 1) ? 2 : 0) +
633
(b > (gx_max_color_value / 2 + 1) ? 1 : 0);
635
return pc_8bit_map_rgb_color(dev, cv);
637
return gx_color_value_to_byte(r) +
638
((uint) gx_color_value_to_byte(g) << 8) +
639
((ulong) gx_color_value_to_byte(b) << 16);
641
return 0; /* error */
644
/* Map a color index to a r-g-b color. */
646
win_pr2_map_color_rgb(gx_device * dev, gx_color_index color,
647
gx_color_value prgb[3])
649
switch (dev->color_info.depth) {
651
gdev_prn_map_color_rgb(dev, color, prgb);
654
/* use only 8 colors */
655
prgb[0] = (color & 4) ? gx_max_color_value : 0;
656
prgb[1] = (color & 2) ? gx_max_color_value : 0;
657
prgb[2] = (color & 1) ? gx_max_color_value : 0;
660
pc_8bit_map_color_rgb(dev, color, prgb);
663
prgb[2] = gx_color_value_from_byte(color >> 16);
664
prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
665
prgb[0] = gx_color_value_from_byte(color & 0xff);
672
win_pr2_set_bpp(gx_device * dev, int depth)
675
gx_device_printer *pdev = (gx_device_printer *)dev;
678
static const gx_device_color_info win_pr2_24color = dci_std_color(24);
680
dev->color_info = win_pr2_24color;
683
if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
684
wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsRGB))) {
686
if (wdev->icc_struct) {
687
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
689
wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
691
if (wdev->icc_struct) {
692
code = gsicc_set_device_profile(dev, dev->memory,
693
(char *)DEFAULT_RGB_ICC, gsDEFAULTPROFILE);
696
code = gs_error_VMerror;
700
} else if (depth >= 8) {
701
/* 8-bit (SuperVGA-style) color. */
702
/* (Uses a fixed palette of 3,3,2 bits.) */
703
static const gx_device_color_info win_pr2_8color = dci_pc_8bit;
705
dev->color_info = win_pr2_8color;
708
if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
709
wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsRGB))) {
711
if (wdev->icc_struct) {
712
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
714
wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
716
if (wdev->icc_struct) {
717
code = gsicc_set_device_profile(dev, dev->memory,
718
(char *)DEFAULT_RGB_ICC, gsDEFAULTPROFILE);
721
code = gs_error_VMerror;
724
} else if (depth >= 3) {
725
/* 3 plane printer */
726
/* suitable for impact dot matrix CMYK printers */
727
/* create 4-bit bitmap, but only use 8 colors */
728
static const gx_device_color_info win_pr2_4color = dci_values(3, 4, 1, 1, 2, 2);
730
dev->color_info = win_pr2_4color;
733
if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
734
wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsCMYK))) {
736
if (wdev->icc_struct) {
737
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
739
wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
741
if (wdev->icc_struct) {
742
code = gsicc_set_device_profile(dev, dev->memory,
743
(char *)DEFAULT_CMYK_ICC, gsDEFAULTPROFILE);
746
code = gs_error_VMerror;
749
} else { /* default is black_and_white */
750
static const gx_device_color_info win_pr2_1color = dci_std_color(1);
752
dev->color_info = win_pr2_1color;
755
if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
756
wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsGRAY))) {
758
if (wdev->icc_struct) {
759
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
761
wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
763
if (wdev->icc_struct) {
764
code = gsicc_set_device_profile(dev, dev->memory,
765
(char *)DEFAULT_GRAY_ICC, gsDEFAULTPROFILE);
768
code = gs_error_VMerror;
773
wdev->selected_bpp = depth;
775
/* copy encode/decode procedures */
776
dev->procs.encode_color = dev->procs.map_rgb_color;
777
dev->procs.decode_color = dev->procs.map_color_rgb;
779
dev->procs.get_color_mapping_procs =
780
gx_default_DevGray_get_color_mapping_procs;
781
dev->procs.get_color_comp_index =
782
gx_default_DevGray_get_color_comp_index;
785
dev->procs.get_color_mapping_procs =
786
gx_default_DevRGB_get_color_mapping_procs;
787
dev->procs.get_color_comp_index =
788
gx_default_DevRGB_get_color_comp_index;
793
/********************************************************************************/
795
/* Get device parameters */
797
win_pr2_get_params(gx_device * pdev, gs_param_list * plist)
799
int code = gdev_prn_get_params(pdev, plist);
801
win_pr2_copy_check(wdev);
804
code = param_write_bool(plist, "NoCancel",
807
code = param_write_int(plist, "QueryUser",
808
&(wdev->query_user));
810
code = win_pr2_write_user_settings(wdev, plist);
812
if ((code >= 0) && (wdev->Duplex_set > 0))
813
code = param_write_bool(plist, "Tumble",
819
/* We implement this ourselves so that we can change BitsPerPixel */
820
/* before the device is opened */
822
win_pr2_put_params(gx_device * pdev, gs_param_list * plist)
825
int old_bpp = pdev->color_info.depth;
827
bool tumble = wdev->tumble;
828
bool nocancel = wdev->nocancel;
830
bool old_duplex = wdev->Duplex;
831
bool old_tumble = wdev->tumble;
832
int old_orient = wdev->user_orient;
833
int old_color = wdev->user_color;
834
int old_paper = wdev->user_paper;
835
int old_mx_dpi = wdev->max_dpi;
837
if (wdev->Duplex_set < 0) {
838
wdev->Duplex_set = 0;
839
wdev->Duplex = false;
840
wdev->tumble = false;
843
win_pr2_copy_check(wdev);
845
code = win_pr2_read_user_settings(wdev, plist);
847
switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
850
if (wdev->selected_bpp == bpp) {
853
ecode = gs_error_rangecheck;
854
} else { /* change dev->color_info is valid before device is opened */
855
code = win_pr2_set_bpp(pdev, bpp);
864
bppe:param_signal_error(plist, "BitsPerPixel", ecode);
869
switch (code = param_read_bool(plist, "NoCancel", &nocancel)) {
872
if (wdev->nocancel == nocancel) {
875
ecode = gs_error_rangecheck;
877
wdev->nocancel = nocancel;
883
nocancele:param_signal_error(plist, "NoCancel", ecode);
888
switch (code = param_read_bool(plist, "Tumble", &tumble)) {
890
wdev->tumble = tumble;
894
param_signal_error(plist, "Tumble", ecode);
899
switch (code = param_read_int(plist, "QueryUser", &queryuser)) {
901
if ((queryuser > 0) &&
903
win_pr2_print_setup_interaction(wdev, queryuser);
908
param_signal_error(plist, "QueryUser", ecode);
913
/* Record if the user has specified a custom profile, so we don't replace it
914
with a default when we change color space - see win_pr2_set_bpp()
915
Here, we only want to know *if* we have a user specced profile, actually
916
setting it will be handled by gdev_prn_put_params()
918
if (!wdev->user_icc) {
919
gs_param_string icc_pro_dummy;
921
wdev->user_icc = param_read_string(plist, "OutputICCProfile", &icc_pro_dummy) == 0;
925
ecode = gdev_prn_put_params(pdev, plist);
927
if (wdev->win32_hdevmode && wdev->hdcprn) {
928
if ( (old_duplex != wdev->Duplex)
929
|| (old_tumble != wdev->tumble)
930
|| (old_orient != wdev->user_orient)
931
|| (old_color != wdev->user_color)
932
|| (old_paper != wdev->user_paper)
933
|| (old_mx_dpi != wdev->max_dpi) ) {
935
LPDEVMODE pdevmode = GlobalLock(wdev->win32_hdevmode);
938
win_pr2_update_win(wdev, pdevmode);
939
ResetDC(wdev->hdcprn, pdevmode);
940
GlobalUnlock(pdevmode);
950
/********************************************************************************/
952
/* Get Device Context for printer */
954
win_pr2_getdc(gx_device_win_pr2 * wdev)
967
int paperwidth, paperheight;
971
LPDEVMODE podevmode, pidevmode;
974
/* first try to derive the printer name from -sOutputFile= */
975
/* is printer if name prefixed by \\spool\ or by %printer% */
976
if (is_spool(wdev->fname)) {
977
device = wdev->fname + 8; /* skip over \\spool\ */
978
wdev->use_old_spool_name = true;
979
} else if (strncmp("%printer%",wdev->fname,9) == 0) {
980
device = wdev->fname + 9; /* skip over %printer% */
981
wdev->use_old_spool_name = false;
986
/* now try to match the printer name against the [Devices] section */
989
char *devices = gs_malloc(wdev->memory, 4096, 1, "win_pr2_getdc");
991
if (devices == (char *)NULL)
993
GetProfileString("Devices", NULL, "", devices, 4096);
996
if (stricmp(p, device) == 0)
1002
gs_free(wdev->memory, devices, 4096, 1, "win_pr2_getdc");
1004
return FALSE; /* doesn't match an available printer */
1006
/* the printer exists, get the remaining information from win.ini */
1007
GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
1011
wchar_t unidrvbuf[sizeof(driverbuf)];
1014
wchar_t *unidev = malloc(utf8_to_wchar(NULL, device)*sizeof(wchar_t));
1017
utf8_to_wchar(unidev, device);
1018
devices = gs_malloc(wdev->memory, 8192, 1, "win_pr2_getdc");
1019
if (devices == (wchar_t *)NULL) {
1023
GetProfileStringW(L"Devices", NULL, L"", devices, 8192);
1026
if (wcsicmp(p, unidev) == 0)
1032
gs_free(wdev->memory, devices, 8192, 1, "win_pr2_getdc");
1035
return FALSE; /* doesn't match an available printer */
1038
/* the printer exists, get the remaining information from win.ini */
1039
GetProfileStringW(L"Devices", unidev, L"", unidrvbuf, sizeof(unidrvbuf));
1041
i = wchar_to_utf8(NULL, unidrvbuf);
1042
if (i < 0 || i > sizeof(driverbuf))
1044
wchar_to_utf8(driverbuf, unidrvbuf);
1047
driver = strtok(driverbuf, ",");
1048
output = strtok(NULL, ",");
1050
if (!gp_OpenPrinter(device, &hprinter))
1052
devmode_size = DocumentProperties(NULL, hprinter, device, NULL, NULL, 0);
1053
if ((podevmode = gs_malloc(wdev->memory, devmode_size, 1, "win_pr2_getdc"))
1054
== (LPDEVMODE) NULL) {
1055
ClosePrinter(hprinter);
1058
if ((pidevmode = gs_malloc(wdev->memory, devmode_size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
1059
gs_free(wdev->memory, podevmode, devmode_size, 1, "win_pr2_getdc");
1060
ClosePrinter(hprinter);
1063
DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);
1065
/* now find out what paper sizes are available */
1066
devcapsize = DeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL);
1067
devcapsize *= sizeof(POINT);
1068
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
1070
n = DeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL);
1071
paperwidth = (int)(wdev->MediaSize[0] * 254 / 72);
1072
paperheight = (int)(wdev->MediaSize[1] * 254 / 72);
1073
papername[0] = '\0';
1077
pp = (POINT *) devcap;
1078
for (i = 0; i < n; i++, pp++) {
1079
if ((pp->x < paperwidth + 20) && (pp->x > paperwidth - 20) &&
1080
(pp->y < paperheight + 20) && (pp->y > paperheight - 20)) {
1083
paperheight = pp->y;
1084
orientation = DMORIENT_PORTRAIT;
1088
if (paperindex < 0) {
1089
/* try again in landscape */
1090
pp = (POINT *) devcap;
1091
for (i = 0; i < n; i++, pp++) {
1092
if ((pp->x < paperheight + 20) && (pp->x > paperheight - 20) &&
1093
(pp->y < paperwidth + 20) && (pp->y > paperwidth - 20)) {
1096
paperheight = pp->y;
1097
orientation = DMORIENT_LANDSCAPE;
1102
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
1104
/* get the dmPaperSize */
1105
devcapsize = DeviceCapabilities(device, output, DC_PAPERS, NULL, NULL);
1106
devcapsize *= sizeof(WORD);
1107
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
1109
n = DeviceCapabilities(device, output, DC_PAPERS, devcap, NULL);
1110
if ((paperindex >= 0) && (paperindex < n))
1111
papersize = ((WORD *) devcap)[paperindex];
1112
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
1114
/* get the paper name */
1115
devcapsize = DeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
1117
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
1119
n = DeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL);
1120
if ((paperindex >= 0) && (paperindex < n))
1121
strcpy(papername, devcap + paperindex * 64);
1122
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
1124
memcpy(pidevmode, podevmode, devmode_size);
1126
pidevmode->dmFields = 0;
1128
wdev->paper_name[0] = 0;
1130
if ( (wdev->user_paper)
1131
&& (wdev->user_paper != papersize) ) {
1132
papersize = wdev->user_paper;
1137
if (wdev->user_orient) {
1138
orientation = wdev->user_orient;
1141
pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
1142
pidevmode->dmFields |= DM_DEFAULTSOURCE;
1143
pidevmode->dmDefaultSource = 0;
1146
wdev->user_orient = orientation;
1149
wdev->user_paper = papersize;
1150
strcpy (wdev->paper_name, papername);
1153
if (paperheight && paperwidth) {
1154
pidevmode->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
1155
pidevmode->dmPaperWidth = paperwidth;
1156
pidevmode->dmPaperLength = paperheight;
1157
wdev->user_media_size[0] = paperwidth / 254.0 * 72.0;
1158
wdev->user_media_size[1] = paperheight / 254.0 * 72.0;
1161
if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
1162
wdev->Duplex_set = 1;
1165
win_pr2_update_win(wdev, pidevmode);
1167
/* merge the entries */
1168
DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
1169
ClosePrinter(hprinter);
1172
wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
1174
if (wdev->win32_hdevmode == NULL)
1175
wdev->win32_hdevmode = GlobalAlloc(0, devmode_size);
1177
if (wdev->win32_hdevmode) {
1178
LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
1180
memcpy(pdevmode, podevmode, devmode_size);
1181
GlobalUnlock(wdev->win32_hdevmode);
1185
gs_free(wdev->memory, pidevmode, devmode_size, 1, "win_pr2_getdc");
1186
gs_free(wdev->memory, podevmode, devmode_size, 1, "win_pr2_getdc");
1188
if (wdev->hdcprn != (HDC) NULL)
1189
return TRUE; /* success */
1191
/* fall back to prompting user */
1196
* Minimalist update of the wdev parameters (mainly for the
1197
* UserSettings parameters).
1201
win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
1206
if (pdevmode->dmFields & DM_COLOR) {
1207
dev->user_color = pdevmode->dmColor;
1209
if (pdevmode->dmFields & DM_ORIENTATION) {
1210
dev->user_orient = pdevmode->dmOrientation;
1212
if (pdevmode->dmFields & DM_PAPERSIZE) {
1213
dev->user_paper = pdevmode->dmPaperSize;
1214
dev->user_media_size[0] = pdevmode->dmPaperWidth / 254.0 * 72.0;
1215
dev->user_media_size[1] = pdevmode->dmPaperLength / 254.0 * 72.0;
1216
dev->paper_name[0] = 0; /* unknown paper size */
1218
if (pdevmode->dmFields & DM_DUPLEX) {
1219
dev->Duplex_set = 1;
1220
dev->Duplex = pdevmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
1221
dev->tumble = pdevmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
1228
win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
1230
if (dev->Duplex_set > 0) {
1231
pdevmode->dmFields |= DM_DUPLEX;
1232
pdevmode->dmDuplex = DMDUP_SIMPLEX;
1234
if (dev->tumble == false) {
1235
pdevmode->dmDuplex = DMDUP_VERTICAL;
1237
pdevmode->dmDuplex = DMDUP_HORIZONTAL;
1242
if (dev->user_color) {
1243
pdevmode->dmColor = dev->user_color;
1244
pdevmode->dmFields |= DM_COLOR;
1247
if (dev->user_orient) {
1248
pdevmode->dmFields |= DM_ORIENTATION;
1249
pdevmode->dmOrientation = dev->user_orient;
1252
if (dev->user_paper) {
1253
pdevmode->dmFields |= DM_PAPERSIZE;
1254
pdevmode->dmPaperSize = dev->user_paper;
1259
/********************************************************************************/
1261
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
1262
switch ( code = pread(dict.list, (param_name = pname), &(pa)) )\
1265
if ( (pa).size != psize )\
1266
ecode = gs_note_error(gs_error_rangecheck);\
1268
/* The body of the processing code goes here. */
1269
/* If it succeeds, it should do a 'break'; */
1270
/* if it fails, it should set ecode and fall through. */
1271
#define END_ARRAY_PARAM(pa, e)\
1276
e: param_signal_error(dict.list, param_name, ecode);\
1278
(pa).data = 0; /* mark as not filled */\
1281
/* Put the user params from UserSettings into our */
1282
/* internal variables. */
1284
win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
1287
gs_param_string docn = { 0 };
1288
const char* dict_name = "UserSettings";
1289
const char* param_name = "";
1293
switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
1295
param_signal_error(plist, dict_name, code);
1301
gs_param_int_array ia;
1303
BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
1304
if ((ia.data[0] < 0) ||
1306
(ia.data[0] > ia.data[1]))
1307
ecode = gs_note_error(gs_error_rangecheck);
1308
wdev->doc_page_begin = ia.data[0];
1309
wdev->doc_page_end = ia.data[1];
1310
END_ARRAY_PARAM(ia, doc_range_error)
1312
BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
1313
if ((ia.data[0] < 0) ||
1315
(ia.data[0] > ia.data[1]))
1316
ecode = gs_note_error(gs_error_rangecheck);
1317
wdev->user_page_begin = ia.data[0];
1318
wdev->user_page_end = ia.data[1];
1319
END_ARRAY_PARAM(ia, sel_range_error)
1321
param_read_int(dict.list, "Copies", &wdev->user_copies);
1322
param_read_int(dict.list, "Paper", &wdev->user_paper);
1323
param_read_int(dict.list, "Orientation", &wdev->user_orient);
1324
param_read_int(dict.list, "Color", &wdev->user_color);
1325
param_read_int(dict.list, "MaxResolution", &wdev->max_dpi);
1327
switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
1329
if (docn.size < sizeof(wdev->doc_name))
1331
code = gs_error_rangecheck;
1335
param_signal_error(plist, param_name, ecode);
1342
param_end_read_dict(plist, dict_name, &dict);
1345
memcpy(wdev->doc_name, docn.data, docn.size);
1346
wdev->doc_name[docn.size] = 0;
1349
wdev->print_copies = 1;
1351
if (wdev->win32_hdevmode) {
1352
LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
1354
devmode->dmCopies = wdev->user_copies;
1355
devmode->dmPaperSize = wdev->user_paper;
1356
devmode->dmOrientation = wdev->user_orient;
1357
devmode->dmColor = wdev->user_color;
1358
GlobalUnlock(wdev->win32_hdevmode);
1369
win_pr2_write_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
1372
gs_param_int_array range;
1373
gs_param_float_array box;
1374
gs_param_string docn;
1375
gs_param_string papn;
1377
const char* pname = "UserSettings";
1381
code = param_begin_write_dict(plist, pname, &dict, false);
1382
if (code < 0) return code;
1384
array[0] = wdev->doc_page_begin;
1385
array[1] = wdev->doc_page_end;
1388
range.persistent = false;
1389
code = param_write_int_array(dict.list, "DocumentRange", &range);
1390
if (code < 0) goto error;
1392
array[0] = wdev->user_page_begin;
1393
array[1] = wdev->user_page_end;
1396
range.persistent = false;
1397
code = param_write_int_array(dict.list, "SelectedRange", &range);
1398
if (code < 0) goto error;
1400
box.data = wdev->user_media_size;
1402
box.persistent = false;
1403
code = param_write_float_array(dict.list, "MediaSize", &box);
1404
if (code < 0) goto error;
1406
code = param_write_int(dict.list, "Copies", &wdev->user_copies);
1407
if (code < 0) goto error;
1409
code = param_write_int(dict.list, "Paper", &wdev->user_paper);
1410
if (code < 0) goto error;
1412
code = param_write_int(dict.list, "Orientation", &wdev->user_orient);
1413
if (code < 0) goto error;
1415
code = param_write_int(dict.list, "Color", &wdev->user_color);
1416
if (code < 0) goto error;
1418
code = param_write_int(dict.list, "MaxResolution", &wdev->max_dpi);
1419
if (code < 0) goto error;
1421
code = param_write_int(dict.list, "PrintCopies", &wdev->print_copies);
1422
if (code < 0) goto error;
1424
docn.data = (const byte*)wdev->doc_name;
1425
docn.size = strlen(wdev->doc_name);
1426
docn.persistent = false;
1428
code = param_write_string(dict.list, "DocumentName", &docn);
1429
if (code < 0) goto error;
1431
papn.data = (const byte*)wdev->paper_name;
1432
papn.size = strlen(wdev->paper_name);
1433
papn.persistent = false;
1435
code = param_write_string(dict.list, "PaperName", &papn);
1436
if (code < 0) goto error;
1438
code = param_write_bool(dict.list, "UserChangedSettings", &wdev->user_changed_settings);
1441
param_end_write_dict(plist, pname, &dict);
1445
/********************************************************************************/
1447
/* Show up a dialog for the user to choose a printer and a paper size.
1448
* If mode == 3, then automatically select the default Windows printer
1449
* instead of asking the user.
1453
win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode)
1457
LPDEVNAMES devnames;
1459
wdev->user_changed_settings = FALSE;
1460
wdev->query_user = mode;
1462
memset(&pd, 0, sizeof(pd));
1463
pd.lStructSize = sizeof(pd);
1464
pd.hwndOwner = PARENT_WINDOW;
1467
case 2: pd.Flags = PD_PRINTSETUP; break;
1468
case 3: pd.Flags = PD_RETURNDEFAULT; break;
1469
default: pd.Flags = 0; break;
1472
pd.Flags |= PD_USEDEVMODECOPIES;
1474
pd.nMinPage = wdev->doc_page_begin;
1475
pd.nMaxPage = wdev->doc_page_end;
1476
pd.nFromPage = wdev->user_page_begin;
1477
pd.nToPage = wdev->user_page_end;
1478
pd.nCopies = wdev->user_copies;
1480
/* Show the Print Setup dialog and let the user choose a printer
1481
* and a paper size/orientation.
1484
if (!PrintDlg(&pd)) return FALSE;
1486
devmode = (LPDEVMODE) GlobalLock(pd.hDevMode);
1487
devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);
1489
wdev->user_changed_settings = TRUE;
1490
if (wdev->use_old_spool_name) {
1491
gs_sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
1493
gs_sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
1497
devmode->dmCopies = wdev->user_copies * wdev->print_copies;
1501
wdev->user_page_begin = pd.nFromPage;
1502
wdev->user_page_end = pd.nToPage;
1503
wdev->user_copies = devmode->dmCopies;
1504
wdev->print_copies = pd.nCopies;
1505
wdev->user_media_size[0] = devmode->dmPaperWidth / 254.0 * 72.0;
1506
wdev->user_media_size[1] = devmode->dmPaperLength / 254.0 * 72.0;
1507
wdev->user_paper = devmode->dmPaperSize;
1508
wdev->user_orient = devmode->dmOrientation;
1509
wdev->user_color = devmode->dmColor;
1511
if (devmode->dmFields & DM_DUPLEX) {
1512
wdev->Duplex_set = 1;
1513
wdev->Duplex = devmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
1514
wdev->tumble = devmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
1520
const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
1521
const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
1522
const char* output = (char*)(devnames)+(devnames->wOutputOffset);
1524
HDC hic = CreateIC(driver, device, output, devmode);
1527
xppinch = (float)GetDeviceCaps(hic, LOGPIXELSX);
1528
yppinch = (float)GetDeviceCaps(hic, LOGPIXELSY);
1529
wdev->user_media_size[0] = GetDeviceCaps(hic, PHYSICALWIDTH) * 72.0 / xppinch;
1530
wdev->user_media_size[1] = GetDeviceCaps(hic, PHYSICALHEIGHT) * 72.0 / yppinch;
1538
GlobalUnlock(pd.hDevMode);
1539
GlobalUnlock(pd.hDevNames);
1541
if (wdev->win32_hdevmode != NULL) {
1542
GlobalFree(wdev->win32_hdevmode);
1544
if (wdev->win32_hdevnames != NULL) {
1545
GlobalFree(wdev->win32_hdevnames);
1548
wdev->win32_hdevmode = pd.hDevMode;
1549
wdev->win32_hdevnames = pd.hDevNames;
1554
/* Check that we are dealing with an original device. If this
1555
* happens to be a copy made by "copydevice", we will have to
1556
* copy the original's handles to the associated Win32 params.
1560
win_pr2_copy_check(gx_device_win_pr2 * wdev)
1562
HGLOBAL hdevmode = wdev->win32_hdevmode;
1563
HGLOBAL hdevnames = wdev->win32_hdevnames;
1564
DWORD devmode_len = (hdevmode) ? GlobalSize(hdevmode) : 0;
1565
DWORD devnames_len = (hdevnames) ? GlobalSize(hdevnames) : 0;
1567
if (wdev->original_device == wdev)
1570
wdev->hdcprn = NULL;
1571
wdev->win32_hdevmode = NULL;
1572
wdev->win32_hdevnames = NULL;
1574
wdev->original_device = wdev;
1577
wdev->win32_hdevmode = GlobalAlloc(0, devmode_len);
1578
if (wdev->win32_hdevmode) {
1579
memcpy(GlobalLock(wdev->win32_hdevmode), GlobalLock(hdevmode), devmode_len);
1580
GlobalUnlock(wdev->win32_hdevmode);
1581
GlobalUnlock(hdevmode);
1586
wdev->win32_hdevnames = GlobalAlloc(0, devnames_len);
1587
if (wdev->win32_hdevnames) {
1588
memcpy(GlobalLock(wdev->win32_hdevnames), GlobalLock(hdevnames), devnames_len);
1589
GlobalUnlock(wdev->win32_hdevnames);
1590
GlobalUnlock(hdevnames);
1595
/* Modeless dialog box - Cancel printing */
1597
CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1601
SetWindowText(hDlg, szAppName);
1604
switch (LOWORD(wParam)) {
1606
DestroyWindow(hDlg);
1615
AbortProc2(HDC hdcPrn, int code)
1617
process_interrupts(NULL);
1618
if (code == SP_OUTOFDISK)
1619
return (FALSE); /* cancel job */