1 /* Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /* $Id: gdevos2p.c,v 1.9 2004/09/27 21:14:00 ghostgum Exp $ */ 18 /* 19 * OS/2 printer device 20 * 21 * By Russell Lang, derived from mswinpr2 device by Russell Lang and 22 * L. Peter Deutsch, Aladdin Enterprises. 23 * 24 * Bug fixed by Pierre Arnaud 2000-03-20 (os2prn_set_bpp did not set anti_alias) 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(gs_memory_t *mem, OS2QL * ql); 85 private void os2prn_free_queue_list(gs_memory_t *mem, 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 errprintf("\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 errprintf("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(dev->memory, &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 errprintf("Invalid os2prn queue name -sOS2QUEUE=\042%s\042\n", opdev->queue_name); 192 errprintf("Valid device names are:\n"); 193 for (i = 0; i < opdev->ql.nqueues; i++) { 194 errprintf(" -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 errprintf("DevOpenDC for printer error 0x%x\n", eid); 212 return gs_error_limitcheck; 213 } 214 os2prn_free_queue_list(dev->memory, &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 bit monochrome 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 if (depth > 1) 260 depth = 24; 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(pdev->memory, 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(pdev->memory, (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 /* Encode a r-g-b color to a color index. */ 565 private gx_color_index 566 os2prn_map_rgb_color(gx_device * dev, const gx_color_value cv[]) 567 { 568 gx_color_value r = cv[0]; 569 gx_color_value g = cv[1]; 570 gx_color_value b = cv[2]; 571 return gx_color_value_to_byte(r) + 572 ((uint) gx_color_value_to_byte(g) << 8) + 573 ((ulong) gx_color_value_to_byte(b) << 16); 574 } 575 576 /* Decode a color index to a r-g-b color. */ 577 private int 578 os2prn_map_color_rgb(gx_device * dev, gx_color_index color, 579 gx_color_value prgb[3]) 580 { 581 prgb[2] = gx_color_value_from_byte(color >> 16); 582 prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff); 583 prgb[0] = gx_color_value_from_byte(color & 0xff); 584 return 0; 585 } 586 587 void 588 os2prn_set_bpp(gx_device * dev, int depth) 589 { 590 gx_device_color_info dci = dev->color_info; 591 static const gx_device_color_info os2prn_dci_rgb = dci_std_color(24); 592 static const gx_device_color_info os2prn_dci_mono = dci_black_and_white; 593 if (depth == 24) { 594 dci = os2prn_dci_rgb; 595 dev->procs.get_color_mapping_procs = gx_default_DevRGB_get_color_mapping_procs; 596 dev->procs.get_color_comp_index = gx_default_DevRGB_get_color_comp_index; 597 dev->procs.map_rgb_color = dev->procs.encode_color = 598 os2prn_map_rgb_color; 599 dev->procs.map_color_rgb = dev->procs.decode_color = 600 os2prn_map_color_rgb; 601 } else { /* default is black and white */ 602 dci = os2prn_dci_mono; 603 dev->procs.get_color_mapping_procs = gx_default_DevGray_get_color_mapping_procs; 604 dev->procs.get_color_comp_index = gx_default_DevGray_get_color_comp_index; 605 dev->procs.map_rgb_color = dev->procs.encode_color = 606 gx_default_b_w_map_rgb_color; 607 dev->procs.map_color_rgb = dev->procs.decode_color = 608 gx_default_b_w_map_color_rgb; 609 } 610 /* restore old anti_alias info */ 611 dci.anti_alias = dev->color_info.anti_alias; 612 dev->color_info = dci; 613 /* Set the mask bits, etc. even though we are setting linear: unknown */ 614 set_linear_color_bits_mask_shift(dev); 615 } 616 617 /* Get list of queues from SplEnumQueue */ 618 /* returns 0 if OK, non-zero for error */ 619 private int 620 os2prn_get_queue_list(gs_memory_t *mem, OS2QL * ql) 621 { 622 SPLERR splerr; 623 USHORT jobCount; 624 ULONG cbBuf; 625 ULONG cTotal; 626 ULONG cReturned; 627 ULONG cbNeeded; 628 ULONG ulLevel; 629 ULONG i; 630 PSZ pszComputerName; 631 PBYTE pBuf; 632 PPRQINFO3 prq; 633 634 ulLevel = 3L; 635 pszComputerName = (PSZ) NULL; 636 splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, 0L, /* cbBuf */ 637 &cReturned, &cTotal, 638 &cbNeeded, NULL); 639 if (splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) { 640 pBuf = gs_malloc(mem, cbNeeded, 1, "OS/2 printer device info buffer"); 641 ql->prq = (PRQINFO3 *) pBuf; 642 if (ql->prq != (PRQINFO3 *) NULL) { 643 ql->len = cbNeeded; 644 cbBuf = cbNeeded; 645 splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, cbBuf, 646 &cReturned, &cTotal, 647 &cbNeeded, NULL); 648 if (splerr == NO_ERROR) { 649 /* Set pointer to point to the beginning of the buffer. */ 650 prq = (PPRQINFO3) pBuf; 651 /* cReturned has the count of the number of PRQINFO3 structures. */ 652 ql->nqueues = cReturned; 653 ql->defqueue = 0; 654 for (i = 0; i < cReturned; i++) { 655 if (prq->fsType & PRQ3_TYPE_APPDEFAULT) 656 ql->defqueue = i; 657 prq++; 658 } /*endfor cReturned */ 659 } 660 } 661 } else { 662 /* If we are here we had a bad error code. Print it and some other info. */ 663 eprintf4("SplEnumQueue Error=%ld, Total=%ld, Returned=%ld, Needed=%ld\n", 664 splerr, cTotal, cReturned, cbNeeded); 665 } 666 if (splerr) 667 return splerr; 668 return 0; 669 } 670 671 672 private void 673 os2prn_free_queue_list(gs_memory_t *mem, OS2QL * ql) 674 { 675 gs_free(mem, (char *)ql->prq, ql->len, 1, "os2prn queue list"); 676 ql->prq = NULL; 677 ql->len = 0; 678 ql->defqueue = 0; 679 ql->nqueues = 0; 680 } 681