~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to devices/gdevwpr2.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
 
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
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.
 
10
 
 
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.
 
14
*/
 
15
 
 
16
 
 
17
/*
 
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)
 
31
 */
 
32
 
 
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.
 
40
 *
 
41
 * This driver doesn't work with some Windows printer drivers.
 
42
 * The reason is unknown.  All printers to which I have access
 
43
 * work.
 
44
 *
 
45
 * rjl 1997-11-20
 
46
 */
 
47
 
 
48
/* Additions by Pierre Arnaud (Pierre.Arnaud@opac.ch)
 
49
 *
 
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).
 
54
 *
 
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
 
58
 * the following keys:
 
59
 *
 
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.
 
63
 *
 
64
 *  SelectedRange  [begin end]          (int array, can be set)
 
65
 *      Defines the pages the user wants to print.
 
66
 *
 
67
 *  MediaSize      [width height]       (float array, read only)
 
68
 *      Current printer's media size.
 
69
 *
 
70
 *  Copies         n                    (integer, can be set)
 
71
 *      User selected number of copies.
 
72
 *
 
73
 *  PrintCopies    n                    (integer, read only)
 
74
 *      Number of copies which must be printed by Ghostscript itself.
 
75
 *      This is still experimental.
 
76
 *
 
77
 *  DocumentName   name                 (string, can be set)
 
78
 *      Name to be associated with the print job.
 
79
 *
 
80
 *  UserChangedSettings                 (bool, read only)
 
81
 *      Set to 'true' if the last QueryUser operation succeeded.
 
82
 *
 
83
 *  Paper          n                    (integer, can be set)
 
84
 *      Windows paper selection (0 = automatic).
 
85
 *
 
86
 *  Orient         n                    (integer, can be set)
 
87
 *      Windows paper orientation (0 = automatic).
 
88
 *
 
89
 *  Color          n                    (integer, can be set)
 
90
 *      Windows color (0 = automatic, 1 = monochrome, 2 = color).
 
91
 *
 
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).
 
97
 */
 
98
 
 
99
/* Supported printer parameters are :
 
100
 *
 
101
 *  -dBitsPerPixel=n
 
102
 *     Override what the Window printer driver returns.
 
103
 *
 
104
 *  -dNoCancel
 
105
 *     Don't display cancel dialog box.  Useful for unattended or
 
106
 *     console EXE operation.
 
107
 *
 
108
 *  -dQueryUser=n
 
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
 
112
 *     supported for n:
 
113
 *     1 => show standard Print dialog
 
114
 *     2 => show Print Setup dialog instead
 
115
 *     3 => select default printer
 
116
 *     other, does nothing
 
117
 *
 
118
 * The /Duplex & /Tumble keys of the setpagedevice dict are supported
 
119
 * if the Windows printer supports duplex printing.
 
120
 */
 
121
 
 
122
#include "gdevprn.h"
 
123
#include "gdevpccm.h"
 
124
 
 
125
#include "windows_.h"
 
126
#include <shellapi.h>
 
127
#include "gp_mswin.h"
 
128
 
 
129
#include "gp.h"
 
130
#include "gpcheck.h"
 
131
#include "commdlg.h"
 
132
#include "gsicc_manage.h"
 
133
 
 
134
/* Make sure we cast to the correct structure type. */
 
135
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
 
136
 
 
137
#undef wdev
 
138
#define wdev ((gx_device_win_pr2 *)dev)
 
139
 
 
140
/* Device procedures */
 
141
 
 
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);
 
150
 
 
151
static int win_pr2_set_bpp(gx_device * dev, int depth);
 
152
 
 
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);
 
157
 
 
158
#define PARENT_WINDOW  HWND_DESKTOP
 
159
BOOL CALLBACK CancelDlgProc(HWND, UINT, WPARAM, LPARAM);
 
160
BOOL CALLBACK AbortProc2(HDC, int);
 
161
 
 
162
/* The device descriptor */
 
163
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
 
164
struct gx_device_win_pr2_s {
 
165
    gx_device_common;
 
166
    gx_prn_device_common;
 
167
    HDC hdcprn;
 
168
    bool nocancel;
 
169
 
 
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) */
 
189
 
 
190
    HANDLE win32_hdevmode;      /* handle to device mode information */
 
191
    HANDLE win32_hdevnames;     /* handle to device names information */
 
192
 
 
193
    DLGPROC lpfnAbortProc;
 
194
    DLGPROC lpfnCancelProc;
 
195
    HWND hDlgModeless;
 
196
 
 
197
    bool use_old_spool_name;    /* user prefers old \\spool\ name */
 
198
    gx_device_win_pr2* original_device; /* used to detect copies */
 
199
};
 
200
 
 
201
gx_device_win_pr2 far_data gs_mswinpr2_device =
 
202
{
 
203
    prn_device_std_body(gx_device_win_pr2, win_pr2_procs, "mswinpr2",
 
204
                      DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72.0, 72.0,
 
205
                        0, 0, 0, 0,
 
206
                        0, win_pr2_print_page),         /* depth = 0 */
 
207
    0,                          /* hdcprn */
 
208
    0,                          /* nocancel */
 
209
    0,                          /* doc_page_begin */
 
210
    0,                          /* doc_page_end */
 
211
    0,                          /* user_page_begin */
 
212
    0,                          /* user_page_end */
 
213
    1,                          /* user_copies */
 
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 */
 
220
    0,                          /* user_paper */
 
221
    0,                          /* user_orient */
 
222
    0,                          /* user_color */
 
223
    0,                          /* max_dpi */
 
224
    0,                          /* ratio */
 
225
    0,                          /* selected_bpp */
 
226
    false,                      /* tumble */
 
227
    -1,                         /* query_user */
 
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 */
 
235
};
 
236
 
 
237
/********************************************************************************/
 
238
 
 
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);
 
246
 
 
247
/********************************************************************************/
 
