home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gif-util.zip / GIF2EPSN.C < prev    next >
C/C++ Source or Header  |  1989-08-01  |  20KB  |  544 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 0.1,    Jul. 1989    *
  5. ******************************************************************************
  6. * Program to dump GIF file into EPSON type printers                 *
  7. * Options:                                     *
  8. * -d factor : use dithering of matrix of size factor by factor.             *
  9. * -t level : set the threshold level of white in the result (0..100).         *
  10. * -m mapping : methods for mapping the 24bits colors into 1 BW bit.         *
  11. * -p printer : specify printer to print to (lpt1: by default).             *
  12. * -n : nice mode : uses double density to achieve better quality.         *
  13. * -i : invert the image.                             *
  14. * -h : on line help.                                 *
  15. ******************************************************************************
  16. * History:                                     *
  17. * 15 Jul 89 - Version 1.0 by Gershon Elber.                     *
  18. *****************************************************************************/
  19.  
  20. #include <graphics.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <ctype.h>
  24. #include <alloc.h>
  25. #include <string.h>
  26. #include <io.h>
  27. #include <dos.h>
  28. #include <bios.h>
  29. #include <fcntl.h>
  30. #include "gif_lib.h"
  31. #include "getarg.h"
  32.  
  33. #define PROGRAM_NAME    "Gif2Epsn"
  34. #define VERSION        "ß Version 1.0, "
  35. #define DEFAULT_PRINTER "lpt1"
  36.  
  37. #define    C2BW_BACK_GROUND    0 /*Methods to map 24bits Colors to 1 BW bit */
  38. #define    C2BW_GREY_LEVELS    1
  39. #define C2BW_DITHER        2
  40. #define C2BW_NUM_METHODS    3             /* Always hold # of methods */
  41.  
  42. #define DEFAULT_THRESHOLD    5000          /* Color -> BW threshold level */
  43.  
  44. #define DITHER_MIN_MATRIX    2
  45. #define DITHER_MAX_MATRIX    4
  46.  
  47. /* The epson specific are defined here:                         */
  48. #define EPSON_WIDTH        80             /* 80 char per line */
  49. #define EPSON_PIXEL_2_CHAR    8    /* 8 pixels per char, in REG_DENSITY */
  50.  
  51. #define EPSON_ESC        "\x1b"         /* Actually regular escape char */
  52. #define EPSON_RESET        EPSON_ESC "@"        /* Reset the printer */
  53. #define EPSON_VERTICAL_SPACE    EPSON_ESC "A" "\x08" /* 8/72 inch vertically */
  54. #define EPSON_REG_DENSITY    EPSON_ESC "K"  /* 640 pixels per 7.5" (line) */
  55. #define EPSON_DUAL_DENSITY    EPSON_ESC "L" /* 1280 pixels per 7.5" (line) */
  56.  
  57. extern unsigned int
  58.     _stklen = 16384;                  /* Increase default stack size */
  59.  
  60. static char
  61.     *VersionStr =
  62.     PROGRAM_NAME
  63.     "    IBMPC "
  64.     VERSION
  65.     "    Gershon Elber,    "
  66.     __DATE__ ",   " __TIME__ "\n"
  67.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  68. static char
  69.     *CtrlStr =
  70.     PROGRAM_NAME
  71.     " d%-DitherSize!d t%-BWThreshold!d m%-Mapping!d i%- n%- p%-PrinterName!s h%- GifFile!*s";
  72. static char
  73.     *PrinterName = DEFAULT_PRINTER;
  74. static char
  75.     *ProgramName;
  76. /* Make some variables global, so we could access them faster: */
  77. static int
  78.     ImageNum = 0,
  79.     BackGround = 0,
  80.     DitherSize = 2, DitherFlag = FALSE,
  81.     BWThresholdFlag = FALSE, Threshold,
  82.     BWThreshold = DEFAULT_THRESHOLD,        /* Color -> BW mapping threshold */
  83.     Mapping, MappingFlag = FALSE,
  84.     InvertFlag = FALSE,
  85.     NiceFlag = FALSE,
  86.     PrinterFlag = FALSE,
  87.     HelpFlag = FALSE,
  88.     ColorToBWMapping = C2BW_BACK_GROUND,
  89.     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should  */
  90.     InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
  91. static GifColorType
  92.     *ColorMap;
  93.  
  94. static void EvalDitheredScanline(RowType *ScreenBuffer, int Row,
  95.                     int RowSize, RowType *DitherBuffer);
  96. static void DumpScreen2Epsn(RowType *ScreenBuffer,
  97.                     int ScreenWidth, int ScreenHeight);
  98. static void PutString(FILE *Prt, int DirectPrint, char *Str, int Len);
  99. static void PutString2(FILE *Prt, int DirectPrint, char *Str, int Len);
  100.  
  101. /******************************************************************************
  102. * Interpret the command line and scan the given GIF file.              *
  103. ******************************************************************************/
  104. void main(int argc, char **argv)
  105. {
  106.     int    i, j, Error, NumFiles, Size, Row, Col, Width, Height, ExtCode, Count;
  107.     GifRecordType RecordType;
  108.     ByteType *Extension;
  109.     char **FileName = NULL;
  110.     RowType *ScreenBuffer;
  111.     GifFileType *GifFile;
  112.  
  113.     if (strlen(ProgramName = argv[0]) == 0)            /* DOS 3.x only! */
  114.     ProgramName = PROGRAM_NAME;      /* Do something reasonable for 2.x */
  115.  
  116.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &DitherFlag, &DitherSize,
  117.         &BWThresholdFlag, &Threshold, &MappingFlag, &Mapping,
  118.         &InvertFlag, &NiceFlag, &PrinterFlag, &PrinterName, &HelpFlag,
  119.         &NumFiles, &FileName)) != FALSE ||
  120.         (NumFiles > 1 && !HelpFlag)) {
  121.     if (Error) GAPrintErrMsg(Error);
  122.     else
  123.     if (NumFiles > 1)
  124.         MESSAGE("Error in command line parsing - one GIF file please\n");
  125.     GAPrintHowTo(CtrlStr);
  126.     exit(1);
  127.     }
  128.  
  129.     if (HelpFlag) {
  130.     fprintf(stderr, VersionStr);
  131.     GAPrintHowTo(CtrlStr);
  132.     exit(0);
  133.     }
  134.  
  135.     if (DitherFlag) {
  136.     /* Make sure we are o.k.: */
  137.     if (DitherSize > DITHER_MAX_MATRIX) DitherSize = DITHER_MAX_MATRIX;
  138.     if (DitherSize < DITHER_MIN_MATRIX) DitherSize = DITHER_MAX_MATRIX;
  139.     }
  140.  
  141.     /* As Threshold is in [0..100] range and BWThreshold is [0..25500]: */
  142.     if (BWThresholdFlag) {
  143.     if (Threshold > 100 || Threshold < 0)
  144.         EXIT("Threshold not in 0..100 percent");
  145.     BWThreshold = Threshold * 255;
  146.     if (BWThreshold == 0) BWThreshold = 1;   /* Overcome divide by zero! */
  147.     }
  148.  
  149.     /* No message is emitted, but mapping method is clipped to exists method */
  150.     if (MappingFlag) ColorToBWMapping = Mapping % C2BW_NUM_METHODS;
  151.  
  152.     if (NumFiles == 1) {
  153.     if ((GifFile = DGifOpenFileName(*FileName)) == NULL) {
  154.         PrintGifError();
  155.         exit(-1);
  156.     }
  157.     }
  158.     else {
  159.     /* Use the stdin instead: */
  160.  
  161.     setmode(0, O_BINARY);
  162.     if ((GifFile = DGifOpenFileHandle(0)) == NULL) {
  163.         PrintGifError();
  164.         exit(-1);
  165.     }
  166.     }
  167.  
  168.     /* Allocate the screen as vector of column of rows. We cannt allocate    */
  169.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  170.     /* 64k at a time and our image can be bigger than that:             */
  171.     /* Note this screen is device independent - its the screen as defined by */
  172.     /* the GIF file parameters itself.                         */
  173.     if ((ScreenBuffer = (RowType *)
  174.     malloc(GifFile -> SHeight * sizeof(RowType *))) == NULL)
  175.         EXIT("Failed to allocate memory required, aborted");
  176.  
  177.     Size = GifFile -> SWidth * sizeof(PixelType);/* Size in bytes of one row */
  178.     if ((ScreenBuffer[0] = (RowType) malloc(Size)) == NULL)     /* First row */
  179.     EXIT("Failed to allocate memory required, aborted");
  180.  
  181.     for (i=0; i<GifFile -> SWidth; i++)      /* And set its color to BackGround */
  182.     ScreenBuffer[0][i] = GifFile -> SBackGroundColor;
  183.     for (i=1; i<GifFile -> SHeight; i++) {
  184.     /* Allocate the other rows, andset their color to background too: */
  185.     if ((ScreenBuffer[i] = (RowType) malloc(Size)) == NULL)
  186.         EXIT("Failed to allocate memory required, aborted\n");
  187.  
  188.     memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
  189.     }
  190.  
  191.     /* Scan the content of the GIF file and load the image(s) in: */
  192.     do {
  193.     if (DGifGetRecordType(GifFile, &RecordType) == ERROR) {
  194.         PrintGifError();
  195.         exit(-1);
  196.     }
  197.     switch (RecordType) {
  198.         case IMAGE_DESC_RECORD_TYPE:
  199.         if (DGifGetImageDesc(GifFile) == ERROR) {
  200.             PrintGifError();
  201.             exit(-1);
  202.         }
  203.         Row = GifFile -> ITop;  /* Image Position relative to Screen */
  204.         Col = GifFile -> ILeft;
  205.         Width = GifFile -> IWidth;
  206.         Height = GifFile -> IHeight;
  207.         fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  208.             ProgramName, ++ImageNum, Col, Row, Width, Height);
  209.         if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth ||
  210.            GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) {
  211.             fprintf(stderr, "Image %d is not confined to screen dimension, aborted\n");
  212.             exit(-2);
  213.         }
  214.         if (GifFile -> IInterlace) {
  215.             /* Need to perform 4 passes on the images: */
  216.             for (Count=i=0; i<4; i++)
  217.             for (j=Row + InterlacedOffset[i]; j<Row + Height;
  218.                          j += InterlacedJumps[i]) {
  219.                 fprintf(stderr, "\b\b\b\b%-4d", Count++);
  220.                 if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
  221.                 Width) == ERROR) {
  222.                 PrintGifError();
  223.                 exit(-1);
  224.                 }
  225.             }
  226.         }
  227.         else {
  228.             for (i=0; i<Height; i++) {
  229.             fprintf(stderr, "\b\b\b\b%-4d", i);
  230.             if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
  231.                 Width) == ERROR) {
  232.                 PrintGifError();
  233.                 exit(-1);
  234.             }
  235.             }
  236.         }
  237.         break;
  238.         case EXTENSION_RECORD_TYPE:
  239.         /* Skip any extension blocks in file: */
  240.         if (DGifGetExtension(GifFile, &ExtCode, &Extension) == ERROR) {
  241.             PrintGifError();
  242.             exit(-1);
  243.         }
  244.         while (Extension != NULL) {
  245.             if (DGifGetExtensionNext(GifFile, &Extension) == ERROR) {
  246.             PrintGifError();
  247.             exit(-1);
  248.             }
  249.         }
  250.         break;
  251.         case TERMINATE_RECORD_TYPE:
  252.         break;
  253.         default:             /* Should be traps by DGifGetRecordType */
  254.         break;
  255.     }
  256.     }
  257.     while (RecordType != TERMINATE_RECORD_TYPE);
  258.  
  259.     /* Lets display it - set the global variables required and do it: */
  260.     BackGround = GifFile -> SBackGroundColor;
  261.     ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap :
  262.                        GifFile -> SColorMap);
  263.     DumpScreen2Epsn(ScreenBuffer, GifFile -> SWidth, GifFile -> SHeight);
  264.  
  265.     if (DGifCloseFile(GifFile) == ERROR) {
  266.     PrintGifError();
  267.     exit(-1);
  268.     }
  269. }
  270.  
  271. /*****************************************************************************
  272. * Routine to evaluate dithered scanlines out of given ones, using Size         *
  273. * dithering matrix, starting from Row. The given scanlines are NOT modified. *
  274. *****************************************************************************/
  275. static void EvalDitheredScanline(RowType *ScreenBuffer, int Row,
  276.                     int RowSize, RowType *DitherBuffer)
  277. {
  278.     static char Dither2[2][2] = {      /* See Foley & Van Dam pp. 597-601 */
  279.     { 1, 3 },
  280.     { 4, 2 }
  281.     };
  282.     static char Dither3[3][3] = {
  283.     { 7, 9, 5 },
  284.     { 2, 1, 4 },
  285.     { 6, 3, 8 }
  286.     };
  287.     static char Dither4[4][4] = {
  288.     { 1,  9,  3,  11 },
  289.     { 13, 5,  15, 7 },
  290.     { 4,  12, 2,  10 },
  291.     { 16, 8,  14, 6 }
  292.     };
  293.     int i, j, k, Level;
  294.     long Intensity;
  295.     GifColorType *ColorMapEntry;
  296.  
  297.     /* Scan the Rows (Size rows) evaluate intensity every Size pixel and use */
  298.     /* the dither matrix to set the dithered result;                 */
  299.     for (i=0; i<=RowSize-DitherSize; i+=DitherSize) {
  300.     Intensity = 0;
  301.     for (j=Row; j<Row+DitherSize; j++)
  302.         for (k=0; k<DitherSize; k++) {
  303.         ColorMapEntry = &ColorMap[ScreenBuffer[j][i+k]];
  304.         Intensity += 30 * ((int) ColorMapEntry->Red) +
  305.                  59 * ((int) ColorMapEntry->Green) +
  306.                  11 * ((int) ColorMapEntry->Blue);
  307.         }
  308.  
  309.     /* Find the intensity level (between 0 and Size^2) of our matrix: */
  310.     /* Expression is "Intensity * BWThreshold / (25500 * DefThresh)"  */
  311.     /* but to prevent from overflow in the long evaluation we do this:*/
  312.     Level = ((Intensity / 2550) * ((long) DEFAULT_THRESHOLD) /
  313.                         (((long) BWThreshold) * 10));
  314.     switch (DitherSize) {
  315.         case 2:
  316.         for (j=0; j<DitherSize; j++)
  317.             for (k=0; k<DitherSize; k++)
  318.             DitherBuffer[j][i+k] = Dither2[j][k] <= Level;
  319.         break;
  320.         case 3:
  321.         for (j=0; j<DitherSize; j++)
  322.             for (k=0; k<DitherSize; k++)
  323.             DitherBuffer[j][i+k] = Dither3[j][k] <= Level;
  324.         break;
  325.         case 4:
  326.         for (j=0; j<DitherSize; j++)
  327.             for (k=0; k<DitherSize; k++)
  328.             DitherBuffer[j][i+k] = Dither4[j][k] <= Level;
  329.         break;
  330.     }
  331.     }
  332. }
  333.  
  334. /******************************************************************************
  335. * The real dumping routine. Few things are taken into account:              *
  336. * 1. The Nice flag. If TRUE each pixel is printed twice in double density.    *
  337. * 2. The Invert flag. If TRUE each pixel before drawn is inverted.          *
  338. * 3. The rendering mode and dither matrix flag if dithering is selected.      *
  339. *   The image is drawn from ScreenBuffer ScreenTop/Left in the bottom/right   *
  340. * directions.                                           *
  341. *   Unfortunatelly, there is a BUG in DOS that does not handle ctrl-Z          *
  342. * correctly if we open lptx: device in binary mode (should treat it as any    *
  343. * other char). Therefore I had to write to it directly using biosprint. I     *
  344. * dont like it either, and if you have better way to do it, let me know.      *
  345. ******************************************************************************/
  346. static void DumpScreen2Epsn(RowType *ScreenBuffer,
  347.                     int ScreenWidth, int ScreenHeight)
  348. {
  349.     int i, j, p, Size, LeftCWidth, Len, DirectPrint = 0,
  350.     DitheredLinesLeft = 0, DitheredLinesCount, MapInvert[2];
  351.     char LinePrefixLen[2];                  /* Length of scan line */
  352.     ByteType *EpsonBuffer;
  353.     PixelType *Line;
  354.     RowType *DitherBuffer;
  355.     GifColorType *ColorMapEntry;
  356.     FILE *Prt = NULL;
  357.  
  358.     strupr(PrinterName);
  359.     if (strcmp(PrinterName, "LPT1") == 0 ||
  360.     strcmp(PrinterName, "PRN") == 0) DirectPrint = 1;
  361.     if (strcmp(PrinterName, "LPT2") == 0) DirectPrint = 2;
  362.     if (strcmp(PrinterName, "LPT3") == 0) DirectPrint = 2;
  363.  
  364.     if (!DirectPrint) {
  365.     if ((Prt = fopen(PrinterName, "wb")) == NULL)
  366.         EXIT("Failed to open output (printer) file\n");
  367.     setvbuf(Prt, NULL, _IOFBF, FILE_BUFFER_SIZE);    /* Fully buffered! */
  368.     }
  369.  
  370.     if ((EpsonBuffer = malloc(ScreenWidth)) == NULL)
  371.     EXIT("Failed to allocate memory required, aborted");
  372.  
  373.     /*   Allocate the buffer to save the dithered information.             */
  374.     if (ColorToBWMapping == C2BW_DITHER) {
  375.     if ((DitherBuffer = (RowType *)
  376.         malloc(DITHER_MAX_MATRIX * sizeof(RowType *))) != NULL) {
  377.         Size = ScreenWidth * sizeof(PixelType);      /* Size of one row */
  378.         for (i=0; i<DITHER_MAX_MATRIX; i++) {
  379.         if ((DitherBuffer[i] = (RowType) malloc(Size)) == NULL) {
  380.             DitherBuffer = NULL;
  381.             break;
  382.         }
  383.         }
  384.     }
  385.     if (DitherBuffer == NULL)
  386.         EXIT("Failed to allocate memory required, aborted");
  387.     }
  388.     else DitherBuffer = NULL;
  389.  
  390.     /* Reset the printer, and make sure no space between adjacent lines: */
  391.     PutString(Prt, DirectPrint, EPSON_RESET, 2);
  392.     PutString(Prt, DirectPrint, EPSON_VERTICAL_SPACE, 3);
  393.  
  394.     /* Prepar the left spacing to begin with, so image will be in the middle */
  395.     LeftCWidth = (EPSON_WIDTH - (ScreenWidth / EPSON_PIXEL_2_CHAR)) / 2;
  396.  
  397.     if (InvertFlag) {           /* Make the inversion as fast a possible. */
  398.     MapInvert[0] = 1;
  399.     MapInvert[1] = 0;
  400.     }
  401.     else {
  402.     MapInvert[0] = 0;
  403.     MapInvert[1] = 1;
  404.     }
  405.  
  406.     for (i=0, p=0; i<ScreenHeight; i++, p++) {
  407.     fprintf(stderr, "\b\b\b\b%-4d", ScreenHeight - i);
  408.     Line = ScreenBuffer[i];
  409.  
  410.     /* If 8 lines were accumulated in the printer buffer - dump them out */
  411.     if (p == 8) {
  412.         for (Len=ScreenWidth-1; Len>=0; Len--) if (EpsonBuffer[Len]) break;
  413.  
  414.         /* Only in case this line is not empty: */
  415.         if (Len++ >= 0) {
  416.         /* Make the left space, so image will be centered: */
  417.         for (j=0; j<LeftCWidth; j++)
  418.             PutString(Prt, DirectPrint,  " ", 1);
  419.  
  420.         /* Full printer line is ready to be dumped - send it out: */
  421.         if (NiceFlag) {
  422.             PutString(Prt, DirectPrint, EPSON_DUAL_DENSITY, 2);
  423.             LinePrefixLen[0] = (Len * 2) % 256;
  424.             LinePrefixLen[1] = (Len * 2) / 256;
  425.             PutString(Prt, DirectPrint, LinePrefixLen, 2);
  426.             PutString2(Prt, DirectPrint, (char *) EpsonBuffer, Len);
  427.         }
  428.         else {
  429.             PutString(Prt, DirectPrint, EPSON_REG_DENSITY, 2);
  430.             LinePrefixLen[0] = Len % 256;
  431.             LinePrefixLen[1] = Len / 256;
  432.             PutString(Prt, DirectPrint, LinePrefixLen, 2);
  433.             PutString(Prt, DirectPrint, (char *) EpsonBuffer, Len);
  434.         }
  435.         }
  436.         PutString(Prt, DirectPrint, "\x0d" "\x0a", 2);
  437.         p = 0;
  438.     }
  439.  
  440.     /* We decide right here what method to map Colors to BW so the inner */
  441.     /* loop will be independent of it (and therefore faster):         */
  442.     switch(ColorToBWMapping) {
  443.         case C2BW_BACK_GROUND:
  444.         for (j=0; j<ScreenWidth; j++)
  445.             EpsonBuffer[j] = (EpsonBuffer[j] << 1) +
  446.                     MapInvert[Line[j] != BackGround];
  447.         break;
  448.         case C2BW_GREY_LEVELS:
  449.         for (j=0; j<ScreenWidth; j++) {
  450.             ColorMapEntry = &ColorMap[Line[j]];
  451.             /* For the transformation from RGB to BW, see Folley &   */
  452.             /* Van Dam pp 613: The Y channel is the BW we need:         */
  453.             /* As colors are 255 maximum, the result can be up to    */
  454.             /* 25500 which is still in range of our 16 bits integers */
  455.             EpsonBuffer[j] = (EpsonBuffer[j] << 1) +
  456.             MapInvert[(30 * (int) ColorMapEntry->Red) +
  457.                    59 * ((int) ColorMapEntry->Green) +
  458.                    11 * ((int) ColorMapEntry->Blue) >
  459.                     BWThreshold];
  460.         }
  461.         break;
  462.         case C2BW_DITHER:
  463.         if (DitheredLinesLeft-- == 0) {
  464.             EvalDitheredScanline(ScreenBuffer,
  465.             (i < ScreenHeight - DitherSize ? i :
  466.                          ScreenHeight - DitherSize),
  467.             ScreenWidth, DitherBuffer);
  468.             DitheredLinesLeft = DitherSize - 1;
  469.             DitheredLinesCount = 0;
  470.         }
  471.         Line = DitherBuffer[DitheredLinesCount++];
  472.         for (j=0; j<ScreenWidth; j++)
  473.             EpsonBuffer[j] = (EpsonBuffer[j] << 1) +
  474.                             MapInvert[Line[j]];
  475.         break;
  476.     }
  477.     }
  478.  
  479.     /* If buffer in incomplete - complete it and dump it out: */
  480.     if (p != 0) {
  481.     for (Len=ScreenWidth-1; Len>=0; Len--) if (EpsonBuffer[Len]) break;
  482.     if (Len++ >= 0) {
  483.         i = 8 - p;                      /* Amount to shift */
  484.         for (j=0; j<ScreenWidth; j++) EpsonBuffer[j] <<= i;
  485.  
  486.         /* Make the left space, so image will be centered: */
  487.         for (j=0; j<LeftCWidth; j++) PutString(Prt, DirectPrint, " ", 1);
  488.  
  489.         if (NiceFlag) {
  490.         PutString(Prt, DirectPrint, EPSON_DUAL_DENSITY, 2);
  491.         LinePrefixLen[0] = (Len * 2) % 256;
  492.         LinePrefixLen[1] = (Len * 2) / 256;
  493.         PutString(Prt, DirectPrint, LinePrefixLen, 2);
  494.         PutString2(Prt, DirectPrint, (char *) EpsonBuffer, Len);
  495.         }
  496.         else {
  497.         PutString(Prt, DirectPrint, EPSON_REG_DENSITY, 2);
  498.         LinePrefixLen[0] = Len % 256;
  499.         LinePrefixLen[1] = Len / 256;
  500.         PutString(Prt, DirectPrint, LinePrefixLen, 2);
  501.         PutString(Prt, DirectPrint, (char *) EpsonBuffer, Len);
  502.         }
  503.     }
  504.     PutString(Prt, DirectPrint, "\x0d" "\x0a", 2);
  505.     }
  506.  
  507.     fclose(Prt);
  508. }
  509.  
  510. /******************************************************************************
  511. * Dumps the string of given length, to Prt. No char in Str has special          *
  512. * meaning, and even zero (NULL) chars are dumped.                  *
  513. * If however DirectPrint is non zero, string is dumped to specifed lpt port.  *
  514. ******************************************************************************/
  515. static void PutString(FILE *Prt, int DirectPrint, char *Str, int Len)
  516. {
  517.     int i;
  518.  
  519.     if (DirectPrint)
  520.      for (i=0; i<Len; i++) biosprint(0, Str[i], DirectPrint - 1);
  521.     else for (i=0; i<Len; i++) fputc(Str[i], Prt);
  522. }
  523.  
  524. /******************************************************************************
  525. * Dumps the string of given length, to Prt. No char in Str has special          *
  526. * meaning, and even zero (NULL) chars are dumped. Every char is dumped twice. *
  527. * If however DirectPrint is non zero, string is dumped to specifed lpt port.  *
  528. ******************************************************************************/
  529. static void PutString2(FILE *Prt, int DirectPrint, char *Str, int Len)
  530. {
  531.     int i;
  532.  
  533.     if (DirectPrint)
  534.     for (i=0; i<Len; i++) {
  535.         biosprint(0, Str[i], DirectPrint - 1);
  536.         biosprint(0, Str[i], DirectPrint - 1);
  537.     }
  538.     else
  539.     for (i=0; i<Len; i++) {
  540.         fputc(Str[i], Prt);
  541.         fputc(Str[i], Prt);
  542.     }
  543. }
  544.