home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 July / IMM0795.ISO / share / os2 / pmfract / src / pmfrprnt.c < prev    next >
Text File  |  1994-01-24  |  20KB  |  578 lines

  1. /*--------------------------------------------------
  2.    PMFRPRNT.C -- FRACTINT for PM
  3.  
  4.       Print Processor
  5.  
  6.    04/07/91      Code by Donald P. Egen (with help)
  7.  
  8.    This module's first function (PrintDriver) is the
  9.    main print action function.
  10.  ---------------------------------------------------*/
  11.  
  12. #define INCL_WIN
  13. #define INCL_GPI
  14. #define INCL_DOS
  15. #define INCL_DEV
  16. #include <os2.h>
  17. #include <process.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <setjmp.h>
  21. #include <float.h>
  22. #include <malloc.h>
  23. #include <string.h>
  24. #include <smplhelp.h>
  25. #include <dos.h>
  26.  
  27. #include "pmfract.h"
  28. #include "fractint.h"
  29. #include "fractype.h"
  30.  
  31. extern HAB    habThread;
  32.  
  33. static int PrintDriverPM(VOID);
  34. static int PrintDriverPJ(VOID);
  35. static int getcolorx(int xdot, int ydot);
  36.  
  37. /*--------------------------------------------------
  38.  
  39.  This subroutine does the necessary mucking around to open
  40.  the Control Panel/Print Manager default printer.
  41.  This activity is not nearly as trivial as it ought to be.
  42.  
  43.  ---------------------------------------------------*/
  44. HDC OpenDefaultPrinterDC( HAB hab,PSZ pszAppName, LONG type)
  45.     {
  46.         #define MAX_STRING_LEN  256
  47.  
  48.         static CHAR     szPrinter[MAX_STRING_LEN];
  49.         static CHAR     szDetails[MAX_STRING_LEN];
  50.         static DRIVDATA driv;
  51.  
  52.         DEVOPENSTRUC    dop;
  53.         PCHAR           pchDelimiter;
  54.  
  55.     /* Get the default printer name, for example, "PRINTER1" */
  56.         WinQueryProfileString( hab,
  57.                 "PM_SPOOLER",       /* section name       */
  58.                 "PRINTER",          /* keyname            */
  59.                 ";",                /* default            */
  60.                 szPrinter,          /* profile string     */
  61.                 MAX_STRING_LEN );   /* maximum characters */
  62.  
  63.         if ( NULL != (pchDelimiter = _fstrchr(szPrinter,';')) )
  64.             *pchDelimiter = '\0';
  65.  
  66.         if (szPrinter[0] == '\0')
  67.               return DEV_ERROR;
  68.  
  69.     /* Get the printer details.
  70.      *  Fill in a supplied string with substrings:
  71.      *  <physical port>;<driver name>;<queue port>;<network params>;
  72.      */
  73.         WinQueryProfileString( hab,
  74.                 "PM_SPOOLER_PRINTER",
  75.                 szPrinter,
  76.                 ";;;;",
  77.                 szDetails,
  78.                 MAX_STRING_LEN );
  79.  
  80.     /* Fill in the DEVOPENSTRUC and DRIVDATA structures */
  81.         if ( NULL == (pchDelimiter = _fstrchr(szDetails,';')) )
  82.             return DEV_ERROR;
  83.         dop.pszDriverName = pchDelimiter + 1;
  84.         if ( NULL == (pchDelimiter = _fstrchr(dop.pszDriverName,';')) )
  85.             return DEV_ERROR;
  86.         dop.pszLogAddress = pchDelimiter + 1;
  87.         *(dop.pszLogAddress + _fstrcspn(dop.pszLogAddress,",;")) = '\0';
  88.         *(dop.pszDriverName + _fstrcspn(dop.pszDriverName,",;")) = '\0';
  89.         dop.pszComment = pszAppName;
  90.         if ( NULL != (pchDelimiter = _fstrchr(dop.pszDriverName,'.')) )
  91.             {
  92.             driv.cb = sizeof(DRIVDATA) - 1;
  93.             driv.lVersion = 0L;
  94.             *pchDelimiter = '\0';
  95.             _fstrncpy( driv.szDeviceName,pchDelimiter+1,
  96.                      sizeof driv.szDeviceName );
  97.             dop.pdriv = &driv;
  98.             }
  99.         else
  100.             dop.pdriv = NULL;
  101.         dop.pszDataType = "PM_Q_RAW";
  102.  
  103.     /* Now open the device context an return to caller */
  104.         return DevOpenDC( hab,
  105.                           type,
  106.                           "*",
  107.                           5L,         /* use first five fields. */
  108.                           (PDEVOPENDATA) &dop,
  109.                           (HDC) NULL );
  110.     }
  111.  
  112.  
  113. void GetPrinterData(HDC hdcPrint)
  114.     {
  115.     /* extract from an open printer DC the global data
  116.        we want.  This is done at program init and also
  117.        just before printing is to commence.
  118.     */
  119.  
  120.     DevQueryCaps(hdcPrint, CAPS_VERTICAL_RESOLUTION, 1L, &cyPrtRes);
  121.     DevQueryCaps(hdcPrint, CAPS_HORIZONTAL_RESOLUTION, 1L, &cxPrtRes);
  122.     DevQueryCaps(hdcPrint, CAPS_WIDTH, 1L, &cxPrinter);
  123.     DevQueryCaps(hdcPrint, CAPS_HEIGHT, 1L, &cyPrinter);
  124.     DevQueryCaps(hdcPrint, CAPS_COLORS, 1L, &lPrinterColors);
  125.  
  126.     }
  127.  
  128. void FAR PrintDriverInit(void)
  129.      {
  130.      /* inquire the dimensions of the current default printer */
  131.      HDC hdcPrint;
  132.  
  133.      /* first open an INFO device context to the default PM Printer */
  134.      if ( NULL == (hdcPrint = OpenDefaultPrinterDC(habThread, szClientClass,
  135.              OD_INFO) ) )
  136.         return;
  137.  
  138.      /* now get what we came for */
  139.      GetPrinterData(hdcPrint);
  140.  
  141.      /* and close it up */
  142.      DevCloseDC (hdcPrint);
  143.  
  144.      }
  145.  
  146. int  FAR PrintDriver (VOID)
  147.      {
  148.  
  149.      int rc;
  150.  
  151.      /* dispatch based on sub-function - do we do PM or PJ? */
  152.  
  153.      switch (cp.sSubFunction)
  154.             {
  155.             case SUB_PRINT_PM:
  156.                  rc = PrintDriverPM();
  157.                  break;
  158.  
  159.             case SUB_PRINT_PJ:
  160.                  rc = PrintDriverPJ();
  161.                  break;
  162.  
  163.             default:
  164.                  rc = 999;   /* let the caller figure it out */
  165.                  break;
  166.  
  167.             }
  168.  
  169.      /* and go back */
  170.  
  171.      return rc;
  172.  
  173.      }
  174.  
  175. static int PrintDriverPM(VOID)
  176.      {
  177.      /* Print to the Default Presentation Manger Printer
  178.  
  179.         The strategy for printing is to
  180.         (1) construct DC and PS for printing.
  181.         (2) set printer PS logical color table to the physical palette
  182.             of the printer.  This should let us handle both
  183.             monochrome and (hopefully) color printers with the
  184.             same code.
  185.         (3) build a memory DC, PS, and Bitmap of the same
  186.             x and y dimensions as the in-core pixel map, but
  187.             with the format requested by the printer.
  188.         (4) load the memory Bitmap from the pixel array using
  189.             an appropriate color table.
  190.         (5) BitBlt the memory bitmap to the printer.
  191.         (6) Clean up.
  192.      */
  193.  
  194.      /* start with bunches of data */
  195.      HDC hdcPrinter;
  196.      HPS hpsPrinter;
  197.      HDC hdcPrMem;
  198.      HPS hpsPrMem;
  199.      HBITMAP hbmPrMem;
  200.      PBITMAPINFO pbmiPrMem;
  201.      SIZEL sizl;
  202.      ULONG _far *alPrPhysClrs;
  203.      BITMAPINFOHEADER bmp;
  204.      LONG   alBmpFormats[12];
  205.      LONG errorcode;
  206.      char FractName[32];
  207.      POINTL aptl[4];
  208.  
  209.      /* obtain the name for use as the printer title */
  210.  
  211.      _fstrcpy(FractName, GetFractalName(cp.iFractType));
  212.  
  213.      /* open up a device context for the printer */
  214.      if (NULL == (hdcPrinter = OpenDefaultPrinterDC(habThread, szTitleBar,
  215.                  OD_QUEUED) ) )
  216.         return(SUB_STAT_ABORT) ;
  217.  
  218.      /* ensure we are working with current information about
  219.         the printer we are using */
  220.      GetPrinterData(hdcPrinter);
  221.  
  222.      /* now get the PS */
  223.      sizl.cx = 0; sizl.cy = 0;
  224.      hpsPrinter = GpiCreatePS (habThread, hdcPrinter, &sizl,
  225.                    PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  226.      /* and set the logical palette to the same as the physical palette */
  227.      alPrPhysClrs = (ULONG _far *) _fmalloc(lPrinterColors * sizeof(ULONG) ) ;
  228.      GpiQueryRealColors(hpsPrinter, LCOLOPT_REALIZED,
  229.                       0L,   lPrinterColors, alPrPhysClrs);
  230.      GpiCreateLogColorTable(hpsPrinter, LCOL_RESET | LCOL_REALIZABLE,
  231.               LCOLF_CONSECRGB, 0L, lPrinterColors, alPrPhysClrs);
  232.  
  233.      /* now the memory DC, PS, and Bitmap */
  234.      hdcPrMem = DevOpenDC (habThread, OD_MEMORY, "*", 0L, NULL, hdcPrinter) ;
  235.      sizl.cx = (LONG) cp.cx; sizl.cy = (LONG) cp.cy;
  236.      hpsPrMem = GpiCreatePS (habThread, hdcPrMem, &sizl,
  237.                     PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  238.  
  239.      GpiQueryDeviceBitmapFormats (hpsPrMem, 12L, alBmpFormats) ;
  240.      bmp.cbFix   = sizeof bmp;
  241.      bmp.cx      = cp.cx;
  242.      bmp.cy      = cp.cy;
  243.      bmp.cPlanes = (USHORT) alBmpFormats[0];
  244.      bmp.cBitCount = (USHORT) alBmpFormats[1];
  245.      hbmPrMem = GpiCreateBitmap (hpsPrMem, &bmp, 0L, NULL, NULL);
  246.      errorcode = WinGetLastError(habThread);
  247.  
  248.      GpiSetBitmap (hpsPrMem, hbmPrMem);
  249.      errorcode = WinGetLastError(habThread);
  250.      GpiSetMix ( hpsPrMem, FM_OVERPAINT) ;
  251.      GpiSetBackMix (hpsPrMem, BM_LEAVEALONE) ;
  252.      GpiCreateLogColorTable(hpsPrMem, LCOL_RESET | LCOL_REALIZABLE,
  253.               LCOLF_CONSECRGB, 0L, lPrinterColors, alPrPhysClrs);
  254.  
  255.      /* Now load the memory bit map from the master pixel array */
  256.      pbmiPrMem = &bmiColorTableBW;
  257.      pbmiPrMem->cx = cp.cx;
  258.      pbmiPrMem->cy = cp.cy;
  259.      pbmiPrMem->cPlanes = cp.cPlanes;
  260.      pbmiPrMem->cBitCount = cp.cBitCount;
  261.      errorcode = GpiSetBitmapBits(hpsPrMem, 0L, (LONG) cp.cy,
  262.                      cp.pixels, pbmiPrMem);
  263.  
  264.      /* now its off to the printer */
  265.      DevEscape (hdcPrinter, DEVESC_STARTDOC,
  266.                _fstrlen(FractName) , FractName, NULL, NULL);
  267.      aptl[0].x = 0;     aptl[0].y = 0;
  268.      aptl[1].x = cxPrinter; aptl[1].y = cyPrinter;
  269.      aptl[2].x = 0;     aptl[2].y = 0;
  270.      aptl[3].x = cp.cx; aptl[3].y = cp.cy;
  271.  
  272.      GpiBitBlt (hpsPrinter, hpsPrMem, 4L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  273.      errorcode = WinGetLastError(habThread);
  274.  
  275.      /* now clean up */
  276.      DevEscape (hdcPrinter, DEVESC_ENDDOC, 0L, NULL, NULL, NULL) ;
  277.  
  278.      GpiSetBitmap(hpsPrMem, (HBITMAP) NULL);
  279.      GpiDeleteBitmap (hbmPrMem);
  280.      GpiDestroyPS(hpsPrMem);
  281.      DevCloseDC (hdcPrMem);
  282.  
  283.      GpiDestroyPS (hpsPrinter) ;
  284.      DevCloseDC (hdcPrinter) ;
  285.  
  286.      _ffree (alPrPhysClrs);
  287.  
  288.      return SUB_STAT_OK;
  289.  
  290.      }
  291.  
  292.  
  293. /*
  294.      Print to an HP-PaintJet ( ... sure wish there was a real driver ...)
  295.  
  296.      Code initially stolen from FRACTINT For DOS.
  297.  
  298.      Rescaling code put in as an afterthought (those 1.5" by 1.8"
  299.      pictures were cute but not what I originally had in mind).
  300.  
  301. */
  302.  
  303. FILE *PRFILE;
  304. extern int extraseg;
  305.  
  306. static unsigned char _huge *pixels;
  307. static int xleftx, xrightx, ybottomy, ytopy;
  308. static SHORT ycy, xpm_xdots;
  309. static USHORT xpixels_per_byte;  /* bitmap configuration data */
  310. static LONG   xpixels_per_bytem1;
  311. static USHORT xpixelshift_per_byte;
  312. static unsigned char xpm_andmask[2];
  313. static unsigned char xpm_notmask[2];
  314. static unsigned char xpm_bitshift[2];
  315.  
  316. void updatesavename(char *name);
  317.  
  318. static int PrintDriverPJ(VOID)
  319. {
  320.     register int y,j;           /* indices                        */
  321.     char buff[192];             /* buffer for 192 sets of pixels  */
  322.                                 /* This is very large so that we can*/
  323.                                 /* get reasonable times printing  */
  324.                                 /* from modes like 2048x2048 disk-*/
  325.                                 /* video.  When this was 24, a 2048*/
  326.                                 /* by 2048 pic took over 2 hours to*/
  327.                                 /* print.  It takes about 15 min now*/
  328.     int BuffSiz;                /* how much of buff[] we'll use   */
  329.     char far *es;               /* pointer to extraseg for buffer */
  330.     int i,x,                    /* more indices                   */
  331.         res,                    /* resolution we're gonna' use    */
  332.                                 /************************************/
  333.         ptrid;                  /* Printer Id code.               */
  334.                                 /* Currently, the following are   */
  335.                                 /* assigned:                      */
  336.                                 /*            1. HPLJ (all)       */
  337.                                 /*               Toshiba PageLaser*/
  338.                                 /*            2. IBM Graphics     */
  339.                                 /*            3. Color Printer    */
  340.                                 /*            4. HP PaintJet      */
  341.                                 /*            5. PostScript       */
  342.                                 /************************************/
  343.     char prfname[128];
  344.     char fmtbuf[128];
  345.  
  346.      /* we want to stretch the bitmap to full page Paintjet size */
  347.      HDC hdcPjMem;
  348.      HPS hpsPjMem;
  349.      HBITMAP hbmPjMem;
  350.      PBITMAPINFO pbmiPjMem;
  351.      SIZEL sizl;
  352.      BITMAPINFOHEADER bmp;
  353.      LONG errorcode;
  354.      POINTL aptl[4];
  355.      LONG pm_bytes;
  356.      static ULONG _far alPjPhysClrs[16] = {  0x00000000, 0x00000080,
  357.                                              0x00008000, 0x00008080,
  358.                                              0x00800000, 0x00800080,
  359.                                              0x00808000, 0x00808080,
  360.                                              0x00CCCCCC, 0x000000FF,
  361.                                              0x0000FF00, 0x0000FFFF,
  362.                                              0x00FF0000, 0x00FF00FF,
  363.                                              0x00FFFF00, 0x00FFFFFF };
  364.  
  365.     for (j=0;j<192;j++) { buff[j]=0; }          /* Clear buffer  */
  366.  
  367.     _fstrcpy(prfname, cp.szPrintName);
  368.  
  369.     if ((PRFILE = fopen(prfname,"wb"))==NULL)
  370.           {
  371.           PMfrSyncMsg(4, szPrintNoOpen);
  372.           return (SUB_STAT_ABORT);
  373.           }
  374.  
  375.     if (extraseg) {
  376.         #ifdef __TURBOC__
  377.             es=MK_FP(extraseg,0);
  378.         #else
  379.             FP_SEG(es)=extraseg;
  380.             FP_OFF(es)=0;
  381.         #endif
  382.         }
  383.  
  384.     /* stretch the bitmap into a larger bitmap that is full page on the Paintjet */
  385.      hdcPjMem = DevOpenDC (habThread, OD_MEMORY, "*", 0L, NULL, cp.hdcScreen) ;
  386.      sizl.cx = 1800L; sizl.cy = 1440L;
  387.      ycy = 1440;
  388.      xpm_xdots = (((ULONG) sizl.cx + 7) & 0xfffffff8);
  389.      xleftx = 0; xrightx = 1799; ybottomy = 1439; ytopy = 0;
  390.      xpixelshift_per_byte = 1;
  391.      xpixels_per_byte = 2;
  392.      xpixels_per_bytem1 = 1;
  393.      xpm_andmask[0] = 0xf0;
  394.      xpm_notmask[0] = 0x0f;
  395.      xpm_bitshift[0] = 4;
  396.      xpm_andmask[1] = 0x0f;
  397.      xpm_notmask[1] = 0xf0;
  398.      xpm_bitshift[1] = 0;
  399.      hpsPjMem = GpiCreatePS (habThread, hdcPjMem, &sizl,
  400.                     PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  401.  
  402.      bmp.cbFix   = sizeof bmp;
  403.      bmp.cx      = sizl.cx;
  404.      bmp.cy      = sizl.cy;
  405.      bmp.cPlanes = 1;   /* paintjet is now at most 16 color as we use it */
  406.      bmp.cBitCount = 4;
  407.      hbmPjMem = GpiCreateBitmap (hpsPjMem, &bmp, 0L, NULL, NULL);
  408.      errorcode = WinGetLastError(habThread);
  409.  
  410.      GpiSetBitmap (hpsPjMem, hbmPjMem);
  411.      errorcode = WinGetLastError(habThread);
  412.      GpiSetMix ( hpsPjMem, FM_OVERPAINT) ;
  413.      GpiSetBackMix (hpsPjMem, BM_LEAVEALONE) ;
  414.      GpiCreateLogColorTable(hpsPjMem, LCOL_RESET,
  415.               LCOLF_CONSECRGB, 0L, 16L, alPjPhysClrs);
  416.  
  417.      aptl[0].x = 0;     aptl[0].y = 0;
  418.      aptl[1].x = 1800L; aptl[1].y = 1440;
  419.      aptl[2].x = 0;     aptl[2].y = 0;
  420.      aptl[3].x = cp.cx; aptl[3].y = cp.cy;
  421.  
  422.      GpiBitBlt (hpsPjMem, cp.hpsMemory, 4L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  423.  
  424.      pm_bytes =  (LONG) (xpm_xdots >> xpixelshift_per_byte) * (LONG) sizl.cy;
  425.  
  426.      pm_bytes = ( (pm_bytes + 7) & 0xfffffff8) >> 3;
  427.      pixels = (unsigned char _huge *) halloc(pm_bytes, 8);
  428.  
  429.      pbmiPjMem = (PBITMAPINFO) _fmalloc( sizeof(BITMAPINFOHEADER) +
  430.                                          16 * sizeof(RGB) );
  431.  
  432.      pbmiPjMem->cbFix = sizeof(BITMAPINFOHEADER);
  433.      pbmiPjMem->cPlanes = 1;
  434.      pbmiPjMem->cBitCount = 4;
  435.      pbmiPjMem->cx = sizl.cx;
  436.      pbmiPjMem->cy = sizl.cy;
  437.  
  438.      GpiQueryBitmapBits(hpsPjMem, 0L, sizl.cy-1, pixels, pbmiPjMem);
  439.  
  440.      /* end of rescale */
  441.  
  442.     ptrid=4;
  443.     res=180;
  444.         /****** PaintJet  *****/
  445.     if ( res < 150 ) res = 90;      /* an arbitrary boundary */
  446.     if ( res >= 150 ) res = 180;
  447.     /*****  Set up buffer size for immediate user gratification *****/
  448.     /*****    AKA, if we don't have to, don't buffer the data   *****/
  449.     BuffSiz=8;
  450.     if (sizl.cx>1024) BuffSiz=192;     /*****   Initialize printer  *****/
  451.  
  452.                                 /******  INITIALIZE GRAPHICS MODES  ******/
  453.     /****** PaintJet *****/
  454.     /* set resolution, 4 colour planes for 90dpi or 3 for 180dpi,
  455.               start raster graphics   */
  456.     sprintf(fmtbuf,"\x1B" "E" "\x1B*t%dR\x1B*r%dU\x1B*r0A",
  457.                        res,res==90?4:3);
  458.     fputs(fmtbuf, PRFILE);
  459.  
  460.     for (j=0;j<192;j++)
  461.          { buff[j]=0; } /* Clear buffer            */
  462.  
  463.                                 /*****  Get And Print Screen **** */
  464.                                /* HP PaintJet       */
  465.          /* DPE mod - Scan it for Landscape printing */
  466.          /* Note: must scan Y from bottom (max) up for the
  467.             printed picture to come out top up.             */
  468.          for (x=0;x<sizl.cx;x++)
  469.          {
  470.  
  471.              sprintf(fmtbuf,"\x1B*b%dV",ycy/8);
  472.              fputs(fmtbuf, PRFILE);
  473.              for (y=ycy-8;y>=0;y-=8)
  474.              {
  475.                  buff[0]=0;
  476.                  for (i=7;i>=0;i--)
  477.                  {
  478.                       buff[0]<<=1;
  479.                       if ( getcolorx(x,y+i)&4 )  /* r */
  480.                                buff[0]++;
  481.                  }
  482.                  fputc(buff[0],PRFILE);
  483.              }
  484.  
  485.              sprintf(fmtbuf,"\x1B*b%dV",ycy/8);
  486.              fputs(fmtbuf, PRFILE);
  487.              for (y=ycy-8;y>=0;y-=8)
  488.              {
  489.                  buff[0]=0;
  490.                  for (i=7;i>=0;i--)
  491.                  {
  492.                      buff[0]<<=1;
  493.                      if ( getcolorx(x,y+i)&2 )  /* g */
  494.                             buff[0]++;
  495.                  }
  496.                  fputc(buff[0],PRFILE);
  497.              }
  498.  
  499.              sprintf(fmtbuf,"\x1B*b%dV",ycy/8);
  500.              fputs(fmtbuf, PRFILE);
  501.              for (y=ycy-8;y>=0;y-=8)
  502.              {
  503.                  buff[0]=0;
  504.                  for (i=7;i>=0;i--)
  505.                  {
  506.                      buff[0]<<=1;
  507.                      if ( getcolorx(x,y+i)&1 )  /* b */
  508.                             buff[0]++;
  509.                  }
  510.                  fputc(buff[0],PRFILE);
  511.              }
  512.  
  513.              if (res == 90)
  514.              {
  515.                 sprintf(fmtbuf,"\x1B*b%dV",ycy/8);
  516.                 fputs(fmtbuf, PRFILE);
  517.                 for (y=ycy-8;y>=0;y-=8)
  518.                 {
  519.                     buff[0]=0;
  520.                     for (i=7;i>=0;i--)
  521.                     {
  522.                         buff[0]<<=1;
  523.                         if ( getcolorx(x,y+i)&8 )  /* i */
  524.                                 buff[0]++;
  525.                     }
  526.                     fputc(buff[0],PRFILE);
  527.                 }
  528.              }
  529.  
  530.              sprintf(fmtbuf,"\x1B*b0W"); /* end colour planes   */
  531.              fputs(fmtbuf, PRFILE);
  532.          }
  533.  
  534.          sprintf(fmtbuf,"\x1B*r0B");  /* end raster graphics */
  535.          fputs(fmtbuf, PRFILE);
  536.          fputs("\x1B" "E",PRFILE);    /* reset printer */
  537.  
  538.     fclose(PRFILE);
  539.  
  540.     /* increment the save name for next time */
  541.     updatesavename(prfname);
  542.     _fstrcpy(cp.szPrintName, prfname);
  543.  
  544.     _ffree(pbmiPjMem);
  545.     hfree(pixels);
  546.     GpiSetBitmap(hpsPjMem, (HBITMAP) NULL);
  547.     GpiDeleteBitmap (hbmPjMem);
  548.     GpiDestroyPS(hpsPjMem);
  549.     DevCloseDC (hdcPjMem);
  550.  
  551.     return (SUB_STAT_OK);
  552.  
  553. }
  554.  
  555. static int getcolorx (int xdot, int ydot)
  556. {
  557.      ULONG pm_y, offset;
  558.  
  559.     if ( ! ((xdot >= xleftx) && (xdot <= xrightx) &&
  560.             (ydot >= ytopy)  && (ydot <= ybottomy)) )
  561.        return 0;        /* arbitrary value */
  562.  
  563.      pm_y = (ULONG) (ycy - ydot - 1);
  564.      offset = ((ULONG) xpm_xdots * pm_y) + (ULONG) xdot;
  565.  
  566.      if (xpixelshift_per_byte == 0)
  567.        {
  568.           return(pixels[offset]);
  569.        }
  570.      else
  571.        {
  572.         USHORT j;
  573.         j = offset & xpixels_per_bytem1;
  574.         offset = offset >> xpixelshift_per_byte;
  575.         return((int)((pixels[offset] & xpm_andmask[j]) >> xpm_bitshift[j]));
  576.        }
  577. }
  578.