248
 
 
249
/* Open the win_pr2 driver */
 
250
static int
 
251
win_pr2_open(gx_device * dev)
 
252
{
 
253
    int code, code1;
 
254
    int depth;
 
255
    PRINTDLG pd;
 
256
    POINT offset;
 
257
    POINT size;
 
258
    float m[4];
 
259
    FILE *pfile;
 
260
    DOCINFO docinfo;
 
261
    float ratio = 1.0;
 
262
 
 
263
    win_pr2_copy_check(wdev);
 
264
 
 
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. */
 
270
 
 
271
        LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
 
272
        LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
 
273
 
 
274
        const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
 
275
        const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
 
276
        const char* output = (char*)(devnames)+(devnames->wOutputOffset);
 
277
 
 
278
        wdev->hdcprn = CreateDC(driver, device, output, devmode);
 
279
 
 
280
        GlobalUnlock(wdev->win32_hdevmode);
 
281
        GlobalUnlock(wdev->win32_hdevnames);
 
282
 
 
283
        if (wdev->hdcprn == NULL) {
 
284
            return gs_error_Fatal;
 
285
        }
 
286
 
 
287
    } else if (!win_pr2_getdc(wdev)) {
 
288
        /* couldn't get a printer from -sOutputFile= */
 
289
        /* Prompt with dialog box */
 
290
 
 
291
        LPDEVMODE devmode = NULL;
 
292
        memset(&pd, 0, sizeof(pd));
 
293
 
 
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;
 
302
 
 
303
        if (!PrintDlg(&pd)) {
 
304
            /* device not opened - exit ghostscript */
 
305
            return gs_error_Fatal;      /* exit Ghostscript cleanly */
 
306
        }
 
307
 
 
308
        devmode = GlobalLock(pd.hDevMode);
 
309
        win_pr2_update_dev(wdev,devmode);
 
310
        GlobalUnlock(pd.hDevMode);
 
311
 
 
312
        if (wdev->win32_hdevmode)
 
313
            GlobalFree(wdev->win32_hdevmode);
 
314
        if (wdev->win32_hdevnames)
 
315
            GlobalFree(wdev->win32_hdevnames);
 
316
 
 
317
        wdev->hdcprn = pd.hDC;
 
318
        wdev->win32_hdevmode = pd.hDevMode;
 
319
        wdev->win32_hdevnames = pd.hDevNames;
 
320
 
 
321
        pd.hDevMode = NULL;
 
322
        pd.hDevNames = NULL;
 
323
    }
 
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;
 
328
    }
 
329
    /* initialise printer, install abort proc */
 
330
    wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
 
331
    SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);
 
332
 
 
333
    /*
 
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.
 
337
     */
 
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;*/
 
344
 
 
345
    if (docinfo.lpszDocName[0] == 0) {
 
346
        docinfo.lpszDocName = "Ghostscript output";
 
347
    }
 
348
 
 
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;
 
354
    }
 
355
 
 
356
    dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
 
357
    dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
 
358
 
 
359
    wdev->ratio = 1;
 
360
 
 
361
    if (wdev->max_dpi > 50) {
 
362
 
 
363
        float dpi_x = dev->x_pixels_per_inch;
 
364
        float dpi_y = dev->y_pixels_per_inch;
 
365
 
 
366
        while ((dev->x_pixels_per_inch > wdev->max_dpi)
 
367
            || (dev->y_pixels_per_inch > wdev->max_dpi)) {
 
368
            ratio += 1.0;
 
369
            wdev->ratio ++;
 
370
            dev->x_pixels_per_inch = dpi_x / ratio;
 
371
            dev->y_pixels_per_inch = dpi_y / ratio;
 
372
        }
 
373
    }
 
374
 
 
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);
 
380
 
 
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);
 
387
 
 
388
    depth = dev->color_info.depth;
 
389
    if (depth == 0) {
 
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);
 
394
    }
 
395
    code1 = win_pr2_set_bpp(dev, depth);
 
396
 
 
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,
 
402
                                 wdev->fname, "wb");
 
403
    fclose(pfile);
 
404
    code = gdev_prn_open(dev);
 
405
    if ((code < 0) && wdev->fname[0])
 
406
        unlink(wdev->fname);
 
407
 
 
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);
 
414
    }
 
415
    if (code1 < 0 && code >= 0) {
 
416
        code = code1;
 
417
    }
 
418
 
 
419
    return code;
 
420
};
 
421
 
 
422
/* Close the win_pr2 driver */
 
423
static int
 
424
win_pr2_close(gx_device * dev)
 
425
{
 
426
    int code;
 
427
    int aborted = FALSE;
 
428
 
 
429
    win_pr2_copy_check(wdev);
 
430
 
 
431
    /* Free resources */
 
432
 
 
433
    if (!wdev->nocancel) {
 
434
        if (!wdev->hDlgModeless)
 
435
            aborted = TRUE;
 
436
        else
 
437
            DestroyWindow(wdev->hDlgModeless);
 
438
        wdev->hDlgModeless = 0;
 
439
    }
 
440
    if (aborted)
 
441
        AbortDoc(wdev->hdcprn);
 
442
    else
 
443
        EndDoc(wdev->hdcprn);
 
444
 
 
445
    DeleteDC(wdev->hdcprn);
 
446
 
 
447
    if (wdev->win32_hdevmode != NULL) {
 
448
        GlobalFree(wdev->win32_hdevmode);
 
449
        wdev->win32_hdevmode = NULL;
 
450
    }
 
451
    if (wdev->win32_hdevnames != NULL) {
 
452
        GlobalFree(wdev->win32_hdevnames);
 
453
        wdev->win32_hdevnames = NULL;
 
454
    }
 
455
 
 
456
    code = gdev_prn_close(dev);
 
457
 
 
458
    /* delete unwanted temporary file */
 
459
    if (wdev->fname[0])
 
460
        unlink(wdev->fname);
 
461
 
 
462
    return code;
 
463
}
 
