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