home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / GIFDEV.ZIP / TGIF.C < prev    next >
C/C++ Source or Header  |  1989-04-10  |  16KB  |  785 lines

  1. /*
  2. **   tgif.c : Two-tone GIF file display utilty
  3. **
  4. **        Written by:    James Lark
  5. **                6101 W. Courtyard Dr.
  6. **                Austin, Tx.  78730
  7. **
  8. */
  9.  
  10. #include    <stdio.h>
  11. #include    <conio.h>
  12. #include    <string.h>
  13. #include    <bios.h>
  14. #include    <graphics.h>
  15. #include    <dos.h>
  16. #include    <malloc.h>
  17. #include    <io.h>
  18.  
  19. #define    YES    1
  20. #define    NO    0
  21. #define    tab1    6
  22. #define    tab2    26
  23. #define tab3    46
  24. #define    tab4    66
  25. #define fbits    32
  26.  
  27. struct {
  28.     char    t_code;
  29.     int    t_link;
  30. } root_tab[4097];            
  31.  
  32. unsigned     nroots;            
  33.  
  34. char        str_buf[4097];
  35. unsigned     str_len;        
  36.  
  37. unsigned    cur_bct, eof_bct, clr_code, eoi_code; 
  38. unsigned    old_code, cur_mask, cur_bits, tab_stor;
  39.  
  40.  
  41. FILE        *giffile;        
  42. long        giffilen;        
  43. char        fname[30];        
  44.  
  45. unsigned    ras_wid, ras_high;    
  46. unsigned    glob_cfg;        
  47. unsigned    glob_bgc;        
  48. int        intens[256];        
  49. int        grey_level;        
  50. int        c_white,c_black;    
  51. int        pix_black = 0;        
  52. int        pix_white = 1;
  53. unsigned    img_csz;        
  54. unsigned    img_cfg;        
  55. unsigned    ilace;            
  56. unsigned    img_top, img_left;    
  57. unsigned    img_wid, img_high;    
  58. unsigned    pix_wid, pix_high;    
  59. unsigned    pix_bwid;        
  60. int        dot_row, dot_col;    
  61. int        vid_mask;        
  62. int        *ras_line;        
  63. int        *rlp;            
  64. int        pix_diag;        
  65. char far    *pix_buf;        
  66. unsigned long    pix_base;        
  67. unsigned long    code_six;        
  68. char        *savl;            
  69. int        savlix;
  70. int        max_pcr;        
  71. unsigned long    mav_codes, mav_length;    
  72. int        i_leave, i_phase;    
  73. int        opt_w, opt_l;        
  74. int        opt_c;            
  75. int        opt_t;            
  76. unsigned    ngifrecs;
  77. unsigned long    ngifcodes;
  78.  
  79.  
  80. int    mygetc()
  81. {
  82.     if( !feof(giffile) ) return fgetc( giffile );
  83.     setvmode( 3 );
  84.     curson();
  85.     clrscrn();
  86.     printf( "\nEOF on input!!\n" );
  87.     exit( 0 );
  88. }
  89.  
  90. void    msg_rc( int row, int col, char *msg )
  91. {
  92.     poscurs( row, col );
  93.     printf( "%s", msg );
  94. }
  95.  
  96. void    msg_rcn( int row, int col, unsigned num )
  97. {
  98.     char    text[20];
  99.     
  100.     sprintf( text, "%-5u", num );
  101.     msg_rc( row, col, text );
  102. }
  103.  
  104. void    msg_rcl( int row, int col, unsigned long num )
  105. {
  106.     char    text[20];
  107.     
  108.     sprintf( text, "%-8lu", num );
  109.     msg_rc( row, col, text );
  110. }
  111.  
  112.  
  113. int    gifsig_ok()
  114. {
  115.     int    i;
  116.     char    prefix[4];
  117.     
  118.     for( i=0; i!=3; i++ ) prefix[i] = mygetc();
  119.     prefix[3] = '\0';
  120.     if( strcmpi( "gif", prefix ) == 0 ) {
  121.         msg_rc( 4, tab3, "GIF signature:" );
  122.         msg_rc( 4, tab4, "GIF" );
  123.         for( i=0; i!=3; i++ ) prefix[i] = mygetc();
  124.         prefix[4] = '\0';
  125.         msg_rc( 4, tab4+3, prefix );
  126.         return YES;
  127.     }
  128.     return NO;
  129. }
  130.  
  131. int    gifscd()
  132. {
  133.     ras_wid = mygetc() | (mygetc() << 8);
  134.     msg_rc( 5, tab1, "Raster width:" );
  135.     msg_rcn( 5, tab2, ras_wid );
  136.  
  137.     ras_high = mygetc() | (mygetc() << 8);
  138.     msg_rc( 6, tab1, "Raster height:" );
  139.     msg_rcn( 6, tab2, ras_high );
  140.  
  141.     glob_cfg = mygetc();
  142.     msg_rc( 5, tab3, "Bits per pixel:" );
  143.     msg_rcn( 5, tab4, (glob_cfg & 7)+1 );
  144.     if( glob_cfg && 128 ) msg_rc( 6, tab3, "Global color map present." );
  145.     else msg_rc( 6, tab3, "Global color map not present." );
  146.  
  147.     glob_bgc = mygetc();
  148.     msg_rc( 7, tab1, "Background color:" );
  149.     msg_rcn( 7, tab2, glob_bgc );
  150.  
  151.     if( mygetc() == 0 ) return YES;
  152.     return NO;
  153. }
  154.  
  155. void    gif_cmap()
  156. {
  157.     int        i, k;
  158.     unsigned    gll;
  159.     
  160.     grey_level = 128;
  161.     if( glob_cfg & 128 ) {
  162.         gll = 0;
  163.         c_black = 256;
  164.         c_white = 0;
  165.         k = 1 << ((glob_cfg & 7)+1) ;
  166.         msg_rc( 7, tab3, "Color map entries:" );
  167.         msg_rcn( 7, tab4, k );
  168.         for( i=0; i!=k; i++ ) {
  169.             intens[i] =(mygetc()+mygetc()+mygetc())/3;
  170.             gll += intens[i];
  171.             if( intens[i] > c_white ) c_white = intens[i];
  172.             if( intens[i] < c_black ) c_black = intens[i];
  173.             intens[i] = intens[i]*fbits;
  174.         }
  175.         grey_level = (gll / k)*fbits;
  176.         c_white *= fbits;
  177.         c_black *= fbits;
  178.     }
  179. }
  180.  
  181.  
  182. void    gif_ext()
  183. {
  184.     int    i;
  185.     
  186.     while( i = mygetc() ) {
  187.         while( i-- ) mygetc();
  188.     }
  189. }
  190.  
  191. void    rooter()
  192. {
  193.     int    i;
  194.     
  195.     cur_bct = 0;
  196.     eof_bct = NO;
  197.     nroots = 1 << img_csz;
  198.     clr_code = nroots;
  199.     eoi_code = nroots+1;
  200.     for( i = 0; i != nroots; i++) {
  201.         root_tab[i].t_code = i;
  202.         root_tab[i].t_link = -1;
  203.     }
  204. }
  205.  
  206. void    set_mask()
  207. {
  208.     cur_bits = img_csz+1;
  209.     tab_stor = 0;
  210.     cur_mask = nroots+nroots-1;
  211. }
  212.  
  213. void    sbar( long percent )
  214. {
  215.     int    i;
  216.     
  217.     poscurs( 21, 20 );
  218.     i = percent;
  219.     while( i-- ) printf( "%c", 219 );
  220.     i = 40-percent;
  221.     while( i-- ) printf( "%c", 176 );
  222. }
  223.  
  224. void    setcsts()
  225. {
  226.     msg_rc( 13, tab1, "Records processed:" );
  227.     msg_rcn( 13, tab2, ngifrecs++ );
  228.     msg_rc( 13, tab3, "Codes unpacked:" );
  229.     msg_rcl( 13, tab4, ngifcodes );
  230.     msg_rc( 15, tab1, "Max. compression:" );
  231.     msg_rcn( 15, tab2, max_pcr );
  232.     msg_rc( 15, tab3, "Avg. compression:" );
  233.     if( mav_length != 0 ) msg_rcl( 15, tab4, (mav_length+(mav_length>>1))/mav_codes );
  234.     else msg_rcn( 15, tab4, 0 );
  235. }
  236.  
  237. unsigned gnxcic()
  238. {
  239.     long    bperc;
  240.     
  241.     if( cur_bct == 0 ) {
  242.         setcsts();
  243.         bperc = 40l * ftell( giffile ) / giffilen ;
  244.         sbar( bperc );
  245.         if( ((cur_bct = mygetc()) == 0) || eof_bct ) {
  246.             eof_bct = YES;
  247.             return 0;
  248.         }
  249.     }
  250.     cur_bct -= 1;
  251.     return mygetc();
  252. }
  253.  
  254. int    mem_setup()
  255. {
  256.     unsigned long pix_size;
  257.  
  258.     savlix = 0;
  259.     if( opt_t ) {
  260.         pix_wid = img_wid * 3;
  261.         pix_high = img_high * 3;
  262.     }
  263.     else {
  264.         if( opt_w ) pix_wid = img_wid + img_wid;
  265.         else pix_wid = img_wid;
  266.         if( opt_l ) pix_high = img_high + img_high;
  267.         else pix_high = img_high;
  268.     }
  269.  
  270.     if( (ras_line = malloc( (sizeof( int ) * pix_wid)+1)) == NULL ) return NO;
  271.     if( (savl = malloc( sizeof( char ) * pix_wid )) == NULL ) return NO;
  272.  
  273.     pix_bwid = pix_wid / 8;
  274.     if( pix_wid & 7 ) pix_bwid += 1;
  275.  
  276.     pix_size = (long)pix_bwid * pix_high;
  277.     if( pix_size < ((long)img_wid*img_high) ) pix_size = (long)img_wid*img_high;
  278.     if( pix_size > farcoreleft() ) return NO;
  279.     pix_buf = farmalloc( pix_size );
  280.     pix_base = fartol( pix_buf );
  281.     code_six = pix_base + (pix_size - ((long)img_wid*img_high));
  282.     return YES;
  283. }
  284.  
  285. void    mem_unset()
  286. {
  287.     free( ras_line );
  288.     free( savl );
  289.     farfree( pix_buf );
  290. }
  291.  
  292.  
  293. char    pbits[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  294.  
  295. void    setpbit( int color )
  296. {
  297.     if( color ) {
  298.         *((char far *)ltofar( pix_base + (long)dot_row*(long)pix_bwid + (long)(dot_col>>3) )) |= pbits[dot_col & 7];
  299.     }
  300. }
  301.  
  302.  
  303. void    pix_out( int code )
  304. {
  305.     int    pix_err, pe38;
  306.     
  307.     if( (*rlp += intens[code]) > grey_level) {
  308.         setpbit( pix_white );
  309.         pix_err = *rlp - c_white;
  310.     }
  311.     else {
  312.         setpbit( pix_black );
  313.         pix_err = *rlp - c_black;
  314.     }
  315.     pe38 = (pix_err+pix_err+pix_err)>>3;
  316.     *rlp++ = pe38 + pix_diag;
  317.     pix_diag = pix_err>>2;
  318.     *rlp += pe38;
  319.     if( ++dot_col == pix_wid ) {
  320.         dot_col = 0;
  321.         rlp = ras_line;
  322.         dot_row += 1;
  323.     }
  324. }
  325.  
  326. void    sc_out( int code )
  327. {
  328.     int    i;
  329.     
  330.     pix_out( code );
  331.     if( opt_t ) {
  332.         pix_out( code );
  333.         pix_out( code );
  334.         savl[savlix++] = code;
  335.         savl[savlix++] = code;
  336.         savl[savlix++] = code;
  337.         if( dot_col == 0 ) {
  338.             for( i=0; i!=savlix; i++ ) pix_out( savl[i] );
  339.             for( i=0; i!=savlix; i++ ) pix_out( savl[i] );
  340.             savlix = 0;
  341.         }
  342.     }
  343.     else {
  344.         if( opt_w ) pix_out( code );
  345.          if( opt_l ) {
  346.              savl[savlix++] = code;
  347.             if( opt_w ) savl[savlix++] = code;
  348.             if( dot_col == 0 ) {
  349.                 for( i=0; i!=savlix; i++ ) pix_out( savl[i] );
  350.                 savlix = 0;
  351.             }
  352.         }
  353.     }
  354. }
  355.  
  356. void    togrey()
  357. {
  358.     unsigned long    pixies, pixct, pixgix;
  359.     char far *cix;
  360.     int    c;
  361.     
  362.     msg_rc( 18, tab2, "    Halftoning..." );
  363.     dot_row = dot_col = 0;
  364.     pixies = (long)img_wid * img_high;
  365.     pixgix = code_six;
  366.     for( pixct = 0l; pixct!=pixies; pixct++ ) {
  367.         cix = (char far *)ltofar( pixgix++ );
  368.         c = *cix;
  369.         *cix = 0;
  370.         sc_out( c );
  371.          if( !(pixct & 4095) ) sbar( (40l*pixct)/pixies );
  372.     }
  373. }
  374.  
  375.  
  376. void    code_out( int code )
  377. {
  378.     ngifcodes++;
  379.     if( ilace ) {
  380.         *((char far *)ltofar( code_six + (long)dot_row*img_wid + (long)dot_col )) = code;
  381.         if( ++dot_col == img_wid ) {
  382.             dot_col = 0;
  383.             if( (dot_row += i_leave) >= img_high ) {
  384.                 switch( i_phase ) {
  385.                     case 0: dot_row = 0;
  386.                         break;
  387.                     case 1: dot_row = 4;
  388.                         i_phase++;
  389.                         break;
  390.                     case 2: dot_row = 2;
  391.                         i_leave = 4;
  392.                         i_phase++;
  393.                         break;
  394.                     case 3: dot_row = 1;
  395.                         i_leave = 2;
  396.                         break;
  397.                     case 4: dot_row = 0;
  398.                         i_leave = 1;
  399.                         break;
  400.                     }
  401.             }
  402.         }
  403.     } else sc_out( code );
  404. }
  405.  
  406.  
  407. void    tran_out( int tran_code )
  408. {
  409.     char    *strix;
  410.     int    i;
  411.     
  412.     strix = str_buf;
  413.     i = 0;
  414.     do {
  415.         *strix++ = root_tab[tran_code].t_code;
  416.         i++;
  417.         tran_code = root_tab[tran_code].t_link;
  418.     } while( tran_code != -1 );
  419.     str_len = i;
  420.     strix--;
  421.     while( i-- ) code_out( *strix-- );
  422. }
  423.  
  424.  
  425. void    procode( int cur_code )
  426. {
  427.     mav_codes++;
  428.     if( tab_stor == 0 ) {
  429.         tab_stor = eoi_code+1;
  430.         tran_out( cur_code );
  431.         mav_length++;
  432.     }
  433.     else {
  434.         if( cur_code != tab_stor ) {
  435.             tran_out( cur_code );
  436.             mav_length += str_len;
  437.             if( str_len > max_pcr ) max_pcr = str_len;
  438.         }
  439.         else {
  440.             tran_out( old_code );
  441.             code_out( str_buf[str_len-1] );
  442.             mav_length += str_len+1;
  443.             if( (str_len+1) > max_pcr ) max_pcr = str_len+1;
  444.         }
  445.         root_tab[tab_stor].t_code = str_buf[str_len-1];
  446.         root_tab[tab_stor].t_link = old_code;
  447.         if( (tab_stor++) == cur_mask ) {
  448.             if( cur_mask != 4095 ) {
  449.                 cur_mask += cur_mask+1;
  450.                 cur_bits++;
  451.             }
  452.         }
  453.     }
  454.     old_code = cur_code;
  455. }
  456.     
  457.         
  458. void    uncode()
  459. {
  460.     int    hi_bits;
  461.     unsigned long shreg;
  462.     int    i, cur_code;
  463.  
  464.     dot_row = 0;
  465.     rlp = ras_line;
  466.     dot_col = 0;
  467.     pix_diag = 0;
  468.      for( i=0; i!=img_wid; i++ ) ras_line[i] = -(rand() % 131)*fbits;
  469.     if( ilace ) msg_rc( 18, tab2,"    Unpacking..." );
  470.     else msg_rc( 18, tab2, "Unpacking and Halftoning..." );
  471.  
  472.     set_mask();
  473.     shreg = gnxcic();
  474.     shreg |= gnxcic() << 8;
  475.     shreg |= (long) gnxcic() << 16;
  476.     hi_bits = 8;
  477.     do {
  478.         cur_code = shreg & cur_mask;
  479.         if( cur_code == eoi_code ) cur_bits = 0;
  480.         else {
  481.             i = cur_bits;
  482.             while( i-- ) {
  483.                 shreg = shreg >> 1;
  484.                 if( !(--hi_bits) ) {
  485.                     shreg |= (long) gnxcic() << 16;
  486.                     hi_bits = 8;
  487.                 }
  488.             }
  489.             if( cur_code == clr_code ) set_mask();
  490.             else procode( cur_code );
  491.         }
  492.     } while( cur_bits );
  493.     setcsts();
  494. }
  495.  
  496.  
  497. void    d_window( int max_row, unsigned long roff )
  498. {
  499.     char far    *scrix[4];
  500.     unsigned    nb, nr, row;
  501.     
  502.     scrix[0] = 0xb8000000;
  503.     scrix[1] = 0xba000000;
  504.     scrix[2] = 0xbc000000;
  505.     scrix[3] = 0xbe000000;
  506.     nb = ( pix_wid > 640 ) ? 640 : pix_wid;
  507.     if( nb & 7 ) nb += 8 - (nb & 7);
  508.     nb /= 8;
  509.     nr = ( pix_high > max_row ) ? max_row : pix_high;
  510.     
  511.     row = 0;
  512.     do {
  513.         farmemcpy( scrix[row], ltofar( pix_base+roff ), nb );
  514.         scrix[row] += 80;
  515.         row = ++row & vid_mask;
  516.         roff += pix_bwid;
  517.     } while( --nr );
  518.     
  519. }
  520.  
  521. void    display_it()
  522. {
  523.     unsigned    max_row;
  524.     unsigned long    porgi, phighmax;
  525.     unsigned    priteoff, pritemax;
  526.     int        disp_done, c;
  527.     
  528.     if( ilace ) togrey();
  529.     porgi = 0;
  530.     max_row = 400;
  531.     vid_mask = 3;
  532.     if( opt_c || (setvmode( 0x74 ) != 0x74) ) {
  533.         setvmode( 6 );
  534.         max_row = 200;
  535.         vid_mask = 1;
  536.     }
  537.     phighmax = (pix_high > max_row) ? (long) (((long)pix_high*pix_bwid - (long)max_row*pix_bwid)) : 0;
  538.     pritemax = (pix_wid > 640 ) ? (pix_wid - 640)/8 : 0;
  539.     priteoff = 0;
  540.     
  541.     disp_done = NO;
  542.     do {
  543.         d_window( max_row, porgi );
  544.         while( (c = getkey()) == EOF );
  545.         if( c == 0 ) {
  546.             while( (c = getkey()) == EOF );
  547.             switch( c ) {
  548.                 case 71:    
  549.                     porgi = (long)priteoff;
  550.                     break;
  551.                 case 72:    
  552.                     if( porgi != 0 ) porgi -= pix_bwid;
  553.                     break;
  554.                 case 80:    
  555.                     if( (porgi+pix_bwid) < phighmax ) porgi += pix_bwid;
  556.                     break;
  557.                 case 73:    
  558.                     if( porgi > (pix_bwid *10) ) porgi -= pix_bwid * 10;
  559.                     else porgi = (long)priteoff;
  560.                     break;
  561.                 case 81:    
  562.                     if( (porgi+pix_bwid*10) < phighmax ) porgi += pix_bwid * 10;
  563.                     break;
  564.                 case 75:    
  565.                     if( priteoff ) {
  566.                         priteoff--;
  567.                         porgi--;
  568.                     }
  569.                     break;
  570.                 case 77:    
  571.                     if( priteoff < pritemax ) {
  572.                         priteoff++;
  573.                         porgi++;
  574.                     }
  575.                     break;
  576.                 case 115:    
  577.                     if( priteoff > 10 ) {
  578.                         priteoff -= 10;
  579.                         porgi -= 10l;
  580.                     }
  581.                     break;
  582.                 case 116:    
  583.                     if( (priteoff+10) < pritemax ) {
  584.                         priteoff += 10;
  585.                         porgi += 10l;
  586.                     }
  587.                     break;
  588.                 case 79:    
  589.                     porgi = phighmax + priteoff;
  590.                     break;
  591.                 case 117:    
  592.                     disp_done = YES;
  593.                     break;
  594.             }
  595.         }
  596.         else {
  597.             switch( c ) {
  598.                 case 0x03:    
  599.                 case 0x1b:    
  600.                 case 'q':    
  601.                 case 'Q':    disp_done = YES;
  602.                         break;
  603.             }
  604.         }
  605.         
  606.     } while( !disp_done );
  607.     setvmode( 3 );
  608.     curson();
  609.     clrscrn();
  610. }
  611.  
  612. void    make_box()
  613. {
  614.     char    boxs[43];
  615.     int    i;
  616.         
  617.     boxs[0] = 201;
  618.     for( i=1; i!=41; boxs[i++] = 205 );
  619.     boxs[41] = 187;
  620.     boxs[42] = 0;
  621.     msg_rc( 20, 19, boxs );
  622.     boxs[0] = 200;
  623.     boxs[41] = 188;
  624.     msg_rc( 22, 19, boxs );
  625.     boxs[0] = 186;
  626.     for( i=1; i!=41; boxs[i++] = 176 );
  627.     boxs[41] = 186;
  628.     msg_rc( 21, 19, boxs );
  629. }
  630.  
  631. void    gif_image()
  632. {
  633.     int    iblkct;
  634.     
  635.     img_left = mygetc() | (mygetc() << 8 );
  636.     msg_rc( 8, tab3, "Left boundary:" );
  637.     msg_rcn( 8, tab4, img_left );
  638.  
  639.     img_top = mygetc() | (mygetc() << 8 );
  640.     msg_rc( 9, tab3, "Top boundary:" );
  641.     msg_rcn( 9, tab4, img_top );
  642.  
  643.     img_wid = mygetc() | (mygetc() << 8);
  644.     msg_rc( 8, tab1, "Image width:" );
  645.     msg_rcn( 8, tab2, img_wid );
  646.  
  647.     img_high = mygetc() | (mygetc() << 8);
  648.     msg_rc( 9, tab1, "Image height:" );
  649.     msg_rcn( 9, tab2, img_high );
  650.  
  651.     img_cfg = mygetc();
  652.     ilace = NO;
  653.     if( img_cfg & 64 ) {
  654.         ilace = YES;
  655.         msg_rc( 10, tab1, "Interlaced image." );
  656.         i_leave = 8;
  657.         i_phase = 1;
  658.     }
  659.     else {
  660.         msg_rc( 10, tab1, "Noninterlaced image." );
  661.         i_leave = 1;
  662.         i_phase = 0;
  663.     }
  664.     if( img_cfg & 128 ) {
  665.         msg_rc( 10, tab3, "Local color map present." );
  666.         gif_cmap();
  667.     }
  668.     img_csz = mygetc();
  669.     msg_rc( 11, tab1, "Image code size:" );
  670.     msg_rcn( 11, tab2, img_csz );
  671.     make_box();
  672.     max_pcr = 0;
  673.     mav_code = 0;
  674.     mav_length = 0;
  675.     ngifrecs = 0;
  676.     ngifcodes = 0;
  677.  
  678.     if( mem_setup() ) {
  679.         rooter();            
  680.         uncode();            
  681.         display_it();            
  682.         mem_unset();            
  683.     }
  684.     else printf( "\n\nNot enough memory to contain image!\n" );
  685. }
  686.  
  687. void    interrupt    cancel()
  688. {
  689.     setvmode( 3 );
  690.     curson();
  691.     clrscrn();
  692.     exit(0);
  693. }
  694.  
  695. int    parse_args( int argc, char *argv[] )
  696. {
  697.     char    *cx;
  698.     
  699.     opt_w = opt_l = opt_c = NO;
  700.     if( argc == 2 ) return YES;
  701.     if( argc != 3 ) return NO;
  702.     cx = argv[1];
  703.     argv[1] = argv[2];
  704.     while( *cx ) {
  705.         if( *cx++ == '/' ) {
  706.             switch( *cx++ ) {
  707.                 case 'w' :
  708.                 case 'W' :    opt_w = YES;
  709.                         break;
  710.                 case 'l' :
  711.                 case 'L' :    opt_l = YES;
  712.                         break;
  713.                 case 'r' :
  714.                 case 'R' :    pix_black = 1;
  715.                         pix_white = 0;
  716.                         break;
  717.                 case 'd':
  718.                 case 'D':    opt_w = opt_l = YES;
  719.                         break;
  720.                 case 'c':
  721.                 case 'C':    opt_c = YES;
  722.                         break;
  723.  
  724.                 case 't':
  725.                 case 'T':    opt_t = YES;
  726.                         break;
  727.                         
  728.                 default:    return NO;
  729.             }
  730.         }
  731.     }
  732. }
  733.  
  734. main( int argc, char *argv[] )
  735. {
  736.     int    gifdone, gc;
  737.     
  738.     if( parse_args( argc, argv ) ) {
  739.         stpcpy( fname, argv[1] );
  740.         if( !stristr( fname, "." ) ) strcat( fname, ".gif" );
  741.         if( giffile = fopen( fname, "rb" ) ) {
  742.             giffilen = filelength( fileno( giffile ) );
  743.             clrscrn();
  744.             msg_rc( 2, 26, "tgif -- Two-tone GIF utility" );
  745.             msg_rc( 4, tab1, "File name:" );
  746.             msg_rc( 4, tab2, fname );
  747.             if( gifsig_ok() ) {
  748.                 if( gifscd() ) {
  749.                     cursoff();
  750.                     setvect( 0x23, cancel );
  751.                     gif_cmap();
  752.                     gifdone = NO;
  753.                     do {
  754.                         switch( gc = mygetc() ) {
  755.                             case '!':    gif_ext();
  756.                                     break;
  757.                             case ',':    gif_image();
  758.                                     break;
  759.                             case '\0':    break;
  760.                             case ';':    gifdone = YES;
  761.                                     break;
  762.                             default:    printf( "\nInvalid command code: %x\n", gc );
  763.                                     gifdone = YES;
  764.                                     break;
  765.                         }
  766.                     } while( !gifdone );
  767.                 } else printf( "\nInvalid screen descriptor.\n" );
  768.             } else printf( "\n%s not a GIF file.\n", fname );
  769.         } else printf( "\nCan't open file: %s\n", fname );
  770.     }
  771.     else {
  772.         printf( "\nUsage:     tgif {/w} {/l} {/d} {/t} {/r} {/c} giffile\n" );
  773.         printf( "\nOptions:   /w == widen image" );
  774.         printf( "\n           /l == lengthen image" );
  775.         printf( "\n           /d == double size" );
  776.         printf( "\n           /t == triple size" );
  777.         printf( "\n           /r == reverse video (for LCD screens)" );
  778.         printf( "\n           /c == force CGA mode\n" );
  779.         printf( "\nExample:   tgif/d/r picture" );
  780.         printf( "\n           Would open picture.GIF and display a double size" );
  781.         printf( "\n           image in reverse video.\n" );
  782.     }
  783. }
  784.         
  785.