464
 
 
465
/* ------ Internal routines ------ */
 
466
 
 
467
#undef wdev
 
468
#define wdev ((gx_device_win_pr2 *)pdev)
 
469
 
 
470
/********************************************************************************/
 
471
 
 
472
/* ------ Private definitions ------ */
 
473
 
 
474
/* new win_pr2_print_page routine */
 
475
 
 
476
/* Write BMP header to memory, then send bitmap to printer */
 
477
/* one scan line at a time */
 
478
static int
 
479
win_pr2_print_page(gx_device_printer * pdev, FILE * file)
 
480
{
 
481
    int raster = gdev_prn_raster(pdev);
 
482
 
 
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;
 
487
    int width;
 
488
    int depth = pdev->color_info.depth;
 
489
    byte *row;
 
490
    int y;
 
491
    int code = 0;               /* return code */
 
492
    MSG msg;
 
493
    char dlgtext[32];
 
494
    HGLOBAL hrow;
 
495
    int ratio = ((gx_device_win_pr2 *)pdev)->ratio;
 
496
 
 
497
    struct bmi_s {
 
498
        BITMAPINFOHEADER h;
 
499
        RGBQUAD pal[256];
 
500
    } bmi;
 
501
 
 
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));
 
505
 
 
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);
 
512
 
 
513
    /* Write the info header. */
 
514
 
 
515
    bmi.h.biSize = sizeof(bmi.h);
 
516
    bmi.h.biWidth = pdev->width;        /* wdev->mdev.width; */
 
517
    bmi.h.biHeight = yslice;
 
518
    bmi.h.biPlanes = 1;
 
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 */
 
524
 
 
525
    StartPage(wdev->hdcprn);
 
526
 
 
527
    /* Write the palette. */
 
528
 
 
529
    if (depth <= 8) {
 
530
        int i;
 
531
        gx_color_value rgb[3];
 
532
        LPRGBQUAD pq;
 
533
 
 
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);
 
539
            pq = &bmi.pal[i];
 
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]);
 
543
            pq->rgbReserved = 0;
 
544
        }
 
545
    } else {
 
546
        bmi.h.biClrUsed = 0;
 
547
        bmi.h.biClrImportant = 0;
 
548
    }
 
549
 
 
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);
 
554
    }
 
555
    for (y = 0; y < scan_lines;) {
 
556
        /* copy slice to row buffer */
 
557
        if (y > scan_lines - yslice)
 
558
            lines = scan_lines - y;
 
559
        else
 
560
            lines = yslice;
 
561
        for (i = 0; i < lines; i++)
 
562
            gdev_prn_copy_scan_lines(pdev, y + i,
 
563
                              row + (bmp_raster * (lines - 1 - i)), raster);
 
564
 
 
565
        if (ratio > 1) {
 
566
            StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio,
 
567
                          0, 0, pdev->width, lines,
 
568
                          row,
 
569
                          (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY);
 
570
        } else {
 
571
            SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines,
 
572
                              0, 0, 0, lines,
 
573
                              row,
 
574
                              (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS);
 
575
        }
 
576
        y += lines;
 
577
 
 
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);
 
582
        }
 
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);
 
588
            }
 
589
        }
 
590
        if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) {
 
591
            /* user pressed cancel button */
 
592
            break;
 
593
        }
 
594
    }
 
595
 
 
596
    if ((!wdev->nocancel) && (wdev->hDlgModeless == 0))
 
597
        code = gs_error_Fatal;  /* exit Ghostscript cleanly */
 
598
    else {
 
599
        /* push out the page */
 
600
        if (!wdev->nocancel)
 
601
            SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE),
 
602
                          "Ejecting page...");
 
603
        EndPage(wdev->hdcprn);
 
604
        if (!wdev->nocancel)
 
605
            ShowWindow(wdev->hDlgModeless, SW_HIDE);
 
606
    }
 
607
 
 
608
    GlobalUnlock(hrow);
 
609
    GlobalFree(hrow);
 
610
 
 
611
    return code;
 
612
}
 
613
 
 
614
/* combined color mappers */
 
615
 
 
616
/* 24-bit color mappers (taken from gdevmem2.c). */
 
617
/* Note that Windows expects RGB values in the order B,G,R. */
 
618
 
 
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[])
 
622
{
 
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) {
 
627
        case 1:
 
628
            return gdev_prn_map_rgb_color(dev, cv);
 
629
        case 4:
 
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);
 
634
        case 8:
 
635
            return pc_8bit_map_rgb_color(dev, cv);
 
636
        case 24:
 
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);
 
640
    }
 
641
    return 0;                   /* error */
 
642
}
 
643
 
 
644
/* Map a color index to a r-g-b color. */
 
645
static int
 
646
win_pr2_map_color_rgb(gx_device * dev, gx_color_index color,
 
647
                      gx_color_value prgb[3])
 
648
{
 
649
    switch (dev->color_info.depth) {
 
650
        case 1:
 
651
            gdev_prn_map_color_rgb(dev, color, prgb);
 
652
            break;
 
653
        case 4:
 
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;
 
658
            break;
 
659
        case 8:
 
660
            pc_8bit_map_color_rgb(dev, color, prgb);
 
661
            break;
 
662
        case 24:
 
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);
 
666
            break;
 
667
    }
 
668
    return 0;
 
669
}
 
670
 
 
671
static int
 
672
win_pr2_set_bpp(gx_device * dev, int depth)
 
