home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 26
/
CD_ASCQ_26_1295.iso
/
vrac
/
reansi12.zip
/
REANSI.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-17
|
25KB
|
726 lines
/* REANSI 1.2: ANSI/AVATAR/PC-8/ASCII conversion program. */
/* Copyright 1995 by Thomas Almy. All rights reserved. */
/* May be distributed freely providing no charge is made for the program,
and the program is distributed complete with source and without
modification */
/* The author can be contacted at tom.almy@tek.com, or 1:105/290,
or by mail at 17830 SW Shasta Trail, Tualatin, OR 97062. When
coresponding via mail, please enclose a stamped self-addressed
envelope if you desire a reply. */
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <string.h>
#include <mem.h>
#include <stdlib.h>
/************************************/
/* SYSTEM DEPENDENT DEFINITIONS */
/************************************/
/* Note, this program requires an ANSI C compiler */
#define USEPATHS /* comment out if OS does not have file paths */
#define PATHSEP '\\' /* pathname separator, make '/' for UNIX */
#define READMODE "rb" /* open a file in binary (no translation) mode */
#define WRITEMODE "wb" /* open a file for writing in binary mode */
/************************************/
#define BITS7 (0x7f)
#define BG(x) ((x)&0x70)
#define BGBITS (4)
#define NOTBG(x) ((x)&~0x70)
#define FG(x) ((x)&0x7)
#define NOTFG(x) ((x)&~0x7)
#define BRIGHT(x) ((x)&0x8)
#define BFG(x) ((x)&0xf)
#define BLINK(x) ((x)&0x80)
#define TRUE 1
#define FALSE 0
#define MAXCOL 80
#define MAXLINE 24 /* can be made 25 to handle 25 line display emulation
for example */
#define LASTLINE (MAXLINE-1)
#define LASTCOL (MAXCOL-1)
char screen[MAXLINE][MAXCOL];
char scratr[MAXLINE][MAXCOL];
char linatr[MAXLINE]; /* attribute of initialized line */
/* zero means unknown */
char ans2ibm[8] = {0, 4, 2, 6, 1, 5, 3, 7}; /* goes either way! */
char pc8map[256] = {
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c',
'e', 'e', 'e', 'i', 'i', 'i', 'a', 'a', /* 0x80-F */
'E', 'e', 'E', 'o', 'o', 'o', 'u', 'u',
'y', 'O', 'U', 'c', '#', 'Y', 'P', 'F', /* 0x90-F */
'a', 'i', 'o', 'u', 'n', 'N', ' ', ' ',
'?', ' ', ' ', ' ', ' ', '!', '"', '"', /* 0xA0-F */
'*', '*', '*', '|', '|', '|', '|', '+',
'+', '+', '|', '+', '+', '+', '+', '+', /* 0xB0-F */
'+', '+', '+', '+', '-', '+', '+', '+',
'+', '+', '+', '+', '+', '=', '+', '+', /* 0xC0-F */
'+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '*', '*', '*', '*', '*', /* 0xD0-F */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* 0xE0-F */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'o', '.', '.', ' ', ' ', ' ', '*', ' '}; /* 0xF0-F */
int curx, cury; /* cursor position */
int attrib = 7; /* white on black, attribute by the input */
int outattrib = 7; /* current attribute on the output "Device" */
int clsattrib = 7; /* clear screen to ... */
FILE *inf, *outf; /* input and output files */
int wflag=TRUE; /* wrapping enabled on input side */
int pflag=FALSE; /* printer input -- nondescructive space char
and don't overprint underscore! */
int woflag=FALSE; /* output wraps */
int notran=FALSE; /* Don't translate PC-8 to ASCII */
int tabs=FALSE; /* use tabs in output */
int ffeed=TRUE; /* use formfeeds in output */
int avatarin=TRUE; /* AVATAR codes on input */
int racodein=FALSE; /* allow inputting RemoteAccess color codes */
int ansi=FALSE; /* ANSI positioning codes */
int mono=TRUE; /* don't send color codes */
int avatar=FALSE; /* AVATAR positioning codes */
int racode=FALSE; /* RemoteAccess color codes out */
int ch; /* last character read */
#define TABSIZE 8 /* constant, standard tab size */
#if 0
void dump(void) {
/* diagnostic routine to dump virtual display to physical display */
char foo[80];
int x, y;
char far *display = (char far *)0xB8000000L;
for (y=0; y<24; y++) for (x=0; x<80; x++) {
*display++= screen[y][x];
*display++= scratr[y][x];
}
gets(foo); /* pause */
}
#endif
void setattrib(int i) {
/* set attribute from ANSI sequence */
switch (i) {
case 0: attrib=7; return; /* normal */
case 1: attrib |= 8; return; /* bold */
case 2: attrib &= ~8; return; /* unbold */
case 5: attrib |= 128; return; /* blink */
default:
if (i >=30 && i <=37)
attrib = NOTFG(attrib) | ans2ibm[i-30];
else if (i>=40 && i <=47)
attrib = NOTBG(attrib) | (ans2ibm[i-40]<<4);
return;
}
}
void printattrib(int new, char c) {
char wreset[20], woreset[20], buff[20];
int i,j;
/* might not need to do anything */
if (mono || new == outattrib || (c==' '&& BG(new)==BG(outattrib))) return;
if (ansi) { /* send ansi codes */
fputs("\033[", outf);
woreset[0] = '\0';
if ((BLINK(new) || !BLINK(outattrib))&&
(BRIGHT(new) || !BRIGHT(outattrib))) {
/* non-reset a possibility */
if (BRIGHT(new) && !BRIGHT(outattrib)) strcat(woreset, "1;");
/* Terminal emulators don't support un-bright. Too bad!
if (BRIGHT(outattrib) && !BRIGHT(new)) strcat(woreset, "2;"); */
if (BLINK(new) && !BLINK(outattrib)) strcat(woreset, "5;");
if (FG(new) != FG(outattrib)) {
sprintf(buff, "%d;", ans2ibm[FG(new)]+30);
strcat(woreset, buff);
}
if (BG(new) != BG(outattrib)) {
sprintf(buff, "%d;", ans2ibm[BG(new)>>BGBITS]+40);
strcat(woreset, buff);
}
/* delete trailing semicolon */
if ((i=strlen(woreset))>0) woreset[i-1] = '\0';
}
/* calculate string with reset */
strcpy(wreset,"0;");
if (BRIGHT(new)) strcat(wreset, "1;");
if (BLINK(new)) strcat(wreset, "5;");
if (FG(new) != 7) {
sprintf(buff, "%d;", ans2ibm[FG(new)]+30);
strcat(wreset, buff);
}
if (BG(new) != 0) {
sprintf(buff, "%d;", ans2ibm[BG(new)>>BGBITS]+40);
strcat(wreset, buff);
}
/* delete trailing semicolon */
wreset[(i=strlen(wreset))-1] = '\0';
/* output shorter sequence */
j=strlen(woreset);
if (j < i && j > 0) fputs(woreset, outf);
else fputs(wreset, outf);
fputc('m', outf);
}
else if (racode) {
fprintf(outf,"\013[%02x",new);
}
else { /* must be AVATAR */
fprintf(outf,"\026\001%c",new & BITS7);
if (BLINK(new)) fputs("\026\002", outf);
}
outattrib = new;
}
void setpos(int pos, int blanks, int spaceatr, int newattrib, int linatr) {
int method=0;
if (ansi) { /* position cursor or output blanks */
blanks = pos-blanks; /* relative movement */
if (BG(outattrib)==BG(linatr)) { /* line and draw the same */
if (blanks>3) method=1;
}
else { /* line and draw different */
if (BG(spaceatr)==BG(newattrib) && blanks<4) {
printattrib(newattrib, 'X');
}
else if (BG(linatr)==BG(spaceatr)) method = 1;
}
if (method==1) {
fprintf(outf,"\033[%dC",blanks);
}
else {
while (blanks--) fputc(' ', outf);
}
}
else if (avatar) { /* similar but different considerations */
blanks = pos-blanks; /* relative movement */
if (BG(spaceatr)==BG(outattrib)) { /* in current color */
if (blanks<=3) {
while (blanks--) fputc(' ', outf);
}
else fprintf(outf,"\031 %c", blanks);
}
else {
if (blanks <= 4) {
while (blanks--) fputs("\026\006", outf);
}
else {
outattrib = spaceatr&BITS7;
fprintf(outf,"\026\001%c\031 %c", outattrib, blanks);
printattrib(newattrib,'x');
}
}
}
else { /* tabs */
/* fill with tabs or spaces */
if(pos == blanks+1) { /* dont convert single space */
fputc(' ', outf);
blanks = -1;
return;
}
while ((pos/TABSIZE) > (blanks/TABSIZE)) {
fputc('\t', outf);
blanks += TABSIZE - (blanks % TABSIZE);
}
while (pos > blanks) {
fputc(' ', outf);
blanks++;
}
}
}
void initdisplay(void) {
/* initialize contents of virtual display */
memset(screen, ' ', sizeof(screen));
memset(scratr, clsattrib, sizeof(scratr));
memset(linatr, clsattrib, sizeof(linatr));
curx = cury = 0;
}
int linelen(char *line, char *attrib, int linatr) {
/* calculate length of line */
int i;
linatr = BG(linatr);
for (i=LASTCOL; i>=0 && line[i]==' ' && BG(attrib[i])==linatr; i--);
return (i+1);
}
void writeline(char *line, char *attribs, char linatr) {
/* writes line, truncated to output file */
int i = linelen(line,attribs,linatr);
int j, lastattrib, k;
int blanks=-1; /* for tabification */
if (i > 0) {
if (tabs || ansi || avatar || racode) {
/* check for sequences of spaces */
blanks=-1;
for (j=0; j<i; j++) {
/* a space is only a space if we don't change bg colors */
/* we can space on either current (outattrib) or original
(linatr) colors */
if (line[j] == ' '&& !racode &&
(mono ||
(blanks==-1 && (BG(attribs[j])==BG(outattrib) ||
BG(attribs[j])==BG(linatr))) ||
(blanks !=-1 && BG(attribs[j]) == BG(linatr)))) {
if (blanks== -1) blanks = j;
lastattrib=attribs[j];
continue;
}
if (blanks != -1) {
setpos(j, blanks,lastattrib,attribs[j],linatr);
blanks = -1;
}
printattrib(attribs[j], line[j]);
if (avatar) { /* check for repeated characters */
for (k=j; k<i; k++)
if (line[j]!=line[k] || attribs[j]!=attribs[k]) break;
if (k-j > 3) {
fprintf(outf,"\031%c%c", line[j], k-j);
j += (k-j)-1;
continue;
}
}
fputc(line[j],outf);
}
}
else fwrite(line, 1, i, outf);
}
if (i < MAXCOL || !woflag){
/* revert to line default attribute at end of line to avoid problems */
if (BG(outattrib)!=BG(linatr) && (ansi||avatar||racode))
printattrib(BG(linatr)|NOTBG(outattrib), ' ');
fputs("\r\n", outf);
}
}
void writedisplay(void) {
/* write display contents */
int i,j;
/* don't write out empty lines at end of virtual screen */
for (i=LASTLINE; i>=0 && linelen(screen[i],scratr[i],linatr[i]) == 0; i--) ;
for (j=0; j<=i; j++) writeline(screen[j], scratr[j], linatr[j]);
}
void docls(void) {
if (avatar) outattrib=3; /* avatar, alone, resets the display attribute */
if (ansi) fputs("\033[2J", outf);
else if (avatar || ffeed || racode) fputc(12, outf);
initdisplay();
}
void cleardisplay(void) {
/* clear the display -- write contents, send formfeed, initialize */
writedisplay();
docls();
}
void clearpage(void) {
/* as above, but write contents downto, and including, cursor line */
int i;
for (i=0; i<=cury; i++) writeline(screen[i], scratr[i], linatr[i]);
docls();
}
void setposition(int x, int y) {
/* set the pseudocursor position */
curx = max(0, min(x, LASTCOL));
cury = max(0, min(y, LASTLINE));
}
void scrollup(void) {
/* write out first line of virtual screen, then scroll screen up */
writeline(screen[0], scratr[0], linatr[0]);
memmove(screen[0], screen[1], MAXCOL*LASTLINE);
memset(screen[LASTLINE], ' ', MAXCOL);
memmove(scratr[0], scratr[1], MAXCOL*LASTLINE);
memset(scratr[LASTLINE], attrib, MAXCOL); /* current input attribute */
memmove(&linatr[0], &linatr[1], LASTLINE);
linatr[LASTLINE] = attrib;
}
void wrapcheck(void) {
/* check cursor wrap */
if (curx > MAXCOL) {
if (wflag) {
curx=0;
if (cury==LASTLINE) scrollup();
else cury++;
}
else {
curx--;
}
}
}
void insertchar(char c) {
/* insert character at cursor, then move cursor */
int ch = (notran? c : pc8map[(unsigned char)c]);
if ((!pflag) || (ch != ' ' && !(ch == '_' && screen[cury][curx] != ' ')))
screen[cury][curx] = ch;
scratr[cury][curx] = attrib;
curx++;
wrapcheck();
}
char readc(void) {
/* read a character from the input stream */
ch = fgetc(inf);
if (ch == EOF) {
writedisplay();
/* force normal state for ansi or avatar */
if (ansi || avatar) printattrib(ansi?7:3, 'x');
exit(0);
}
return ch;
}
void usage(char *s) {
fprintf(stderr,
"Usage: %s [in [out]] [-p] [-s] [-cN] [-i] [-r]\n"
" [-x] [-f] [-w] [-t|-a|-m|-v|-o]\n"
" in -- input file, default is read from stdin (keyboard)\n"
" out -- output file, default is write to stdout (display)\n"
" -p -- input is for printer\n"
" -s -- input assumes cursor sticks at right edge\n"
" -cN -- initial color attribute is N (hexidecimal value)\n"
" -i -- ignore AVATAR codes in input\n"
" -r -- accept RemoteAccess color codes in input\n"
" -x -- don't translate PC-8 to ASCII\n"
" -f -- don't output formfeeds\n"
" -w -- output wraps after 80 characters\n"
" -t -- use tab characters in output\n"
" -o -- output RemoteAccess color codes\n"
" -a -- output ANSI positioning codes and color codes\n"
" -m -- output ANSI positioning codes only\n"
" -v -- output AVATAR codes\n", s);
exit(1);
}
/* ANSI state machine states */
#define START 0
#define STARTARG 1
#define INNUM 2
#define FINNUM 3
#define DOCMD 4
void ansisequence(void) {
/* handle ANSI.SYS escape sequences */
/* Will parse only to extent necessary for this program. */
static int savex=0, savey=0;
int state = START;
int args[10]; /* extra sure */
int argnum = 0;
int i;
for (i=0; i<10; i++) args[i]=1; /* default values */
readc(); /* prime pump */
while (TRUE) switch (state) {
case START:
if (ch != '[') return; /* No telling what this is */
while (readc() == '?' || ch == '='); /* toss flag chars */
state = STARTARG;
/* break; */
case STARTARG:
if (ch == ';') { /* default argument */
argnum = min(9, argnum+1);
readc();
break;
}
if (ch>='0' && ch<='9') { /* number */
state = INNUM;
break;
}
if (ch=='\'' || ch == '\"') { /* string -- parse and ignore*/
i = ch;
while (readc() != i);
readc();
state = FINNUM;
break;
}
state = DOCMD; /* reached end */
break;
case INNUM:
args[argnum] = 0;
do {
args[argnum] = args[argnum]*10 + ch - '0';
} while (readc() >= '0' && ch <= '9');
argnum = min(9, argnum+1);
state = FINNUM;
/* break; */
case FINNUM:
if (ch == ';') { /* more to come */
readc();
state = STARTARG;
break;
}
state = DOCMD;
/* break; */
case DOCMD:
switch (ch) {
case 'H': /* cursor position */
case 'f':
cury = max(0, min(LASTLINE, args[0]-1));
curx = max(0, min(LASTCOL, args[1]-1));
break;
case 'A': /* cursor up */
cury = max(0, cury-args[0]);
break;
case 'B': /* cursor down */
cury = min(LASTLINE, cury+args[0]);
break;
case 'C': /* cursor forward */
curx = min(LASTCOL, curx+args[0]);
break;
case 'D': /* cursor back */
curx = max(0, curx-args[0]);
break;
case 's': /* cursor save */
savex = curx;
savey = cury;
break;
case 'u': /* cursor restore */
curx = savex;
cury = savey;
break;
case 'J': /* erase display -- we will ignore argument */
clsattrib=attrib;/* clears to color of current attribute*/
cleardisplay();
break;
case 'K': /* erase line -- we will ignore argument */
memset(&screen[cury][curx],' ', LASTCOL-curx);
memset(&scratr[cury][curx],attrib, LASTCOL-curx);
break;
case 'h': /* set mode -- only look at line wrap */
if (args[0]==7) wflag = TRUE;
break;
case 'l': /* reset mode -- only look at line wrap */
if (args[0]==7) wflag = FALSE;
break;
case 'm': /* set color */
for (i=0; i<argnum; i++) {
setattrib(args[i]);
}
break;
/* all other commands are ignored completely */
}
return; /* finished with ANSI sequence */
}
}
void avatarsequence(void) {
/* handle avatar control-V sequences on input */
readc();
switch(ch) {
case 1: /* attribute set */
readc();
attrib = ch & BITS7;
break;
case 2: /* blink */
attrib |= 0x80;
break;
case 3: /* move up */
cury = max(0, cury-1);
break;
case 4: /* move down */
cury = min(LASTLINE, cury+1);
break;
case 5: /* move left */
curx = max(0, curx-1);
break;
case 6: /* move right */
curx = min(LASTCOL, curx+1);
break;
case 7: /* clear to end of line */
memset(&screen[cury][curx],' ', LASTCOL-curx);
memset(&scratr[cury][curx],attrib, LASTCOL-curx);
break;
case 8: /* move cursor row col */
readc();
cury = max(0, min(LASTLINE, ch));
readc();
curx = max(0, min(LASTCOL, ch));
break;
}
}
void main(int argc, char **argv) {
char *progname = *argv++;
char *s;
int i;
#ifdef USEPATHS
if ((s=strrchr(progname, PATHSEP)) != NULL) {
/* simplify program name */
progname = s+1;
}
if ((s=strrchr(progname, '.')) != NULL) {
*s = 0; /* get rid of extension */
}
#endif
fprintf(stderr,
"REANSI 1.2: ANSI/AVATAR/PC-8/ASCII conversion program.\n"
"Copyright 1995 by Thomas Almy. All rights reserved.\n"
"Run %s -? for help.\n\n", progname);
argc--;
if (argc > 0 && **argv != '-') {
/* must be input file name */
if ((inf = fopen(*argv, READMODE)) == NULL) {
fprintf(stderr,"%s: Cannot open input file %s.", progname, *argv);
exit(1);
}
argv++;
argc--;
}
else {
inf = stdin;
setmode(fileno(inf), O_BINARY); /* force binary mode */
}
if (argc > 0 && **argv != '-') {
/* must be output file name */
if ((outf = fopen(*argv, WRITEMODE)) == NULL) {
fprintf(stderr,"%s: Cannot open output file %s.",progname, *argv);
exit(1);
}
argv++;
argc--;
}
else {
outf = stdout;
setmode(fileno(outf), O_BINARY);
}
while (argc-- > 0) {
if (**argv == '-' && strlen(*argv) >=2 && (*argv)[1]=='c') {
if (sscanf((*argv)+2, "%x", &attrib) != 1 || attrib<0 || attrib>255){
fprintf(stderr, "%s: Invalid color attribute %s\n",progname, (*argv)+2);
usage(progname);
}
outattrib = attrib;
argv++;
continue;
}
if (**argv != '-' || strlen(*argv) != 2) {
fprintf(stderr,"%s: Unrecognized argument %s\n",progname, *argv);
usage(progname);
}
switch ((*argv)[1]) {
case 'p': pflag=TRUE; break;
case 's': wflag=FALSE; break;
case 't': tabs=TRUE; break;
case 'w': woflag=TRUE; break;
case 'x': notran=TRUE; break;
case 'f': ffeed=FALSE; break;
case 'i': avatarin=FALSE; break;
case 'r': racodein=TRUE; break;
case 'a': ansi=TRUE; racode=mono=avatar=FALSE; break;
case 'v': avatar=TRUE; racode=mono=ansi=FALSE; break;
case 'm': mono=ansi=TRUE; racode=avatar=FALSE; break;
case 'o': racode=TRUE; mono=ansi=avatar=FALSE; break;
case '?': usage(progname); break;
default:
fprintf(stderr,"%s: Unrecognized switch %s\n",progname, *argv);
usage(progname);
break;
}
argv++;
}
initdisplay();
while(TRUE) switch (readc()) {
case 8: /* backspace */
curx = max(0, curx-1);
break;
case 9: /* tab */
curx = (curx+8) & -8;
wrapcheck();
break;
case 10: /* linefeed */
if (cury==LASTLINE) scrollup();
else cury++;
break;
case 11: /* RA codes */
if (racodein) {
readc();
if (ch=='[') {
char buf[3];
readc();
buf[0]=ch;
readc();
buf[1]=ch;
buf[2]=0;
sscanf(buf,"%x",&attrib);
break;
}
insertchar(11); /* not a match -- insert into buffer */
}
insertchar(ch);
break;
case 12: /* formfeed */
if (avatarin) clsattrib=3; /* clear to AVATAR color */
clearpage();
break;
case 13: /* carriage return */
curx = 0;
break;
case 22: /* avatar commands */
if (avatarin) avatarsequence();
else insertchar(ch);
break;
case 25: /* AVATAR RLE */
if (avatarin) {
readc(); /* get count */
i = ch;
readc(); /* get character to repeat */
while (ch-- > 0) insertchar(i);
}
else insertchar(ch);
break;
case 26: /* Control-Z gets ignored */
break;
case 27: /* escape sequence */
ansisequence();
break;
default:
insertchar(ch);
break;
}
}