home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / graf / macpnt1.zip / MACPAINT.C < prev    next >
Text File  |  1987-01-18  |  30KB  |  1,105 lines

  1.  
  2. /*
  3.  * Program to read and otherwise manipulate files produced by Macpaint
  4.  * on the Apple Macintosh, as well as RLE files.
  5.  *
  6.  * Written 1/2/87 by Joan Riff for Computerwise Consulting Services.
  7.  *
  8.  *
  9.  *
  10.  ************************************************************************
  11.  *
  12.  * (c) Copyright 1987 by:
  13.  *
  14.  *          Computerwise Consulting Services
  15.  *          P.O. Box 813
  16.  *          McLean, VA 22101
  17.  *          (703) 280-2809
  18.  *
  19.  * All rights reserved.
  20.  *
  21.  * Permission is granted for personal use of this program, with the
  22.  * exception that the following potential users ARE EXPLICITLY DENIED
  23.  * PERMISSION TO RECEIVE, USE, OR TRANSFER THIS PROGRAM IN SOURCE OR
  24.  * OBJECT OR EXECUTABLE OR ANY OTHER FORM:
  25.  *
  26.  *     1) Lotus Development Corporation, and any employee thereof
  27.  *        or consultant thereto;
  28.  *
  29.  *     2) ADAPSO, and any firm which is a member thereof, or any
  30.  *        employee of such a firm.
  31.  *
  32.  * These two organizations have - in the opinion of CCS - acted as
  33.  * "software pirates" by continually and intentionally violating
  34.  * U.S. Copyright law, specifically by first "copy-protecting" software
  35.  * disks and then zealously prosecuting innocent users who exercised
  36.  * their rights under the law to make copies of their own property.
  37.  *
  38.  * Further, permission is granted to transfer this program only if
  39.  * it is transferred absolutely unmodified in any form.
  40.  *
  41.  ************************************************************************
  42.  *
  43.  *
  44.  * This program:
  45.  *
  46.  *    1) Recognizes various versions of MACPAINT files (including
  47.  *       improper "short" files)
  48.  *    2) Supports (and automatically detects) the CGA, EGA, and HERCULES
  49.  *    3) Allows printing of the pictures to various printers
  50.  *    4) What the heck! It supports RLE files too!
  51.  *
  52.  *
  53.  * HELP! I saw an EGA for the first time last night. The code that I have
  54.  *       used to put the image to the EGA ** seems ** to work, but I would
  55.  *       prefer to have some EGA heavy look it over and give me feedback.
  56.  *       Call our answering machine at (703) 280-2809 with results.
  57.  *
  58.  * This program is written for Microsoft C version 3.0, and is compiled
  59.  * with the following batch file:
  60.  *
  61.  *     CL -Ml -K /Zp /Ze /Fefoo macpaint.c
  62.  *     exepack foo.exe macpaint.exe
  63.  *     erase macpaint.obj
  64.  *     erase foo.exe
  65.  *
  66.  */
  67.  
  68.  
  69.  
  70. /*
  71.  *********************************************************************
  72.  *                      About MACPAINT files
  73.  *********************************************************************
  74.  *
  75.  * On the MAC, the picture was a grid of 720 lines, each holding 576
  76.  * pixels (72 bytes per line). This 720x576 image corresponded to an
  77.  * 8"x10" page image (72 dots per inch).
  78.  *
  79.  * There are exactly 72 bytes (576 pixels) encoded for each line, and
  80.  * exactly 720 lines represented. The encoding is as follows:
  81.  *
  82.  *    <count> <data> [<data>...]  <count> <data> [<data>...]
  83.  *
  84.  *    <count> = number of MAC bytes accounted for by this sequence, minus 1
  85.  *
  86.  *        Example: 71 = 72 bytes accounted for
  87.  *                 18 = 19 bytes accounted for
  88.  *
  89.  *        If this count has the high-order bit set (0x80), then negate
  90.  *        it before adding 1 to it.
  91.  *
  92.  *        Example: -2  (0xFE) = 3 bytes accounted for
  93.  *                 -71 (0xB9) = 72 bytes accounted for
  94.  *
  95.  *    <data>  = data byte(s), per count:
  96.  *
  97.  *        If <count> was negative, then <data> is a single byte to
  98.  *        be repeated <count> times.
  99.  *
  100.  *        Example: -71 0 (0xB9 0x00) = 72 bytes of zero (a blank line)
  101.  *
  102.  *        Otherwise, it is a single byte of output pixel data, and
  103.  *        as many subsequent bytes are to be treated as such as
  104.  *        <count> says.
  105.  *
  106.  * Now, all of this would be too simple. So in real life what we find are
  107.  * one or two special header records prepended to the file. They are explained
  108.  * in the _macpaint structure below. The first - the MacBinary header - is put
  109.  * there by MacBinary-compatible Mac communications programs, and serves to
  110.  * allow the resultant file to be properly created on the Mac. The second is
  111.  * put there by MacPaint itself, and defines brush/fill patterns etc.
  112.  *
  113.  * NOTE: There is another type of file that we have run across - one formatted
  114.  *       as a "StartupScreen" file. This one seems to include the 128-byte
  115.  *       MacBinary header, but has no 512-byte MacPaint header. In addition,
  116.  *       the image data for such a file IS NOT encoded per the above, but
  117.  *       seems to be a raw image organized as n 64-byte lines. This data can
  118.  *       just be used as-is (properly centered within our 72-byte image, that is).
  119.  *
  120.  */
  121.  
  122.  
  123.  
  124. /*
  125.  *********************************************************************
  126.  *                      About RLE files
  127.  *********************************************************************
  128.  *
  129.  * RLE stands for "Run Length Encoded". This is a crude method of
  130.  * encoding a graphics image as ASCII characters. It is used by CompuServe
  131.  * to present graphic data during an otherwise alphanumeric session.
  132.  *
  133.  * There are two types of RLE files:
  134.  *
  135.  *    1) "High resolution" data, which forms an image 256 pixels wide
  136.  *       by 192 pixels high. OK, so that's not very high resolution.
  137.  *       This is CompuServe's terminology, not mine.
  138.  *
  139.  *    2) "Medium Resolution" (How can you get any lower!!!???) data, which
  140.  *       forms an image 128 pixels wide by 96 pixels high.
  141.  *
  142.  * Both of these are mono images, although there are rumors of support for
  143.  * color and higher resolution "Real Soon Now".
  144.  *
  145.  * Compared to MacPaint files, these are certainly primitive. RLE's saving grace
  146.  * is that there is a wealth of encoded RLE graphics images on CompuServe. For
  147.  * this reason - and since we have already done all of the video display and
  148.  * printer code for the MacPaint files anyway - we decided to throw in support
  149.  * for this RLE format too.
  150.  *
  151.  * An RLE file has the following format:
  152.  *
  153.  *    1) A "start graphics" escape code:
  154.  *
  155.  *        a) "<ESC> G H" if this is a High Resolution file
  156.  *        b) "<ESC> G M" if this is a Medium Resolution file
  157.  *
  158.  *    2) Data itself, as pairs of ASCII characters. Each is a count, with
  159.  *       32 decimal (ASCII blank) added to it. The first byte of each pair
  160.  *       is the number of background (black) pixels to be set, and the
  161.  *       second is the number of foreground (white) pixels to be set. Data
  162.  *       wraps from the end of one line to the next.
  163.  *
  164.  *    3) An "end graphics" escape code: "<ESC> G N". This is actually an
  165.  *       offshoot of the VIDTEX protocol, which means "return to normal
  166.  *       mode" (hence the "N").
  167.  *
  168.  * NOTE: Not all files have the "<ESC> G N" at the end. The best test that we've
  169.  *       found is as follows:
  170.  *
  171.  *        1) Physical end of file, or
  172.  *        2) Full picture has been received (256x192 or 128x96 pixels), or
  173.  *        3) "<ESC> G N" found in data
  174.  *
  175.  *       whichever comes first.
  176.  *
  177.  * NOTE: There may be embedded control chars in the data. Besides checking for
  178.  *       the terminating "<ESC> G N", these should be ignored.
  179.  *
  180.  * Because RLE images are so small, this program will load up to six RLE
  181.  * pictures into each screen image, and display all six at once. This makes
  182.  * for a nice "gallery" of these smaller images. They can they be saved
  183.  * as one MacPaint picture via the "Write" command.
  184.  *
  185.  */
  186.  
  187.  
  188.  
  189. /*
  190.  *********************************************************************
  191.  *                      About Color and Sizing
  192.  *********************************************************************
  193.  *
  194.  * COLOR:
  195.  *
  196.  * In MacPaint files, a 0 bit corresponds to one pixel of the background
  197.  * color, and a 1 bit to one pixel of the foreground color. We can't tell
  198.  * from a given picture's data whether the 1 bits were the "on" color or
  199.  * the 0 bits were.
  200.  *
  201.  * With RLE files, the same applies. All we know is that the first data
  202.  * entry describes how many "background" pixels to plot, and from there
  203.  * on the data bytes alternately describe "foreground" and "background"
  204.  * pixels.
  205.  *
  206.  * What this means in short is that only the user looking at the screen can
  207.  * decide what looks right. We have included a command to invert the screen
  208.  * image, changing foreground to background and vice versa. This allows the
  209.  * user to produce whatever looks best.
  210.  *
  211.  * Note that printed images may need to be inverted in order to look nice.
  212.  * Again, there's no way that this program can figure it out. Some pictures
  213.  * have shading, others are simple white-on-black images. Caveat Practicum.
  214.  *
  215.  * SIZING:
  216.  *
  217.  * The aspect ration of the original artist's creation is lost to us. If we
  218.  * make the assumption that a MacPaint picture looked "about right" in terms
  219.  * of the vertical versus horizontal dimensions, then we can translate this
  220.  * into something close on the various video adapters that are supported. This
  221.  * program does this. In doing this, it must handle the CGA (boo!) by
  222.  * squishing the picture vertically. This loses a tremendous amount of
  223.  * clarity, ESPECIALLY WHEN VIEWING RLE FILES (which didn't have a lot of
  224.  * resolution to start with). Note, however, that the printed image will
  225.  * show full resolution.
  226.  *
  227.  */
  228.  
  229.  
  230. #include <fcntl.h>
  231. #include <stdio.h>
  232. #include <string.h>
  233. #include <sys\types.h>
  234. #include <sys\stat.h>
  235. #include <dos.h>
  236. #include <io.h>
  237.  
  238. /*
  239.  * Local function definitions for any that don't return an int
  240.  */
  241.  
  242. typedef unsigned char BYTE;
  243.  
  244. BYTE *        wildcard();
  245. BYTE *        decode();
  246. BYTE *        adjust();
  247. BYTE        vslice();
  248. long        ticker();
  249. unsigned    write_pic();
  250.  
  251.  
  252. /*
  253.  * Video adapter types
  254.  */
  255.  
  256. #define TYPE_NONE    0    /* No video adapter (or printer) selected */
  257.  
  258. #define TYPE_HERC    1    /* Hercules Mono adapter (720x348) */
  259. #define HERC_HORIZ    720
  260. #define HERC_VERT    348
  261.  
  262. #define TYPE_CGA    2    /* IBM CGA (640x200) */
  263. #define CGA_HORIZ    640
  264. #define CGA_VERT    200
  265.  
  266. #define TYPE_EGA    3    /* IBM EGA (640x350) */
  267. #define EGA_HORIZ    640
  268. #define EGA_VERT    350
  269.  
  270. /*
  271.  * Macros to return line and column positions for RLE image number n (0-5)
  272.  */
  273.  
  274. #define    RLE_LINE(n)    ( (((n/2) % 3) * (MAC_VERT/3)) + 36 )
  275. #define    RLE_COL(n)    ( ((n&1) * ((MAC_HORIZ/8)/2)) + 2 )
  276.  
  277.  
  278. /*
  279.  * Misc equates
  280.  */
  281.  
  282. #define    NEAR        near    /* 16-bit address here, please */
  283. #define NASTY        1    /* Non-zero for -OK option enforcement */
  284. #define DEBUG        0    /* Non-zero for our decode-timing stats, etc */
  285. #define    MAC_HORIZ    (576)    /* Pixels across a MACPAINT picture */
  286. #define    MAC_VERT    (720)    /* Lines in a MACPAINT picture */
  287. #define GRAPHICS    (-1)    /* Request for GRAPHICS mode */
  288. #define TEXT        0    /* Request for TEXT mode */
  289. #define JUMP        40    /* Number of lines to jump with PgUp PgDn */
  290. #define    COLOR        11    /* Initial color to use on EGA and CGA (1-15) */
  291. #define    ENCODED        1    /* Data is encoded as we would expect */
  292. #define    RAW        2    /* Data is NOT encoded, but is raw image */
  293.  
  294. /*
  295.  * Structure of a MACPAINT file.
  296.  *
  297.  * NOTE: Because this comes off of a 68000 system, binary values ARE NOT
  298.  *       byte-swapped as they are on the 8086. A 16-bit binary 5, for
  299.  *       example, appears as "00 05" AND NOT as "05 00" as it would on
  300.  *       the 8086.
  301.  */
  302.  
  303. struct _macpaint
  304.     {
  305.  
  306.     /*
  307.      * 128-byte header added by MACBINARY-compatible Macintosh
  308.      * communications programs. This is not present on all files
  309.      * that we've seen. It depends on who uploaded the file, and
  310.      * whether they knew what they were doing.
  311.      */
  312.  
  313.     struct _macbinary_header
  314.         {
  315.         BYTE version;        /* Macbinary version number? Normally zero */
  316.         BYTE name_size;        /* # bytes used in following filename */
  317.         BYTE filename[63];    /* Filename itself */
  318.  
  319.         /*
  320.          * Info for use by the Mac Finder
  321.          */
  322.  
  323.         struct _finder_info
  324.             {
  325.             BYTE file_type[4];        /*
  326.                              * Examples that we've seen:
  327.                              *
  328.                              * SCRN = StartupScreen
  329.                              * PNTG = painting
  330.                              */
  331.  
  332.             BYTE creator[4];        /*
  333.                              * Examples that we've seen:
  334.                              *
  335.                              * NONE = StartupScreen
  336.                              * PANT = Fullpaint
  337.                              * MPNT = Macpaint
  338.                              */
  339.  
  340.             BYTE flags;            /*
  341.                              * Bit 7 =  locked
  342.                              * Bit 6 =  invisible
  343.                              * Bit 5 =  bundle
  344.                              * Bit 4 =  system
  345.                              * Bit 3 =  Bozo
  346.                              * Bit 2 =  busy
  347.                              * Bit 1 =  changed
  348.                              * Bit 0 =  Init'd
  349.                              */
  350.  
  351.             BYTE zero;            /* A zero byte */
  352.             unsigned vert_pos;        /* File's vertical position within its window */
  353.             unsigned horiz_pos;        /* File's horizontal position within its window */
  354.             unsigned ID;            /* ID of file's window or folder */
  355.             }
  356.             finder_info;
  357.  
  358.         BYTE flag;                /* Bit 0 = "protected" */
  359.         BYTE zero;                /* A zero byte */
  360.         unsigned long data_fork_length;        /* Length of data fork (the picture data itself) */
  361.         unsigned long resource_fork_length;    /* Length of resource fork (normally zero) */
  362.         BYTE create_date[4];            /* File's creation date */
  363.         BYTE modified_date[4];            /* File's "last modified" date */
  364.         BYTE reserved[27];
  365.         BYTE OS_ID[2];                /* Reserved for OS and computer ID */
  366.         }
  367.         macbinary_header;
  368.  
  369.     /*
  370.      * 512-byte header put on file (and used) by Macpaint. StartupScreen
  371.      * files don't have this, but ALL OTHERS DO!!!
  372.      */
  373.  
  374.     struct _header
  375.         {
  376.         unsigned long version;            /*
  377.                              * Macpaint version number:
  378.                              *
  379.                              *   2 = Macpaint
  380.                              *   3 = FullPaint
  381.                              */
  382.  
  383.         BYTE patterns[38][8];            /* Brush/fill patterns */
  384.         BYTE filler[84];            /* Used by Macpaint? */
  385.  
  386.         /*
  387.          * Area used by FullPaint, but presumably unused by Macpaint
  388.          */
  389.  
  390.         struct _fullpaint
  391.             {
  392.             unsigned selected_font_number;
  393.             unsigned selected_font_size;
  394.             unsigned user_font_size;
  395.             BYTE user_font_size_ON;        /* Boolean value */
  396.             BYTE font_face;
  397.             unsigned alignment;        /* 1=left, 2=middle, 3=right */
  398.             BYTE grid_ON;            /* Boolean value */
  399.             BYTE rulers_ON;            /* Boolean value */
  400.             BYTE mode;            /* 0 = normal, 1 = FatBits */
  401.             BYTE ruler_units;
  402.             unsigned selected_pattern;
  403.             BYTE visible_rectangle[8];
  404.             BYTE FatBits_view_rectangle_point[4];
  405.             BYTE FatBits_point[4];
  406.             BYTE desk_rectangle[8];
  407.             BYTE filler[80];
  408.             }
  409.             fullpaint;
  410.         }
  411.         header;
  412.  
  413.     /*
  414.      * Start of actual Macpaint picture data bytes
  415.      */
  416.  
  417.     BYTE picture_data[1];            /* First of many bytes */
  418.     };
  419.  
  420.  
  421.  
  422. /*
  423.  * Global data
  424.  */
  425.  
  426.     /*
  427.      * Flag to force exit from program
  428.      */
  429.  
  430. static int time2quit = 0;        /* Non-zero to exit */
  431.  
  432.     /*
  433.      * Variables used to support RLE pictures
  434.      */
  435.  
  436. static int rle_pic = 0;            /* Number of RLE pictures on the screen */
  437. static unsigned rle_horiz[6] =        /* Horizontal sizes of 6 RLE images */
  438.     { 0,0,0,0,0,0 };
  439. static unsigned rle_vert[6] =        /* Vertical sizes of 6 RLE images */
  440.     { 0,0,0,0,0,0 };
  441.  
  442.     /*
  443.      * Palette values for background and foreground. EGA uses both. CGA
  444.      * uses fg_color only, as value for the Color-Select Register.
  445.      * HERC uses neither.
  446.      */
  447.  
  448. static int bg_color = 0;
  449. static int fg_color = COLOR;
  450.  
  451.     /*
  452.      * Current mode that we're in (TEXT or GRAPHICS)
  453.      */
  454.  
  455. static int cur_mode = TEXT;
  456.  
  457.     /*
  458.      * Flag indicating that -OK arg was present on command line
  459.      */
  460.  
  461. static int ok_flag = 0;
  462.  
  463.     /*
  464.      * Flag controlling print-only of all files.
  465.      */
  466.  
  467. static int print_all = 0;        /* Non-zero to just print all files */
  468.  
  469.     /*
  470.      * Flag indicating the type of image data we have in this file
  471.      * (either ENCODED or RAW).
  472.      */
  473.  
  474. static int data_type = ENCODED;
  475.  
  476.     /*
  477.      * Fill value (1's or 0's) to be used to fill screen areas outside
  478.      * of actual image bounds.
  479.      */
  480.      
  481. static BYTE fill_type = 0;
  482.  
  483.     /*
  484.      * Number of lines in non-RLE image. This basically tells us
  485.      * how many true data lines we had in a short MacPaint file.
  486.      * The picture may have been short because it's a corrupted
  487.      * MacPaint file, or because it's a StartupScreen image.
  488.      */
  489.      
  490. static int end_of_image = 0;
  491.  
  492.     /*
  493.      * Flag controlling automatic invert() of next file
  494.      */
  495.  
  496. static int auto_invert = 0;        /* Non-zero to do auto invert of next file */
  497.  
  498.     /*
  499.      * Flag controlling automatic invert() of all files
  500.      */
  501.  
  502. static int all_invert = 0;        /* Non-zero to do auto invert of all files */
  503.  
  504. #if DEBUG
  505.  
  506.     /*
  507.      * Timings (in clock ticks) of decodes of each input file. These allow
  508.      * us to see what effect various speed improvement changes actually have
  509.      * on picture decode times. That RLE format is a killer!
  510.      */
  511.  
  512. static long elapsed[50] = { 0L };    /* Elapsed ticks for each decode */
  513. static int next_elapsed = 0;        /* Next free entry in above table */
  514.  
  515. #endif
  516.  
  517.  
  518.     /*
  519.      * "Printer has hit an error, and we are to cancel current print" flag
  520.      */
  521.  
  522. static int print_error = 0;        /* Non-zero if cancelling current print */
  523.  
  524.     /*
  525.      * What type of video adapter we have
  526.      */
  527.      
  528. static int screen_type = TYPE_NONE;
  529.  
  530.     /*
  531.      * What type of printer we have. This is an index into printers[],
  532.      * or -1 if we haven't specified one yet.
  533.      */
  534.      
  535. static int print_type = -1;
  536.  
  537.     /*
  538.      * Printer names, descriptions, and escape sequences
  539.      */
  540.      
  541. static struct _printer
  542.     {
  543.     BYTE *name;            /* Short name for this printer */
  544.     BYTE *desc;            /* Description of it */
  545.     BYTE *crlf;            /* String sent to move to next line */
  546.     BYTE *page_init;        /* String sent at start of dump */
  547.     BYTE *line_init;        /* String sent before data bytes ("enter graphics mode") */
  548.     BYTE *line_end;            /* String sent after data bytes ("exit graphics mode") */
  549.     BYTE *wrapup;            /* String sent after whole dump is done */
  550.  
  551.     int buffered;            /*
  552.                      * How data bytes are sent:
  553.                      *
  554.                      * 0 = send 1 byte at a time, edited
  555.                      *     per 'special' below, after sending
  556.                      *     line_init and before line_end. Use this
  557.                      *     value if line_init has only "here comes
  558.                      *     some graphics data" without a count of
  559.                      *     how many bytes are coming, and some
  560.                      *     editing is required.
  561.                      *
  562.                      * 1 = send line_init, then 576 graphics bytes,
  563.                      *     and then line_end. Use this value
  564.                      *     if line_init has "here come 576 graphics
  565.                      *     bytes" coded into it. No editing can be done.
  566.                      */
  567.  
  568.     int reversed;            /* Passed to vslice() */
  569.     int delta;            /* # wires fired per pass (7 or 8) */
  570.     int ignore;            /* Ignore print request */
  571.  
  572.     int special;            /*
  573.                      * Special editing needed. If non-zero,
  574.                      * then buffered really ought to be set
  575.                      * to zero.
  576.                      *
  577.                      * 0 = none
  578.                      * 1 = DP8050 check for CHR$(3) etc
  579.                      */
  580.     }
  581.     printers[] =
  582.     {
  583.         {
  584. /* name      */    "IGNORE",
  585. /* desc      */    "Ignore print requests",
  586. /* crlf      */    NULL,
  587. /* page_init */    NULL,
  588. /* line_init */    NULL,
  589. /* line_end  */    NULL,
  590. /* wrapup    */    NULL,
  591.         0,                    /* buffered    */
  592.         0,                    /* reversed    */
  593.         0,                    /* delta    */
  594.         -1,                    /* ignore    */
  595.         0                    /* special    */
  596.         },
  597.  
  598.  
  599.         {
  600. /* name      */    "OKI192",
  601. /* desc      */    "Okidata Microline 192 (narrow carriage)",
  602. /* crlf      */    "\r\n",
  603. /* page_init */    "\x1BA\007\x1B2\x1BU\x01\x12\r",
  604. /* line_init */    "                \x1BL\x40\x02",
  605. /* line_end  */    NULL,
  606. /* wrapup    */    "\r\x1BA\x55\x1B2\n\x1BA\x4d\x1B2\n\x1BA\x0c\x1B2\r",
  607.         1,                    /* buffered    */
  608.         0,                    /* reversed    */
  609.         8,                    /* delta    */
  610.         0,                    /* ignore    */
  611.         0                    /* special    */
  612.         },
  613.  
  614.  
  615.         {
  616. /* name      */    "OKI193",
  617. /* desc      */    "Okidata Microline 193 (wide carriage)",
  618. /* crlf      */    "\r\n",
  619. /* page_init */    "\x1BA\007\x1B2\x1BU\x01\r\x12",
  620. /* line_init */    "                    \x1BK\x40\x02",
  621. /* line_end  */    NULL,
  622. /* wrapup    */    "\r\x1BA\x55\x1B2\n\x1BA\x4d\x1B2\n\x1BA\x0c\x1B2\r",
  623.         1,                    /* buffered    */
  624.         0,                    /* reversed    */
  625.         8,                    /* delta    */
  626.         0,                    /* ignore    */
  627.         0                    /* special    */
  628.         },
  629.  
  630.  
  631.         {
  632. /* name      */    "OKI182",
  633. /* desc      */    "Okidata Microline 182 (narrow carriage)",
  634. /* crlf      */    "\r\n",
  635. /* page_init */    "\x1BA\007\x1B2\x12\r",
  636. /* line_init */    "                \x1BL\x40\x02",
  637. /* line_end  */    NULL,
  638. /* wrapup    */    "\r\x1BA\x55\x1B2\n\x1BA\x4d\x1B2\n\x1BA\x0c\x1B2\r",
  639.         1,                    /* buffered    */
  640.         0,                    /* reversed    */
  641.         8,                    /* delta    */
  642.         0,                    /* ignore    */
  643.         0                    /* special    */
  644.         },
  645.  
  646.  
  647.         {
  648. /* name      */    "IBM",
  649. /* desc      */    "IBM Graphics printer (narrow carriage)",
  650. /* crlf      */    "\r\n",
  651. /* page_init */    "\x1BA\007\x1B2\x1BU\x01\x12\r",
  652. /* line_init */    "                \x1BL\x40\x02",
  653. /* line_end  */    NULL,
  654. /* wrapup    */    "\r\x1BA\x55\x1B2\n\x1BA\x4d\x1B2\n\x1BA\x0c\x1B2\r",
  655.         1,                    /* buffered    */
  656.         0,                    /* reversed    */
  657.         8,                    /* delta    */
  658.         0,                    /* ignore    */
  659.         0                    /* special    */
  660.         },
  661.  
  662.  
  663.         {
  664. /* name      */    "MX",
  665. /* desc      */    "Epson MX-80, MX-100",
  666. /* crlf      */    "\r\n",
  667. /* page_init */    "\x1BA\007\x1BU\x01\x12\r",
  668. /* line_init */    "                \x1BL\x40\x02",
  669. /* line_end  */    NULL,
  670. /* wrapup    */    "\r\x1BA\x55\n\x1BA\x4d\n\x1BA\x0c\r",
  671.         1,                    /* buffered    */
  672.         0,                    /* reversed    */
  673.         8,                    /* delta    */
  674.         0,                    /* ignore    */
  675.         0                    /* special    */
  676.         },
  677.  
  678.  
  679.         {
  680. /* name      */    "8510",
  681. /* desc      */    "C.ITOH Prowriter M-8510A",
  682. /* crlf      */    "\r\n",
  683. /* page_init */    "\x1BT16\x1B[\x1BE\x1Bf\x1B\"\x1BY\x1BL000\x1B>\r",
  684. /* line_init */    "            \x1BS0576",
  685. /* line_end  */    NULL,
  686. /* wrapup    */    "\r\n\n\n\n\n\n\n\n\n\x1BA\x1B]\x1B<",
  687.         1,                    /* buffered    */
  688.         -1,                    /* reversed    */
  689.         8,                    /* delta    */
  690.         0,                    /* ignore    */
  691.         0                    /* special    */
  692.         },
  693.  
  694.  
  695.         {
  696. /* name      */    "DP8050",
  697. /* desc      */    "Data Products 8050 and 8070",
  698. /* crlf      */    "\n",
  699. /* page_init */    "\x1Bx,0,$\x1Ba,0,$\x1Bj,1,$\x1BB,12,$\x1BQ,4,$\r",
  700. /* line_init */    "\x03",
  701. /* line_end  */ "\x03\x02",
  702. /* wrapup    */    "\f\x18",
  703.         0,                    /* buffered    */
  704.         -1,                    /* reversed    */
  705.         7,                    /* delta    */
  706.         0,                    /* ignore    */
  707.         1                    /* special    */
  708.         }
  709.  
  710.     };
  711.  
  712. #define    NUMPRINT    ( sizeof(printers) / sizeof(struct _printer) )
  713.  
  714. /*
  715.  * Misc scratch
  716.  */
  717.      
  718. static union REGS inregs, outregs;    /* For int86() use */
  719. static BYTE scratch[60000];        /* Plenty big for max MACPAINT file */
  720.  
  721. /*
  722.  * Decoded MACPAINT picture as 720 576-pixel lines
  723.  */
  724.      
  725. static BYTE mem_image[MAC_VERT][MAC_HORIZ/8];
  726.  
  727.  
  728. /*
  729.  ********************************************
  730.  *  M A I N       P R O G R A M             *
  731.  ********************************************
  732.  */
  733.  
  734. main(argc, argv)
  735. int argc;
  736. BYTE *argv[];
  737. {
  738.     BYTE *filepath;
  739.     int i;
  740.  
  741.     fprintf(stderr, "\nJoan Riff's MACPAINT and RLE picture viewer for HERCULES, EGA, CGA boards.");
  742.  
  743.     if ( argc < 2 )
  744.         {
  745.         use();
  746.         exit(-1);
  747.         }
  748.  
  749.     /*
  750.      * Determine type of video display being used
  751.      */
  752.      
  753.     vtype();
  754.  
  755. #if NASTY
  756.  
  757.     /*
  758.      * Pre-scan command line for -OK command-line arg
  759.      */
  760.  
  761.     for ( i = 1; i < argc; i++ )
  762.         {
  763.         if ( strcmpi(argv[i], "-OK") == 0 )
  764.             {
  765.             ok_flag = -1;
  766.             }
  767.         }
  768.  
  769. #else
  770.  
  771.     fprintf(stderr, "\n(c) 1987 by Computerwise Consulting Services");
  772.     
  773. #endif
  774.  
  775.     warning();
  776.  
  777.  
  778.     /*
  779.      * Handle all command-line args and filenames
  780.      */
  781.  
  782.     while( --argc && !time2quit )
  783.         {
  784.         argv++;                /* Up to next filename */
  785.  
  786.         /*
  787.          * If this arg starts with a "-", then process it as a
  788.          * command-line argument
  789.          */
  790.  
  791.         if ( **argv == '-' )
  792.             {
  793.             pswitch(*argv);
  794.             continue;
  795.             }
  796.  
  797.         /*
  798.          * Continue, assuming that anything else we find is
  799.          * a filename. It may contain wildcards, so we must
  800.          * expand them into true paths. Note that in this way
  801.          * we apply command-line args like "-invert" etc to
  802.          * whole bunches of files even though they count as
  803.          * one filename on the command line. This is a feature,
  804.          * not a bug.
  805.          */
  806.  
  807.         if ( all_invert )        /* Inverting all files? */
  808.             {
  809.  
  810.             /*
  811.              * We are inverting all files. In this case,
  812.              * a -INVERT flag for one file means to NOT
  813.              * invert this one. The absence of a -INVERT
  814.              * means that we set it for him.
  815.              */
  816.  
  817.             auto_invert = auto_invert ? 0 : -1;
  818.             }
  819.  
  820.         wildcard(0, *argv, 0);        /* Seed our wildcard pattern */
  821.  
  822.         while ( (filepath = wildcard(1, NULL,0)) != NULL )
  823.             {
  824.             if ( time2quit )
  825.                 {
  826.                 break;
  827.                 }
  828.  
  829.             if ( readmac(filepath) )    /* Try to read it in and display/print it */
  830.                 {
  831.  
  832.                 /*
  833.                  * We encountered an error
  834.                  */
  835.  
  836.                 if ( cur_mode != TEXT )
  837.                     {
  838.                     mode(TEXT);
  839.                     }
  840.  
  841.                 fprintf(stderr, "\nError reading file '%s'! Press RETURN...", *argv);
  842.                 key();
  843.                 cls();
  844.                 }
  845.             }
  846.  
  847.         auto_invert = 0;            /* Clear for this "filename" */
  848.         }
  849.  
  850.     /*
  851.      * We may have some dangling RLE images, which have been read in but not
  852.      * yet flushed. Now's the time!
  853.      */
  854.  
  855.     if ( rle_pic )
  856.         {
  857.         flush();
  858.         }
  859.  
  860.     mode(TEXT);                    /* Restore screen */
  861.  
  862. #if DEBUG
  863.  
  864.     /*
  865.      * Dump elapsed timings for all decodes
  866.      */
  867.  
  868.     fprintf(stderr, "\nDecode time ticks:\n");
  869.  
  870.     for ( i = 0; i < next_elapsed; i++ )
  871.         {
  872.         fprintf( stderr, "%12ld    ", elapsed[i] );
  873.         }
  874.  
  875. #endif
  876.  
  877.  
  878. }
  879.  
  880.  
  881. /*
  882.  * Issue various warnings
  883.  */
  884.  
  885. warning()
  886. {
  887.  
  888. #if NASTY
  889.  
  890.     if ( ok_flag ) return;            /* He wants them suppressed */
  891.  
  892.     mode(TEXT);
  893.     fprintf(stderr, "(c) Copyright 1987 by Computerwise Consulting Services");
  894.     fprintf(stderr, "\n                      P.O. Box 813, McLean, VA 22101 (703) 280-2809");
  895.     fprintf(stderr, "\n");
  896.     fprintf(stderr, "\nThis program will not run unless you use the special command-line argument");
  897.     fprintf(stderr, "\n'-OK', meaning 'OK, I agree that Computerwise Consulting Services - as the");
  898.     fprintf(stderr, "\nowner of the copyright for this program - has every legal right to define");
  899.     fprintf(stderr, "\nwho may and may not use it, and I agree to be bound by this licensing");
  900.     fprintf(stderr, "\nagreement.'");
  901.     fprintf(stderr, "\n");
  902.     fprintf(stderr, "\n                       LICENSING AGREEMENT");
  903.     fprintf(stderr, "\nComputerwise Consulting Services hereby grants to any and all potential");
  904.     fprintf(stderr, "\nusers (EXCEPT FOR THOSE DEFINED BELOW) permission to receive, use, and");
  905.     fprintf(stderr, "\ntransfer this program 'as-is', with no warrantees etc etc.");
  906.     fprintf(stderr, "\n");
  907.     fprintf(stderr, "\nSpecifically DENIED all permissions are those who in the opinion of CCS have");
  908.     fprintf(stderr, "\nproven to be 'software pirates' by violating U.S. Copyright law, to wit:");
  909.     fprintf(stderr, "\n");
  910.     fprintf(stderr, "\n    LOTUS DEVELOPMENT CORPORATION, and any employee thereof or");
  911.     fprintf(stderr, "\n       consultant thereto.");
  912.     fprintf(stderr, "\n    ADAPSO, and any firm which is a member thereof, and any employee");
  913.     fprintf(stderr, "\n       of such a firm.");
  914.     fprintf(stderr, "\n");
  915.     fprintf(stderr, "\n(Press RETURN...)");
  916.     key();
  917.  
  918. #endif
  919.  
  920.     /*
  921.      * Issue a mild warning if the poor guy has only a CGA
  922.      */
  923.  
  924.     if ( screen_type == TYPE_CGA )
  925.         {
  926.         mode(TEXT);
  927.         fprintf(stderr, "\nWarning: You are running this program on an IBM-compatible");
  928.         fprintf(stderr, "\nColor/Graphics Adapter.");
  929.         fprintf(stderr, "\n");
  930.         fprintf(stderr, "\nTo preserve a decent aspect ratio, this program must display every");
  931.         fprintf(stderr, "\nOTHER picture line on the screen. This results in some rough images,");
  932.         fprintf(stderr, "\nESPECIALLY WHEN DISPLAYING RLE FILES. But don't worry. Printed images");
  933.         fprintf(stderr, "\nwill contain the full resolution present in the picture file.");
  934.         fprintf(stderr, "\n");
  935.         fprintf(stderr, "\nYou should consider getting a HERCULES Monochrome board or an Enhanced");
  936.         fprintf(stderr, "\nGraphics Adapter and display, if you want to see some good graphics");
  937.         fprintf(stderr, "\nimages on the screen.");
  938.         fprintf(stderr, "\n");
  939.         fprintf(stderr, "\n(Just a friendly reminder)     - Joan");
  940.         fprintf(stderr, "\n");
  941.         fprintf(stderr, "\n(Press RETURN...)");
  942.         key();
  943.         }
  944.  
  945. #if NASTY
  946.     exit(-1);
  947. #endif
  948.  
  949. }
  950.  
  951.  
  952.  
  953. /*
  954.  * We have a screen image in mem_image. Flush it to the screen or the
  955.  * printer, cause it's about to be overwritten!!!
  956.  */
  957.  
  958. flush()
  959. {
  960.     if ( time2quit )        /* Are we aborting program? */
  961.         {
  962.         return;            /* Yes, get back to mainline fast! */
  963.         }
  964.  
  965.     if ( print_all )        /* Just printing? */
  966.         {
  967.         print();        /* Yes, send it to the printer */
  968.         }
  969.     else
  970.         {
  971.         browse();        /* No, show it */
  972.         }
  973. }
  974.  
  975.  
  976.  
  977. /*
  978.  * Explain program use
  979.  */
  980.  
  981. use()
  982. {
  983.     int i;
  984.  
  985.     fprintf(stderr, "\n\nUse: MACPAINT%s[-PRINT] [-INVALL] [-printer] {[-n] [-INVERT] filename}...\n",
  986.     
  987. #if NASTY
  988.         " -OK "
  989. #else
  990.         " "
  991. #endif
  992.         );
  993.  
  994. #if NASTY
  995.     fprintf(stderr, "\n-OK      = 'OK, I agree to abide by your licensing agreement'");
  996. #endif
  997.  
  998.     fprintf(stderr,   "\n-PRINT   = automatically print all files, don't show 'em");
  999.     fprintf(stderr,   "\n-INVALL  = automatically invert all file images");
  1000.     fprintf(stderr,   "\n-n       = set default fill to 0's ('-0') or 1's ('-1')");
  1001.     fprintf(stderr,   "\n-INVERT  = automatically invert the next file's image");
  1002.     fprintf(stderr,   "\nfilename = name of a MACPAINT or RLE file (wildcards OK)");
  1003.     fprintf(stderr,   "\n-printer = the type of printer on your system:\n");
  1004.  
  1005.     for ( i = 0; i < NUMPRINT; i++ )
  1006.         {
  1007.         fprintf(stderr, "\n    -%-6s = %s", printers[i].name, printers[i].desc );
  1008.         }
  1009.  
  1010.     fprintf(stderr, "\n");
  1011. }
  1012.  
  1013.  
  1014. #if DEBUG
  1015.  
  1016. /*
  1017.  * Return the number of clock ticks since midnight. This is only used for
  1018.  * timing studies, to help us speed up the decode processing.
  1019.  */
  1020.  
  1021. long ticker()
  1022. {
  1023.     inregs.h.ah = 0;
  1024.     int86( 0x1a, &inregs, &outregs );
  1025.     return( (outregs.x.cx << 16) | outregs.x.dx );
  1026. }
  1027.  
  1028. #endif
  1029.  
  1030.  
  1031.  
  1032.  
  1033. /*
  1034.  * Process command-line switch s
  1035.  */
  1036.  
  1037. pswitch(s)
  1038. BYTE *s;
  1039. {
  1040.     int i;
  1041.     
  1042.     s++;            /* Skip over "-" at front */
  1043.  
  1044.     /*
  1045.      * See if it's a printer name
  1046.      */
  1047.  
  1048.     for( i = 0; i < NUMPRINT; i++ )
  1049.         {
  1050.         if ( strcmpi(s, printers[i].name) == 0 )
  1051.             {
  1052.             print_type = i;
  1053.             return;
  1054.             }
  1055.         }
  1056.  
  1057.  
  1058.     /*
  1059.      * Try for a switch
  1060.      */
  1061.  
  1062.     if ( strcmp(s, "1") == 0 )
  1063.         {
  1064.         fill_type = 0xff;
  1065.         return;
  1066.         }
  1067.  
  1068.     if ( strcmp(s, "0") == 0 )
  1069.         {
  1070.         fill_type = 0x00;
  1071.         return;
  1072.         }
  1073.  
  1074.     if ( strcmpi(s, "PRINT") == 0 )
  1075.         {
  1076.         print_all = -1;
  1077.         return;
  1078.         }
  1079.  
  1080.     if ( strcmpi(s, "INVERT") == 0 )
  1081.         {
  1082.         auto_invert = -1;
  1083.         return;
  1084.         }
  1085.  
  1086.     if ( strcmpi(s, "INVALL") == 0 )
  1087.         {
  1088.         all_invert = -1;
  1089.         return;
  1090.         }
  1091.  
  1092.     /*
  1093.      * It's not anything that we recognize
  1094.      */
  1095.  
  1096. }
  1097.  
  1098.  
  1099. #include "video.c"
  1100. #include "readmac.c"
  1101. #include "writemac.c"
  1102. #include "printer.c"
  1103. #include "wildcard.c"
  1104.  
  1105.