673
{
 
674
    int code = 0;
 
675
    gx_device_printer *pdev = (gx_device_printer *)dev;
 
676
 
 
677
    if (depth > 8) {
 
678
        static const gx_device_color_info win_pr2_24color = dci_std_color(24);
 
679
 
 
680
        dev->color_info = win_pr2_24color;
 
681
        depth = 24;
 
682
 
 
683
        if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
 
684
             wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsRGB))) {
 
685
 
 
686
            if (wdev->icc_struct) {
 
687
                rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
 
688
            }
 
689
            wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
 
690
 
 
691
            if (wdev->icc_struct) {
 
692
                code = gsicc_set_device_profile(dev, dev->memory,
 
693
                  (char *)DEFAULT_RGB_ICC, gsDEFAULTPROFILE);
 
694
            }
 
695
            else {
 
696
                code = gs_error_VMerror;
 
697
            }
 
698
        }
 
699
 
 
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;
 
704
 
 
705
        dev->color_info = win_pr2_8color;
 
706
        depth = 8;
 
707
 
 
708
        if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
 
709
             wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsRGB))) {
 
710
 
 
711
            if (wdev->icc_struct) {
 
712
                rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
 
713
            }
 
714
            wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
 
715
 
 
716
            if (wdev->icc_struct) {
 
717
                code = gsicc_set_device_profile(dev, dev->memory,
 
718
                  (char *)DEFAULT_RGB_ICC, gsDEFAULTPROFILE);
 
719
            }
 
720
            else {
 
721
                code = gs_error_VMerror;
 
722
            }
 
723
        }
 
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);
 
729
 
 
730
        dev->color_info = win_pr2_4color;
 
731
        depth = 4;
 
732
 
 
733
        if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
 
734
             wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsCMYK))) {
 
735
 
 
736
            if (wdev->icc_struct) {
 
737
                rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
 
738
            }
 
739
            wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
 
740
 
 
741
            if (wdev->icc_struct) {
 
742
                code = gsicc_set_device_profile(dev, dev->memory,
 
743
                  (char *)DEFAULT_CMYK_ICC, gsDEFAULTPROFILE);
 
744
            }
 
745
            else {
 
746
                code = gs_error_VMerror;
 
747
            }
 
748
        }
 
749
    } else {                    /* default is black_and_white */
 
750
        static const gx_device_color_info win_pr2_1color = dci_std_color(1);
 
751
 
 
752
        dev->color_info = win_pr2_1color;
 
753
        depth = 1;
 
754
 
 
755
        if (!wdev->user_icc && (!wdev->icc_struct || (wdev->icc_struct &&
 
756
             wdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsGRAY))) {
 
757
 
 
758
            if (wdev->icc_struct) {
 
759
                rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
 
760
            }
 
761
            wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
 
762
 
 
763
            if (wdev->icc_struct) {
 
764
                code = gsicc_set_device_profile(dev, dev->memory,
 
765
                  (char *)DEFAULT_GRAY_ICC, gsDEFAULTPROFILE);
 
766
            }
 
767
            else {
 
768
                code = gs_error_VMerror;
 
769
            }
 
770
        }
 
771
    }
 
772
 
 
773
    wdev->selected_bpp = depth;
 
774
 
 
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;
 
778
    if (depth == 1) {
 
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;
 
783
    }
 
784
    else {
 
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;
 
789
    }
 
790
    return(code);
 
791
}
 
792
 
 
793
/********************************************************************************/
 
794
 
 
795
/* Get device parameters */
 
796
int
 
797
win_pr2_get_params(gx_device * pdev, gs_param_list * plist)
 
798
{
 
799
    int code = gdev_prn_get_params(pdev, plist);
 
800
 
 
801
    win_pr2_copy_check(wdev);
 
802
 
 
803
    if (code >= 0)
 
804
        code = param_write_bool(plist, "NoCancel",
 
805
                                &(wdev->nocancel));
 
806
    if (code >= 0)
 
807
        code = param_write_int(plist, "QueryUser",
 
808
                                &(wdev->query_user));
 
809
    if (code >= 0)
 
810
        code = win_pr2_write_user_settings(wdev, plist);
 
811
 
 
812
    if ((code >= 0) && (wdev->Duplex_set > 0))
 
813
        code = param_write_bool(plist, "Tumble",
 
814
                                &(wdev->tumble));
 
815
 
 
816
    return code;
 
817
}
 
818
 
 
819
/* We implement this ourselves so that we can change BitsPerPixel */
 
820
/* before the device is opened */
 
821
int
 
822
win_pr2_put_params(gx_device * pdev, gs_param_list * plist)
 
823
{
 
824
    int ecode = 0, code;
 
825
    int old_bpp = pdev->color_info.depth;
 
826
    int bpp = old_bpp;
 
827
    bool tumble   = wdev->tumble;
 
828
    bool nocancel = wdev->nocancel;
 
829
    int queryuser = 0;
 
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;
 
836
 
 
837
    if (wdev->Duplex_set < 0) {
 
838
        wdev->Duplex_set = 0;
 
839
        wdev->Duplex = false;
 
840
        wdev->tumble = false;
 
841
    }
 
842
 
 
843
    win_pr2_copy_check(wdev);
 
844
 
 
845
    code = win_pr2_read_user_settings(wdev, plist);
 
846
 
 
847
    switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
 
848
        case 0:
 
849
            if (pdev->is_open) {
 
850
                if (wdev->selected_bpp == bpp) {
 
851
                    break;
 
852
                }
 
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);
 
856
                if (code < 0) {
 
857
                    ecode = code;
 
858
                }
 
859
                break;
 
860
            }
 
861
            goto bppe;
 
862
        default:
 
863
            ecode = code;
 
864
          bppe:param_signal_error(plist, "BitsPerPixel", ecode);
 
865
        case 1:
 
866
            break;
 
867
    }
 
868
 
 
869
    switch (code = param_read_bool(plist, "NoCancel", &nocancel)) {
 
870
        case 0:
 
871
            if (pdev->is_open) {
 
872
                if (wdev->nocancel == nocancel) {
 
873
                    break;
 
874
                }
 
875
                ecode = gs_error_rangecheck;
 
876
            } else {
 
877
                wdev->nocancel = nocancel;
 
878
                break;
 
879
            }
 
880
            goto nocancele;
 
881
        default:
 
882
            ecode = code;
 
883
          nocancele:param_signal_error(plist, "NoCancel", ecode);
 
884
        case 1:
 
885
            break;
 
886
    }
 
