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

« back to all changes in this revision

Viewing changes to devices/gdevos2p.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
 * OS/2 printer device
 
18
 *
 
19
 * By Russell Lang, derived from mswinpr2 device by Russell Lang and
 
20
 * L. Peter Deutsch, Aladdin Enterprises.
 
21
 *
 
22
 * Bug fixed by Pierre Arnaud 2000-03-20 (os2prn_set_bpp did not set anti_alias)
 
23
 */
 
24
 
 
25
/* This device works when GS is a DLL loaded by a PM program */
 
26
/* It does not work when GS is a text mode EXE */
 
27
 
 
28
/* This driver uses the printer default size and resolution and
 
29
 * ignores page size and resolution set using -gWIDTHxHEIGHT and
 
30
 * -rXxY.  You must still set the correct PageSize to get the
 
31
 * correct clipping path.  If you don't specify a value for
 
32
 * -dBitsPerPixel, the depth will be obtained from the printer
 
33
 * device context.
 
34
 */
 
35
 
 
36
#define INCL_DOS
 
37
#define INCL_DOSERRORS
 
38
#define INCL_DEV
 
39
#define INCL_GPIBITMAPS
 
40
#define INCL_SPL
 
41
#define INCL_SPLDOSPRINT
 
42
#define INCL_SPLERRORS
 
43
 
 
44
#include <os2.h>
 
45
 
 
46
#include "gdevprn.h"
 
47
#include "gdevpccm.h"
 
48
#include "gp.h"
 
49
#include "gscdefs.h"            /* for gs_product */
 
50
 
 
51
extern HWND hwndtext;           /* in gp_os2.h */
 
52
 
 
53
typedef struct tagOS2QL {
 
54
    PRQINFO3 *prq;              /* queue list */
 
55
    ULONG len;                  /* bytes in queue list (for gs_free) */
 
56
    int defqueue;               /* default queue */
 
57
    int nqueues;                /* number of queues */
 
58
} OS2QL;
 
59
 
 
60
#ifndef NERR_BufTooSmall
 
61
#define NERR_BufTooSmall 2123   /* For SplEnumQueue */
 
62
#endif
 
63
 
 
64
/* Make sure we cast to the correct structure type. */
 
65
typedef struct gx_device_os2prn_s gx_device_os2prn;
 
66
 
 
67
#undef opdev
 
68
#define opdev ((gx_device_os2prn *)dev)
 
69
 
 
70
/* Device procedures */
 
71
 
 
72
/* See gxdevice.h for the definitions of the procedures. */
 
73
static dev_proc_open_device(os2prn_open);
 
74
static dev_proc_close_device(os2prn_close);
 
75
static dev_proc_print_page(os2prn_print_page);
 
76
static dev_proc_map_rgb_color(os2prn_map_rgb_color);
 
77
static dev_proc_map_color_rgb(os2prn_map_color_rgb);
 
78
static dev_proc_put_params(os2prn_put_params);
 
79
static dev_proc_get_params(os2prn_get_params);
 
80
 
 
81
static void os2prn_set_bpp(gx_device * dev, int depth);
 
82
static int os2prn_get_queue_list(gs_memory_t *mem, OS2QL * ql);
 
83
static void os2prn_free_queue_list(gs_memory_t *mem, OS2QL * ql);
 
84
int os2prn_get_printer(OS2QL * ql);
 
85
 
 
86
static gx_device_procs os2prn_procs =
 
87
prn_color_params_procs(os2prn_open, gdev_prn_output_page, os2prn_close,
 
88
                       os2prn_map_rgb_color, os2prn_map_color_rgb,
 
89
                       os2prn_get_params, os2prn_put_params);
 
90
 
 
91
/* The device descriptor */
 
