home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
tools
/
pep
/
ansi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-28
|
9KB
|
277 lines
/* 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 */