887
 
 
888
    switch (code = param_read_bool(plist, "Tumble", &tumble)) {
 
889
        case 0:
 
890
            wdev->tumble = tumble;
 
891
            break;
 
892
        default:
 
893
            ecode = code;
 
894
            param_signal_error(plist, "Tumble", ecode);
 
895
        case 1:
 
896
            break;
 
897
    }
 
898
 
 
899
    switch (code = param_read_int(plist, "QueryUser", &queryuser)) {
 
900
        case 0:
 
901
            if ((queryuser > 0) &&
 
902
                (queryuser < 4)) {
 
903
                win_pr2_print_setup_interaction(wdev, queryuser);
 
904
            }
 
905
            break;
 
906
        default:
 
907
            ecode = code;
 
908
            param_signal_error(plist, "QueryUser", ecode);
 
909
        case 1:
 
910
            break;
 
911
    }
 
912
 
 
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()
 
917
     */
 
918
    if (!wdev->user_icc) {
 
919
        gs_param_string icc_pro_dummy;
 
920
 
 
921
        wdev->user_icc = param_read_string(plist, "OutputICCProfile", &icc_pro_dummy) == 0;
 
922
    }
 
923
 
 
924
    if (ecode >= 0)
 
925
        ecode = gdev_prn_put_params(pdev, plist);
 
926
 
 
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) ) {
 
934
 
 
935
            LPDEVMODE pdevmode = GlobalLock(wdev->win32_hdevmode);
 
936
 
 
937
            if (pdevmode) {
 
938
                win_pr2_update_win(wdev, pdevmode);
 
939
                ResetDC(wdev->hdcprn, pdevmode);
 
940
                GlobalUnlock(pdevmode);
 
941
            }
 
942
        }
 
943
    }
 
944
 
 
945
    return ecode;
 
946
}
 
947
 
 
948
#undef wdev
 
949
 
 
950
/********************************************************************************/
 
951
 
 
952
/* Get Device Context for printer */
 
953
static int
 
954
win_pr2_getdc(gx_device_win_pr2 * wdev)
 
955
{
 
956
    char *device;
 
957
    char driverbuf[512];
 
958
    char *driver;
 
959
    char *output;
 
960
    char *devcap;
 
961
    int devcapsize;
 
962
    int devmode_size;
 
963
 
 
964
    int i, n;
 
965
    POINT *pp;
 
966
    int paperindex;
 
967
    int paperwidth, paperheight;
 
968
    int orientation;
 
969
    int papersize;
 
970
    char papername[64];
 
971
    LPDEVMODE podevmode, pidevmode;
 
972
    HANDLE hprinter;
 
973
 
 
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;
 
982
    } else {
 
983
        return FALSE;
 
984
    }
 
985
 
 
986
    /* now try to match the printer name against the [Devices] section */
 
987
#ifdef GS_NO_UTF8
 
988
    {
 
989
        char *devices = gs_malloc(wdev->memory, 4096, 1, "win_pr2_getdc");
 
990
        char *p;
 
991
        if (devices == (char *)NULL)
 
992
            return FALSE;
 
993
        GetProfileString("Devices", NULL, "", devices, 4096);
 
994
        p = devices;
 
995
        while (*p) {
 
996
            if (stricmp(p, device) == 0)
 
997
                break;
 
998
            p += strlen(p) + 1;
 
999
        }
 
1000
        if (*p == '\0')
 
1001
            p = NULL;
 
1002
        gs_free(wdev->memory, devices, 4096, 1, "win_pr2_getdc");
 
1003
        if (p == NULL)
 
1004
            return FALSE;  /* doesn't match an available printer */
 
1005
 
 
1006
        /* the printer exists, get the remaining information from win.ini */
 
1007
        GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
 
1008
    }
 
1009
#else
 
1010
    {
 
1011
        wchar_t unidrvbuf[sizeof(driverbuf)];
 
1012
        wchar_t *devices;
 
1013
        wchar_t *p;
 
1014
        wchar_t *unidev = malloc(utf8_to_wchar(NULL, device)*sizeof(wchar_t));
 
1015
        if (unidev == NULL)
 
1016
            return FALSE;
 
1017
        utf8_to_wchar(unidev, device);
 
1018
        devices = gs_malloc(wdev->memory, 8192, 1, "win_pr2_getdc");
 
1019
        if (devices == (wchar_t *)NULL) {
 
1020
            free(unidev);
 
1021
            return FALSE;
 
1022
        }
 
1023
        GetProfileStringW(L"Devices", NULL, L"", devices, 8192);
 
1024
        p = devices;
 
1025
        while (*p) {
 
1026
            if (wcsicmp(p, unidev) == 0)
 
1027
                break;
 
1028
            p += wcslen(p) + 1;
 
1029
        }
 
1030
        if (*p == '\0')
 
1031
            p = NULL;
 
1032
        gs_free(wdev->memory, devices, 8192, 1, "win_pr2_getdc");
 
1033
        if (p == NULL) {
 
1034
            free(unidev);
 
1035
            return FALSE;  /* doesn't match an available printer */
 
1036
        }
 
1037
 
 
1038
        /* the printer exists, get the remaining information from win.ini */
 
1039
        GetProfileStringW(L"Devices", unidev, L"", unidrvbuf, sizeof(unidrvbuf));
 
1040
        free(unidev);
 
1041
        i = wchar_to_utf8(NULL, unidrvbuf);
 
1042
        if (i < 0 || i > sizeof(driverbuf))
 
1043
            return FALSE;
 
1044
        wchar_to_utf8(driverbuf, unidrvbuf);
 
1045
    }
 
1046
#endif
 
