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