/* ** DOANSI_1.C - Portable ANSI screen code interpreter ** ** From DRSK_105.LZH (ansi.c), hereby declared free for use for whatever ** purposes by author: Mark Kimes */ #include #include #include #include "doansi.h" /* * to initialize: * call set_screensize(<# lines to reserve>); * to print through ansi interpreter: * call ansi_out(); */ char curattr = 7; int curx = 0,cury = 0; int maxx = 80, maxy = 25; /* size of ansi output window */ int realmaxy,realmaxx; /* real screen size */ char useansi = 1; /* while true, interp ansi seqs */ int tabspaces = 8; static int savx,savy,issaved = 0; static char ansi_terminators[] = "HFABCDnsuJKmp"; #define MAXARGLEN 128 #define NOTHING 0 #define WASESCAPE 1 #define WASBRKT 2 /* "generic" support functions closely related to ansi_out */ void set_pos (char *argbuf,int arglen,char cmd) { int y,x; char *p; if (!*argbuf || !arglen) { curx = cury = 0; } y = atoi(argbuf) - 1; p = strchr(argbuf,';'); if (y >= 0 && p) { x = atoi(p + 1) - 1; if(x >= 0) { curx = x; cury = y; } } } void go_up (char *argbuf,int arglen,char cmd) { int x; x = atoi(argbuf); if (!x) x = 1; for ( ; x ; x--) { if (!cury) break; cury--; } } void go_down (char *argbuf,int arglen,char cmd) { int x; x = atoi(argbuf); if (!x) x = 1; for ( ; x ; x--) { if (cury == maxy - 1) break; cury++; } } void go_left (char *argbuf,int arglen,char cmd) { int x; x = atoi(argbuf); if (!x) x = 1; for ( ; x ; x--) { if(!curx) break; curx--; } } void go_right (char *argbuf,int arglen,char cmd) { int x; x = atoi(argbuf); if (!x) x = 1; for ( ; x ; x--) { if (curx == maxx - 1) break; curx++; } } void report (char *argbuf,int arglen,char cmd) { /* you figure out how to implement it ... */ } void save_pos (char *argbuf,int arglen,char cmd) { savx = curx; savy = cury; issaved = 1; } void restore_pos (char *argbuf,int arglen,char cmd) { if(issaved) { curx = savx; cury = savy; issaved = 0; } } void clear_screen (char *argbuf,int arglen,char cmd) { /* needs error checking */ clearwindow(0,0,maxx - 1,maxy - 1,curattr); curx = cury = 0; } void kill_line (char *argbuf,int arglen,char cmd) { cleartoeol(curx,cury,maxx - 1,curattr); } void set_colors (char *argbuf,int arglen,char cmd) { char *p,*pp; if (*argbuf && arglen) { pp = argbuf; do { p = strchr(pp,';'); if (p && *p) { *p = 0; p++; } switch (atoi(pp)) { case 0: /* all attributes off */ curattr = 7; break; case 1: /* bright on */ curattr |= 8; break; case 2: /* faint on */ curattr &= (~8); break; case 3: /* italic on */ break; case 5: /* blink on */ curattr |= 128; break; case 6: /* rapid blink on */ break; case 7: /* reverse video on */ curattr = 112; break; case 8: /* concealed on */ curattr = 0; break; case 30: /* black fg */ curattr &= (~7); break; case 31: /* red fg */ curattr &= (~7); curattr |= 4; break; case 32: /* green fg */ curattr &= (~7); curattr |= 2; break; case 33: /* yellow fg */ curattr &= (~7); curattr |= 6; break; case 34: /* blue fg */ curattr &= (~7); curattr |= 1; break; case 35: /* magenta fg */ curattr &= (~7); curattr |= 5; break; case 36: /* cyan fg */ curattr &= (~7); curattr |= 3; break; case 37: /* white fg */ curattr |= 7; break; case 40: /* black bg */ curattr &= (~112); break; case 41: /* red bg */ curattr &= (~112); curattr |= (4 << 4); break; case 42: /* green bg */ curattr &= (~112); curattr |= (2 << 4); break; case 43: /* yellow bg */ curattr &= (~112); curattr |= (6 << 4); break; case 44: /* blue bg */ curattr &= (~112); curattr |= (1 << 4); break; case 45: /* magenta bg */ curattr &= (~112); curattr |= (5 << 4); break; case 46: /* cyan bg */ curattr &= (~112); curattr |= (3 << 4); break; case 47: /* white bg */ curattr |= 112; break; case 48: /* subscript bg */ break; case 49: /* superscript bg */ break; default: /* unsupported */ break; } pp = p; } while (p); } } int ansi_out (char *buf) { int arglen = 0, ansistate = NOTHING, x; char *b = buf, argbuf[MAXARGLEN] = ""; /* cursor is off while string is being displayed so we don't have to keep updating it. works to our detriment only if using BIOS writes under MS-DOS */ hardcursor_off(); if (!useansi) /* is ANSI interp on? */ { ansistate = NOTHING; arglen = 0; *argbuf = 0; } while (*b) { switch (ansistate) { case NOTHING: switch (*b) { case '\x1b': if (useansi) { ansistate = WASESCAPE; break; } case '\r': curx = 0; break; case '\n': cury++; if (cury > maxy - 1) { scroll_up(0,0,maxx - 1,maxy - 1,curattr); cury--; } break; case '\t': /* so _you_ figure out what to do... */ for (x = 0; x < tabspaces; x++) { put_char(' ',curattr,curx,cury); curx++; if (curx > maxx - 1) { curx = 0; cury++; if (cury > maxy - 1) { scroll_up(0, 0, maxx - 1, maxy - 1, curattr); cury--; } } } break; case '\b': if (curx) { curx--; } break; case '\07': /* usually a console bell */ putchar('\07'); break; default: put_char(*b,curattr,curx,cury); curx++; if (curx > maxx - 1) { curx = 0; cury++; if (cury > maxy - 1) { scroll_up(0,0,maxx - 1,maxy - 1,curattr); cury--; } } break; } break; case WASESCAPE: if (*b == '[') { ansistate = WASBRKT; arglen = 0; *argbuf = 0; break; } ansistate = NOTHING; break; case WASBRKT: if (strchr(ansi_terminators, (int)*b)) { switch ((int)*b) { case 'H': /* set cursor position */ case 'F': set_pos(argbuf,arglen,*b); break; case 'A': /* up */ go_up(argbuf,arglen,*b); break; case 'B': /* down */ go_down(argbuf,arglen,*b); break; case 'C': /* right */ go_right(argbuf,arglen,*b); break; case 'D': /* left */ go_left(argbuf,arglen,*b); break; case 'n': /* report pos */ report(argbuf,arglen,*b); break; case 's': /* save pos */ save_pos(argbuf,arglen,*b); break; case 'u': /* restore pos */ restore_pos(argbuf,arglen,*b); break; case 'J': /* clear screen */ clear_screen(argbuf,arglen,*b); break; case 'K': /* delete to eol */ kill_line(argbuf,arglen,*b); break; case 'm': /* set video attribs */ set_colors(argbuf,arglen,*b); break; case 'p': /* keyboard redef -- disallowed */ break; default: /* unsupported */ break; } ansistate = NOTHING; arglen = 0; *argbuf = 0; } else { if (arglen < MAXARGLEN) { argbuf[arglen] = *b; argbuf[arglen + 1] = 0; arglen++; } } break; default: pos_hardcursor(curx,cury); fputs("\n **Error in ANSI state machine.\n",stderr); break; } b++; } pos_hardcursor(curx,cury); hardcursor_on(curx,cury); return ((int)b - (int)buf); }