1047
    driver = strtok(driverbuf, ",");
 
1048
    output = strtok(NULL, ",");
 
1049
 
 
1050
    if (!gp_OpenPrinter(device, &hprinter))
 
1051
        return FALSE;
 
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);
 
1056
        return FALSE;
 
1057
    }
 
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);
 
1061
        return FALSE;
 
1062
    }
 
1063
    DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);
 
1064
 
 
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)
 
1069
        return FALSE;
 
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';
 
1074
    papersize = 0;
 
1075
    paperindex = -1;
 
1076
    orientation = 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)) {
 
1081
            paperindex = i;
 
1082
            paperwidth = pp->x;
 
1083
            paperheight = pp->y;
 
1084
            orientation = DMORIENT_PORTRAIT;
 
1085
            break;
 
1086
        }
 
1087
    }
 
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)) {
 
1094
                paperindex = i;
 
1095
                paperwidth = pp->x;
 
1096
                paperheight = pp->y;
 
1097
                orientation = DMORIENT_LANDSCAPE;
 
1098
                break;
 
1099
            }
 
1100
        }
 
1101
    }
 
1102
    gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
 
1103
 
 
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)
 
1108
        return FALSE;
 
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");
 
1113
 
 
1114
    /* get the paper name */
 
1115
    devcapsize = DeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
 
1116
    devcapsize *= 64;
 
1117
    if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
 
1118
        return FALSE;
 
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");
 
1123
 
 
1124
    memcpy(pidevmode, podevmode, devmode_size);
 
1125
 
 
1126
    pidevmode->dmFields = 0;
 
1127
 
 
1128
    wdev->paper_name[0] = 0;
 
1129
 
 
1130
    if ( (wdev->user_paper)
 
1131
      && (wdev->user_paper != papersize) ) {
 
1132
        papersize = wdev->user_paper;
 
1133
        paperheight = 0;
 
1134
        paperwidth = 0;
 
1135
        papername[0] = 0;
 
1136
    }
 
1137
    if (wdev->user_orient) {
 
1138
        orientation = wdev->user_orient;
 
1139
    }
 
1140
 
 
1141
    pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
 
1142
    pidevmode->dmFields |= DM_DEFAULTSOURCE;
 
1143
    pidevmode->dmDefaultSource = 0;
 
1144
 
 
1145
    if (orientation) {
 
1146
        wdev->user_orient = orientation;
 
1147
    }
 
1148
    if (papersize) {
 
1149
        wdev->user_paper = papersize;
 
1150
        strcpy (wdev->paper_name, papername);
 
1151
    }
 
1152
 
 
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;
 
1159
    }
 
1160
 
 
1161
    if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
 
1162
        wdev->Duplex_set = 1;
 
1163
    }
 
1164
 
 
1165
    win_pr2_update_win(wdev, pidevmode);
 
1166
 
 
1167
    /* merge the entries */
 
1168
    DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
 
1169
    ClosePrinter(hprinter);
 
1170
 
 
1171
    /* now get a DC */
 
1172
    wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
 
1173
 
 
1174
    if (wdev->win32_hdevmode == NULL)
 
1175
        wdev->win32_hdevmode = GlobalAlloc(0, devmode_size);
 
1176
 
 
1177
    if (wdev->win32_hdevmode) {
 
1178
        LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
 
1179
        if (pdevmode) {
 
1180
            memcpy(pdevmode, podevmode, devmode_size);
 
1181
            GlobalUnlock(wdev->win32_hdevmode);
 
1182
        }
 
1183
    }
 
1184
 
 
1185
    gs_free(wdev->memory, pidevmode, devmode_size, 1, "win_pr2_getdc");
 
1186
    gs_free(wdev->memory, podevmode, devmode_size, 1, "win_pr2_getdc");
 
1187
 
 
1188
    if (wdev->hdcprn != (HDC) NULL)
 
1189
        return TRUE;            /* success */
 
1190
 
 
1191
    /* fall back to prompting user */
 
1192
    return FALSE;
 
1193
}
 
1194
 
 
1195
/*
 
1196
 *  Minimalist update of the wdev parameters (mainly for the
 
1197
 *  UserSettings parameters).
 
1198
 */
 
1199
 
 
1200
static int
 
1201
win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
 
1202
{
 
1203
    if (pdevmode == 0)
 
1204
        return FALSE;
 
1205
 
 
1206
    if (pdevmode->dmFields & DM_COLOR) {
 
1207
        dev->user_color = pdevmode->dmColor;
 
1208
    }
 
1209
    if (pdevmode->dmFields & DM_ORIENTATION) {
 
1210
        dev->user_orient = pdevmode->dmOrientation;
 
1211
    }
 
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 */
 
1217
    }
 
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;
 
1222
    }
 
1223
 
 
1224
    return TRUE;
 
1225
}
 
1226
 
 
1227
static int
 
1228
win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
 
1229
{
 
1230
    if (dev->Duplex_set > 0) {
 
1231
        pdevmode->dmFields |= DM_DUPLEX;
 
1232
        pdevmode->dmDuplex = DMDUP_SIMPLEX;
 
1233
        if (dev->Duplex) {
 
1234
            if (dev->tumble == false) {
 
1235
                pdevmode->dmDuplex = DMDUP_VERTICAL;
 
1236
            } else {
 
1237
                pdevmode->dmDuplex = DMDUP_HORIZONTAL;
 
1238
            }
 
1239
        }
 
1240
    }
 
1241
 
 
1242
    if (dev->user_color) {
 
1243
        pdevmode->dmColor = dev->user_color;
 
1244
        pdevmode->dmFields |= DM_COLOR;
 
1245
    }
 
1246
 
 
1247
    if (dev->user_orient) {
 
1248
        pdevmode->dmFields |= DM_ORIENTATION;
 
1249
        pdevmode->dmOrientation = dev->user_orient;
 
1250
    }
 
1251
 
 
1252
    if (dev->user_paper) {
 
1253
        pdevmode->dmFields |= DM_PAPERSIZE;
 
1254
        pdevmode->dmPaperSize = dev->user_paper;
 
1255
    }
 
1256
    return 0;
 
1257
}
 