92
struct gx_device_os2prn_s {
 
93
    gx_device_common;
 
94
    gx_prn_device_common;
 
95
    HAB hab;
 
96
    HDC hdc;
 
97
    HPS hps;
 
98
    char queue_name[256];       /* OS/2 printer queue name */
 
99
    int newframe;               /* false before first page */
 
100
    OS2QL ql;
 
101
    int clipbox[4];             /* llx, lly, urx, ury in pixels */
 
102
    HDC hdcMem;
 
103
    HPS hpsMem;
 
104
};
 
105
 
 
106
gx_device_os2prn far_data gs_os2prn_device =
 
107
{
 
108
    prn_device_std_body(gx_device_os2prn, os2prn_procs, "os2prn",
 
109
                        DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72, 72,
 
110
                        0, 0, 0, 0,
 
111
                        0, os2prn_print_page),  /* depth = 0 */
 
112
    0,                          /* hab */
 
113
    0,                          /* hdc */
 
114
    0,                          /* hps */
 
115
    ""                          /* queue_name */
 
116
};
 
117
 
 
118
/* Open the os2prn driver */
 
119
static int
 
120
os2prn_open(gx_device * dev)
 
121
{
 
122
    int code;
 
123
    PTIB pptib;
 
124
    PPIB pppib;
 
125
    DEVOPENSTRUC dop;
 
126
    ULONG cbBuf;
 
127
    ULONG cbNeeded;
 
128
    APIRET rc;
 
129
    PBYTE pbuf;
 
130
    char *p;
 
131
    SIZEL sizlPage;
 
132
    LONG caps[2];
 
133
    HCINFO hcinfo;
 
134
    LONG nforms;
 
135
    float m[4];
 
136
    int depth;
 
137
    FILE *pfile;
 
138
    int i;
 
139
    char *prefix = "\\\\spool\\";       /* 8 characters long */
 
140
 
 
141
    PRQINFO3 *pprq;
 
142
    gx_device_os2prn *oprn;
 
143
 
 
144
    oprn = opdev;
 
145
 
 
146
    if (DosGetInfoBlocks(&pptib, &pppib)) {
 
147
        errprintf(dev->memory, "\nos2prn_open: Couldn't get pid\n");
 
148
        return gs_error_limitcheck;
 
149
    }
 
150
    if (pppib->pib_ultype != 3) {
 
151
        /* if caller is not PM app */
 
152
        errprintf(dev->memory, "os2prn device can only be used from a PM application\n");
 
153
        return gs_error_limitcheck;
 
154
    }
 
155
    opdev->hab = WinQueryAnchorBlock(hwndtext);
 
156
    opdev->newframe = 0;
 
157
 
 
158
    if (os2prn_get_queue_list(dev->memory, &opdev->ql))
 
159
        return gs_error_limitcheck;
 
160
 
 
161
    if (opdev->queue_name[0] == '\0') {
 
162
        /* obtain printer name from filename */
 
163
        p = opdev->fname;
 
164
        for (i = 0; i < 8; i++) {
 
165
            if (prefix[i] == '\\') {
 
166
                if ((*p != '\\') && (*p != '/'))
 
167
                    break;
 
168
            } else if (tolower(*p) != prefix[i])
 
169
                break;
 
170
            p++;
 
171
        }
 
172
        if (i == 8 && (strlen(p) != 0))
 
173
            strcpy(opdev->queue_name, p);
 
174
    }
 
175
    pprq = NULL;
 
176
    if (opdev->queue_name[0] != '\0') {
 
177
        for (i = 0; i < opdev->ql.nqueues; i++) {
 
178
            if (strcmp(opdev->ql.prq[i].pszName, opdev->queue_name) == 0) {
 
179
                pprq = &(opdev->ql.prq[i]);
 
180
                break;
 
181
            }
 
182
        }
 
183
    } else {
 
184
        /* use default queue */
 
185
        pprq = &(opdev->ql.prq[opdev->ql.defqueue]);
 
186
    }
 
187
    if (pprq == (PRQINFO3 *) NULL) {
 
188
        errprintf(opdev->memory, "Invalid os2prn queue  name -sOS2QUEUE=\042%s\042\n", opdev->queue_name);
 
189
        errprintf(opdev->memory, "Valid device names are:\n");
 
190
        for (i = 0; i < opdev->ql.nqueues; i++) {
 
191
            errprintf(opdev->memory, "  -sOS2QUEUE=\042%s\042\n", opdev->ql.prq[i].pszName);
 
192
        }
 
193
        return gs_error_rangecheck;
 
194
    }
 
195
    /* open printer device */
 
196
    memset(&dop, 0, sizeof(dop));
 
197
    dop.pszLogAddress = pprq->pszName;  /* queue name */
 
198
    p = strchr(pprq->pszDriverName, '.');
 
199
    if (p != (char *)NULL)
 
200
        *p = '\0';
 
201
    dop.pszDriverName = pprq->pszDriverName;
 
202
    dop.pszDataType = "PM_Q_STD";
 
203
    dop.pdriv = pprq->pDriverData;
 
204
    opdev->hdc = DevOpenDC(opdev->hab, OD_QUEUED, "*", 9L, (PDEVOPENDATA) & dop, (HDC) NULL);
 
205
    if (opdev->hdc == DEV_ERROR) {
 
206
        ERRORID eid = WinGetLastError(opdev->hab);
 
207
 
 
208
        errprintf(opdev->memory, "DevOpenDC for printer error 0x%x\n", eid);
 
209
        return gs_error_limitcheck;
 
210
    }
 
211
    os2prn_free_queue_list(dev->memory, &opdev->ql);
 
212
 
 
213
    /* find out resolution of printer */
 
214
    /* this is returned in pixels/metre */
 
215
    DevQueryCaps(opdev->hdc, CAPS_HORIZONTAL_RESOLUTION, 2, caps);
 
216
    dev->x_pixels_per_inch = (int)(caps[0] * 0.0254 + 0.5);
 
217
    dev->y_pixels_per_inch = (int)(caps[1] * 0.0254 + 0.5);
 
218
 
 
219
    /* find out page size and margins */
 
220
    /* these are returned in millimetres */
 
221
    nforms = DevQueryHardcopyCaps(opdev->hdc, 0, 0, &hcinfo);
 
222
    for (i = 0; i < nforms; i++) {
 
223
        DevQueryHardcopyCaps(opdev->hdc, i, 1, &hcinfo);
 
224
        if (hcinfo.flAttributes & HCAPS_CURRENT)
 
225
            break;              /* this is the default page size */
 
226
    }
 
227
    /* GS size is in pixels */
 
228
    dev->width = hcinfo.cx * caps[0] / 1000;
 
229
    dev->height = hcinfo.cy * caps[1] / 1000;
 
230
    /* GS margins are in inches */
 
231
    m[0] /*left */  = hcinfo.xLeftClip / 25.4;
 
232
    m[1] /*bottom */  = hcinfo.yBottomClip / 25.4;
 
233
    m[2] /*right */  = (hcinfo.cx - hcinfo.xRightClip) / 25.4;
 
234
    m[3] /*top */  = (hcinfo.cy - hcinfo.yTopClip) / 25.4;
 
235
    gx_device_set_margins(dev, m, true);
 
236
    /* set bounding box in pixels for later drawing */
 
237
    opdev->clipbox[0] = (int)(hcinfo.xLeftClip / 25.4 * dev->x_pixels_per_inch + 1);    /* round inwards */
 
238
    opdev->clipbox[1] = (int)(hcinfo.yBottomClip / 25.4 * dev->y_pixels_per_inch + 1);
 
239
    opdev->clipbox[2] = (int)(hcinfo.xRightClip / 25.4 * dev->x_pixels_per_inch);
 
240
    opdev->clipbox[3] = (int)(hcinfo.yTopClip / 25.4 * dev->y_pixels_per_inch);
 
241
 
 
242
    /* get presentation space */
 
243
    sizlPage.cx = dev->width;
 
244
    sizlPage.cy = dev->height;
 
245
    opdev->hps = GpiCreatePS(opdev->hab, opdev->hdc, &sizlPage,
 
246
                         PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
 
247
 
 
248
    depth = dev->color_info.depth;
 
249
    if (depth == 0) {
 
250
        /* Set parameters that were unknown before opening device */
 
251
        /* Find out if the device supports color */
 
252
        /* We recognize 1 bit monochrome and 24 bit color devices */
 
253
        DevQueryCaps(opdev->hdc, CAPS_COLOR_PLANES, 2, caps);
 
254
        /* caps[0] is #color planes, caps[1] is #bits per plane */
 
255
        depth = caps[0] * caps[1];
 
256
        if (depth > 1)
 
257
            depth = 24;
 
258
    }
 
259
    os2prn_set_bpp(dev, depth);
 
260
 
 
261
    /* create a memory DC compatible with printer */
 
262
    opdev->hdcMem = DevOpenDC(opdev->hab, OD_MEMORY, "*", 0L, NULL, opdev->hdc);
 
263
    if (opdev->hdcMem == DEV_ERROR) {
 
264
        ERRORID eid = WinGetLastError(opdev->hab);
 
265
 
 
266
        errprintf(opdev->memory, "DevOpenDC for memory error 0x%x\n", eid);
 
267
        return gs_error_limitcheck;
 
268
    }
 
269
    sizlPage.cx = dev->width;
 
270
    sizlPage.cy = dev->height;
 
271
    opdev->hpsMem = GpiCreatePS(opdev->hab, opdev->hdcMem, &sizlPage,
 
272
                         PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
 
273
    if (opdev->hpsMem == GPI_ERROR) {
 
274
        ERRORID eid = WinGetLastError(opdev->hab);
 
275
 
 
276
        errprintf(opdev->memory, "GpiCreatePS for memory error 0x%x\n", eid);
 
277
        return gs_error_limitcheck;
 
278
    }
 
279
    if (DevEscape(opdev->hdc, DEVESC_STARTDOC, (LONG) strlen(gs_product),
 
280
                  (char *)gs_product, NULL, NULL) == DEVESC_ERROR) {
 
281
        ERRORID eid = WinGetLastError(opdev->hab);
 
282
 
 
283
        errprintf(opdev->memory, "DEVESC_STARTDOC error 0x%x\n", eid);
 
284
        return gs_error_limitcheck;
 
285
    }
 
286
    /* gdev_prn_open opens a temporary file which we don't want */
 
287
    /* so we specify the name now so we can delete it later */
 
288
    pfile = gp_open_scratch_file(opdev->memory, gp_scratch_file_name_prefix,
 
289
                                 opdev->fname, "wb");
 
290
    fclose(pfile);
 
291
    code = gdev_prn_open(dev);
 
292
 
 
293
    return code;
 
294
}
 
295
 
 
296
/* Close the os2prn driver */
 
297
static int
 
298
os2prn_close(gx_device * dev)
 
299
{
 
300
    int code;
 
301
    LONG lOut;
 
302
    USHORT usJobID;
 
303
 
 
304
    /* tell printer that all is finished */
 
305
    DevEscape(opdev->hdc, DEVESC_ENDDOC, 0L, NULL, &lOut, (PBYTE) & usJobID);
 
306
    /* Free resources */
 
307
    GpiAssociate(opdev->hps, (HDC) NULL);
 
308
    GpiDestroyPS(opdev->hps);
 
309
    DevCloseDC(opdev->hdc);
 
310
 
 
311
    if (opdev->hpsMem != GPI_ERROR)
 
312
        GpiDestroyPS(opdev->hpsMem);
 
313
    if (opdev->hdcMem != DEV_ERROR)
 
314
        DevCloseDC(opdev->hdcMem);
 
315
 
 
316
    code = gdev_prn_close(dev);
 
317
    /* delete unwanted temporary file */
 
318
    unlink(opdev->fname);
 
319
    return code;
 
320
}
 
321
 
 
322
/* Get os2pm parameters */
 
323
int
 
324
os2prn_get_params(gx_device * dev, gs_param_list * plist)
 
325
{
 
326
    int code = gdev_prn_get_params(dev, plist);
 
327
    gs_param_string qs;
 
328
 
 
329
    qs.data = opdev->queue_name, qs.size = strlen(qs.data),
 
330
        qs.persistent = false;
 
331
    code < 0 ||
 
332
        (code = param_write_string(plist, "OS2QUEUE", &qs)) < 0;
 
333
    return code;
 
334
}
 
335
 
 
336
/* We implement this ourselves so that we can change BitsPerPixel */
 
337
/* before the device is opened */
 
338
int
 
339
os2prn_put_params(gx_device * dev, gs_param_list * plist)
 
340
{
 
341
    int ecode = 0, code;
 
342
    int old_bpp = dev->color_info.depth;
 
343
    int bpp = old_bpp;
 
344
    gs_param_string qs;
 
345
 
 
346
    /* Handle extra parameters */
 
347
    switch (code = param_read_string(plist, "OS2QUEUE", &qs)) {
 
348
        case 0:
 
349
            if (qs.size == strlen(opdev->queue_name) &&
 
350
                !memcmp(opdev->queue_name, qs.data, qs.size)
 
351
                ) {
 
352
                qs.data = 0;
 
353
                break;
 
354
            }
 
355
            if (dev->is_open)
 
356
                ecode = gs_error_rangecheck;
 
357
            else if (qs.size >= sizeof(opdev->queue_name))
 
358
                ecode = gs_error_limitcheck;
 
359
            else
 
360
                break;
 
361
            goto qe;
 
362
        default:
 
363
            ecode = code;
 
364
          qe:param_signal_error(plist, "OS2QUEUE", ecode);
 
365
        case 1:
 
366
            qs.data = 0;
 
367
            break;
 
368
    }
 
369
 
 
370
    switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
 
371
        case 0:
 
372
            if (dev->is_open)
 
373
                ecode = gs_error_rangecheck;
 
374
            else {              /* change dev->color_info is valid before device is opened */
 
375
                os2prn_set_bpp(dev, bpp);
 
376
                break;
 
377
            }
 
378
            goto bppe;
 
379
        default:
 
380
            ecode = code;
 
381
          bppe:param_signal_error(plist, "BitsPerPixel", ecode);
 
382
        case 1:
 
383
            break;
 
384
    }
 
385
 
 
386
    if (ecode >= 0)
 
387
        ecode = gdev_prn_put_params(dev, plist);
 
388
 
 
389
    if ((ecode >= 0) && (qs.data != 0)) {
 
390
        memcpy(opdev->queue_name, qs.data, qs.size);
 
391
        opdev->queue_name[qs.size] = 0;
 
392
    }
 
393
    return ecode;
 
394
}
 
395
 
 
396
/* ------ Internal routines ------ */
 
397
 
 
398
#undef opdev
 
399
#define opdev ((gx_device_os2prn *)pdev)
 
400
 
 
401
/************************************************/
 
402
 
 
403
/* ------ Private definitions ------ */
 
404
 
 
405
/* new os2prn_print_page routine */
 
406
 
 
407
/* Write BMP header to memory, then send bitmap to printer */
 
408
/* one scan line at a time */
 
409
static int
 
410
os2prn_print_page(gx_device_printer * pdev, FILE * file)
 
411
{
 
412
    int raster = gdev_prn_raster(pdev);
 
413
 
 
414
    /* BMP scan lines are padded to 32 bits. */
 
415
    ulong bmp_raster = (raster + 3) & (~3);
 
416
    ulong bmp_raster_multi;
 
417
    int height = pdev->height;
 
418
    int depth = pdev->color_info.depth;
 
419
    byte *row;
 
420
    int y;
 
421
    int code = 0;               /* return code */
 
422
    POINTL apts[4];
 
423
    APIRET rc;
 
424
    POINTL aptsb[4];
 
425
    HBITMAP hbmp, hbmr;
 
426
    int i, lines;
 
427
    int ystart, yend;
 
428
    int yslice;
 
429
 
 
430
    struct bmi_s {
 
431
        BITMAPINFOHEADER2 h;
 
432
        RGB2 pal[256];
 
433
    } bmi;
 
434
 
 
435
    yslice = 65535 / bmp_raster;
 
436
    bmp_raster_multi = bmp_raster * yslice;
 
437
    row = (byte *) gs_malloc(pdev->memory, bmp_raster_multi, 1, "bmp file buffer");
 
438
    if (row == 0)               /* can't allocate row buffer */
 
439
        return_error(gs_error_VMerror);
 
440
 
 
441
    if (opdev->newframe)
 
442
        DevEscape(opdev->hdc, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL);
 
443
    opdev->newframe = 1;
 
444
 
 
445
    /* Write the info header. */
 
446
 
 
447
    memset(&bmi.h, 0, sizeof(bmi.h));
 
448
    bmi.h.cbFix = sizeof(bmi.h);
 
449
    bmi.h.cx = pdev->width;     /* opdev->mdev.width; */
 
450
    /* bmi.h.cy = height; */
 
451
    bmi.h.cy = yslice;          /* size for memory PS */
 
452
    bmi.h.cPlanes = 1;
 
453
    bmi.h.cBitCount = pdev->color_info.depth;
 
454
 
 
455
    /* Write the palette. */
 
456
 
 
457
    if (depth <= 8) {
 
458
        int i;
 
459
        gx_color_value rgb[3];
 
460
        PRGB2 pq;
 
461
 
 
462
        bmi.h.cclrUsed = 1 << depth;
 
463
        bmi.h.cclrImportant = 1 << depth;
 
464
        for (i = 0; i != 1 << depth; i++) {
 
465
            (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
 
466
                                              (gx_color_index) i, rgb);
 
467
            pq = &bmi.pal[i];
 
468
            pq->bRed = gx_color_value_to_byte(rgb[0]);
 
469
            pq->bGreen = gx_color_value_to_byte(rgb[1]);
 
470
            pq->bBlue = gx_color_value_to_byte(rgb[2]);
 
471
            pq->fcOptions = 0;
 
472
        }
 
473
    } else {
 
474
        bmi.h.cclrUsed = 0;
 
475
        bmi.h.cclrImportant = 0;
 
476
    }
 
477
 
 
478
    /* for GpiDrawBits */
 
479
    /* target is inclusive */
 
480
    apts[0].x = 0;
 
481
    apts[0].y = 0;              /* filled in later */
 
482
    apts[1].x = pdev->width - 1;
 
483
    apts[1].y = 0;              /* filled in later */
 
484
    /* source is not inclusive of top & right borders */
 
485
    apts[2].x = 0;
 
486
    apts[2].y = 0;
 
487
    apts[3].x = pdev->width;
 
488
    apts[3].y = 0;              /* filled in later */
 
489
 
 
490
    /* for GpiBitBlt */
 
491
    /* target is not inclusive */
 
492
    aptsb[0].x = opdev->clipbox[0];
 
493
    aptsb[0].y = 0;             /* filled in later */
 
494
    aptsb[1].x = opdev->clipbox[2];
 
495
    aptsb[1].y = 0;             /* filled in later */
 
496
    /* source is not inclusive */
 
497
    aptsb[2].x = opdev->clipbox[0];
 
498
    aptsb[2].y = 0;
 
499
    aptsb[3].x = opdev->clipbox[2];
 
500
    aptsb[3].y = 0;             /* filled in later */
 
501
 
 
502
    /* write the bits */
 
503
    ystart = opdev->clipbox[3];
 
504
    yend = opdev->clipbox[1];
 
505
    y = ystart;
 
506
    while (y > yend) {
 
507
        /* create a bitmap for the memory DC */
 
508
        hbmp = GpiCreateBitmap(opdev->hpsMem, &bmi.h, 0L, NULL, NULL);
 
509
        if (hbmp == GPI_ERROR)
 
510
            goto bmp_done;
 
511
        hbmr = GpiSetBitmap(opdev->hpsMem, hbmp);
 
512
 
 
513
        /* copy slice to memory bitmap */
 
514
        if (y > yend + yslice)
 
515
            lines = yslice;
 
516
        else
 
517
            lines = y - yend;
 
518
        y -= lines;
 
519
        for (i = lines - 1; i >= 0; i--)
 
520
            gdev_prn_copy_scan_lines(pdev, ystart - 1 - (y + i), row + (bmp_raster * i), raster);
 
521
        apts[0].y = 0;          /* target */
 
522
        apts[1].y = lines;
 
523
        apts[3].y = lines - 1;  /* source */
 
524
        /* copy DIB bitmap to memory bitmap */
 
525
        rc = GpiDrawBits(opdev->hpsMem, row, (BITMAPINFO2 *) & bmi, 4, apts,
 
526
                         (depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0);
 
527
 
 
528
        /* copy slice to printer */
 
529
        aptsb[0].y = y;
 
530
        aptsb[1].y = y + lines;
 
531
        aptsb[3].y = lines;
 
532
        rc = GpiBitBlt(opdev->hps, opdev->hpsMem, 4, aptsb, ROP_SRCCOPY, BBO_IGNORE);
 
533
 
 
534
        /* delete bitmap */
 
535
        if (hbmr != HBM_ERROR)
 
536
            GpiSetBitmap(opdev->hpsMem, (ULONG) 0);
 
537
        hbmr = HBM_ERROR;
 
538
        if (hbmp != GPI_ERROR)
 
539
            GpiDeleteBitmap(hbmp);
 
540
        hbmp = GPI_ERROR;
 
541
    }
 
542
 
 
543
  bmp_done:
 
544
    if (row)
 
545
        gs_free(pdev->memory, (char *)row, bmp_raster_multi, 1, "bmp file buffer");
 
546
 
 
547
    return code;
 
548
}
 
549
 
 
550
/* combined color mappers */
 
551
 
 
552
/* 24-bit color mappers (taken from gdevmem2.c). */
 
553
/* Note that OS/2 expects RGB values in the order B,G,R. */
 
554
 
 
555
/* Encode a r-g-b color to a color index. */
 
556
static gx_color_index
 
557
os2prn_map_rgb_color(gx_device * dev, const gx_color_value cv[])
 
558
{
 
559
    gx_color_value r = cv[0];
 
560
    gx_color_value g = cv[1];
 
561
    gx_color_value b = cv[2];
 
562
    return gx_color_value_to_byte(r) +
 
563
                ((uint) gx_color_value_to_byte(g) << 8) +
 
564
                ((ulong) gx_color_value_to_byte(b) << 16);
 
565
}
 
566
 
 
567
/* Decode a color index to a r-g-b color. */
 
568
static int
 
569
os2prn_map_color_rgb(gx_device * dev, gx_color_index color,
 
570
                     gx_color_value prgb[3])
 
571
{
 
572
    prgb[2] = gx_color_value_from_byte(color >> 16);
 
573
    prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
 
574
    prgb[0] = gx_color_value_from_byte(color & 0xff);
 
575
    return 0;
 
576
}
 
577
 
 
578
void
 
579
os2prn_set_bpp(gx_device * dev, int depth)
 
580
{
 
581
    gx_device_color_info dci = dev->color_info;
 
582
    static const gx_device_color_info os2prn_dci_rgb = dci_std_color(24);
 
583
    static const gx_device_color_info os2prn_dci_mono = dci_black_and_white;
 
584
    if (depth == 24) {
 
585
        dci = os2prn_dci_rgb;
 
586
        dev->procs.get_color_mapping_procs = gx_default_DevRGB_get_color_mapping_procs;
 
587
        dev->procs.get_color_comp_index = gx_default_DevRGB_get_color_comp_index;
 
588
        dev->procs.map_rgb_color = dev->procs.encode_color =
 
589
                os2prn_map_rgb_color;
 
590
        dev->procs.map_color_rgb = dev->procs.decode_color =
 
591
                os2prn_map_color_rgb;
 
592
    } else {    /* default is black and white */
 
593
        dci = os2prn_dci_mono;
 
594
        dev->procs.get_color_mapping_procs = gx_default_DevGray_get_color_mapping_procs;
 
595
        dev->procs.get_color_comp_index = gx_default_DevGray_get_color_comp_index;
 
596
        dev->procs.map_rgb_color = dev->procs.encode_color =
 
597
                gx_default_b_w_map_rgb_color;
 
598
        dev->procs.map_color_rgb = dev->procs.decode_color =
 
599
                gx_default_b_w_map_color_rgb;
 
600
    }
 
601
    /* restore old anti_alias info */
 
602
    dci.anti_alias = dev->color_info.anti_alias;
 
603
    dev->color_info = dci;
 
604
    /* Set the mask bits, etc. even though we are setting linear: unknown */
 
605
    set_linear_color_bits_mask_shift(dev);
 
606
}
 
607
 
 
608
/* Get list of queues from SplEnumQueue */
 
609
/* returns 0 if OK, non-zero for error */
 
610
static int
 
611
os2prn_get_queue_list(gs_memory_t *mem, OS2QL * ql)
 
612
{
 
613
    SPLERR splerr;
 
614
    USHORT jobCount;
 
615
    ULONG cbBuf;
 
616
    ULONG cTotal;
 
617
    ULONG cReturned;
 
618
    ULONG cbNeeded;
 
619
    ULONG ulLevel;
 
620
    ULONG i;
 
621
    PSZ pszComputerName;
 
622
    PBYTE pBuf;
 
623
    PPRQINFO3 prq;
 
624
 
 
625
    ulLevel = 3L;
 
626
    pszComputerName = (PSZ) NULL;
 
627
    splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, 0L,   /* cbBuf */
 
628
                          &cReturned, &cTotal,
 
629
                          &cbNeeded, NULL);
 
630
    if (splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) {
 
631
        pBuf = gs_malloc(mem, cbNeeded, 1, "OS/2 printer device info buffer");
 
632
        ql->prq = (PRQINFO3 *) pBuf;
 
633
        if (ql->prq != (PRQINFO3 *) NULL) {
 
634
            ql->len = cbNeeded;
 
635
            cbBuf = cbNeeded;
 
636
            splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, cbBuf,
 
637
                                  &cReturned, &cTotal,
 
638
                                  &cbNeeded, NULL);
 
639
            if (splerr == NO_ERROR) {
 
640
                /* Set pointer to point to the beginning of the buffer.           */
 
641
                prq = (PPRQINFO3) pBuf;
 
642
                /* cReturned has the count of the number of PRQINFO3 structures.  */
 
643
                ql->nqueues = cReturned;
 
644
                ql->defqueue = 0;
 
645
                for (i = 0; i < cReturned; i++) {
 
646
                    if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
 
647
                        ql->defqueue = i;
 
648
                    prq++;
 
649
                }               /*endfor cReturned */
 
650
            }
 
651
        }
 
652
    } else {
 
653
        /* If we are here we had a bad error code. Print it and some other info. */
 
654
        emprintf4(mem,
 
655
                 "SplEnumQueue Error=%ld, Total=%ld, Returned=%ld, Needed=%ld\n",
 
656
                 splerr, cTotal, cReturned, cbNeeded);
 
657
    }
 
658
    if (splerr)
 
659
        return splerr;
 
660
    return 0;
 
661
}
 
662
 
 
663
static void
 
664
os2prn_free_queue_list(gs_memory_t *mem, OS2QL * ql)
 
665
{
 
666
    gs_free(mem, (char *)ql->prq, ql->len, 1, "os2prn queue list");
 
667
    ql->prq = NULL;
 
668
    ql->len = 0;
 
669
    ql->defqueue = 0;
 
670
    ql->nqueues = 0;
 
671
}