home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / simcode.arc / IBMPR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1984-05-13  |  7.3 KB  |  354 lines

  1.  
  2. /*
  3.  *    ibmpr [-p]
  4.  *    convert nroff TTY37 output to right form for IBM-PC terminals.
  5.  *    -p indicates hard copy desired
  6.  *    -i output ITALICS for 'underlines' (EPSON w/GRAFTRAX)
  7.  */
  8.  
  9.  
  10. #include <stdio.h>
  11. #include <signal.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include "sys/ioctl.h"
  15. #include "termio.h"
  16. #define    ESC    033    /* escape */
  17. #define    HFWD    '9'
  18. #define    HREV    '8'
  19. #define    FREV    '7'
  20. #define LF    '\n'
  21. #define CR    015
  22. #define    NFLAG    0200    /* hi-bit flag for non-showing chars */
  23. #define    NMASK    0177
  24. #define AMP    046    /* & */
  25. #define DEE    0144    /* d */
  26. #define ATSIGN    0100    /* @ */
  27. #define    BFSIZ    1024    /* size of output buffer (bigger because of tbl weirds
  28.                 and nroff idiosyncracies */
  29. #define ALLDELAY 0177400    /* all delay bits in termio.c_oflag */
  30.  
  31. /*    puty adds control char to output, marked by hi-bit */
  32. #define puty(c)    putx(c|NFLAG)
  33. #define flg(x) ((char)(x|NFLAG))   /* set hi-bit of x */
  34. int    nlcnt,        /* accumulated newline count */
  35.     frevcnt,    /* accumulated reverse line-feeds */
  36.     halfpos,    /* half-line position: -1 = above, +1 = below */
  37.     restrict = 0,    /* 0==> full terminal, 1==> no display enhancements */
  38.     minimiz;    /* 0==> normal, 1==> remove extra newlines */
  39. char    *ttydev;
  40. int    svstmode;    /* for mesg restore */
  41. int    restore();
  42. char    *ttyname();
  43. int    svsgflgs;
  44. struct    termio    sgb;
  45. int    retcode    = 2;    /* return code */
  46. char    peekbuf[2];
  47. char    *peekstr = peekbuf;    /* lookahead ptr */
  48.  
  49. char    outbf[BFSIZ];    /* output assembly buffer */
  50. char    *bfnext = outbf,    /* addr of next empty byte */
  51.     *bflast =  &outbf[BFSIZ-1];    /* addr of last usable byte */
  52.  
  53. /*    normal display enhancement strings */
  54. char    *enunder =    "\033&dD",    /* underline */
  55.     *ennorml =    "\033&d@",    /* normal output */
  56.     *ensuper =    "\033&dH",    /* superscript (half) */
  57.     *ensubsc =    "\033&dL",    /* subscript (half, underlined */
  58.     *enbold =    "\033&dB";    /* BOLD (inverse only) */
  59.  
  60. int    restore();
  61. main(argc, argv)
  62. char **argv;
  63. {
  64.     register c;
  65.     scanarg(argc,argv);
  66.     signal(SIGINT, restore);
  67.     signal(SIGQUIT, restore);
  68.     if (ioctl(1, TCGETA, &sgb) == 0)
  69.         fixtty();
  70.     setbuf(stdin, calloc(BUFSIZ,1));
  71.     while((c = getchal()) != EOF) {
  72.         if (nlcnt && c != LF) flushnl();
  73.         if (frevcnt && c != ESC) flushrv();
  74.         if (c == LF) {
  75.             if (++nlcnt == 1) flushln();
  76.             continue;
  77.         }
  78.         if (c == ESC)
  79.             escape();
  80.         else if (c == '\b')
  81.             backsp();
  82.         else if (c == '_') {        /* C nroff */
  83.             if ((c = getchal()) == '\b') {
  84.                 undersc();
  85.             } else {
  86.                 putx('_');
  87.                 peekbuf[0] = c;
  88.                 peekstr = peekbuf;
  89.             }
  90.         }
  91.         else
  92.             putx(c);
  93.     }
  94.     flusher();
  95.     retcode = 0;
  96.     restore();
  97. }
  98.  
  99. getchal()
  100. {
  101.     if (*peekstr)
  102.         return(*peekstr++);
  103.     return(getchar());
  104. }
  105.  
  106. /*    scanarg: scan arguments and set flags; ignore unknown args */
  107. scanarg(argc,argv)
  108.     int argc; char **argv;
  109. {
  110.     register char *p;
  111.     while ( --argc > 0) {
  112.         p = *++argv;
  113.         if (*p == '-') {
  114.             ++p;
  115.             if (*p == 'p') {
  116.                 if (p[1] == 0) printf("\033P1");
  117.                 if (p[1] == 'c') printf("\033P2");
  118.             }
  119.             else if (*p == 'i') printf("\033Pi"); /* italics */
  120.         }
  121.     }
  122. }
  123.  
  124. /*    fixtty: get tty status and save; remove delay and CR-LF mapping */
  125. fixtty()
  126. {
  127.     struct stat sb;
  128.  
  129.     svsgflgs = sgb.c_oflag;
  130.     sgb.c_oflag &= ~(ALLDELAY|ONLRET|OCRNL|ONLCR);
  131.     ioctl(1, TCSETAW, &sgb);    /* stty nl nl0 cr0 tab0 ff0 */
  132.     fstat(1, &sb);
  133.     svstmode = sb.st_mode;
  134.     ttydev = ttyname(1);
  135.     chmod(ttydev, 0600);    /* mesg n */
  136. }
  137.  
  138. /*    flusher: flush accumulated newlines, reverse line feeds, buffer */
  139. flusher()
  140. {
  141.     flushln();
  142.     if (nlcnt) flushnl();
  143.     if (frevcnt) flushrv();
  144.     fflush(stdout);
  145. }
  146.  
  147. /*    flushrv: flush accumulated reverse line feeds */
  148. flushrv()
  149. {
  150.     while (frevcnt--) 
  151.         putstr("\033A");
  152.     putstr(ennorml);
  153.     frevcnt = 0;
  154. }
  155.  
  156. /*    flushnl: flush accumulated newlines (count in nlcnt) */
  157. flushnl()
  158. {
  159.     if (minimiz != 0 && nlcnt > 2) nlcnt = 2;
  160.     putchar(CR);
  161.     while (nlcnt--)
  162.         putchar(LF);
  163.     nlcnt = 0;
  164. }
  165.  
  166. putstr(p)
  167. char *p;
  168. {
  169.     register char *pp;
  170.     pp = p;
  171.     while (*pp) puty(*pp++);
  172. }
  173.  
  174. restore(){
  175.     if (isatty(1)) {
  176.         sgb.c_oflag = svsgflgs;
  177.         ioctl(1, TCSETAW, &sgb);
  178.         chmod(ttydev, svstmode);
  179.     }
  180.     printf("     \r");
  181.     printf("\033P0");
  182.     printf("\033&d@");
  183.     exit(retcode);
  184. }
  185.  
  186. /*    escape: handle escape sequences */
  187. escape()
  188. {
  189.     register int c;
  190.     c = getchal();
  191.     if (frevcnt && c != FREV) flushrv();
  192.     switch (c) {
  193.     case FREV:
  194.         frevcnt++;
  195.         break;
  196.     case HREV:
  197.         if (halfpos == 0) {
  198.             putstr(ensuper);
  199.             halfpos--;
  200.         }
  201.         else if (halfpos > 0) {
  202.             putstr(ennorml);
  203.             halfpos--;
  204.         }
  205.         else {
  206.             putstr("\033A"); /* roll back 1 */
  207.             putstr(ennorml);
  208.             halfpos = 0;
  209.         }
  210.         break;
  211.     case HFWD:
  212.         if (halfpos == 0) {
  213.             putstr(ensubsc);
  214.             halfpos++;
  215.         }
  216.         else if (halfpos < 0) {
  217.             putstr(ennorml);
  218.             halfpos++;
  219.         }
  220.         else {
  221.             putstr("\012");    /* roll up 1, i.e., LF w/o CR */
  222.             putstr(ennorml);
  223.             halfpos = 0;
  224.         }
  225.         break;
  226.     case '&':
  227.         putstr("\033&");
  228.         puty(c = getchal());
  229.         if (c == 'd') puty(getchal());
  230.         break;
  231.     case ')':
  232.         putstr("\033)");
  233.         puty(getchal());
  234.         break;
  235. default:
  236.         puty(ESC);
  237.         puty(c);
  238.         break;
  239.     }
  240. }
  241.  
  242. char peeku[3];
  243. /*    backsp: handle backspacing */
  244. /* sequences are handled such that : ( \b is backspace )   */
  245. /*    a\b_ -> a in inverse video    */
  246. /*    _\ba -> a in inverse video    */
  247. /*    c\bd -> c in inverse video    */
  248. /* if a control char (ESC) precedes or follows '\b'  */
  249. /* then an actual backspace movement is performed    */
  250. backsp()
  251. {
  252.     register char *bftmp;
  253.     register int c;
  254.     char *bfhi;
  255.     int i, j, ncnt, bscnt;
  256.     int boldflag;
  257.     boldflag = 0;
  258.     while(1){
  259.         c = getchal();
  260.         if (c==bfnext[-1]){
  261.             if (boldflag==0){
  262.                 boldflag = 1;
  263.                 /* if last thing in the buffer are to turn off
  264.                    the BOLD, remove it */
  265.                 if ((bfnext[-5]==flg(ESC))&&
  266.                     (bfnext[-4]==flg(AMP))&&
  267.                     (bfnext[-3]==flg(DEE))&&
  268.                     (bfnext[-2]==flg(ATSIGN))){
  269.                     bfnext[-5] = bfnext[-1];
  270.                     bfnext=bfnext-4;
  271.                 }
  272.                 else{
  273.                     bftmp = bfnext+4;
  274.                     bfnext[3] = bfnext[-1];
  275.                     bfnext--;
  276.                     putstr(enbold);
  277.                     bfnext=bftmp;
  278.                 }
  279.             }
  280.             c = getchal();
  281.             if (c=='\b') continue;
  282.         }
  283.         else putx('\b');
  284.         break;
  285.     }
  286.     if (boldflag==1) putstr(ennorml);
  287.     /* put last char read back */
  288.     peeku[0] = c;
  289.     peeku[1] = '\0';
  290.     peekstr = peeku;
  291. }
  292. /*    undersc: handle C nroff's (_ BS char)+ sequences
  293.  *    assumes _ BS already found
  294.  *    if char is a control char, put char back and break.
  295.  */
  296. undersc()
  297. {
  298.     register char c;
  299.  
  300.     putstr(enunder);
  301.     while (1) {
  302.         if ((c=getchal())==ESC) {
  303.             peeku[0] = c; peeku[1] = '\0';
  304.             peekstr = peeku;
  305.             break;
  306.         }
  307.         else
  308.             putx(c);
  309.         if ((c = getchal()) != '_') {
  310.             peeku[0] = c; peeku[1] = '\0';
  311.             peekstr = peeku;
  312.             break;
  313.         }
  314.         if ((c = getchal()) != '\b') {
  315.             peeku[0] = '_'; peeku[1] = c;
  316.             peekstr = peeku;
  317.             break;
  318.         }
  319.     }
  320.     putstr(ennorml);
  321. }
  322.  
  323. /*    flushln: flush out accumulated line */
  324. flushln()
  325. {
  326. register char c, *p;
  327.     putx('\0');
  328.     p = outbf;
  329.     while (c = (*p++ & NMASK)) putchar(c);
  330.     bfnext = outbf;
  331. }
  332.  
  333. /*    putx: add normal (printing) char to output */
  334. putx(c)
  335. char c;
  336. {
  337.     if (bfnext <= bflast)
  338.         *bfnext++ = c;
  339.     else die("line too long\n");
  340. }
  341.  
  342. die(mesg)
  343. char *mesg;
  344. {
  345.     register char *p;
  346.     char *c = "ibmpr: ";
  347.  
  348.     write(2, c, 4);
  349.     p = mesg;
  350.     while (*p)
  351.         write(2, p++, 1);
  352.     restore();
  353. }
  354.