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