home *** CD-ROM | disk | FTP | other *** search
- /* ansi.c 1989 december 10 [gh]
- +-----------------------------------------------------------------------------
- | Abstract:
- | Ansi terminal interpreter.
- |
- | Authorship:
- | Copyright (c) 1988, 1989 Gisle Hannemyr.
- | Permission is granted to hack, make and distribute copies of this module
- | as long as this notice and the copyright notices are not removed.
- | If you intend to distribute changed versions of this module, please make
- | an entry in the "history" log (below) and mark the hacked lines with your
- | initials. I maintain the module, and shall appreiciate copies of bug
- | fixes and new versions.
- | Flames, bug reports, comments and improvements to:
- | snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway
- | email: X400: gisle@nr.uninett
- | RFC: gisle@ifi.uio.no
- | (and several BBS mailboxes in the Oslo area).
- |
- | Access programs:
- | void doansi() : Interprete one file.
- |
- | History:
- | 4 jun 89 [gh] Latest update.
- |
- | Bugs:
- | * Currently, highlighting etc. in ANSI sequences is removed. It might be
- | fun to translate the lot into Postscript.
- | * Not all ANSI sequences are implemented so far. It should cover
- | ANSI.SYS, but some exotic stuff are left out, as well as the NANSI.SYS
- | extensions. All unknown sequences produces an error message. Users
- | who can explain the exact sematics of such sequences are encouraged
- | to contact author.
- |
- | See main module for more comments.
- +---------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include "pep.h"
- #include <ctype.h>
-
-
- /*---( defines )------------------------------------------------------------*/
-
- #define MAXPAR 3 /* Max no. of ANSI param's to store */
- #define MAXX 80 /* ANSI terminal screen width */
- #define MAXY 25 /* ANSI terminal screen height */
-
- /*---( variables )----------------------------------------------------------*/
-
- static unsigned char Screen[MAXX][MAXY]; /* Output ANSI terminal screen */
- static int GuardL; /* ANSI overwrite guard level */
- static int LineYy = 0; /* ANSI terminal cursor pos. */
-
-
- /*---( housekeeping )-------------------------------------------------------*/
-
- /*
- | Abs: Display ansi warning message.
- */
- static void amess(err,cc)
- int err, cc;
- {
- fprintf(stderr,"\ransi (%ld): ",LCount);
- switch(err) {
- case 1: fprintf(stderr,"exepected 5bh (got <%02xh>)",cc); break;
- case 2: fprintf(stderr,"unknown ANSI command <%02xh>",cc); break;
- case 3: fprintf(stderr,"unknown control code <%02xh>",cc); break;
- case 4: fputs("X right of screen edge", stderr); break;
- case 5: fputs("X left of screen edge", stderr); break;
- case 6: fputs("Y above screen edge", stderr); break;
- case 7: fputs("auto line wrap (warning)", stderr); break;
- case 8: fputs("cursor outside screen", stderr); break;
- default: fputs("unknown error", stderr); break;
- } /* switch */
- putc('\n',stderr);
- } /* amess */
-
-
- /*---( ansi emulation )-----------------------------------------------------*/
-
- /*
- | Abs: Erase entire screen and send cursor home.
- */
- static void clearscreen()
- {
- int xx, yy;
-
- for (xx = 0; xx < MAXX; xx++) for (yy = 0; yy < MAXY; yy++)
- Screen[xx][yy] = ' ';
- LineXx = 0;
- LineYy = 0;
- } /* clearscreen */
-
-
- static void docrlf()
- {
- if (EndOLn == -1) { putc('\r',Fdo); putc('\n',Fdo); }
- else if (EndOLn != -2) putc(EndOLn,Fdo);
- } /* docrlf */
-
-
- /*
- | Abs: Print a horizontal line,
- */
- static void horline()
- {
- int xx;
- for (xx = 0; xx < (MAXX-1); xx++) putc('=',Fdo); docrlf();
- } /* horline */
-
-
- /*
- | Abs: Print screen image.
- */
- static void printscreen(frame)
- int frame;
- {
- int xx, yy;
- static int oldframe = FALSE;
-
- if (oldframe) horline();
- for (yy = 0; yy < MAXY; yy++) {
- xx = MAXX-1;
- while ((xx) && (Screen[xx][yy] == ' ')) { Screen[xx][yy] = '\0'; xx--; }
- xx = 0;
- while (Screen[xx][yy]) { putc(Screen[xx][yy],Fdo); xx++; }
- docrlf();
- showprogress();
- }
- if (oldframe) horline();
- oldframe = frame;
- clearscreen();
- } /* printscreen */
-
-
- static void pputc(cc)
- char cc;
- {
- if (LineXx >= MAXX) {
- LineXx = 0; LineYy++;
- amess(7); /* auto line wrap (warning) */
- } else if ((LineXx < 0) || (LineYy >= MAXY) || (LineYy < 0)) {
- amess(8); /* cursor outside screen */
- printscreen(FALSE);
- }
- switch (GuardL) {
- case 2: if (Screen[LineXx][LineYy] != ' ') break;
- case 1: if (cc == ' ') break;
- case 0: Screen[LineXx][LineYy] = cc;
- }
- LineXx++;
- } /* pputc */
-
-
- /*
- | Abs: Interprete ANSI command after ESC CSI.
- */
- static void esccsi()
- {
- int ii, jj, cc, dd;
- int pp[MAXPAR];
- static int oldxx, oldyy;
-
- for (ii = 0; ii < MAXPAR; ii++) pp[ii] = 0; dd = ii = 0;
- while ((cc = getc(Fdi)) != EOF) {
- if (isdigit(cc)) { pp[ii] = pp[ii] * 10 + cc - '0'; dd++; }
- else if (cc == ';') {
- if (!dd) pp[ii] = 1; /* default to 1 */
- dd = 0;
- if (ii < MAXPAR-1) ii++;
- }
- else break;
- }
- if (dd) ii++; /* We've one parameter that's not terminated */
- for (jj = ii; jj < MAXPAR; jj++) pp[jj] = 1; /* Default */
- /* Exotic stuff we do not attempt to interprete *
- | case 'h': break; /* + SM -- set mode *
- | case 'l': break; /* + RM -- reset mode *
- | case 'p': break; /* + KKR -- keyboard key reassign *
- | case 'R': break; /* + CPR -- cursor position rep. *
- |
- | NANSI stuff for future implementation *
- | case '@': /* ICH -- insert characters *
- | case 'L': /* IL -- insert lines *
- | case 'M': /* DL -- delete lines *
- | case 'P': /* DCH -- delete characters *
- | case 'y': /* OCT -- output chr. translate *
- */
- switch (cc) {
- case 'A': /* + CUU -- cursor up */
- LineYy -= pp[0];
- if (LineYy < 0) { amess(6); LineYy = 0; } /* Y above screen edge */
- break;
- case 'B': /* + CUD -- cursor down */
- LineYy += pp[0];
- if (LineYy >= MAXY) printscreen(FALSE);
- break;
- case 'C': /* + CUF -- cursor forward */
- LineXx += pp[0];
- if (LineXx >= MAXX) { amess(4); LineXx = MAXX - 1; } /* X right of screen */
- break;
- case 'D': /* + CUB -- cursor backward */
- LineXx -= pp[0];
- if (LineXx < 0) { amess(5); LineXx = 0; } /* X left of screen edge */
- break;
- case 'H': /* + CUP -- cursor position */
- LineXx = pp[1] - 1; LineYy = pp[0] -1;
- break;
- case 'J': /* + ED -- erase display */
- if (pp[0] == 2) printscreen(TRUE);
- else { amess(2,cc); pputc(cc); } /* unknown ANSI command */
- break;
- case 'K': /* + EL -- erase in line */
- if (!GuardL) while (LineXx < MAXX) Screen[LineXx++][LineYy] = ' ';
- break;
- case 'f': /* HVP -- cursor position */
- LineXx = pp[1] - 1; LineYy = pp[0] - 1;
- break;
- case 'n': /* + DSR -- device staus report */
- break;
- case 'm': /* + SGR -- set graphic rendition */
- break;
- case 's': /* + SCP -- save cursor position */
- oldxx = LineXx;
- oldyy = LineYy;
- break;
- case 'u': /* + RCP -- restore cursor pos. */
- LineXx = oldxx;
- LineYy = oldyy;
- break;
- default: amess(2,cc); pputc(cc); /* unknown ANSI command */
- } /* switch */
- /*
- if (hack) {
- printf("CSI: ");
- for (jj = 0; jj < ii; jj++) printf("%d;",pp[jj]);
- printf("%c\n",cc);
- }
- */
- } /* esccsi */
-
-
- /*---( file loop )----------------------------------------------------------*/
-
- /*
- | Abs: Read (and write) one complete ANSI-file.
- | Par: guardl = ANSI overwrite guard level.
- */
- void doansi(guardl)
- int guardl;
- {
- int cc;
-
- GuardL = guardl;
- clearscreen();
- while ((cc = getc(Fdi)) != EOF) {
- if ((cc >= 0x20) && (cc <= 0xff)) pputc(cc);
- else if (cc == 0x07) ; /* BELL */
- else if (cc == '\b') { /* BS */
- LineXx--;
- if (LineXx < 0) { amess(5); LineXx = 0; } /* X left of screen edge */
- }
- else if (cc == '\t') LineXx = (LineXx / ITabSz + 1) * ITabSz;
- else if (cc == '\n') { LineYy++; if (LineYy >= MAXY) printscreen(FALSE); }
- else if (cc == '\r') LineXx = 0;
- else if (cc == 0x1b) { /* ESC */
- cc = getc(Fdi);
- if (cc == 0x5b) esccsi(); else amess(1,cc); /* exepected 5bh */
- }
- else amess(3,cc); /* unknown control code */
- } /* while */
- printscreen(FALSE);
- } /* doansi */
-
- /* EOF */
-