home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / pep21.arc / ANSI.C < prev    next >
C/C++ Source or Header  |  1989-12-29  |  9KB  |  277 lines

  1. /* ansi.c  1989 december 10 [gh]
  2. +-----------------------------------------------------------------------------
  3. | Abstract:
  4. |    Ansi terminal interpreter.
  5. |
  6. | Authorship:
  7. |    Copyright (c) 1988, 1989 Gisle Hannemyr.
  8. |    Permission is granted to hack, make and distribute copies of this module
  9. |    as long as this notice and the copyright notices are not removed.
  10. |    If you intend to distribute changed versions of this module, please make
  11. |    an entry in the "history" log (below) and mark the hacked lines with your
  12. |    initials. I maintain the module, and shall appreiciate copies of bug
  13. |    fixes and new versions.
  14. |    Flames, bug reports, comments and improvements to:
  15. |       snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway
  16. |       email: X400: gisle@nr.uninett
  17. |              RFC:  gisle@ifi.uio.no
  18. |              (and several BBS mailboxes in the Oslo area).
  19. |
  20. | Access programs:
  21. |    void doansi() : Interprete one file.
  22. |
  23. | History:
  24. |     4 jun 89 [gh] Latest update.
  25. |
  26. | Bugs:
  27. |    * Currently, highlighting etc. in ANSI sequences is removed. It might be
  28. |      fun to translate the lot into Postscript.
  29. |    * Not all ANSI sequences are implemented so far.  It should cover
  30. |      ANSI.SYS, but some exotic stuff are left out, as well as the NANSI.SYS
  31. |      extensions.  All unknown sequences produces an error message.  Users
  32. |      who can explain the exact sematics of such sequences are encouraged
  33. |      to contact author.
  34. |
  35. | See main module for more comments.
  36. +---------------------------------------------------------------------------*/
  37.  
  38. #include <stdio.h>
  39. #include "pep.h"
  40. #include <ctype.h>
  41.  
  42.  
  43. /*---( defines )------------------------------------------------------------*/
  44.  
  45. #define MAXPAR      3                   /* Max no. of ANSI param's to store */
  46. #define MAXX        80                  /* ANSI terminal screen width       */
  47. #define MAXY        25                  /* ANSI terminal screen height      */
  48.  
  49. /*---( variables )----------------------------------------------------------*/
  50.  
  51. static unsigned char Screen[MAXX][MAXY];    /* Output ANSI terminal screen  */
  52. static int  GuardL;                         /* ANSI overwrite guard level   */
  53. static int  LineYy = 0;                     /* ANSI terminal cursor pos.    */
  54.  
  55.  
  56. /*---( housekeeping )-------------------------------------------------------*/
  57.  
  58. /*
  59. | Abs: Display ansi warning message.
  60. */
  61. static void amess(err,cc)
  62. int err, cc;
  63. {
  64.    fprintf(stderr,"\ransi (%ld): ",LCount);
  65.    switch(err) {
  66.       case  1: fprintf(stderr,"exepected 5bh  (got <%02xh>)",cc); break;
  67.       case  2: fprintf(stderr,"unknown ANSI command <%02xh>",cc); break;
  68.       case  3: fprintf(stderr,"unknown control code <%02xh>",cc); break;
  69.       case  4: fputs("X right of screen edge",     stderr);       break;
  70.       case  5: fputs("X left of screen edge",      stderr);       break;
  71.       case  6: fputs("Y above screen edge",        stderr);       break;
  72.       case  7: fputs("auto line wrap (warning)",   stderr);       break;
  73.       case  8: fputs("cursor outside screen",      stderr);       break;
  74.       default: fputs("unknown error",              stderr);       break;
  75.    } /* switch */
  76.    putc('\n',stderr);
  77. } /* amess */
  78.  
  79.  
  80. /*---( ansi emulation )-----------------------------------------------------*/
  81.  
  82. /*
  83. | Abs: Erase entire screen and send cursor home.
  84. */
  85. static void clearscreen()
  86. {
  87.    int xx, yy;
  88.  
  89.    for (xx = 0; xx < MAXX; xx++) for (yy = 0; yy < MAXY; yy++)
  90.       Screen[xx][yy] = ' ';
  91.    LineXx = 0;
  92.    LineYy = 0;
  93. } /* clearscreen */
  94.  
  95.  
  96. static void docrlf()
  97. {
  98.    if      (EndOLn == -1) { putc('\r',Fdo); putc('\n',Fdo); }
  99.    else if (EndOLn != -2)   putc(EndOLn,Fdo);
  100. } /* docrlf */
  101.  
  102.  
  103. /*
  104. | Abs: Print a horizontal line,
  105. */
  106. static void horline()
  107. {
  108.    int xx;
  109.    for (xx = 0; xx < (MAXX-1); xx++) putc('=',Fdo); docrlf();
  110. } /* horline */
  111.  
  112.  
  113. /*
  114. | Abs: Print screen image.
  115. */
  116. static void printscreen(frame)
  117. int frame;
  118. {
  119.    int xx, yy;
  120.    static int oldframe = FALSE;
  121.  
  122.    if (oldframe) horline();
  123.    for (yy = 0; yy < MAXY; yy++) {
  124.       xx = MAXX-1;
  125.       while ((xx) && (Screen[xx][yy] == ' ')) { Screen[xx][yy] = '\0'; xx--; }
  126.       xx = 0;
  127.       while (Screen[xx][yy]) { putc(Screen[xx][yy],Fdo); xx++; }
  128.       docrlf();
  129.       showprogress();
  130.    }
  131.    if (oldframe) horline();
  132.    oldframe = frame;
  133.    clearscreen();
  134. } /* printscreen */
  135.  
  136.  
  137. static void pputc(cc)
  138. char cc;
  139. {
  140.    if (LineXx >= MAXX) {
  141.       LineXx = 0; LineYy++;
  142.       amess(7); /* auto line wrap (warning) */
  143.    } else if ((LineXx < 0) || (LineYy >= MAXY) || (LineYy < 0)) {
  144.       amess(8); /* cursor outside screen */
  145.       printscreen(FALSE);
  146.    }
  147.    switch (GuardL) {
  148.       case 2: if (Screen[LineXx][LineYy] != ' ') break;
  149.       case 1: if (cc == ' ') break;
  150.       case 0: Screen[LineXx][LineYy] = cc;
  151.    }
  152.    LineXx++;
  153. } /* pputc */
  154.  
  155.  
  156. /*
  157. | Abs: Interprete ANSI command after ESC CSI.
  158. */
  159. static void esccsi()
  160. {
  161.    int ii, jj, cc, dd;
  162.    int pp[MAXPAR];
  163.    static int oldxx, oldyy;
  164.  
  165.    for (ii = 0; ii < MAXPAR; ii++) pp[ii] = 0; dd = ii = 0;
  166.    while ((cc = getc(Fdi)) != EOF) {
  167.       if (isdigit(cc)) { pp[ii] = pp[ii] * 10 + cc - '0'; dd++; }
  168.       else if (cc == ';') {
  169.          if (!dd) pp[ii] = 1; /* default to 1 */
  170.          dd = 0;
  171.          if (ii < MAXPAR-1) ii++;
  172.       }
  173.       else break;
  174.    }
  175.    if (dd) ii++; /* We've one parameter that's not terminated */
  176.    for (jj = ii; jj < MAXPAR; jj++) pp[jj] = 1;    /* Default */
  177.    /* Exotic stuff we do not attempt to interprete       *
  178.    |  case 'h': break; /* + SM  -- set   mode            *
  179.    |  case 'l': break; /* + RM  -- reset mode            *
  180.    |  case 'p': break; /* + KKR -- keyboard key reassign *
  181.    |  case 'R': break; /* + CPR -- cursor position rep.  *
  182.    |
  183.    |  NANSI stuff for future implementation              *
  184.    |  case '@': /*   ICH -- insert characters            *
  185.    |  case 'L': /*   IL  -- insert lines                 *
  186.    |  case 'M': /*   DL  -- delete lines                 *
  187.    |  case 'P': /*   DCH -- delete characters            *
  188.    |  case 'y': /*   OCT -- output chr. translate        *
  189.    */
  190.    switch (cc) {
  191.       case 'A': /* + CUU -- cursor up             */
  192.          LineYy -= pp[0];
  193.          if (LineYy < 0) { amess(6); LineYy = 0; } /* Y above screen edge  */
  194.          break;
  195.       case 'B': /* + CUD -- cursor down           */
  196.          LineYy += pp[0];
  197.          if (LineYy >= MAXY) printscreen(FALSE);
  198.          break;
  199.       case 'C': /* + CUF -- cursor forward        */
  200.          LineXx += pp[0];
  201.          if (LineXx >= MAXX) { amess(4); LineXx = MAXX - 1; } /* X right of screen */
  202.          break;
  203.       case 'D': /* + CUB -- cursor backward       */
  204.          LineXx -= pp[0];
  205.          if (LineXx < 0) { amess(5); LineXx = 0; } /* X left of screen edge */
  206.          break;
  207.       case 'H': /* + CUP -- cursor position       */
  208.          LineXx = pp[1] - 1; LineYy = pp[0] -1;
  209.          break;
  210.       case 'J': /* + ED  -- erase display         */
  211.          if (pp[0] == 2) printscreen(TRUE);
  212.          else { amess(2,cc); pputc(cc); } /* unknown ANSI command */
  213.          break;
  214.       case 'K': /* + EL  -- erase in line         */
  215.          if (!GuardL) while (LineXx < MAXX) Screen[LineXx++][LineYy] = ' ';
  216.          break;
  217.       case 'f': /*   HVP -- cursor position       */
  218.          LineXx = pp[1] - 1; LineYy = pp[0] - 1;
  219.          break;
  220.       case 'n': /* + DSR -- device staus report   */
  221.          break;
  222.       case 'm': /* + SGR -- set graphic rendition */
  223.          break;
  224.       case 's': /* + SCP -- save cursor position  */
  225.          oldxx = LineXx;
  226.          oldyy = LineYy;
  227.          break;
  228.       case 'u': /* + RCP -- restore cursor pos.   */
  229.          LineXx = oldxx;
  230.          LineYy = oldyy;
  231.          break;
  232.       default: amess(2,cc); pputc(cc); /* unknown ANSI command */
  233.    } /* switch */
  234.    /*
  235.    if (hack) {
  236.       printf("CSI: ");
  237.       for (jj = 0; jj < ii; jj++) printf("%d;",pp[jj]);
  238.       printf("%c\n",cc);
  239.    }
  240.    */
  241. } /* esccsi */
  242.  
  243.  
  244. /*---( file loop )----------------------------------------------------------*/
  245.  
  246. /*
  247. | Abs: Read (and write) one complete ANSI-file.
  248. | Par: guardl = ANSI overwrite guard level.
  249. */
  250. void doansi(guardl)
  251. int guardl;
  252. {
  253.    int cc;
  254.  
  255.    GuardL = guardl;
  256.    clearscreen();
  257.    while ((cc = getc(Fdi)) != EOF) {
  258.       if ((cc >= 0x20) && (cc <= 0xff)) pputc(cc);
  259.       else if (cc == 0x07) ; /* BELL    */
  260.       else if (cc == '\b') { /* BS      */
  261.          LineXx--;
  262.          if (LineXx < 0) { amess(5); LineXx = 0; } /* X left of screen edge */
  263.       }
  264.       else if (cc == '\t') LineXx = (LineXx / ITabSz + 1) * ITabSz;
  265.       else if (cc == '\n') { LineYy++; if (LineYy >= MAXY) printscreen(FALSE); }
  266.       else if (cc == '\r') LineXx = 0;
  267.       else if (cc == 0x1b) { /* ESC     */
  268.          cc = getc(Fdi);
  269.          if (cc == 0x5b) esccsi(); else amess(1,cc); /* exepected 5bh */
  270.       }
  271.       else amess(3,cc); /* unknown control code */
  272.    } /* while */
  273.    printscreen(FALSE);
  274. } /* doansi */
  275.  
  276. /* EOF */
  277.