1258
 
 
1259
/********************************************************************************/
 
1260
 
 
1261
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
 
1262
  switch ( code = pread(dict.list, (param_name = pname), &(pa)) )\
 
1263
  {\
 
1264
  case 0:\
 
1265
        if ( (pa).size != psize )\
 
1266
          ecode = gs_note_error(gs_error_rangecheck);\
 
1267
        else {
 
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)\
 
1272
        }\
 
1273
        goto e;\
 
1274
  default:\
 
1275
        ecode = code;\
 
1276
e:      param_signal_error(dict.list, param_name, ecode);\
 
1277
  case 1:\
 
1278
        (pa).data = 0;          /* mark as not filled */\
 
1279
  }
 
1280
 
 
1281
/* Put the user params from UserSettings into our */
 
1282
/* internal variables. */
 
1283
static int
 
1284
win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
 
1285
{
 
1286
    gs_param_dict dict;
 
1287
    gs_param_string docn = { 0 };
 
1288
    const char* dict_name = "UserSettings";
 
1289
    const char* param_name = "";
 
1290
    int code = 0;
 
1291
    int ecode = 0;
 
1292
 
 
1293
    switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
 
1294
        default:
 
1295
            param_signal_error(plist, dict_name, code);
 
1296
            return code;
 
1297
        case 1:
 
1298
            break;
 
1299
        case 0:
 
1300
            {
 
1301
                gs_param_int_array ia;
 
1302
 
 
1303
                BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
 
1304
                if ((ia.data[0] < 0) ||
 
1305
                    (ia.data[1] < 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)
 
1311
 
 
1312
                BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
 
1313
                if ((ia.data[0] < 0) ||
 
1314
                    (ia.data[1] < 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)
 
1320
 
 
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);
 
1326
 
 
1327
                switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
 
1328
                    case 0:
 
1329
                        if (docn.size < sizeof(wdev->doc_name))
 
1330
                            break;
 
1331
                        code = gs_error_rangecheck;
 
1332
                        /* fall through */
 
1333
                    default:
 
1334
                        ecode = code;
 
1335
                        param_signal_error(plist, param_name, ecode);
 
1336
                        /* fall through */
 
1337
                    case 1:
 
1338
                        docn.data = 0;
 
1339
                        break;
 
1340
                }
 
1341
 
 
1342
                param_end_read_dict(plist, dict_name, &dict);
 
1343
 
 
1344
                if (docn.data) {
 
1345
                    memcpy(wdev->doc_name, docn.data, docn.size);
 
1346
                    wdev->doc_name[docn.size] = 0;
 
1347
                }
 
1348
 
 
1349
                wdev->print_copies = 1;
 
1350
 
 
1351
                if (wdev->win32_hdevmode) {
 
1352
                    LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
 
1353
                    if (devmode) {
 
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);
 
1359
                    }
 
1360
                }
 
1361
            }
 
1362
            break;
 
1363
    }
 
1364
 
 
1365
    return code;
 
1366
}
 
1367
 
 
1368
static int
 
1369
win_pr2_write_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
 
1370
{
 
1371
    gs_param_dict dict;
 
1372
    gs_param_int_array range;
 
1373
    gs_param_float_array box;
 
1374
    gs_param_string docn;
 
1375
    gs_param_string papn;
 
1376
    int array[2];
 
1377
    const char* pname = "UserSettings";
 
1378
    int code;
 
1379
 
 
1380
    dict.size = 12;
 
1381
    code = param_begin_write_dict(plist, pname, &dict, false);
 
1382
    if (code < 0) return code;
 
1383
 
 
1384
    array[0] = wdev->doc_page_begin;
 
1385
    array[1] = wdev->doc_page_end;
 
1386
    range.data = array;
 
1387
    range.size = 2;
 
1388
    range.persistent = false;
 
1389
    code = param_write_int_array(dict.list, "DocumentRange", &range);
 
1390
    if (code < 0) goto error;
 
1391
 
 
1392
    array[0] = wdev->user_page_begin;
 
1393
    array[1] = wdev->user_page_end;
 
1394
    range.data = array;
 
1395
    range.size = 2;
 
1396
    range.persistent = false;
 
1397
    code = param_write_int_array(dict.list, "SelectedRange", &range);
 
1398
    if (code < 0) goto error;
 
1399
 
 
1400
    box.data = wdev->user_media_size;
 
1401
    box.size = 2;
 
1402
    box.persistent = false;
 
1403
    code = param_write_float_array(dict.list, "MediaSize", &box);
 
1404
    if (code < 0) goto error;
 
1405
 
 
1406
    code = param_write_int(dict.list, "Copies", &wdev->user_copies);
 
1407
    if (code < 0) goto error;
 
1408
 
 
1409
    code = param_write_int(dict.list, "Paper", &wdev->user_paper);
 
1410
    if (code < 0) goto error;
 
1411
 
 
1412
    code = param_write_int(dict.list, "Orientation", &wdev->user_orient);
 
1413
    if (code < 0) goto error;
 
1414
 
 
1415
    code = param_write_int(dict.list, "Color", &wdev->user_color);
 
1416
    if (code < 0) goto error;
 
1417
 
 
1418
    code = param_write_int(dict.list, "MaxResolution", &wdev->max_dpi);
 
1419
    if (code < 0) goto error;
 
1420
 
 
1421
    code = param_write_int(dict.list, "PrintCopies", &wdev->print_copies);
 
1422
    if (code < 0) goto error;
 
1423
 
 
1424
    docn.data = (const byte*)wdev->doc_name;
 
1425
    docn.size = strlen(wdev->doc_name);
 
1426
    docn.persistent = false;
 
1427
 
 
1428
    code = param_write_string(dict.list, "DocumentName", &docn);
 
1429
    if (code < 0) goto error;
 
1430
 
 
1431
    papn.data = (const byte*)wdev->paper_name;
 
1432
    papn.size = strlen(wdev->paper_name);
 
1433
    papn.persistent = false;
 
1434
 
 
1435
    code = param_write_string(dict.list, "PaperName", &papn);
 
1436
    if (code < 0) goto error;
 
1437
 
 
1438
    code = param_write_bool(dict.list, "UserChangedSettings", &wdev->user_changed_settings);
 
1439
 
 
1440
error:
 
1441
    param_end_write_dict(plist, pname, &dict);
 
1442
    return code;
 
1443
}
 
