home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / FILUTL / UUXFER20.ZIP / UUXFER20.C next >
Encoding:
C/C++ Source or Header  |  1990-11-05  |  40.4 KB  |  1,715 lines

  1. /*  UUXFER -- a complete uuencode/uudecode package
  2.  *
  3.  *  ver. 2.0 copyright (C) 1990 David M. Read   All rights reserved.
  4.  *
  5.  *
  6.  *  In the lines below, you should #define whatever is appropriate
  7.  *  for your system.  If you have the CURSES package available, I
  8.  *  suggest you use it.  DUMB_IO will be defined if neither CURSES
  9.  *  nor TURBO_C is defined.
  10.  *
  11.  *  If you are using an ANSI-compliant compiler, define ANSI_C.
  12.  *
  13.  */ 
  14.  
  15. #define ANSI_C
  16. #define MS_DOS
  17. #define TURBO_C
  18.  
  19. /*
  20. #define DUMB_IO
  21. #define CURSES
  22. #define UNIX
  23. */
  24.  
  25. #if (!defined (CURSES) && !defined (TURBO_C) && !defined (DUMB_IO))
  26. #define DUMB_IO
  27. #endif
  28.  
  29. #define ESC      27
  30. #define OFF      0
  31. #define ON       ~OFF
  32. #define INIT     0
  33. #define UPDATE   1
  34. #define SEEK_SET 0
  35. #define SEEK_CUR 1
  36. #define SEEK_END 2
  37.  
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <ctype.h>
  41.  
  42. #ifdef MS_DOS
  43. #include <stdlib.h>
  44. #include <io.h>
  45. #define UPDATE_CHAR 176
  46. #endif
  47.  
  48. #ifdef TURBO_C
  49. #include <conio.h>
  50. #endif
  51.  
  52. #ifdef UNIX
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #endif
  56.  
  57. #ifdef CURSES
  58. #include <curses.h>
  59. #define clrscr clearscr
  60. #define gotoxy moveto
  61. #define printf printw
  62.  
  63. #ifdef DUMB_IO
  64. #undef DUMB_IO
  65. #endif
  66.  
  67. #endif
  68.  
  69. #ifdef DUMB_IO
  70. #define clrscr clearscr
  71. #define gotoxy moveto
  72. #define getch  getcharacter
  73. #endif
  74.  
  75. #ifndef UPDATE_CHAR
  76. #define UPDATE_CHAR 'X'
  77. #endif
  78.  
  79. typedef unsigned char  uchar;
  80.  
  81. /* Global variables which are parameters for the en/decoding process */
  82.  
  83. int    cells_per_line = 15,
  84.        multiple_input = OFF,
  85.        multiple_output = OFF,
  86.        overwrite = OFF,
  87.        interactive = ON,
  88.        xx_set = OFF,
  89.        table_output = OFF,
  90.        line_count = 0,
  91.        ext_set = OFF;
  92. long   max_size = 32767;
  93.  
  94. uchar  xx_chars[] = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  95. uchar  uu_chars[65],
  96.        ext_chars[65];
  97. uchar *char_set = uu_chars,
  98.        table[128];
  99.  
  100. #ifdef ANSI_C      /* function prototypes for ANSI C compilers   */
  101.  
  102. int encode_file (char *infilename, char *tempfilename);
  103. int encode_line (uchar *indata, uchar *outdata, int bytes_in);
  104. int encode_block (FILE *infile, FILE *outfile, char *infilename,
  105.                   char *outfilename, int section, int two_percent);
  106. int encode_cell (uchar *indata, uchar *outdata);
  107. int process_command_line (int argc, char **argv, char *infilename);
  108. int get_parameters (int argc, char **argv);
  109. int decode_file (char *infilename, char *tempfilename);
  110. int decode_line (char *indata, char *outdata);
  111. int decode_cell (char *indata, char *outdata);
  112. int find_good_data_line (FILE  *infile, char  *indata, int  line_excess);
  113. int get_excess (FILE *infile, char *indata);
  114. int get_outfilename (char *indata, FILE *infile, int *mode);
  115. int get_filenames (char *infilename, char *outfilename);
  116. void get_filesize (void);
  117. void get_cells_per_line (void);
  118. void show_status_line (void);
  119. void clear_extension (char *filename);
  120. int no_extension (char *filename);
  121. void menu (void);
  122. void show_about (void);
  123. int ok_to_write (char *filename);
  124. int build_table (void);
  125. void build_uu_chars (void);
  126. int read_charset (FILE *infile);
  127. int write_table (FILE *outfile);
  128. int read_external_set (void);
  129. int check_xx (int byte);
  130. long get_size (char *filename);
  131. int update_progress (int mode);
  132. long filesize (FILE *fileptr);
  133. void press_key (void);
  134. void curses_refresh (void);
  135.  
  136. #ifdef CURSES
  137. void clearscr (void);
  138. void moveto (int x, int y);
  139. int  wherex (void);
  140. int  wherey (void);
  141. #endif
  142.  
  143. #ifdef DUMB_IO
  144. void clearscr (void);
  145. void moveto (int x, int y);
  146. int getcharacter (void);
  147. #endif
  148.  
  149. #else                   /* function prototypes for UNIX systems */
  150.  
  151. void get_filesize ();
  152. void get_cells_per_line ();
  153. void show_status_line ();
  154. void clear_extension ();
  155. void menu ();
  156. void show_about ();
  157. void build_uu_chars ();
  158. void press_key ();
  159. void curses_refresh ();
  160. long get_size ();
  161. long filesize ();
  162.  
  163. #ifdef CURSES
  164. void clearscr ();
  165. void moveto ();
  166. int  wherex ();
  167. int  wherey ();
  168. #endif
  169.  
  170. #ifdef DUMB_IO 
  171. void clearscr ();
  172. void moveto ();
  173. int getcharacter ();
  174. #endif
  175.  
  176. #endif                  /* end of #ifdef ANSI_C                 */
  177.  
  178. /* Constants for use in command-line parsing */
  179.  
  180. #define NOTHING    0
  181. #define ENCODE     1
  182. #define DECODE     2
  183.  
  184.  
  185. main (argc, argv)
  186. int     argc;
  187. char  **argv;
  188. {
  189.    char  infilename[64],
  190.          outfilename[64];
  191.    int   action;
  192.  
  193. #ifndef CURSES
  194.    clrscr();
  195. #else
  196.    initscr ();
  197.    cbreak ();
  198.    echo ();
  199.    leaveok (stdscr, FALSE);
  200.    refresh ();
  201. #endif
  202.    
  203.    if (get_parameters (argc, argv))        /* Gets parameters from the */
  204.       return 0;                            /* command line             */
  205.  
  206.    if (xx_set)
  207.       char_set = xx_chars;
  208.    build_uu_chars ();
  209.    build_table ();
  210.  
  211.    do
  212.    {
  213.       action = process_command_line (argc, argv, infilename);
  214.  
  215.       /* process_command_line selects the next action/filename specified
  216.        * on the command line and copies it into infilename, returning
  217.        * what action was specified: encode or decode.  Returns
  218.        * action = nothing if there are no more files on the command line.
  219.        */
  220.  
  221.       *outfilename = '\0';    /* clear outfilename in the command-line case */
  222.  
  223.       if (action == ENCODE)
  224.          encode_file (infilename, outfilename);
  225.       else if (action == DECODE)
  226.          decode_file (infilename, outfilename);
  227.  
  228.    } while (action != NOTHING);           /* stop command-line processing */
  229.  
  230.    if (interactive)                       /* interactive is set to 1 if   */
  231.    {                                      /* get_parameters detects no    */
  232.       menu ();                            /* action parameters            */
  233.       show_about ();
  234.    }
  235.    else
  236.    {
  237.       printf ("\n\nUUXFER ver 2.0 copyright (c) 1990 David M. Read\n\n");
  238.       printf ("This program is shareware.  Read the instructions concerning\n");
  239.       printf ("program registration, available by typing `uuxfer -i' from\n");
  240.       printf ("the command-line, or by activating the program in menu-driven mode.\n\n");
  241.       curses_refresh ();
  242.    }
  243.  
  244.    return 0;
  245. }
  246.  
  247.  
  248. encode_file (infilename, outfilename)
  249. char  *infilename,
  250.       *outfilename;
  251. {
  252.    FILE   *infile,
  253.           *outfile;
  254.    char    extension[4];
  255.    int     rcode,
  256.            section = 1,
  257.            tot_sections,
  258.            two_percent;
  259.    long    in_size,
  260.            out_size;
  261.  
  262.    printf ("\nOpening input file %s for encoding...\n", infilename);
  263.    curses_refresh ();
  264.  
  265.    if ((infile = fopen (infilename, "rb")) == NULL)
  266.    {
  267.       printf ("Error opening input file %s\n", infilename);
  268.       curses_refresh ();
  269.       return -1;
  270.    }
  271.  
  272.    in_size = filesize (infile);
  273.    out_size = (in_size * 1424) / 1000;
  274.  
  275. /* The factor of 1.42 comes mostly from the conversion from 3 input bytes
  276.  * to 4 output bytes, and the remaining part comes from the extra bytes
  277.  * added to every output line...This isn't a *great* estimate, but it's
  278.  * better than nothing, and it only has to be accurate to a few hundred
  279.  * bytes or so...
  280.  *
  281.  * In the next section, the addition of the denominator to the
  282.  * numerand cures the "round-down" problem of integer division;
  283.  * without it, tot_sections will be too small (resulting in the
  284.  * incorrect output of the number of sections), and two_percent
  285.  * will be too small, resulting in 51 updates instead of 50.
  286.  */
  287.  
  288.    if (multiple_output)
  289.       tot_sections = (max_size - 1 + out_size) / max_size;
  290.    else
  291.       tot_sections = 1;
  292.  
  293.    two_percent = 1 + (49 + in_size) / 50;
  294.  
  295.    if (strlen(outfilename) == 0)           /* check if we need to supply an */
  296.    {                                       /* output filename               */
  297.       strcpy (outfilename, infilename);    /* copy the infilename           */
  298.       clear_extension (outfilename);       /* kills off anything past '.'   */
  299.       if (xx_set)
  300.          strcat (outfilename, "xxe");      /* add '.xxe' to the end         */
  301.       else
  302.          strcat (outfilename, "uue");      /* add '.uue' to the end         */
  303.    }
  304.  
  305.    printf ("0%%..............................................100%%\n");
  306.    update_progress (INIT);
  307.  
  308.    do
  309.    {
  310.       if (multiple_output)                 /* We'll be supplying the sequen-*/
  311.       {                                    /* tial extensions here.         */
  312.          clear_extension (outfilename);
  313.          sprintf (extension, "%d", section);  /* convert number -> text        */
  314.          strcat (outfilename, extension);  /* stick it on the end           */
  315.       }
  316.  
  317.       printf ("\nWriting uuencoded file %s...", outfilename);
  318.       curses_refresh ();
  319.  
  320.       if (!ok_to_write (outfilename))
  321.          return -1;
  322.       if ((outfile = fopen (outfilename, "wt")) == NULL)
  323.       {
  324.          printf ("\nError opening output file %s", outfilename);
  325.          press_key ();
  326.          return -1;
  327.       }
  328.  
  329.       /* add 'cut here' lines and other info to make netters happy */
  330.  
  331.       if (section == 1)
  332.       {
  333.          fprintf (outfile, "\n%12s:  decoded size: %li\n", infilename, in_size);
  334.          fprintf (outfile, "%12s   encoded size: %li (approximate)\n", " ", out_size);
  335.       }
  336.  
  337.       fprintf (outfile, "\n%-12s   section %2d/%-2d",
  338.                infilename, section, tot_sections);
  339.       fprintf (outfile, "  UUXFER ver 2.0 by David M. Read\n\n");
  340.  
  341.       fprintf (outfile, "BEGIN----------------------CUT HERE--------------------------\n");
  342.  
  343.       if (ext_set)
  344.          if (read_external_set ())
  345.          {
  346.             printf ("Unable to open external table file TABLE.UUX.\n");
  347.             curses_refresh ();
  348.             return -1;
  349.          }
  350.  
  351.       if (table_output)
  352.          write_table (outfile);
  353.  
  354.       rcode = encode_block (infile, outfile, infilename, outfilename,
  355.                             section, two_percent);
  356.  
  357.       /* encode_block encodes pieces of the file.  It looks at the
  358.        * multiple_output global variable to see whether it should return
  359.        * after encoding max_size bytes. It returns -1 on an error or
  360.        * encountering EOF.
  361.        */
  362.  
  363.       fprintf (outfile, "END------------------------CUT HERE--------------------------\n");
  364.  
  365.       section++;                       /* increment section for file-naming */
  366.       fclose (outfile);
  367.  
  368.    } while (rcode == 0);
  369.  
  370.    fclose (infile);
  371.    return 0;
  372. }
  373.  
  374.  
  375. encode_block (infile, outfile, infilename, outfilename, section, two_percent)
  376. FILE  *infile;
  377. FILE  *outfile;
  378. char  *infilename;
  379. char  *outfilename;
  380. int   section;
  381. int   two_percent;
  382. {
  383.    int    bytes_in,
  384.           bytes_out,
  385.           rcode = -1;
  386.    uchar  indata[256],
  387.           outdata[256];
  388.    long   section_bytes = 0;
  389.    static long total_bytes,
  390.                next_update;
  391.  
  392.    /* Output the 'begin' line, but only if on the 1st section.
  393.     * Also, clear the static variables & set up the bargraph
  394.     * update information.
  395.     */
  396.  
  397.    if (section == 1)
  398.    {
  399.       fprintf (outfile, "begin 644 %s\n", infilename);
  400.       total_bytes = 0;
  401.       next_update = two_percent;
  402.    }
  403.  
  404.    bytes_in = fread (indata, 1, 3 * cells_per_line, infile); /* get data */
  405.    while (bytes_in > 0)
  406.    {
  407.       bytes_out = encode_line (indata, outdata, bytes_in);
  408.  
  409.       /* encode_line encodes one line of data, reading the unencoded data
  410.        * from indata and placing the encoded data in outdata.  It
  411.        * then returns the total length of the encoded data line
  412.        */
  413.  
  414.       if (fwrite (outdata, 1, bytes_out, outfile) != bytes_out)
  415.       {
  416.          printf ("\a\aError writing to output file %s\n", outfilename);
  417.          curses_refresh ();
  418.          return -1;
  419.       }
  420.       section_bytes += bytes_out;
  421.       total_bytes += bytes_in;
  422.  
  423.       while (total_bytes > next_update)
  424.       {
  425.          update_progress (UPDATE);
  426.          next_update += two_percent;
  427.       }
  428.  
  429.      /* check to see if you're near the maximum size for output files...
  430.       * make a guess about the size of the next line.
  431.       */
  432.  
  433.       if (multiple_output != 0 && section_bytes + bytes_out > max_size)
  434.       {
  435.          rcode = 0;
  436.          break;
  437.       }
  438.  
  439.       bytes_in = fread (indata, 1, 3 * cells_per_line, infile);
  440.    }
  441.  
  442.    if (bytes_in == 0)                      /* you're at the end of the file */
  443.    {                                       /* If you just stopped because   */
  444.                                            /* of multiple_output, bytes_in  */
  445.       putc (char_set[0], outfile);         /* would be > 0 and you wouldn't */
  446.       fprintf (outfile, "\nend\n");        /* want the 'end' line.  The     */
  447.    }                                       /* encoded 0 tells decoders to   */
  448.                                            /* stop.                         */
  449.  
  450.    return rcode;
  451. }
  452.  
  453.  
  454. encode_line (indata, outdata, bytes_in)
  455. uchar *indata;
  456. uchar *outdata;
  457. int   bytes_in;
  458. {
  459.    int     bytes_out = 0,
  460.            i;
  461.  
  462.    *outdata++ = char_set[bytes_in];      /* Encode the line length          */
  463.  
  464.    for (i = 0; i < bytes_in; i += 3)     /* Encode the data line, 1 cell at */
  465.    {                                     /* a time, until all done.         */
  466.       encode_cell (indata, outdata);     /* This is what actually does the  */
  467.       indata += 3;                       /* encoding of each cell!          */
  468.       outdata += 4;                      /* increment all pointers and the  */
  469.       bytes_out += 4;                    /* number of output bytes.         */
  470.    }
  471.  
  472.    *outdata++ = '\n';                    /* terminate the line with a LF    */ 
  473.  
  474.    return bytes_out + 2;                 /* bytes_out + 1(count) + 1(LF)    */ 
  475. }
  476.  
  477.  
  478. encode_cell (indata, outdata)
  479. uchar  *indata;
  480. uchar  *outdata;
  481. {
  482.  
  483. /* This is just a simple table look-up into the table created earlier. */
  484.  
  485.    outdata[0] = char_set [((indata[0] >> 2) & 63)];
  486.    outdata[1] = char_set [(((indata[0] << 4) | (indata[1] >> 4)) & 63)];
  487.    outdata[2] = char_set [(((indata[1] << 2) | (indata[2] >> 6)) & 63)];
  488.    outdata[3] = char_set [(indata[2] & 63)];
  489.  
  490.    return 0;
  491. }
  492.  
  493.  
  494. int decode_file (tempfilename, outfilename)
  495. char  *tempfilename;
  496. char  *outfilename;
  497. {
  498.    FILE  *infile,
  499.          *outfile = NULL;
  500.    char   infilename[64],
  501.           newfilename[64],
  502.           extension[4],
  503.           indata[256],
  504.           outdata[256];
  505.    int    section = 1,
  506.           done = 0,
  507.           rc,
  508.           num_bytes,
  509.           line_excess,
  510.           two_percent,
  511.           mode;
  512.    long   tot_size,
  513.           last_ftell,
  514.           cur_ftell,
  515.           next_update,
  516.           total_bytes = 0;
  517.  
  518.    line_count = 1;
  519.  
  520.    do
  521.    {
  522.       last_ftell = 0;
  523.  
  524.       strcpy (infilename, tempfilename);    /* This is all basically the    */
  525.                                             /* as the encode_file set-up    */
  526.  
  527.       if (no_extension (infilename))
  528.          if (xx_set)
  529.             strcat (infilename, "xxe");
  530.          else
  531.             strcat (infilename, "uue");
  532.  
  533.       if (multiple_input)
  534.       {
  535.          if (section == 1)
  536.          {
  537.             clear_extension (infilename);
  538.             tot_size = get_size (infilename);
  539.          }
  540.  
  541.          clear_extension (infilename);
  542.          sprintf (extension, "%d", section);
  543.          strcat (infilename, extension);
  544.       }
  545.       else
  546.       {
  547.          tot_size = get_size (infilename);
  548.          done = 1;
  549.       }
  550.  
  551.       if (section == 1)
  552.       {
  553.          two_percent = (49 + tot_size) / 50;
  554.          next_update = two_percent;
  555.          printf ("0%%..............................................100%%\n");
  556.          update_progress (INIT);
  557.       }
  558.  
  559.       printf ("Opening input file %s for decoding...\n", infilename);
  560.       curses_refresh ();
  561.  
  562.       if ((infile = fopen (infilename, "rt")) == NULL)
  563.       {
  564.          if (multiple_input)
  565.          {
  566.             printf ("    Unable to open next file (%s)\n", infilename);
  567.         printf ("    ...assuming no more sections.");
  568.             press_key ();
  569.         if (!interactive) 
  570.             {
  571.            printf ("\n");
  572.                curses_refresh ();
  573.             }
  574.             done = 1;
  575.             continue;
  576.          }
  577.          else
  578.          {
  579.             printf ("Unable to open input file %s!\n", infilename);
  580.             curses_refresh ();
  581.             return -1;
  582.          }
  583.       }
  584.  
  585.       if (section == 1)
  586.       {
  587.          /* get_outfilename searches for a 'begin' line and extracts the
  588.           * output filename from it...if it can't find a 'begin' line,
  589.           * it returns -1.  It also watches for 'table' entries.
  590.           */
  591.  
  592.          if (get_outfilename (newfilename, infile, &mode) == -1)
  593.             return -1;
  594.  
  595.          cur_ftell = ftell (infile);
  596.          total_bytes += cur_ftell - last_ftell;
  597.          last_ftell = cur_ftell;
  598.  
  599.          if (*outfilename == '\0')               /* if an alternate output  */
  600.         strcpy (outfilename, newfilename);   /* filename was specified, */
  601.                                                  /* use it. Otherwise, use  */
  602.                                                  /* the one extracted from  */
  603.                                                  /* the data as the default */
  604.  
  605.          printf ("    uudecoded output file will be named %s\n", outfilename);
  606.          curses_refresh ();
  607.  
  608.          if (!ok_to_write (outfilename))
  609.             return -1;
  610.          if ((outfile = fopen (outfilename, "wb")) == NULL)
  611.          {
  612.         printf ("Error opening output file %s\n", outfilename);
  613.             press_key ();
  614.             return -1;
  615.          }
  616.  
  617.       /* get_excess reads the first line after the 'begin' line and stores
  618.        * it in indata, and then calculates the difference between the actual
  619.        * line length & the predicted line length so find_good_data_line can
  620.        * handle oddball encoders.  Note that if the excess comes up less than
  621.        * zero, it is set to zero.  This can happen if a mailer program
  622.        * truncates any trailing spaces from a data line, but not if the
  623.        * encoding program inserts trailing characters to prevent this, in
  624.        * which case the line excess will be > 0 anyway!
  625.        *
  626.        * get_excess also checks for the presence of an 'XX' character set,
  627.        * and sets the xx_set parameter & builds the proper table if such
  628.        * is detected.
  629.        */
  630.  
  631.          if ((line_excess = get_excess (infile, indata)) < 0)
  632.          {
  633.             printf ("Error in file %s", infilename);
  634.             press_key ();
  635.             return -1;
  636.          }
  637.       }
  638.       else
  639.       {
  640.  
  641.       /* find_good_data_line searches for the next line of data in which the
  642.        * encoded length of the line is equal to the actual length of the
  643.        * line.  This is how headers & trailers are skipped... the chances of
  644.        * normal text meeting this condition are *small* but it might happen,
  645.        * in which case you're basically screwed...trim off the header!
  646.        */
  647.  
  648.          if (find_good_data_line (infile, indata, line_excess) == -1)
  649.          {
  650.             printf ("\aNo legitimate data found!\n");
  651.             press_key ();
  652.  
  653.             return -1;
  654.          }
  655.       }
  656.  
  657.       do   /* loops until there's no more valid data. */
  658.       {
  659.          /* decode_line is the decode counterpart to encode_line */
  660.  
  661.          if ((num_bytes = decode_line (indata, outdata)) == -1)
  662.             break;
  663.          else
  664.             fwrite (outdata, 1, num_bytes, outfile);
  665.  
  666.          cur_ftell = ftell (infile);
  667.          total_bytes += cur_ftell - last_ftell;
  668.          last_ftell = cur_ftell;
  669.  
  670.          while (total_bytes > next_update)
  671.          {
  672.             update_progress (UPDATE);
  673.             next_update += two_percent;
  674.          }
  675.  
  676.       } while ((rc = find_good_data_line (infile, indata, line_excess)) == 0);
  677.  
  678.       cur_ftell = ftell (infile);
  679.       total_bytes += cur_ftell - last_ftell;
  680.       last_ftell = cur_ftell;
  681.  
  682.       fclose (infile);
  683.  
  684.       if (rc == -1 && !multiple_input)
  685.       {
  686.          printf ("'end' line not found!\n");
  687.          curses_refresh ();
  688.       }
  689.  
  690.       if (rc == 1)
  691.          done = 1;
  692.  
  693.       section++;
  694.  
  695.    } while (!done && multiple_input);
  696.  
  697.    fclose (outfile);
  698.  
  699.    return 0;
  700. }
  701.  
  702.  
  703. int decode_line (indata, outdata)
  704. char  *indata;
  705. char  *outdata;
  706. {
  707.    int     num_bytes,
  708.            i;
  709.    char   *dataptr;
  710.  
  711.    dataptr = outdata;
  712.  
  713.    /* decode the number of bytes to be output..again, see the long commen at
  714.     * the end of the source module.
  715.     */
  716.  
  717.    num_bytes = table [*indata];
  718.  
  719.    indata++;                               /* advance past the counter byte */
  720.    for (i = 0; i < num_bytes; i += 3)      /* loop over output byte count   */
  721.    {                                       /* Next line does the work.      */
  722.       decode_cell (indata, dataptr);
  723.       indata += 4;                         /* increment pointers & counters */
  724.       dataptr += 3;
  725.    }
  726.  
  727.    return num_bytes;
  728. }
  729.  
  730.  
  731. int decode_cell (indata, outdata)
  732. char   *indata;
  733. char   *outdata;
  734. {
  735.    int    i;
  736.    char  *iptr,
  737.           ochar;
  738.  
  739.    /* see the big comment at the end. */
  740.  
  741.    iptr = indata;
  742.    for (i = 0; i < 4; i++)
  743.    {
  744.       ochar = table[*iptr];
  745.       if (ochar > 64)
  746.       {
  747.          printf ("\nFile corrupted!  Bad data on line %i: %c",
  748.                     line_count, *iptr);
  749.          curses_refresh ();
  750.          return -1;
  751.       }
  752.       else
  753.          *iptr = table[*iptr];
  754.       iptr++;
  755.    }
  756.  
  757.    outdata[0] = (indata[0] << 2) | (indata[1] >> 4);
  758.    outdata[1] = (indata[1] << 4) | (indata[2] >> 2);
  759.    outdata[2] = (indata[2] << 6) | indata[3];
  760.    outdata[3] = '\0';
  761.  
  762.    return 0;
  763. }
  764.  
  765.  
  766. int find_good_data_line (infile, indata, line_excess)
  767. FILE  *infile;
  768. char  *indata;
  769. int    line_excess;
  770. {
  771.     int   length,
  772.           elength,
  773.           num_bytes;
  774.  
  775.  
  776.     while (fgets (indata, 255, infile) != NULL)    /* read a line */
  777.     {
  778.        line_count++;
  779.  
  780.        if (strncmp (indata, "end", 3) == 0)        /* Check for end of data */
  781.           return 1;
  782.  
  783.        if (!multiple_input)
  784.           return 0;
  785.  
  786.        num_bytes = table[*indata];                 /* decode the count byte */
  787.        elength = (( 2 + num_bytes) / 3) * 4 + 2;   /* figure out how many   */
  788.        length = strlen (indata);                   /* bytes this implies... */
  789.                                                    /* Adding 2 makes it     */
  790.                                                    /* round *up*            */
  791.  
  792.        if (length == elength + line_excess)        /* It's a good data line */
  793.           return 0;
  794.  
  795.     }
  796.  
  797.     return -1;
  798. }
  799.  
  800.  
  801. int get_excess (infile, indata)
  802. FILE  *infile;
  803. char  *indata;
  804. {
  805.     int   length,
  806.           elength,
  807.           num_bytes;
  808.  
  809.  
  810.     if (fgets (indata, 255, infile) == NULL)       /* read a line */
  811.        return -1;
  812.  
  813.     num_bytes = table[*indata];                    /* decode the count byte */
  814.  
  815.     if (num_bytes == 255)                          /* check if it's valid   */
  816.     {
  817.        num_bytes = check_xx (*indata);             /* see if it's XX        */
  818.        if (num_bytes == 255)                       /* see if *this* one is  */
  819.        {
  820.           printf ("Bad count byte!\n");
  821.           curses_refresh ();
  822.           return -1;                               /* valid; crash if it    */
  823.        }
  824.     }                                              /* is not                */
  825.  
  826.     elength = (( 2 + num_bytes) / 3) * 4 + 2;      /* figure out how many   */
  827.     length = strlen (indata);                      /* bytes this implies... */
  828.                                                    /* Adding 2 makes it     */
  829.                                                    /* round *up*            */
  830.  
  831.     return  ((length > elength) ? length - elength : 0);
  832. }
  833.  
  834.  
  835. int get_outfilename (indata, infile, mode)
  836. char   *indata;
  837. FILE   *infile;
  838. int    *mode;
  839. {
  840.    char destname[64];
  841.  
  842.    while (1)  /* read lines until one of them starts with 'begin' */
  843.    {
  844.       if (fgets ((char *)indata, 255, infile) == NULL)
  845.       {
  846.          printf ("Unable to find begin line!\n");
  847.          curses_refresh ();
  848.          return -1;
  849.       }
  850.  
  851.       line_count++;
  852.  
  853.       if (strncmp ((char *)indata, "table", 5) == 0)
  854.          read_charset (infile);
  855.  
  856.       if (strncmp((char *)indata, "begin ", 6) == 0)
  857.          break;
  858.    }
  859.  
  860.    /* Now that a line starts with 'begin' extract the filename and open
  861.     * mode from it and return this info.  I wrote this specifically for
  862.     * MS-DOS, so the open mode is never actually used.
  863.     */
  864.  
  865.    sscanf ((char *)indata, "begin %o %s", &mode, destname);
  866.    strcpy ((char *)indata, destname);
  867.  
  868.    return 0;
  869. }
  870.  
  871.  
  872. int get_parameters (argc, argv)
  873. int     argc;
  874. char  **argv;
  875. {
  876.    int   i,
  877.      val;
  878.    long  lval;
  879.    char  param;
  880.  
  881.    /* This one loops over parameters, extracting any information from
  882.     * parameters it recognizes...if it sees -e or -d, it sets
  883.     * interactive to OFF so that the program can be run from a batch.
  884.     */
  885.  
  886.    for (i = 1; i < argc; i++)
  887.    {
  888.       if (*argv[i] == '-')
  889.       {
  890.          param = toupper(*(argv[i] + 1));
  891.          switch (param)
  892.          {
  893.             case 'C':
  894.                val = atoi (argv[i] + 2);
  895.                if (val > 0 && val <= 19)
  896.                   cells_per_line = val;
  897.            break;
  898.         case 'D':
  899.         case 'E':
  900.                interactive = OFF;
  901.            break;
  902.             case 'I':
  903.                show_about ();
  904.                return -1;
  905.             case 'M':
  906.                multiple_input = ON;
  907.                multiple_output = ON;
  908.                break;
  909.             case 'O':
  910.                overwrite = ON;
  911.                break;
  912.             case 'R':
  913.                ext_set = ON;
  914.                table_output = ON;
  915.                break;
  916.             case 'S':
  917.                lval = atol (argv[i] + 2);
  918.                if (lval > 0 && val <= 32767)
  919.                   max_size = lval;
  920.                break;
  921.             case 'T':
  922.                table_output = ON;
  923.                break;
  924.             case 'X':
  925.                xx_set = ON;
  926.                break;
  927.             default:
  928.                printf ("Disregarding unknown parameter %c\n", param);
  929.                curses_refresh ();
  930.                break;
  931.          }
  932.       }
  933.    }
  934.  
  935.    return 0;
  936. }
  937.  
  938.  
  939. int process_command_line (argc, argv, infilename)
  940. int     argc;
  941. char  **argv;
  942. char   *infilename;
  943. {
  944.    int   i,
  945.      action = NOTHING;
  946.    char  param;
  947.  
  948.    static int start = 1;
  949.  
  950.    /* This one loops over command-line parameters, looking for -e or -d;
  951.     * every time it finds one, it increments ths static variable 'start'
  952.     * so that the next time through, it starts at the next parameter on the
  953.     * command line.
  954.     */
  955.  
  956.    for (i = start; i < argc; i++)
  957.    {
  958.       if (*argv[i] == '-')
  959.       {
  960.          param = toupper (*(argv[i] + 1));
  961.          switch (param)
  962.          {
  963.             case 'C':
  964.                break;
  965.             case 'D':
  966.            action = DECODE;
  967.            strcpy (infilename, argv[i] + 2);
  968.            start = i + 1;
  969.                break;
  970.             case 'E':
  971.                action = ENCODE;
  972.            strcpy (infilename, argv[i] + 2);
  973.            start = i + 1;
  974.                break;
  975.             case 'I':
  976.                break;
  977.             case 'M':
  978.                break;
  979.             case 'O':
  980.                break;
  981.             case 'S':
  982.            break;
  983.             case 'X':
  984.                break;
  985.         default:
  986.                break;
  987.      }
  988.      if (action != NOTHING)
  989.         return action;
  990.       }
  991.    }
  992.  
  993.    return action;
  994. }
  995.  
  996.  
  997. void clear_extension (filename)
  998. char  *filename;
  999. {
  1000.    char *ptr;
  1001.  
  1002.    /* really sophomoric...go until you get a '.' and then cut off what's
  1003.     * after it by putting a NULL byte there.  If you reach a NULL byte,
  1004.     * put a '.' there...actually it does that either way.
  1005.     */
  1006.  
  1007.    ptr = filename;
  1008.    while (*ptr != '.' && *ptr != '\0')
  1009.       ptr++;
  1010.    *ptr++ = '.';
  1011.    *ptr   = '\0';
  1012.  
  1013.    return;
  1014. }
  1015.  
  1016.  
  1017. int no_extension (filename)
  1018. char  *filename;
  1019. {
  1020.    char  *ptr;
  1021.    int    extension = 0;
  1022.  
  1023.    ptr = filename;
  1024.    while (*ptr != '.' && *ptr != '\0')
  1025.       ptr++;
  1026.    if (*ptr == '\0')
  1027.    {
  1028.       strcat (filename, ".");
  1029.       extension = -1;
  1030.    }
  1031.    else if (*(ptr + 1) == '\0')
  1032.       extension = -1;
  1033.  
  1034.    return extension;
  1035. }
  1036.  
  1037.  
  1038. void show_about ()
  1039. {
  1040.  
  1041.    clrscr();
  1042.  
  1043.    printf ("\nUUXFER ver 2.0 copyright (c) 1990 David M. Read\n\n");
  1044.    printf ("This program is shareware, which means that you are entitled\n");
  1045.    printf ("to use this program under the following conditions:\n\n");
  1046.    printf ("(1) You may not distribute altered versions of the source code\n");
  1047.    printf ("    or the executable.  You may not distribute this program unless\n");
  1048.    printf ("    all documentation files are included with it.\n");
  1049.    printf ("(2) You may use this program without payment for a period of thirty\n");
  1050.    printf ("    (30) days, after which you must register it if you intend\n");
  1051.    printf ("    to continue using it.  To register UUXFER, send $10 along with\n");
  1052.    printf ("    your name and current address to\n\n");
  1053.    printf ("        Blade Technologies\n");
  1054.    printf ("        Attn: David Read\n");
  1055.    printf ("        6101 Balcones Dr. Suite 300\n");
  1056.    printf ("        Austin, TX 78731\n\n");
  1057.    printf ("(3) You must leave this message intact.  If you have suggestions or\n");
  1058.    printf ("    questions concerning this program,  please contact the author at\n");
  1059.    printf ("    the above address or at  readdm@dopey.cc.utexas.edu\n\n");
  1060.  
  1061.    curses_refresh ();
  1062.  
  1063.    return;
  1064. }
  1065.  
  1066.  
  1067. int get_filenames (infilename, outfilename)
  1068. char  *infilename;
  1069. char  *outfilename;
  1070. {
  1071.    int quit = 0;
  1072.  
  1073.    if (infilename == NULL || outfilename == NULL)
  1074.       return -1;
  1075.  
  1076.    clrscr();
  1077.  
  1078. #ifdef CURSES
  1079.    nocbreak ();
  1080. #endif
  1081.  
  1082.    printf ("Enter input filename -=> ");
  1083.    curses_refresh ();
  1084.    gets (infilename);
  1085.    if (strlen(infilename) == 0)
  1086.       quit = 1; 
  1087.  
  1088.    if (quit == 0)
  1089.    {
  1090.       printf ("Enter output filename -=> ");
  1091.       curses_refresh ();
  1092.       gets (outfilename);
  1093.    }
  1094.  
  1095. #ifdef CURSES
  1096.    cbreak ();
  1097. #endif
  1098.  
  1099.    if (quit == 0)
  1100.       return 0;
  1101.    else
  1102.       return -1; 
  1103.  
  1104. }
  1105.  
  1106.  
  1107. void menu ()
  1108. {
  1109.    int    choice = 0,
  1110.           repaint = 1;
  1111.    char   infilename[32],
  1112.           outfilename[32];
  1113.  
  1114.    do
  1115.    {
  1116.       if (repaint)
  1117.       {
  1118.          clrscr();
  1119.          printf ("\n\n\n\n");
  1120.  
  1121.          printf ("                            UUXFER MENU\n\n");
  1122.          printf ("                          E) Encode file\n");
  1123.          printf ("                          D) Decode file\n\n");
  1124.          printf ("                          I) Information\n");
  1125.          printf ("                             About Registering\n\n\n");
  1126.          printf ("                          0) Exit UUXFER\n\n\n\n\n");
  1127.  
  1128. #ifndef DUMB_IO
  1129.          printf ("                          Your choice -=>");
  1130.          repaint = 0;
  1131. #else
  1132.          printf ("\n\n\n\n");
  1133.          repaint = 1;
  1134. #endif
  1135.  
  1136.          curses_refresh ();
  1137.          show_status_line ();
  1138.       }
  1139.  
  1140.       do
  1141.       {
  1142.          gotoxy (43, 19);
  1143.  
  1144. #ifdef CURSES
  1145.          noecho ();
  1146. #endif
  1147.  
  1148.          choice = toupper (getch());
  1149.  
  1150. #ifdef CURSES
  1151.          echo (); 
  1152. #endif
  1153.  
  1154.          switch (choice)
  1155.          {
  1156.             case '0':
  1157.             case ESC:
  1158.                choice = '0';
  1159.                clrscr();
  1160.                continue;
  1161.             case 'E':
  1162.                repaint = 1;
  1163.            if (get_filenames (infilename, outfilename))
  1164.                   continue;
  1165.  
  1166.                encode_file (infilename, outfilename);
  1167.                break;
  1168.             case 'D':
  1169.                repaint = 1;
  1170.                if (get_filenames (infilename, outfilename))
  1171.                   continue;
  1172.  
  1173.                decode_file (infilename, outfilename);
  1174.                break;
  1175.             case 'I':
  1176.                show_about ();
  1177.                getch();
  1178.                repaint = 1;
  1179.                break;
  1180.             case 'A':
  1181.                multiple_output = ~multiple_output;
  1182.                show_status_line ();
  1183.                break;
  1184.             case 'M':
  1185.                multiple_input = ~multiple_input;
  1186.                show_status_line ();
  1187.                break;
  1188.             case 'S':
  1189.                get_filesize ();
  1190.                repaint = 1;
  1191.                break;
  1192.             case 'C':
  1193.                get_cells_per_line ();
  1194.                repaint = 1;
  1195.                break;
  1196.             case 'X':
  1197.                xx_set = ~xx_set;
  1198.                show_status_line ();
  1199.                break;
  1200.             case 'T':
  1201.                table_output = ~table_output;
  1202.                show_status_line ();
  1203.                break;
  1204.             case 'R':
  1205.                ext_set = ~ext_set;
  1206.                if (ext_set)
  1207.                   table_output = ON;
  1208.                show_status_line ();
  1209.                break;
  1210.             case 'O':
  1211.                overwrite = ~overwrite;
  1212.                show_status_line ();
  1213.                break;
  1214.             default:
  1215.                printf ("\a");
  1216.                choice = -1;
  1217.                break;
  1218.          }
  1219.       } while (choice == -1);
  1220.    } while (choice != '0');
  1221.  
  1222.    return;
  1223. }
  1224.  
  1225.  
  1226. void show_status_line ()
  1227. {
  1228.  
  1229.    gotoxy (1, 23);
  1230.  
  1231.    printf ("  A-Split = ");
  1232.    if (multiple_output)
  1233.       printf ("ON   ");
  1234.    else
  1235.       printf ("OFF  ");
  1236.  
  1237.    printf ("M-Merge = ");
  1238.    if (multiple_input)
  1239.       printf ("ON   ");
  1240.    else
  1241.       printf ("OFF  ");
  1242.  
  1243.    printf ("S-Max file size = %6ld  ", max_size);
  1244.    printf ("C-Cells = %2d\n", cells_per_line);
  1245.  
  1246.    printf ("  X-XX set = ");
  1247.    if (xx_set)
  1248.       printf ("ON   ");
  1249.    else
  1250.       printf ("OFF  ");
  1251.  
  1252.    printf ("T-Write table = ");
  1253.    if (table_output)
  1254.       printf ("ON   ");
  1255.    else
  1256.       printf ("OFF  ");
  1257.  
  1258.    printf ("R-Ext. set = ");
  1259.    if (ext_set)
  1260.       printf ("ON   ");
  1261.    else
  1262.       printf ("OFF  ");
  1263.  
  1264.    printf ("O-Overwrite = ");
  1265.    if (overwrite)
  1266.       printf ("ON   ");
  1267.    else
  1268.       printf ("OFF  ");
  1269.  
  1270.    curses_refresh ();
  1271.  
  1272.    return;
  1273. }
  1274.  
  1275.  
  1276. void get_cells_per_line ()
  1277. {
  1278.    char   buffer[32];
  1279.    int    num = 0;
  1280.  
  1281.    do
  1282.    {
  1283.       clrscr();
  1284.  
  1285.       printf ("There may not be less than 1 cell or more than 19 on a line.\n");
  1286.       printf ("Enter number of output cells per line, or -1 to abort: ");
  1287.       curses_refresh ();
  1288.       gets (buffer);
  1289.       num = atol (buffer);
  1290.       if (num > 19)
  1291.          num = 0;
  1292.  
  1293.    } while (num == 0);
  1294.  
  1295.    if (num > 0)
  1296.       cells_per_line = num;
  1297.  
  1298.    return;
  1299. }
  1300.  
  1301.  
  1302. void get_filesize ()
  1303. {
  1304.    char   buffer[32];
  1305.    long   num = 0;
  1306.  
  1307.    do
  1308.    {
  1309.       clrscr();
  1310.  
  1311.       printf ("Enter maximum size for output encoded data, or -1 to abort: ");
  1312.       curses_refresh ();
  1313.       gets (buffer);
  1314.       num = atol (buffer);
  1315.  
  1316.    } while (num == 0);
  1317.  
  1318.    if (num > 0)
  1319.       max_size = num;
  1320.  
  1321.    return;
  1322. }
  1323.  
  1324.  
  1325. int ok_to_write (filename)
  1326. char *filename;
  1327. {
  1328.    FILE  *temp;
  1329.    char   choice;
  1330.  
  1331.    temp = fopen (filename, "r");
  1332.    if (temp == NULL)
  1333.       return -1;
  1334.  
  1335.    fclose (temp);
  1336.  
  1337.    if (overwrite)
  1338.       return -1;
  1339.  
  1340.    printf ("\n  File %s already exists.  ", filename);
  1341.    curses_refresh ();
  1342.  
  1343.    if (interactive)
  1344.    {
  1345.       printf ("Overwrite? (N/y) ");
  1346.       curses_refresh ();
  1347.       while ((choice = toupper (getch())) != 'Y' && choice != 'N')
  1348.          ;
  1349.       printf ("\n");
  1350.       curses_refresh ();
  1351.       if (choice == 'Y')
  1352.          return -1;
  1353.    }
  1354.  
  1355.    return 0;
  1356. }
  1357.  
  1358.  
  1359. int build_table ()
  1360. {
  1361.    char  *ptr;
  1362.    int    i,
  1363.           entry;
  1364.  
  1365.    ptr = (char *)table;           /* clear table */
  1366.    for (i = 0; i < 128; i++)
  1367.      *(ptr++) = 127;
  1368.  
  1369.    ptr = (char *) char_set;       /* fill table */
  1370.    for (i = 0; i < 64; i++)
  1371.    {
  1372.       entry = *(ptr++) & 127;
  1373.       if (table [entry] != 127)
  1374.          return -1;
  1375.       table [entry] = i;
  1376.    }
  1377.  
  1378.    if (!(xx_set || ext_set))      /* i.e. we're using the standard 'uu' set */
  1379.       table[' '] = 0;             /* make it decode ' ' the same as `       */
  1380.  
  1381.    return 0;
  1382. }
  1383.  
  1384.  
  1385. void build_uu_chars ()
  1386. {
  1387.    int i;
  1388.  
  1389.    for (i = 0; i < 64; i++)
  1390.      uu_chars [i] = i + 32;
  1391.  
  1392.    uu_chars[0] = 96;      /* use ` instead of space */
  1393.  
  1394.    return;
  1395. }
  1396.  
  1397.  
  1398. int read_charset (infile)
  1399. FILE *infile;
  1400. {
  1401.    uchar  ch,
  1402.           line[256],
  1403.          *ptr;
  1404.    int    i,
  1405.           len;
  1406.  
  1407.  
  1408.    for (i = 0; i < 64; )
  1409.    {
  1410.       len = strlen (fgets ((char *)line, 255, infile));
  1411.       if (len <= 0)
  1412.          return -1;
  1413.  
  1414.       line_count++;
  1415.  
  1416.       if (strncmp ((char *)line, "begin ", 6) == 0)
  1417.          break;
  1418.  
  1419.       ptr = line;
  1420.       do
  1421.       {
  1422.          ch = *ptr;
  1423.          if (ch == '\n')
  1424.            break;
  1425.          if (ch > 0 && ch < 128)
  1426.          {
  1427.             ext_chars [i] = ch;
  1428.             i++;
  1429.             len--;
  1430.             ptr++;
  1431.          }
  1432.       } while (len > 0);
  1433.    }
  1434.  
  1435.    if (i < 64)
  1436.    {
  1437.       printf ("Invalid character table! (not enough characters in table)\n");
  1438.       curses_refresh ();
  1439.       return -1;
  1440.    }
  1441.  
  1442.    char_set = ext_chars;
  1443.    if (build_table () != 0)
  1444.    {
  1445.       printf ("Invalid character table! (table build failed)\n");
  1446.       curses_refresh ();
  1447.       return -1;
  1448.    }
  1449.  
  1450.    return 0;
  1451. }
  1452.  
  1453.  
  1454. int write_table (outfile)
  1455. FILE *outfile;
  1456. {
  1457.    int   i;
  1458.  
  1459.    fprintf (outfile, "table\n");
  1460.  
  1461.    for (i = 0; i < 32; i++)
  1462.       fputc (char_set [i], outfile);
  1463.    fputc ('\n', outfile);
  1464.  
  1465.    for (i = 32; i < 64; i++)
  1466.       fputc (char_set [i], outfile);
  1467.    fputc ('\n', outfile);
  1468.  
  1469.    return 0;
  1470. }
  1471.  
  1472.  
  1473. int read_external_set ()
  1474. {
  1475.    FILE  *fileptr;
  1476.    int    rc;
  1477.  
  1478.    if ((fileptr = fopen ("TABLE.UUX", "rt")) == NULL)
  1479.       return -1;
  1480.  
  1481.    rc = read_charset (fileptr);
  1482.  
  1483.    fclose (fileptr);
  1484.  
  1485.    return rc;
  1486. }
  1487.  
  1488.  
  1489. int check_xx (byte)
  1490. int byte;
  1491. {
  1492.    int i;
  1493.  
  1494.    for (i = 0; i < 64; i++)
  1495.       if (xx_chars[i] == byte)
  1496.          break;
  1497.  
  1498.    if (i == 64)
  1499.       return table[byte];
  1500.  
  1501.    xx_set = ON;
  1502.    char_set = xx_chars;
  1503.    build_table();
  1504.  
  1505.    return table[byte];
  1506. }
  1507.  
  1508.  
  1509. long get_size (filename)
  1510. char  *filename;
  1511. {
  1512.    int     i;
  1513.    long    tot_size;
  1514.    FILE   *fileptr;
  1515.    char    extension[5];
  1516.  
  1517.  
  1518.    if (!multiple_input)
  1519.    {
  1520.       if ((fileptr = fopen (filename, "rt")) == NULL)
  1521.          return -1;
  1522.       tot_size = filesize (fileptr);
  1523.  
  1524.       fclose (fileptr);
  1525.  
  1526.       return tot_size;
  1527.    }
  1528.  
  1529.    tot_size = 0;
  1530.    for (i = 1; 1; i++)
  1531.    {
  1532.       clear_extension (filename);
  1533.       sprintf (extension, "%d", i);
  1534.       strcat (filename, extension);
  1535.  
  1536.       if ((fileptr = fopen (filename, "rt")) == NULL)
  1537.          break;
  1538.       tot_size += filesize (fileptr);
  1539.  
  1540.       fclose (fileptr);
  1541.    }
  1542.  
  1543.    return tot_size;
  1544. }
  1545.  
  1546.  
  1547. #ifndef DUMB_IO
  1548.  
  1549. int update_progress (mode)
  1550. int mode;
  1551. {
  1552.    static int lastx,
  1553.               lasty;
  1554.    int    curx,
  1555.           cury;
  1556.  
  1557.    if (mode == INIT)
  1558.    {
  1559.       lastx = wherex();
  1560.       lasty = wherey();
  1561.       printf ("\n");
  1562.    }
  1563.  
  1564.    curx = wherex();
  1565.    cury = wherey();
  1566.  
  1567.    gotoxy (lastx, lasty);
  1568. #ifdef CURSES
  1569.    addch (UPDATE_CHAR);
  1570.    refresh();
  1571. #else
  1572.    putchar (UPDATE_CHAR);
  1573. #endif
  1574.    lastx = wherex();
  1575.    lasty = wherey();
  1576.  
  1577.    gotoxy (curx, cury);
  1578.  
  1579.    return 0;
  1580. }
  1581.  
  1582. #else    /* dumb I/O */
  1583.  
  1584. int update_progress (mode)
  1585. int mode;
  1586. {
  1587.    static int num_calls;     /* will store # of times this routine has */
  1588.                              /* been called.                           */
  1589.  
  1590.    if (mode == INIT)
  1591.    {
  1592.       num_calls = 0;
  1593.       printf ("  ");
  1594.    }
  1595.    else
  1596.    {
  1597.       num_calls++;
  1598.       if ((num_calls % 5) == 0)
  1599.          printf ("  %d%%", 10*(num_calls / 5));
  1600.    }
  1601.  
  1602.    return;
  1603. }
  1604.  
  1605.  
  1606. void clearscr ()
  1607. {
  1608.    int i;
  1609.  
  1610.    for (i = 0; i < 24; i++)
  1611.       printf ("\n");
  1612.  
  1613.    return;
  1614. }
  1615.  
  1616.  
  1617. void moveto (x, y)
  1618. int x;
  1619. int y;
  1620. {
  1621.    if (x == 0 || y == 0)    /* Ok, this is really stupid, and I'm lazy.   */
  1622.       ;                     /* I want this function to do nothing, and    */ 
  1623.                             /* for the compiler not to complain about it. */
  1624.    return;
  1625. }
  1626.  
  1627.  
  1628. int getcharacter ()
  1629. {
  1630.    int i;
  1631.  
  1632.    i = getchar();
  1633.    fflush (stdin);
  1634.  
  1635.    return i;
  1636. }
  1637.  
  1638. #endif
  1639.  
  1640. #ifdef CURSES
  1641.  
  1642. void moveto (x, y)
  1643. int x;
  1644. int y;
  1645. {
  1646.    move (y - 1, x - 1); 
  1647.    refresh ();
  1648.  
  1649.    return;
  1650.  
  1651. int wherex ()
  1652. {
  1653.    int x,
  1654.        y;
  1655.  
  1656.    getyx (stdscr, y, x);
  1657.  
  1658.    return x + 1;
  1659. }
  1660.  
  1661. int wherey ()
  1662. {
  1663.    int x,
  1664.        y;
  1665.  
  1666.    getyx (stdscr, y, x);
  1667.  
  1668.    return y + 1;
  1669. }
  1670.  
  1671. void clearscr ()
  1672. {
  1673.    clear ();
  1674.    refresh ();
  1675. }
  1676.  
  1677. #endif
  1678.  
  1679. long filesize (fileptr)
  1680. FILE *fileptr;
  1681. {
  1682.    long cur_pos,
  1683.         length;
  1684.  
  1685.    cur_pos = ftell (fileptr);
  1686.    fseek (fileptr, 0, SEEK_END);
  1687.    length = ftell (fileptr);
  1688.    fseek (fileptr, cur_pos, SEEK_SET);
  1689.  
  1690.    return length;
  1691. }
  1692.  
  1693. void press_key ()
  1694. {
  1695.    if (interactive)
  1696.    {
  1697.       printf ("Press any key to continue...");
  1698.       curses_refresh ();
  1699.       getch();
  1700.    }
  1701.  
  1702.    return;
  1703. }
  1704.  
  1705. void curses_refresh ()
  1706. {
  1707. #ifdef CURSES
  1708.    refresh ();
  1709. #endif
  1710.  
  1711.    return;
  1712. }
  1713.  
  1714.