|
|
researchv10 Norman
/*
* hp [-e] [-m]
* convert nroff TTY37 output to right form for HP2640x terminals.
* -e indicates enhanced terminal with underline, etc.
* -m requests minimization of output by removing multiple newlines
*/
char hpvers[] = "@(#)hp.c 1.6";
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sgtty.h>
#define ESC 033 /* escape */
#define HFWD '9'
#define HREV '8'
#define FREV '7'
#define SO 016 /* shift out - enter greek */
#define SI 017 /* shift in */
#define LF '\n'
#define CR 015
#define NFLAG 0200 /* hi-bit flag for non-showing chars */
#define NMASK 0177
#define AMP 046 /* & */
#define DEE 0144 /* d */
#define BFSIZ 4096 /* size of output buffer */
/* (bigger because of tbl weirds */
/* and nroff idiosyncracies */
/* puty adds control char to output, marked by hi-bit */
#define puty(c) putx(c|NFLAG)
#define flg(x) ((char)(x|NFLAG)) /* set hi-bit of x */
int nlcnt, /* accumulated newline count */
frevcnt, /* accumulated reverse line-feeds */
halfpos, /* half-line position: -1 = above, +1 = below */
restrict = 1, /* 0==> full terminal, 1==> no display enhancements */
minimiz; /* 0==> normal, 1==> remove extra newlines */
char *ttydev;
int svstmode; /* for mesg restore */
int restore();
char *ttyname();
int svsgflgs;
struct sgttyb sgb;
int retcode = 2; /* return code */
char peekbuf[2];
char *peekstr = peekbuf; /* lookahead ptr */
char outbf[BFSIZ]; /* output assembly buffer */
char *bfnext = outbf, /* addr of next empty byte */
*bflast = &outbf[BFSIZ-1]; /* addr of last usable byte */
/* normal display enhancement strings */
char *enunder = "\033&dD", /* underline */
*ennorml = "\033&d@", /* normal output */
*ensuper = "\033&dH", /* superscript (half) */
*ensubsc = "\033&dL", /* subscript (half, underlined */
*enrestr = "\033&dB"; /* restricted (inverse only) */
int restore();
main(argc, argv)
char **argv;
{
register c;
scanarg(argc,argv);
if (((int)signal(SIGINT, SIG_IGN) & 01) == 0)
signal(SIGINT, restore);
if (gtty(1, &sgb) == 0)
fixtty();
setbuf(stdin, calloc(BUFSIZ,1));
while((c = getchal()) != EOF) {
if (nlcnt && c != LF) flushnl();
if (frevcnt && c != ESC) flushrv();
if (c == LF) {
if (++nlcnt == 1) flushln();
continue;
}
if (c == ESC)
escape();
else if (c == SO)
special();
else if (c == '\b')
backsp();
else if (c == '_') { /* C nroff */
if ((c = getchal()) == '\b') {
undersc();
} else {
putx('_');
peekbuf[0] = c;
peekstr = peekbuf;
}
}
else
putx(c);
}
flusher();
retcode = 0;
restore();
}
getchal()
{
if (*peekstr)
return(*peekstr++);
return(getchar());
}
/* scanarg: scan arguments and set flags; ignore unknown args */
scanarg(argc,argv)
int argc; char **argv;
{
register char *p;
while ( --argc > 0) {
p = *++argv;
if (*p == '-') {
++p;
if (*p == 'e') restrict = 0;
else if (*p == 'm') minimiz = 1;
}
}
if (restrict)
enunder = ensuper = ensubsc = enrestr;
}
/* fixtty: get tty status and save; remove delay and CR-LF mapping */
fixtty()
{
struct stat sb;
svsgflgs = sgb.sg_flags;
sgb.sg_flags &= ~(ALLDELAY|CRMOD);
stty(1, &sgb); /* stty nl nl0 cr0 tab0 ff0 */
fstat(1, &sb);
svstmode = sb.st_mode;
ttydev = ttyname(1);
if (ttydev && *ttydev)
chmod(ttydev, 0600); /* mesg n */
}
/* flusher: flush accumulated newlines, reverse line feeds, buffer */
flusher()
{
flushln();
if (nlcnt) flushnl();
if (frevcnt) flushrv();
fflush(stdout);
}
/* flushrv: flush accumulated reverse line feeds */
flushrv()
{
while (frevcnt--)
putstr("\033T");
putstr(ennorml);
frevcnt = 0;
}
/* flushnl: flush accumulated newlines (count in nlcnt) */
flushnl()
{
if (minimiz != 0 && nlcnt > 2) nlcnt = 2;
putchar(CR);
while (nlcnt--)
putchar(LF);
nlcnt = 0;
}
putstr(p)
char *p;
{
register char *pp;
pp = p;
while (*pp) puty(*pp++);
}
restore(){
if (isatty(1)) {
sgb.sg_flags = svsgflgs;
stty(1, &sgb);
if (ttydev && *ttydev)
chmod(ttydev, svstmode);
}
exit(retcode);
}
char tab[] = {
'A','A', /* alpha */
'B','B', /* beta */
'D','W', /* delta */
'W','V', /* DELTA */
'S','E', /* epsilon */
'N','H', /* eta */
'\\','Q', /* gamma */
'G','+', /* GAMMA */
'o','<', /* infinity - not in M37 */
'^','\'', /* integral */
'L','G', /* lambda */
'E',';', /* LAMBDA */
'M','M', /* mu */
'[','$', /* nabla (del) */
'_','\\', /* not */
'@','N', /* nu */
'C','L', /* omega */
'Z',':', /* OMEGA */
']','F', /* partial */
'U','D', /* phi */
'F','.', /* PHI */
'V','C', /* psi */
'H',',', /* PSI */
'J','P', /* pi */
'P','*', /* PI */
'K','O', /* rho */
'Y','S', /* sigma */
'R','?', /* SIGMA */
'I','T', /* tau */
'T','R', /* theta */
'O','J', /* THETA */
'X','U', /* xi */
'Q','Z', /* zeta */
'v','Y',
0
};
char spec1[] = {LF,SO,0};
special(){
register int c;
register char *p;
puty(SO);
while ((c = getchal()) != EOF) {
if (c == SI) {
puty(c);
return;
}
if (c == LF) {
peekstr = spec1;
return;
}
for (p = tab; *p != 0; p += 2)
if (c == *p) {
c = *++p;
break;
}
putx(c);
}
}
/* escape: handle escape sequences */
escape()
{
register int c;
c = getchal();
if (frevcnt && c != FREV) flushrv();
switch (c) {
case FREV:
frevcnt++;
break;
case HREV:
if (halfpos == 0) {
putstr(ensuper);
halfpos--;
}
else if (halfpos > 0) {
putstr(ennorml);
halfpos--;
}
else {
putstr("\033T"); /* roll back 1 */
putstr(ennorml);
halfpos = 0;
}
break;
case HFWD:
if (halfpos == 0) {
putstr(ensubsc);
halfpos++;
}
else if (halfpos < 0) {
putstr(ennorml);
halfpos++;
}
else {
putstr("\033S"); /* roll up 1, i.e., LF w/o CR */
putstr(ennorml);
halfpos = 0;
}
break;
case '&':
putstr("\033&");
puty(c = getchal());
if (c == 'd') puty(getchal());
break;
case ')':
putstr("\033)");
puty(getchal());
break;
default:
puty(ESC);
puty(getchal());
break;
}
}
char peeku[3];
/* backsp: handle backspacing */
/* sequences are handled such that : ( \b is backspace ) */
/* a\b_ -> a in inverse video */
/* _\ba -> a in inverse video */
/* c\bd -> c in inverse video */
/* if a control char (ESC) precedes or follows '\b' */
/* then an actual backspace movement is performed */
backsp()
{
register char *bftmp;
register int c;
char *bfhi;
int i, j, ncnt, bscnt;
char *p, *p1;
p = bfnext-2;
p1 = bfnext-4;
/* check if last char put in buffer was escape sequence */
/* if so, put backspace control sequence in buffer */
/* check against "\033&d" */
if ((*p == flg(ESC)) ||
(*p1++ == flg(ESC) && *p1++==flg(AMP) && *p1==flg(DEE))) {
putstr("\033D");
while((c=getchal())=='\b') putstr("\033D");
/* put last char back */
peeku[0] = c;
peeku[1] = '\0';
peekstr = peeku;
return;
}
bscnt = 1;
c = getchal();
/* count backspaces */
while (c == '\b') {
bscnt++;
c = getchal();
}
/* read in chars until bscnt have been read */
/* or until an ESC is read */
ncnt = 0;
if (c!=ESC) {
for (ncnt=0; (ncnt<bscnt && c!=ESC); ncnt++)
c = getchal();
/* since there were normal chars with backsp */
/* insert inverse video chars in buffer */
bftmp = bfhi = bfnext + 4;
for (i=0; i<bscnt;)
if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++;
putstr(enunder);
bfnext = bfhi;
}
/* if number of bcksp is not = to number normal chars */
/* then some bcksp chars will be inserted as actual */
/* bcksp movement and not inverse video for another char */
j = bscnt - ncnt;
if (j == 0) putstr(ennorml);
else {
/* move chars over and insert normal char seq */
if (ncnt > 0) {
bftmp = bfhi = bfnext + 4;
for (i=0; i<j;)
if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++;
putstr(ennorml);
bfnext = bfhi;
}
/* insert backspace movement chars */
while (j--) putstr("\033D");
}
/* put last char read back */
peeku[0] = c;
peeku[1] = '\0';
peekstr = peeku;
}
/* undersc: handle C nroff's (_ BS char)+ sequences
* assumes _ BS already found
* if char is a control char, put char back and break.
*/
undersc()
{
register char c;
putstr(enunder);
while (1) {
if ((c=getchal())==ESC) {
peeku[0] = c; peeku[1] = '\0';
peekstr = peeku;
break;
}
else
putx(c);
if ((c = getchal()) != '_') {
peeku[0] = c; peeku[1] = '\0';
peekstr = peeku;
break;
}
if ((c = getchal()) != '\b') {
peeku[0] = '_'; peeku[1] = c;
peekstr = peeku;
break;
}
}
putstr(ennorml);
}
/* flushln: flush out accumulated line */
flushln()
{
register char c, *p;
putx('\0');
p = outbf;
while (c = (*p++ & NMASK)) putchar(c);
bfnext = outbf;
}
/* putx: add normal (printing) char to output */
putx(c)
char c;
{
if (bfnext <= bflast)
*bfnext++ = c;
else die("line too long\n");
}
die(mesg)
char *mesg;
{
register char *p;
char *c = "hp: ";
write(2, c, 4);
p = mesg;
while (*p)
write(2, p++, 1);
restore();
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.