home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 26 / CD_ASCQ_26_1295.iso / vrac / reansi12.zip / REANSI.C < prev    next >
C/C++ Source or Header  |  1995-08-17  |  25KB  |  726 lines

  1. /* REANSI 1.2:  ANSI/AVATAR/PC-8/ASCII conversion program. */
  2. /* Copyright 1995 by Thomas Almy. All rights reserved. */
  3. /* May be distributed freely providing no charge is made for the program,
  4.    and the program is distributed complete with source and without
  5.    modification */
  6.  
  7. /* The author can be contacted at tom.almy@tek.com, or 1:105/290,
  8.    or by mail at 17830 SW Shasta Trail, Tualatin, OR 97062. When
  9.    coresponding via mail, please enclose a stamped self-addressed 
  10.    envelope if you desire a reply. */
  11.  
  12. #include <stdio.h>
  13. #include <fcntl.h>
  14. #include <io.h>
  15. #include <string.h>
  16. #include <mem.h>
  17. #include <stdlib.h>
  18.  
  19. /************************************/
  20. /*   SYSTEM DEPENDENT DEFINITIONS   */
  21. /************************************/
  22.  
  23. /* Note, this program requires an ANSI C compiler */
  24.  
  25. #define USEPATHS        /* comment out if OS does not have file paths */
  26. #define PATHSEP '\\'    /* pathname separator, make '/' for UNIX */
  27. #define READMODE "rb"   /* open a file in binary (no translation) mode */
  28. #define WRITEMODE "wb"   /* open a file for writing in binary mode */
  29.  
  30. /************************************/
  31. #define BITS7 (0x7f)
  32. #define BG(x) ((x)&0x70)
  33. #define BGBITS (4)
  34. #define NOTBG(x) ((x)&~0x70)
  35. #define FG(x) ((x)&0x7)
  36. #define NOTFG(x) ((x)&~0x7)
  37. #define BRIGHT(x) ((x)&0x8)
  38. #define BFG(x) ((x)&0xf)
  39. #define BLINK(x) ((x)&0x80)
  40. #define TRUE 1
  41. #define FALSE 0
  42.  
  43. #define MAXCOL 80
  44. #define MAXLINE 24  /* can be made 25 to handle 25 line display emulation
  45.                         for example */
  46.  
  47. #define LASTLINE (MAXLINE-1)
  48. #define LASTCOL  (MAXCOL-1)
  49.  
  50. char screen[MAXLINE][MAXCOL];
  51. char scratr[MAXLINE][MAXCOL];
  52. char linatr[MAXLINE];   /* attribute of initialized line */
  53.                         /* zero means unknown */
  54.  
  55. char ans2ibm[8] = {0, 4, 2, 6, 1, 5, 3, 7}; /* goes either way! */
  56.  
  57. char pc8map[256] = {
  58.     32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
  59.     32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
  60.     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  61.     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  62.     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
  63.     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  64.     96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  65.     112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  66.     'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', 
  67.     'e', 'e', 'e', 'i', 'i', 'i', 'a', 'a', /* 0x80-F */
  68.  
  69.     'E', 'e', 'E', 'o', 'o', 'o', 'u', 'u', 
  70.     'y', 'O', 'U', 'c', '#', 'Y', 'P', 'F', /* 0x90-F */
  71.  
  72.     'a', 'i', 'o', 'u', 'n', 'N', ' ', ' ', 
  73.     '?', ' ', ' ', ' ', ' ', '!', '"', '"', /* 0xA0-F */
  74.  
  75.     '*', '*', '*', '|', '|', '|', '|', '+', 
  76.     '+', '+', '|', '+', '+', '+', '+', '+', /* 0xB0-F */
  77.  
  78.     '+', '+', '+', '+', '-', '+', '+', '+', 
  79.     '+', '+', '+', '+', '+', '=', '+', '+', /* 0xC0-F */
  80.  
  81.     '+', '+', '+', '+', '+', '+', '+', '+', 
  82.     '+', '+', '+', '*', '*', '*', '*', '*', /* 0xD0-F */
  83.  
  84.     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 
  85.     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* 0xE0-F */
  86.  
  87.     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 
  88.     'o', '.', '.', ' ', ' ', ' ', '*', ' '}; /* 0xF0-F */
  89.     
  90.  
  91. int curx, cury;  /* cursor position */
  92. int attrib = 7;  /* white on black, attribute by the input */
  93. int outattrib = 7;  /* current attribute on the output "Device" */
  94. int clsattrib = 7;  /* clear screen to ... */
  95. FILE *inf, *outf;   /* input and output files */
  96.  
  97. int wflag=TRUE;        /* wrapping enabled on input side */
  98. int pflag=FALSE;        /* printer input -- nondescructive space char
  99.                            and don't overprint underscore! */
  100. int woflag=FALSE;       /* output wraps */
  101. int notran=FALSE;       /* Don't translate PC-8 to ASCII */
  102. int tabs=FALSE;         /* use tabs in output */
  103. int ffeed=TRUE;         /* use formfeeds in output */
  104. int avatarin=TRUE;      /* AVATAR codes on input */
  105. int racodein=FALSE;     /* allow inputting RemoteAccess color codes */
  106. int ansi=FALSE;         /* ANSI positioning codes */
  107. int mono=TRUE;          /* don't send color codes */
  108. int avatar=FALSE;       /* AVATAR positioning codes */
  109. int racode=FALSE;       /* RemoteAccess color codes out */
  110. int ch;             /* last character read */
  111.  
  112. #define TABSIZE 8   /* constant, standard tab size */
  113.  
  114. #if 0
  115. void dump(void) {
  116.     /* diagnostic routine to dump virtual display to physical display */
  117.     char foo[80];
  118.     int x, y;
  119.     char far *display = (char far *)0xB8000000L;
  120.  
  121.     for (y=0; y<24; y++) for (x=0; x<80; x++) {
  122.         *display++= screen[y][x];
  123.         *display++= scratr[y][x];
  124.     }
  125.     gets(foo);      /* pause */
  126. }
  127. #endif
  128.  
  129. void setattrib(int i) {
  130.     /* set attribute from ANSI sequence */
  131.     switch (i) {
  132.         case 0: attrib=7; return;       /* normal */
  133.         case 1: attrib |= 8; return;    /* bold */
  134.         case 2: attrib &= ~8; return;   /* unbold */
  135.         case 5: attrib |= 128; return;  /* blink */
  136.         default:
  137.             if (i >=30 && i <=37)
  138.                 attrib = NOTFG(attrib) | ans2ibm[i-30];
  139.             else if (i>=40 && i <=47)
  140.                 attrib = NOTBG(attrib) | (ans2ibm[i-40]<<4);
  141.             return;
  142.     }
  143. }
  144.  
  145. void printattrib(int new, char c) {
  146.     char wreset[20], woreset[20], buff[20];
  147.     int i,j;
  148.     /* might not need to do anything */
  149.     if (mono || new == outattrib || (c==' '&& BG(new)==BG(outattrib))) return;
  150.     if (ansi) { /* send ansi codes */
  151.         fputs("\033[", outf);
  152.             woreset[0] = '\0';
  153.         if ((BLINK(new) || !BLINK(outattrib))&&
  154.             (BRIGHT(new) || !BRIGHT(outattrib))) {
  155.             /* non-reset a possibility */
  156.             if (BRIGHT(new) && !BRIGHT(outattrib)) strcat(woreset, "1;");
  157. /*          Terminal emulators don't support un-bright. Too bad!
  158.             if (BRIGHT(outattrib) && !BRIGHT(new)) strcat(woreset, "2;"); */
  159.             if (BLINK(new) && !BLINK(outattrib)) strcat(woreset, "5;");
  160.             if (FG(new) != FG(outattrib)) {
  161.                 sprintf(buff, "%d;", ans2ibm[FG(new)]+30);
  162.                 strcat(woreset, buff);
  163.             }
  164.             if (BG(new) != BG(outattrib)) {
  165.                 sprintf(buff, "%d;", ans2ibm[BG(new)>>BGBITS]+40);
  166.                 strcat(woreset, buff);
  167.             }
  168.             /* delete trailing semicolon */
  169.             if ((i=strlen(woreset))>0) woreset[i-1] = '\0';
  170.         }
  171.         /* calculate string with reset */
  172.         strcpy(wreset,"0;");
  173.         if (BRIGHT(new)) strcat(wreset, "1;");
  174.         if (BLINK(new)) strcat(wreset, "5;");
  175.         if (FG(new) != 7) {
  176.             sprintf(buff, "%d;", ans2ibm[FG(new)]+30);
  177.             strcat(wreset, buff);
  178.         }
  179.         if (BG(new) != 0) {
  180.             sprintf(buff, "%d;", ans2ibm[BG(new)>>BGBITS]+40);
  181.             strcat(wreset, buff);
  182.         }
  183.         /* delete trailing semicolon */
  184.         wreset[(i=strlen(wreset))-1] = '\0';
  185.         /* output shorter sequence */
  186.         j=strlen(woreset);
  187.         if (j < i && j > 0) fputs(woreset, outf);
  188.         else fputs(wreset, outf);
  189.         fputc('m', outf);
  190.     }
  191.     else if (racode) {
  192.         fprintf(outf,"\013[%02x",new);
  193.     }
  194.     else { /* must be AVATAR */
  195.         fprintf(outf,"\026\001%c",new & BITS7);
  196.         if (BLINK(new)) fputs("\026\002", outf);
  197.     }
  198.     outattrib = new;
  199. }
  200.  
  201. void setpos(int pos, int blanks, int spaceatr, int newattrib, int linatr) {
  202.     int method=0;
  203.     if (ansi) { /* position cursor or output blanks */
  204.         blanks = pos-blanks;    /* relative movement */
  205.         if (BG(outattrib)==BG(linatr)) { /* line and draw the same */
  206.             if (blanks>3) method=1;
  207.         }
  208.         else { /* line and draw different */
  209.             if (BG(spaceatr)==BG(newattrib) && blanks<4) {
  210.                 printattrib(newattrib, 'X');
  211.             }
  212.             else if (BG(linatr)==BG(spaceatr)) method = 1;
  213.         }
  214.         if (method==1) {
  215.             fprintf(outf,"\033[%dC",blanks);
  216.         }
  217.         else {
  218.             while (blanks--) fputc(' ', outf);
  219.         }
  220.     }
  221.     else if (avatar) { /* similar but different considerations */
  222.         blanks = pos-blanks;    /* relative movement */
  223.         if (BG(spaceatr)==BG(outattrib)) { /* in current color */
  224.             if (blanks<=3) {
  225.                 while (blanks--) fputc(' ', outf);
  226.             }
  227.             else fprintf(outf,"\031 %c", blanks);
  228.         }
  229.         else {
  230.             if (blanks <= 4) {
  231.                 while (blanks--) fputs("\026\006", outf);
  232.             }
  233.             else {
  234.                 outattrib = spaceatr&BITS7;
  235.                 fprintf(outf,"\026\001%c\031 %c", outattrib, blanks);
  236.                 printattrib(newattrib,'x');
  237.             }
  238.         }
  239.     }
  240.     else { /* tabs */
  241.     /* fill with tabs or spaces */
  242.         if(pos == blanks+1) {   /* dont convert single space */
  243.             fputc(' ', outf);
  244.             blanks = -1;
  245.             return;
  246.         }
  247.         while ((pos/TABSIZE) > (blanks/TABSIZE)) {
  248.             fputc('\t', outf);
  249.             blanks += TABSIZE - (blanks % TABSIZE);
  250.         }
  251.         while (pos > blanks) {
  252.             fputc(' ', outf);
  253.             blanks++;
  254.         }
  255.     }
  256. }
  257.  
  258.  
  259. void initdisplay(void) {
  260.     /* initialize contents of virtual display */
  261.     memset(screen, ' ', sizeof(screen));
  262.     memset(scratr, clsattrib, sizeof(scratr));
  263.     memset(linatr, clsattrib, sizeof(linatr));
  264.     curx = cury = 0;
  265. }
  266.  
  267. int linelen(char *line, char *attrib, int linatr) {
  268.     /* calculate length of line */
  269.     int i;
  270.     linatr = BG(linatr);
  271.     for (i=LASTCOL; i>=0 && line[i]==' ' && BG(attrib[i])==linatr; i--);
  272.     return (i+1);
  273. }
  274.  
  275. void writeline(char *line, char *attribs, char linatr) {
  276.     /* writes line, truncated to output file */
  277.     int i = linelen(line,attribs,linatr);
  278.     int j, lastattrib, k;
  279.     int blanks=-1;      /* for tabification */
  280.     
  281.     if (i > 0) {
  282.         if (tabs || ansi || avatar || racode) {
  283.             /* check for sequences of spaces */
  284.             blanks=-1;
  285.             for (j=0; j<i; j++) {
  286.                 /* a space is only a space if we don't change bg colors */
  287.                 /* we can space on either current (outattrib) or original
  288.                    (linatr) colors */
  289.                 if (line[j] == ' '&& !racode &&
  290.                     (mono ||
  291.                      (blanks==-1 && (BG(attribs[j])==BG(outattrib) ||
  292.                                      BG(attribs[j])==BG(linatr))) ||
  293.                      (blanks !=-1 && BG(attribs[j]) == BG(linatr)))) {
  294.                     if (blanks== -1) blanks = j;
  295.                     lastattrib=attribs[j];
  296.                     continue;
  297.                 }
  298.                 if (blanks != -1) {
  299.                     setpos(j, blanks,lastattrib,attribs[j],linatr);
  300.                     blanks = -1;
  301.                 }
  302.                 printattrib(attribs[j], line[j]);
  303.                 if (avatar) { /* check for repeated characters */
  304.                     for (k=j; k<i; k++)
  305.                         if (line[j]!=line[k] || attribs[j]!=attribs[k]) break;
  306.                     if (k-j > 3) {
  307.                         fprintf(outf,"\031%c%c", line[j], k-j);
  308.                         j += (k-j)-1;
  309.                         continue;
  310.                     }
  311.                 }
  312.                 fputc(line[j],outf);
  313.             }
  314.         }
  315.         else fwrite(line, 1, i, outf);
  316.     }
  317.     if (i < MAXCOL || !woflag){
  318.         /* revert to line default attribute at end of line to avoid problems */
  319.         if (BG(outattrib)!=BG(linatr) && (ansi||avatar||racode))
  320.                 printattrib(BG(linatr)|NOTBG(outattrib), ' ');
  321.         fputs("\r\n", outf);
  322.     }
  323. }
  324.  
  325. void writedisplay(void) {
  326.     /* write display contents */
  327.     int i,j;
  328.     /* don't write out empty lines at end of virtual screen */
  329.     for (i=LASTLINE; i>=0 && linelen(screen[i],scratr[i],linatr[i]) == 0; i--) ;
  330.     
  331.     for (j=0; j<=i; j++) writeline(screen[j], scratr[j], linatr[j]);
  332. }
  333.  
  334. void docls(void) {
  335.     if (avatar) outattrib=3; /* avatar, alone, resets the display attribute */
  336.     if (ansi)  fputs("\033[2J", outf);
  337.     else if (avatar || ffeed || racode) fputc(12, outf);
  338.     initdisplay();
  339. }
  340.  
  341. void cleardisplay(void) {
  342.     /* clear the display -- write contents, send formfeed, initialize */
  343.     writedisplay();
  344.  
  345.     docls();
  346. }
  347.  
  348. void clearpage(void) {
  349.     /* as above, but write contents downto, and including, cursor line */
  350.     int i;
  351.     for (i=0; i<=cury; i++) writeline(screen[i], scratr[i], linatr[i]);
  352.  
  353.     docls();
  354. }
  355.  
  356.  
  357. void setposition(int x, int y) {
  358.     /* set the pseudocursor position */
  359.     curx = max(0, min(x, LASTCOL));
  360.     cury = max(0, min(y, LASTLINE));
  361. }
  362.  
  363. void scrollup(void) {
  364.     /* write out first line of virtual screen, then scroll screen up */
  365.     writeline(screen[0], scratr[0], linatr[0]);
  366.     memmove(screen[0], screen[1], MAXCOL*LASTLINE);
  367.     memset(screen[LASTLINE], ' ', MAXCOL);
  368.     memmove(scratr[0], scratr[1], MAXCOL*LASTLINE);
  369.     memset(scratr[LASTLINE], attrib, MAXCOL);   /* current input attribute */
  370.     memmove(&linatr[0], &linatr[1], LASTLINE);
  371.     linatr[LASTLINE] = attrib;
  372. }
  373.  
  374. void wrapcheck(void) {
  375.     /* check cursor wrap */
  376.     if (curx > MAXCOL) {
  377.         if (wflag) {
  378.             curx=0;
  379.             if (cury==LASTLINE) scrollup();
  380.             else cury++;
  381.         }
  382.         else {
  383.             curx--;
  384.         }
  385.     }
  386. }
  387. void insertchar(char c) {
  388.     /* insert character at cursor, then move cursor */
  389.     int ch = (notran? c : pc8map[(unsigned char)c]);
  390.     if ((!pflag) || (ch != ' ' && !(ch == '_' && screen[cury][curx] != ' ')))
  391.         screen[cury][curx] = ch;
  392.     scratr[cury][curx] = attrib;
  393.     curx++;
  394.     wrapcheck();
  395. }
  396.  
  397. char readc(void) {
  398.     /* read a character from the input stream */
  399.     ch = fgetc(inf);
  400.     if (ch == EOF) {
  401.         writedisplay();
  402.         /* force normal state for ansi or avatar */
  403.         if (ansi || avatar) printattrib(ansi?7:3, 'x');
  404.         exit(0);
  405.     }
  406.     return ch;
  407. }
  408.  
  409.  
  410. void usage(char *s) {
  411.     fprintf(stderr,
  412. "Usage: %s [in [out]] [-p] [-s] [-cN] [-i] [-r]\n"
  413. "                     [-x] [-f] [-w] [-t|-a|-m|-v|-o]\n"
  414.         "   in     -- input file, default is read from stdin (keyboard)\n"
  415.         "   out    -- output file, default is write to stdout (display)\n"
  416.         "   -p     -- input is for printer\n"
  417.         "   -s     -- input assumes cursor sticks at right edge\n"
  418.         "   -cN    -- initial color attribute is N (hexidecimal value)\n"
  419.         "   -i     -- ignore AVATAR codes in input\n"
  420.         "   -r     -- accept RemoteAccess color codes in input\n"
  421.         "   -x     -- don't translate PC-8 to ASCII\n"
  422.         "   -f     -- don't output formfeeds\n"
  423.         "   -w     -- output wraps after 80 characters\n"
  424.         "   -t     -- use tab characters in output\n"
  425.         "   -o     -- output RemoteAccess color codes\n"
  426.         "   -a     -- output ANSI positioning codes and color codes\n"
  427.         "   -m     -- output ANSI positioning codes only\n"
  428.         "   -v     -- output AVATAR codes\n", s);
  429.     exit(1);
  430. }
  431.  
  432.  
  433. /* ANSI state machine states */
  434. #define START 0
  435. #define STARTARG 1
  436. #define INNUM 2
  437. #define FINNUM 3
  438. #define DOCMD 4
  439.  
  440. void ansisequence(void) {
  441.     /* handle ANSI.SYS escape sequences */
  442.     /* Will parse only to extent necessary for this program. */
  443.     static int savex=0, savey=0;
  444.     int state = START;
  445.     int args[10];        /* extra sure */
  446.     int argnum = 0;
  447.     int i;
  448.     for (i=0; i<10; i++) args[i]=1;  /* default values */
  449.     readc();    /* prime pump */
  450.     while (TRUE) switch (state) {
  451.         case START:
  452.             if (ch != '[') return;  /* No telling what this is */
  453.             while (readc() == '?' || ch == '='); /* toss flag chars */
  454.             state = STARTARG;
  455.             /* break; */
  456.         case STARTARG:
  457.             if (ch == ';') { /* default argument */
  458.                 argnum = min(9, argnum+1);
  459.                 readc();
  460.                 break;
  461.             }
  462.             if (ch>='0' && ch<='9') {   /* number */
  463.                 state = INNUM;
  464.                 break;
  465.             }
  466.             if (ch=='\'' || ch == '\"') { /* string -- parse and ignore*/
  467.                 i = ch;
  468.                 while (readc() != i);
  469.                 readc();
  470.                 state = FINNUM;
  471.                 break;
  472.             }
  473.             state = DOCMD;  /* reached end */
  474.             break;
  475.         case INNUM:
  476.             args[argnum] = 0;
  477.             do {
  478.                 args[argnum] = args[argnum]*10 + ch - '0';
  479.             } while (readc() >= '0' && ch <= '9');
  480.             argnum = min(9, argnum+1);
  481.             state = FINNUM;
  482.             /* break; */
  483.         case FINNUM:
  484.             if (ch == ';') {    /* more to come */
  485.                 readc();
  486.                 state = STARTARG;
  487.                 break;
  488.             }
  489.             state = DOCMD;
  490.             /* break; */
  491.         case DOCMD:
  492.             switch (ch) {
  493.                 case 'H': /* cursor position */
  494.                 case 'f':
  495.                     cury = max(0, min(LASTLINE, args[0]-1));
  496.                     curx = max(0, min(LASTCOL,  args[1]-1));
  497.                     break;
  498.                 case 'A': /* cursor up */
  499.                     cury = max(0, cury-args[0]);
  500.                     break;
  501.                 case 'B': /* cursor down */
  502.                     cury = min(LASTLINE, cury+args[0]);
  503.                     break;
  504.                 case 'C': /* cursor forward */
  505.                     curx = min(LASTCOL, curx+args[0]);
  506.                     break;
  507.                 case 'D': /* cursor back */
  508.                     curx = max(0, curx-args[0]);
  509.                     break;
  510.                 case 's': /* cursor save */
  511.                     savex = curx;
  512.                     savey = cury;
  513.                     break;
  514.                 case 'u': /* cursor restore */
  515.                     curx = savex;
  516.                     cury = savey;
  517.                     break;
  518.                 case 'J': /* erase display -- we will ignore argument */
  519.                     clsattrib=attrib;/* clears to color of current attribute*/
  520.                     cleardisplay();
  521.                     break;
  522.                 case 'K': /* erase line -- we will ignore argument */
  523.                     memset(&screen[cury][curx],' ', LASTCOL-curx);
  524.                     memset(&scratr[cury][curx],attrib, LASTCOL-curx);
  525.                     break;
  526.                 case 'h': /* set mode -- only look at line wrap */
  527.                     if (args[0]==7) wflag = TRUE;
  528.                     break;
  529.                 case 'l': /* reset mode -- only look at line wrap */
  530.                     if (args[0]==7) wflag = FALSE;
  531.                     break;
  532.                 case 'm': /* set color */
  533.                     for (i=0; i<argnum; i++) {
  534.                         setattrib(args[i]);
  535.                     }
  536.                     break;
  537.                 /* all other commands are ignored completely */
  538.             }
  539.             return; /* finished with ANSI sequence */   
  540.     }
  541.  
  542. }
  543.  
  544. void avatarsequence(void) {
  545.     /* handle avatar control-V sequences on input */
  546.     readc();
  547.     switch(ch) {
  548.         case 1: /* attribute set */
  549.             readc();
  550.             attrib = ch & BITS7;
  551.             break;
  552.         case 2: /* blink */
  553.             attrib |= 0x80;
  554.             break;
  555.         case 3: /* move up */
  556.             cury = max(0, cury-1);
  557.             break;
  558.         case 4: /* move down */
  559.             cury = min(LASTLINE, cury+1);
  560.             break;
  561.         case 5: /* move left */
  562.             curx = max(0, curx-1);
  563.             break;
  564.         case 6: /* move right */
  565.             curx = min(LASTCOL, curx+1);
  566.             break;
  567.         case 7: /* clear to end of line */
  568.             memset(&screen[cury][curx],' ', LASTCOL-curx);
  569.             memset(&scratr[cury][curx],attrib, LASTCOL-curx);
  570.             break;
  571.         case 8: /* move cursor row col */
  572.             readc();
  573.             cury = max(0, min(LASTLINE, ch));
  574.             readc();
  575.             curx = max(0, min(LASTCOL, ch));
  576.             break;
  577.     }
  578. }
  579.  
  580. void main(int argc, char **argv) {
  581.     char *progname = *argv++;
  582.     char *s;
  583.     int i;
  584.  
  585. #ifdef USEPATHS
  586.     if ((s=strrchr(progname, PATHSEP)) != NULL) {
  587.         /* simplify program name */
  588.         progname = s+1;
  589.     }
  590.     if ((s=strrchr(progname, '.'))  != NULL) {
  591.         *s = 0; /* get rid of extension */
  592.     }
  593. #endif
  594.  
  595.     fprintf(stderr, 
  596.         "REANSI 1.2: ANSI/AVATAR/PC-8/ASCII conversion program.\n"
  597.         "Copyright 1995 by Thomas Almy. All rights reserved.\n"
  598.         "Run %s -? for help.\n\n", progname);
  599.  
  600.     argc--;
  601.     if (argc > 0 && **argv != '-') {
  602.         /* must be input file name */
  603.         if ((inf = fopen(*argv, READMODE)) == NULL) {
  604.             fprintf(stderr,"%s: Cannot open input file %s.", progname, *argv);
  605.             exit(1);
  606.         }
  607.         argv++;
  608.         argc--;
  609.     }
  610.     else {
  611.         inf = stdin;
  612.         setmode(fileno(inf), O_BINARY); /* force binary mode */
  613.     }
  614.     
  615.     if (argc > 0 && **argv != '-') {
  616.         /* must be output file name */
  617.         if ((outf = fopen(*argv, WRITEMODE)) == NULL) {
  618.             fprintf(stderr,"%s: Cannot open output file %s.",progname, *argv);
  619.             exit(1);
  620.         }
  621.         argv++;
  622.         argc--;
  623.     }
  624.     else {
  625.         outf = stdout;
  626.         setmode(fileno(outf), O_BINARY);
  627.     }
  628.     
  629.     while (argc-- > 0) {
  630.         if (**argv == '-' && strlen(*argv) >=2 && (*argv)[1]=='c') {
  631.             if (sscanf((*argv)+2, "%x", &attrib) != 1 || attrib<0 || attrib>255){
  632.                 fprintf(stderr, "%s: Invalid color attribute %s\n",progname, (*argv)+2);
  633.                 usage(progname);
  634.             }
  635.             outattrib = attrib;
  636.             argv++;
  637.             continue;
  638.         }
  639.             
  640.         if (**argv != '-' || strlen(*argv) != 2) {
  641.             fprintf(stderr,"%s: Unrecognized argument %s\n",progname, *argv);
  642.             usage(progname);
  643.         }
  644.         switch ((*argv)[1]) {
  645.             case 'p': pflag=TRUE; break;
  646.             case 's': wflag=FALSE; break;
  647.             case 't': tabs=TRUE;   break;
  648.             case 'w': woflag=TRUE; break;
  649.             case 'x': notran=TRUE; break;
  650.             case 'f': ffeed=FALSE; break;
  651.             case 'i': avatarin=FALSE; break;
  652.             case 'r': racodein=TRUE; break;
  653.             case 'a': ansi=TRUE; racode=mono=avatar=FALSE; break;
  654.             case 'v': avatar=TRUE; racode=mono=ansi=FALSE; break;
  655.             case 'm': mono=ansi=TRUE; racode=avatar=FALSE; break;
  656.             case 'o': racode=TRUE; mono=ansi=avatar=FALSE; break;
  657.             case '?': usage(progname); break;
  658.             default: 
  659.                 fprintf(stderr,"%s: Unrecognized switch %s\n",progname, *argv);
  660.                 usage(progname);
  661.                 break;
  662.         }
  663.         argv++;
  664.     }
  665.     initdisplay();
  666.     
  667.     while(TRUE) switch (readc()) {
  668.         case 8: /* backspace */
  669.             curx = max(0, curx-1);
  670.             break;
  671.         case 9: /* tab */
  672.             curx = (curx+8) & -8;
  673.             wrapcheck();
  674.             break;
  675.         case 10: /* linefeed */
  676.             if (cury==LASTLINE) scrollup();
  677.             else cury++;
  678.             break;
  679.         case 11: /* RA codes */
  680.             if (racodein) {
  681.                 readc();
  682.                 if (ch=='[') {
  683.                     char buf[3];
  684.                     readc();
  685.                     buf[0]=ch;
  686.                     readc();
  687.                     buf[1]=ch;
  688.                     buf[2]=0;
  689.                     sscanf(buf,"%x",&attrib);
  690.                     break;
  691.                 }
  692.                 insertchar(11); /* not a match -- insert into buffer */
  693.             }
  694.             insertchar(ch);
  695.             break;
  696.         case 12: /* formfeed */
  697.             if (avatarin) clsattrib=3;  /* clear to AVATAR color */
  698.             clearpage();
  699.             break;
  700.         case 13: /* carriage return */
  701.             curx = 0;
  702.             break;
  703.         case 22: /* avatar commands */
  704.             if (avatarin) avatarsequence();
  705.             else insertchar(ch);
  706.             break;
  707.         case 25: /* AVATAR RLE */
  708.             if (avatarin) {
  709.                 readc();    /* get count */
  710.                 i = ch;
  711.                 readc();    /* get character to repeat */
  712.                 while (ch-- > 0) insertchar(i);
  713.             }
  714.             else insertchar(ch);
  715.             break;
  716.         case 26: /* Control-Z gets ignored */
  717.             break;
  718.         case 27: /* escape sequence */
  719.             ansisequence();
  720.             break;
  721.         default: 
  722.             insertchar(ch);
  723.             break;
  724.     }
  725. }
  726.