home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * ibmpr [-p]
- * convert nroff TTY37 output to right form for IBM-PC terminals.
- * -p indicates hard copy desired
- * -i output ITALICS for 'underlines' (EPSON w/GRAFTRAX)
- */
-
-
- #include <stdio.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "sys/ioctl.h"
- #include "termio.h"
- #define ESC 033 /* escape */
- #define HFWD '9'
- #define HREV '8'
- #define FREV '7'
- #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 ATSIGN 0100 /* @ */
- #define BFSIZ 1024 /* size of output buffer (bigger because of tbl weirds
- and nroff idiosyncracies */
- #define ALLDELAY 0177400 /* all delay bits in termio.c_oflag */
-
- /* 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 = 0, /* 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 termio 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 */
- *enbold = "\033&dB"; /* BOLD (inverse only) */
-
- int restore();
- main(argc, argv)
- char **argv;
- {
- register c;
- scanarg(argc,argv);
- signal(SIGINT, restore);
- signal(SIGQUIT, restore);
- if (ioctl(1, TCGETA, &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 == '\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 == 'p') {
- if (p[1] == 0) printf("\033P1");
- if (p[1] == 'c') printf("\033P2");
- }
- else if (*p == 'i') printf("\033Pi"); /* italics */
- }
- }
- }
-
- /* fixtty: get tty status and save; remove delay and CR-LF mapping */
- fixtty()
- {
- struct stat sb;
-
- svsgflgs = sgb.c_oflag;
- sgb.c_oflag &= ~(ALLDELAY|ONLRET|OCRNL|ONLCR);
- ioctl(1, TCSETAW, &sgb); /* stty nl nl0 cr0 tab0 ff0 */
- fstat(1, &sb);
- svstmode = sb.st_mode;
- ttydev = ttyname(1);
- 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("\033A");
- 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.c_oflag = svsgflgs;
- ioctl(1, TCSETAW, &sgb);
- chmod(ttydev, svstmode);
- }
- printf(" \r");
- printf("\033P0");
- printf("\033&d@");
- exit(retcode);
- }
-
- /* 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("\033A"); /* 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("\012"); /* 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(c);
- 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;
- int boldflag;
- boldflag = 0;
- while(1){
- c = getchal();
- if (c==bfnext[-1]){
- if (boldflag==0){
- boldflag = 1;
- /* if last thing in the buffer are to turn off
- the BOLD, remove it */
- if ((bfnext[-5]==flg(ESC))&&
- (bfnext[-4]==flg(AMP))&&
- (bfnext[-3]==flg(DEE))&&
- (bfnext[-2]==flg(ATSIGN))){
- bfnext[-5] = bfnext[-1];
- bfnext=bfnext-4;
- }
- else{
- bftmp = bfnext+4;
- bfnext[3] = bfnext[-1];
- bfnext--;
- putstr(enbold);
- bfnext=bftmp;
- }
- }
- c = getchal();
- if (c=='\b') continue;
- }
- else putx('\b');
- break;
- }
- if (boldflag==1) putstr(ennorml);
- /* 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 = "ibmpr: ";
-
- write(2, c, 4);
- p = mesg;
- while (*p)
- write(2, p++, 1);
- restore();
- }
-