NS_IMETHODIMP nsDeviceContextSpecOS2::BeginDocument(PRUnichar* aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage) { #ifdef debug_thebes_print printf("nsDeviceContextSpecOS2[%#x]::BeginPrinting(%s, %s)\n", (unsigned)this, NS_LossyConvertUTF16toASCII(nsString(aTitle)).get(), NS_LossyConvertUTF16toASCII(nsString(aPrintToFileName)).get()); #endif // don't try to send device escapes for non-native output (like PDF) PRInt16 outputFormat; mPrintSettings->GetOutputFormat(&outputFormat); if (outputFormat != nsIPrintSettings::kOutputFormatNative) { return NS_OK; } char *title = GetACPString(aTitle); const PSZ pszGenericDocName = "Mozilla Document"; PSZ pszDocName = title ? title : pszGenericDocName; LONG lResult = DevEscape(mPrintDC, DEVESC_STARTDOC, strlen(pszDocName) + 1, pszDocName, (PLONG)NULL, (PBYTE)NULL); mPrintingStarted = PR_TRUE; if (title) { nsMemory::Free(title); } return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTDOC; }
/*@ XPrinterDevice::OpenPrinterJob(char *pszJobTitle) @remarks Open a printer job @parameters char * title title of the printer job @returns BOOL success */ BOOL XPrinterDevice::OpenPrinterJob(const char *pszJobTitle) { hdc = DevOpenDC(pSetup->hab, pSetup->lDCType, (PSZ) "*", 9, pSetup->pDevOpenData, (HDC) 0); if (hdc == NULLHANDLE) return FALSE; SIZEL sizel; sizel.cx = 0; sizel.cy = 0; hps = GpiCreatePS(pSetup->hab, hdc, &sizel, pSetup->lWorldCoordinates | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC); if (GPI_ERROR == hps) { DevCloseDC(hdc); hdc = (HDC) 0; hps = (HPS) 0; return FALSE; } DevEscape(hdc, DEVESC_STARTDOC, strlen(pszJobTitle), (PSZ) pszJobTitle, NULL, NULL); if (!GpiSetCharMode(hps, CM_MODE2)) return FALSE; if (!GpiSetTextAlignment(hps, TA_NORMAL_HORIZ, TA_NORMAL_VERT)) return FALSE; SIZEL sizPage; if (!GpiQueryPS(hps, &sizPage)) return FALSE; width = sizPage.cx; height = sizPage.cy; return TRUE; }
/*@ XPrinterDevice::NewPage() @remarks Add a new page to the printer-job. @returns BOOL success */ BOOL XPrinterDevice::NewPage() const { if (hdc) { if (DevEscape(hdc, DEVESC_NEWFRAME, 0, NULL, NULL, NULL) == DEV_OK) return TRUE; } return FALSE; }
NS_IMETHODIMP nsDeviceContextSpecOS2::EndDocument() { PRInt16 outputFormat; mPrintSettings->GetOutputFormat(&outputFormat); if (outputFormat != nsIPrintSettings::kOutputFormatNative) { return NS_OK; } LONG lOutCount = 2; USHORT usJobID = 0; LONG lResult = DevEscape(mPrintDC, DEVESC_ENDDOC, 0L, (PBYTE)NULL, &lOutCount, (PBYTE)&usJobID); return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_ENDDOC; }
NS_IMETHODIMP nsDeviceContextSpecOS2::BeginPage() { PRInt16 outputFormat; mPrintSettings->GetOutputFormat(&outputFormat); if (outputFormat != nsIPrintSettings::kOutputFormatNative) { return NS_OK; } if (mPrintingStarted) { // we don't want an extra page break at the start of the document mPrintingStarted = PR_FALSE; return NS_OK; } LONG lResult = DevEscape(mPrintDC, DEVESC_NEWFRAME, 0L, (PBYTE)NULL, (PLONG)NULL, (PBYTE)NULL); return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTPAGE; }
/*@ XPrinterDevice::KillPrinterJob() @remarks Remove the printer job from the printer queue. */ void XPrinterDevice::KillPrinterJob() { DevEscape(hdc, DEVESC_ABORTDOC, 0, NULL, NULL, NULL); if (hps) { GpiSetCharSet(hps, 0); GpiAssociate(hps, (HDC) 0); GpiDestroyPS(hps); hps = (HPS) 0; } if (hdc) { DevCloseDC(hdc); hdc = (HDC) 0; } }
NS_IMETHODIMP nsDeviceContextSpecOS2::EndDocument() { // don't try to send device escapes for non-native output (like PDF) // but clear the filename to make sure that we don't overwrite it next time PRInt16 outputFormat; mPrintSettings->GetOutputFormat(&outputFormat); if (outputFormat != nsIPrintSettings::kOutputFormatNative) { mPrintSettings->SetToFileName(NULL); nsCOMPtr<nsIPrintSettingsService> pss = do_GetService("@mozilla.org/gfx/printsettings-service;1"); if (pss) pss->SavePrintSettingsToPrefs(mPrintSettings, PR_TRUE, nsIPrintSettings::kInitSaveToFileName); return NS_OK; } LONG lOutCount = 2; USHORT usJobID = 0; LONG lResult = DevEscape(mPrintDC, DEVESC_ENDDOC, 0L, (PBYTE)NULL, &lOutCount, (PBYTE)&usJobID); return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_ENDDOC; }
/* Close the os2prn driver */ static int os2prn_close(gx_device * dev) { int code; LONG lOut; USHORT usJobID; /* tell printer that all is finished */ DevEscape(opdev->hdc, DEVESC_ENDDOC, 0L, NULL, &lOut, (PBYTE) & usJobID); /* Free resources */ GpiAssociate(opdev->hps, (HDC) NULL); GpiDestroyPS(opdev->hps); DevCloseDC(opdev->hdc); if (opdev->hpsMem != GPI_ERROR) GpiDestroyPS(opdev->hpsMem); if (opdev->hdcMem != DEV_ERROR) DevCloseDC(opdev->hdcMem); code = gdev_prn_close(dev); /* delete unwanted temporary file */ unlink(opdev->fname); return code; }
/* one scan line at a time */ static int os2prn_print_page(gx_device_printer * pdev, FILE * file) { int raster = gdev_prn_raster(pdev); /* BMP scan lines are padded to 32 bits. */ ulong bmp_raster = (raster + 3) & (~3); ulong bmp_raster_multi; int height = pdev->height; int depth = pdev->color_info.depth; byte *row; int y; int code = 0; /* return code */ POINTL apts[4]; APIRET rc; POINTL aptsb[4]; HBITMAP hbmp, hbmr; int i, lines; int ystart, yend; int yslice; struct bmi_s { BITMAPINFOHEADER2 h; RGB2 pal[256]; } bmi; yslice = 65535 / bmp_raster; bmp_raster_multi = bmp_raster * yslice; row = (byte *) gs_malloc(pdev->memory, bmp_raster_multi, 1, "bmp file buffer"); if (row == 0) /* can't allocate row buffer */ return_error(gs_error_VMerror); if (opdev->newframe) DevEscape(opdev->hdc, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL); opdev->newframe = 1; /* Write the info header. */ memset(&bmi.h, 0, sizeof(bmi.h)); bmi.h.cbFix = sizeof(bmi.h); bmi.h.cx = pdev->width; /* opdev->mdev.width; */ /* bmi.h.cy = height; */ bmi.h.cy = yslice; /* size for memory PS */ bmi.h.cPlanes = 1; bmi.h.cBitCount = pdev->color_info.depth; /* Write the palette. */ if (depth <= 8) { int i; gx_color_value rgb[3]; PRGB2 pq; bmi.h.cclrUsed = 1 << depth; bmi.h.cclrImportant = 1 << depth; for (i = 0; i != 1 << depth; i++) { (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev, (gx_color_index) i, rgb); pq = &bmi.pal[i]; pq->bRed = gx_color_value_to_byte(rgb[0]); pq->bGreen = gx_color_value_to_byte(rgb[1]); pq->bBlue = gx_color_value_to_byte(rgb[2]); pq->fcOptions = 0; } } else { bmi.h.cclrUsed = 0; bmi.h.cclrImportant = 0; } /* for GpiDrawBits */ /* target is inclusive */ apts[0].x = 0; apts[0].y = 0; /* filled in later */ apts[1].x = pdev->width - 1; apts[1].y = 0; /* filled in later */ /* source is not inclusive of top & right borders */ apts[2].x = 0; apts[2].y = 0; apts[3].x = pdev->width; apts[3].y = 0; /* filled in later */ /* for GpiBitBlt */ /* target is not inclusive */ aptsb[0].x = opdev->clipbox[0]; aptsb[0].y = 0; /* filled in later */ aptsb[1].x = opdev->clipbox[2]; aptsb[1].y = 0; /* filled in later */ /* source is not inclusive */ aptsb[2].x = opdev->clipbox[0]; aptsb[2].y = 0; aptsb[3].x = opdev->clipbox[2]; aptsb[3].y = 0; /* filled in later */ /* write the bits */ ystart = opdev->clipbox[3]; yend = opdev->clipbox[1]; y = ystart; while (y > yend) { /* create a bitmap for the memory DC */ hbmp = GpiCreateBitmap(opdev->hpsMem, &bmi.h, 0L, NULL, NULL); if (hbmp == GPI_ERROR) goto bmp_done; hbmr = GpiSetBitmap(opdev->hpsMem, hbmp); /* copy slice to memory bitmap */ if (y > yend + yslice) lines = yslice; else lines = y - yend; y -= lines; for (i = lines - 1; i >= 0; i--) gdev_prn_copy_scan_lines(pdev, ystart - 1 - (y + i), row + (bmp_raster * i), raster); apts[0].y = 0; /* target */ apts[1].y = lines; apts[3].y = lines - 1; /* source */ /* copy DIB bitmap to memory bitmap */ rc = GpiDrawBits(opdev->hpsMem, row, (BITMAPINFO2 *) & bmi, 4, apts, (depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0); /* copy slice to printer */ aptsb[0].y = y; aptsb[1].y = y + lines; aptsb[3].y = lines; rc = GpiBitBlt(opdev->hps, opdev->hpsMem, 4, aptsb, ROP_SRCCOPY, BBO_IGNORE); /* delete bitmap */ if (hbmr != HBM_ERROR) GpiSetBitmap(opdev->hpsMem, (ULONG) 0); hbmr = HBM_ERROR; if (hbmp != GPI_ERROR) GpiDeleteBitmap(hbmp); hbmp = GPI_ERROR; } bmp_done: if (row) gs_free(pdev->memory, (char *)row, bmp_raster_multi, 1, "bmp file buffer"); return code; }
/* Open the os2prn driver */ static int os2prn_open(gx_device * dev) { int code; PTIB pptib; PPIB pppib; DEVOPENSTRUC dop; ULONG cbBuf; ULONG cbNeeded; APIRET rc; PBYTE pbuf; char *p; SIZEL sizlPage; LONG caps[2]; HCINFO hcinfo; LONG nforms; float m[4]; int depth; FILE *pfile; int i; char *prefix = "\\\\spool\\"; /* 8 characters long */ PRQINFO3 *pprq; gx_device_os2prn *oprn; oprn = opdev; if (DosGetInfoBlocks(&pptib, &pppib)) { errprintf("\nos2prn_open: Couldn't get pid\n"); return gs_error_limitcheck; } if (pppib->pib_ultype != 3) { /* if caller is not PM app */ errprintf("os2prn device can only be used from a PM application\n"); return gs_error_limitcheck; } opdev->hab = WinQueryAnchorBlock(hwndtext); opdev->newframe = 0; if (os2prn_get_queue_list(dev->memory, &opdev->ql)) return gs_error_limitcheck; if (opdev->queue_name[0] == '\0') { /* obtain printer name from filename */ p = opdev->fname; for (i = 0; i < 8; i++) { if (prefix[i] == '\\') { if ((*p != '\\') && (*p != '/')) break; } else if (tolower(*p) != prefix[i]) break; p++; } if (i == 8 && (strlen(p) != 0)) strcpy(opdev->queue_name, p); } pprq = NULL; if (opdev->queue_name[0] != '\0') { for (i = 0; i < opdev->ql.nqueues; i++) { if (strcmp(opdev->ql.prq[i].pszName, opdev->queue_name) == 0) { pprq = &(opdev->ql.prq[i]); break; } } } else { /* use default queue */ pprq = &(opdev->ql.prq[opdev->ql.defqueue]); } if (pprq == (PRQINFO3 *) NULL) { errprintf("Invalid os2prn queue name -sOS2QUEUE=\042%s\042\n", opdev->queue_name); errprintf("Valid device names are:\n"); for (i = 0; i < opdev->ql.nqueues; i++) { errprintf(" -sOS2QUEUE=\042%s\042\n", opdev->ql.prq[i].pszName); } return gs_error_rangecheck; } /* open printer device */ memset(&dop, 0, sizeof(dop)); dop.pszLogAddress = pprq->pszName; /* queue name */ p = strchr(pprq->pszDriverName, '.'); if (p != (char *)NULL) *p = '\0'; dop.pszDriverName = pprq->pszDriverName; dop.pszDataType = "PM_Q_STD"; dop.pdriv = pprq->pDriverData; opdev->hdc = DevOpenDC(opdev->hab, OD_QUEUED, "*", 9L, (PDEVOPENDATA) & dop, (HDC) NULL); if (opdev->hdc == DEV_ERROR) { ERRORID eid = WinGetLastError(opdev->hab); errprintf("DevOpenDC for printer error 0x%x\n", eid); return gs_error_limitcheck; } os2prn_free_queue_list(dev->memory, &opdev->ql); /* find out resolution of printer */ /* this is returned in pixels/metre */ DevQueryCaps(opdev->hdc, CAPS_HORIZONTAL_RESOLUTION, 2, caps); dev->x_pixels_per_inch = (int)(caps[0] * 0.0254 + 0.5); dev->y_pixels_per_inch = (int)(caps[1] * 0.0254 + 0.5); /* find out page size and margins */ /* these are returned in millimetres */ nforms = DevQueryHardcopyCaps(opdev->hdc, 0, 0, &hcinfo); for (i = 0; i < nforms; i++) { DevQueryHardcopyCaps(opdev->hdc, i, 1, &hcinfo); if (hcinfo.flAttributes & HCAPS_CURRENT) break; /* this is the default page size */ } /* GS size is in pixels */ dev->width = hcinfo.cx * caps[0] / 1000; dev->height = hcinfo.cy * caps[1] / 1000; /* GS margins are in inches */ m[0] /*left */ = hcinfo.xLeftClip / 25.4; m[1] /*bottom */ = hcinfo.yBottomClip / 25.4; m[2] /*right */ = (hcinfo.cx - hcinfo.xRightClip) / 25.4; m[3] /*top */ = (hcinfo.cy - hcinfo.yTopClip) / 25.4; gx_device_set_margins(dev, m, true); /* set bounding box in pixels for later drawing */ opdev->clipbox[0] = (int)(hcinfo.xLeftClip / 25.4 * dev->x_pixels_per_inch + 1); /* round inwards */ opdev->clipbox[1] = (int)(hcinfo.yBottomClip / 25.4 * dev->y_pixels_per_inch + 1); opdev->clipbox[2] = (int)(hcinfo.xRightClip / 25.4 * dev->x_pixels_per_inch); opdev->clipbox[3] = (int)(hcinfo.yTopClip / 25.4 * dev->y_pixels_per_inch); /* get presentation space */ sizlPage.cx = dev->width; sizlPage.cy = dev->height; opdev->hps = GpiCreatePS(opdev->hab, opdev->hdc, &sizlPage, PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC); depth = dev->color_info.depth; if (depth == 0) { /* Set parameters that were unknown before opening device */ /* Find out if the device supports color */ /* We recognize 1 bit monochrome and 24 bit color devices */ DevQueryCaps(opdev->hdc, CAPS_COLOR_PLANES, 2, caps); /* caps[0] is #color planes, caps[1] is #bits per plane */ depth = caps[0] * caps[1]; if (depth > 1) depth = 24; } os2prn_set_bpp(dev, depth); /* create a memory DC compatible with printer */ opdev->hdcMem = DevOpenDC(opdev->hab, OD_MEMORY, "*", 0L, NULL, opdev->hdc); if (opdev->hdcMem == DEV_ERROR) { ERRORID eid = WinGetLastError(opdev->hab); errprintf("DevOpenDC for memory error 0x%x\n", eid); return gs_error_limitcheck; } sizlPage.cx = dev->width; sizlPage.cy = dev->height; opdev->hpsMem = GpiCreatePS(opdev->hab, opdev->hdcMem, &sizlPage, PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC); if (opdev->hpsMem == GPI_ERROR) { ERRORID eid = WinGetLastError(opdev->hab); errprintf("GpiCreatePS for memory error 0x%x\n", eid); return gs_error_limitcheck; } if (DevEscape(opdev->hdc, DEVESC_STARTDOC, (LONG) strlen(gs_product), (char *)gs_product, NULL, NULL) == DEVESC_ERROR) { ERRORID eid = WinGetLastError(opdev->hab); errprintf("DEVESC_STARTDOC error 0x%x\n", eid); return gs_error_limitcheck; } /* gdev_prn_open opens a temporary file which we don't want */ /* so we specify the name now so we can delete it later */ pfile = gp_open_scratch_file(gp_scratch_file_name_prefix, opdev->fname, "wb"); fclose(pfile); code = gdev_prn_open(dev); return code; }