1444
 
 
1445
/********************************************************************************/
 
1446
 
 
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.
 
1450
 */
 
1451
 
 
1452
static int
 
1453
win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode)
 
1454
{
 
1455
    PRINTDLG pd;
 
1456
    LPDEVMODE  devmode;
 
1457
    LPDEVNAMES devnames;
 
1458
 
 
1459
    wdev->user_changed_settings = FALSE;
 
1460
    wdev->query_user = mode;
 
1461
 
 
1462
    memset(&pd, 0, sizeof(pd));
 
1463
    pd.lStructSize = sizeof(pd);
 
1464
    pd.hwndOwner = PARENT_WINDOW;
 
1465
 
 
1466
    switch (mode) {
 
1467
        case 2: pd.Flags = PD_PRINTSETUP; break;
 
1468
        case 3: pd.Flags = PD_RETURNDEFAULT; break;
 
1469
        default: pd.Flags = 0; break;
 
1470
    }
 
1471
 
 
1472
    pd.Flags |= PD_USEDEVMODECOPIES;
 
1473
 
 
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;
 
1479
 
 
1480
    /* Show the Print Setup dialog and let the user choose a printer
 
1481
     * and a paper size/orientation.
 
1482
     */
 
1483
 
 
1484
    if (!PrintDlg(&pd)) return FALSE;
 
1485
 
 
1486
    devmode = (LPDEVMODE) GlobalLock(pd.hDevMode);
 
1487
    devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);
 
1488
 
 
1489
    wdev->user_changed_settings = TRUE;
 
1490
    if (wdev->use_old_spool_name) {
 
1491
        gs_sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
 
1492
    } else {
 
1493
        gs_sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
 
1494
    }
 
1495
 
 
1496
    if (mode == 3) {
 
1497
        devmode->dmCopies = wdev->user_copies * wdev->print_copies;
 
1498
        pd.nCopies = 1;
 
1499
    }
 
1500
 
 
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;
 
1510
 
 
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;
 
1515
    }
 
1516
 
 
1517
    {
 
1518
        float xppinch = 0;
 
1519
        float yppinch = 0;
 
1520
        const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
 
1521
        const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
 
1522
        const char* output = (char*)(devnames)+(devnames->wOutputOffset);
 
1523
 
 
1524
        HDC hic = CreateIC(driver, device, output, devmode);
 
1525
 
 
1526
        if (hic) {
 
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;
 
1531
            DeleteDC(hic);
 
1532
        }
 
1533
    }
 
1534
 
 
1535
    devmode = NULL;
 
1536
    devnames = NULL;
 
1537
 
 
1538
    GlobalUnlock(pd.hDevMode);
 
1539
    GlobalUnlock(pd.hDevNames);
 
1540
 
 
1541
    if (wdev->win32_hdevmode != NULL) {
 
1542
        GlobalFree(wdev->win32_hdevmode);
 
1543
    }
 
1544
    if (wdev->win32_hdevnames != NULL) {
 
1545
        GlobalFree(wdev->win32_hdevnames);
 
1546
    }
 
1547
 
 
1548
    wdev->win32_hdevmode = pd.hDevMode;
 
1549
    wdev->win32_hdevnames = pd.hDevNames;
 
1550
 
 
1551
    return TRUE;
 
1552
}
 
1553
 
 
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.
 
1557
 */
 
1558
 
 
1559
static void
 
1560
win_pr2_copy_check(gx_device_win_pr2 * wdev)
 
1561
{
 
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;
 
1566
 
 
1567
    if (wdev->original_device == wdev)
 
1568
        return;
 
1569
 
 
1570
    wdev->hdcprn = NULL;
 
1571
    wdev->win32_hdevmode = NULL;
 
1572
    wdev->win32_hdevnames = NULL;
 
1573
 
 
1574
    wdev->original_device = wdev;
 
1575
 
 
1576
    if (devmode_len) {
 
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);
 
1582
        }
 
1583
    }
 
1584
 
 
1585
    if (devnames_len) {
 
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);
 
1591
        }
 
1592
    }
 
1593
}
 
1594
 
 
1595
/* Modeless dialog box - Cancel printing */
 
1596
BOOL CALLBACK
 
1597
CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 
1598
{
 
1599
    switch (message) {
 
1600
        case WM_INITDIALOG:
 
1601
            SetWindowText(hDlg, szAppName);
 
1602
            return TRUE;
 
1603
        case WM_COMMAND:
 
1604
            switch (LOWORD(wParam)) {
 
1605
                case IDCANCEL:
 
1606
                    DestroyWindow(hDlg);
 
1607
                    EndDialog(hDlg, 0);
 
1608
                    return TRUE;
 
1609
            }
 
1610
    }
 
1611
    return FALSE;
 
1612
}
 
1613
 
 
1614
BOOL CALLBACK
 
1615
AbortProc2(HDC hdcPrn, int code)
 
1616
{
 
1617
    process_interrupts(NULL);
 
1618
    if (code == SP_OUTOFDISK)
 
1619
        return (FALSE);         /* cancel job */
 
1620
    return (TRUE);
 
1621
}