home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume3 / vtem < prev    next >
Internet Message Format  |  1986-11-30  |  21KB

  1. From: seismo!enea!erix!erisun!leif (Leif Samuelsson)
  2. Subject: vtem - a VT100 emulator based on termcap
  3. Keywords: VT100 BSD4.2 pseudo terminal
  4. Newsgroups: mod.sources
  5. Approved: jpn@panda.UUCP
  6.  
  7. Mod.sources:  Volume 3, Issue 97
  8. Submitted by: seismo!enea!erix!erisun!leif (Leif Samuelsson)
  9.  
  10.  
  11. # This is a shell archive.  Remove anything before this line,
  12. # then unpack it by saving it in a file and typing "sh file".
  13. #
  14. # Wrapped by erisun!leif on Fri Jan 24 14:06:57 MET 1986
  15. # Contents:  vtem.1 Makefile vtem.h vtem.c term.c out.c
  16.  
  17. echo x - vtem.1
  18. sed 's/^@//' > "vtem.1" <<'@//E*O*F vtem.1//'
  19. @.TH VTEM 1 1986-01-24
  20. @.SH NAME
  21. vtem - a VT100 emulator based on termcap
  22. @.SH SYNOPSIS
  23. @.I vtem
  24. @.SH DESCRIPTION
  25. @.I vtem
  26. runs on BSD4.2 and works by starting a sub-shell and then translating
  27. output escape sequences. It's function is limited by the capabilities
  28. listed in the termcap database and the capabilities of the actual
  29. terminal that it is being run on.
  30.  
  31. It has been tested with Per Lindberg's excellent verifier "vttest" and
  32. has been found to give acceptable results on the following terminals:
  33.  
  34.     Sun windows
  35. @.br
  36.     PC-Kermit in h19 emulation mode.
  37. @.br
  38.     VT100    (!)
  39.  
  40. On a Sun, you can use the following Suntools rootmenu entry:
  41.  
  42. @.nf
  43. "VT100 Tool" shelltool -Ww 80 -Wh 24 -Wl " VT100 Tool" vtem
  44. @.fi
  45. @.SH BUGS
  46. Release 1.0 of vtem has the following bugs and limitations:
  47.  
  48. Region scroll will only work on terminals with
  49. cs or al/dl.
  50.  
  51. It will never write in the last position of the screen,
  52. because of the unpredictable behaviour of many terminals.
  53.  
  54. VT102 capabilities are not yet implemented.
  55.  
  56. No soft scroll.
  57.  
  58. 132 width not supported.
  59.  
  60. Input is not translated, which means no function key emulation.
  61.  
  62. No double height or double width lines.
  63.  
  64. No alternate character set, meaning no graphics.
  65.  
  66. No printer support.
  67.  
  68. No status reports, answerback messages, etc.
  69.  
  70. No SETUP mode.
  71.  
  72. No LEDs.
  73. @.SH AUTHOR
  74. Leif Samuelsson 
  75. @.br
  76. leif@erisun.UUCP  or  ..enea!erix!erisun!leif
  77.  
  78. @//E*O*F vtem.1//
  79. chmod u=rw,g=r,o=r vtem.1
  80.  
  81. echo x - Makefile
  82. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  83. CFLAGS= -O
  84.  
  85.  
  86. vtem:    vtem.o term.o out.o
  87.     $(CC) $(CFLAGS) -o vtem vtem.o term.o out.o -ltermcap
  88.  
  89. @.c.o:    ; $(CC) $(CFLAGS) -c $*.c
  90.  
  91. shar:    ; shar -v vtem.1 Makefile vtem.h vtem.c term.c out.c > vtem.shar
  92. @//E*O*F Makefile//
  93. chmod u=rw,g=r,o=r Makefile
  94.  
  95. echo x - vtem.h
  96. sed 's/^@//' > "vtem.h" <<'@//E*O*F vtem.h//'
  97. #include <stdio.h>
  98. #include <signal.h>
  99. #include <sys/types.h>
  100. #include <sys/time.h>
  101. #include <sys/stat.h>
  102. #include <sys/ioctl.h>
  103.  
  104. #define FALSE 0
  105. #define TRUE 1
  106.  
  107. typedef short Bool;
  108.  
  109. extern char *getenv();
  110. extern putchar_x();
  111.  
  112. extern struct sgttyb oldb, newb;
  113. extern struct tchars oldtchars, newtchars;
  114. extern struct ltchars oldltchars, newltchars;
  115. extern int oldlb, newlb, oldl, newl;
  116.  
  117. extern int master;
  118.  
  119. extern Bool BS;
  120. extern int CO, LI;
  121. extern char *AL, *BC, *BL, *CD, *CL, *CE, *CM, *CR, *CS, *DL, *DO, *KE, *KS, *MB, *MD, *ME, *MR, *ND, *NL, *SE, *SO, *SR, *TI, *TE, *UE, *UP, *US, *MAL, *MDL;
  122.  
  123. #define tputs_x(s)        (tputs(s, 0, putchar_x))
  124.  
  125. #define backspace()        (tputs_x(BC))
  126. #define clear_screen()        (tputs_x(CL))
  127. #define set_cursor(c, r)    (tputs_x(tgoto(CM, (c), (r))))
  128. #define linefeed()        (tputs_x(NL))
  129. #define cr()            (tputs_x(CR))
  130. @//E*O*F vtem.h//
  131. chmod u=rw,g=r,o=r vtem.h
  132.  
  133. echo x - vtem.c
  134. sed 's/^@//' > "vtem.c" <<'@//E*O*F vtem.c//'
  135. /*
  136.  * vt - A termcap driven VT100 emulator for BSD Unix
  137.  *
  138.  * Version 1.0
  139.  *
  140.  * Public domain software.
  141.  * Written by Leif Samuelsson (leif@erisun) in December, 1985
  142.  */
  143.  
  144. #include "vtem.h"
  145. #include <sys/wait.h>
  146.  
  147. int master, slave, child;
  148. char linec, linen;
  149.  
  150.  
  151. done()
  152. {
  153. union wait status;
  154.  
  155.     if (wait3(&status, WNOHANG, 0) != child)
  156.         return;
  157.     setupterm(0);
  158.     exit(0);
  159. }
  160.  
  161. main()
  162. {
  163.     /* Strategy: Start three processes, one for input, one for output
  164.          * and one shell.
  165.          */
  166.     setup_master();
  167.     setupterm(TRUE);
  168.     signal(SIGCHLD, done);
  169.     if (child = fork())
  170.         handle_input();
  171.     else {
  172.         if (fork())
  173.         handle_output();
  174.         else
  175.         start_shell();
  176.     }
  177. }
  178.  
  179. handle_input()
  180. {
  181. char buf[BUFSIZ];
  182. int i;
  183.  
  184.     while (i = read(0, buf, BUFSIZ))
  185.         write(master, buf, i);
  186.     setupterm(0);
  187.     exit(0);
  188. }
  189.  
  190.  
  191. start_shell()
  192. {
  193. int t;
  194. char *shell, *tail, *rindex();
  195.  
  196.     if ((shell = getenv("SHELL")) == (char *) 0)
  197.         shell = "/bin/sh";
  198.     if ((tail = rindex(shell, '/')) == (char *) 0)
  199.         tail = "sh";
  200.     else
  201.         tail++;
  202.     if ((t = open("/dev/tty", 2)) >= 0) {
  203.         ioctl(t, TIOCNOTTY, (char *)0);
  204.         close(t);
  205.     }
  206.     setup_slave();
  207.     close(master);
  208.     dup2(slave, 0);
  209.     dup2(slave, 1);
  210.     dup2(slave, 2);
  211.     close(slave);
  212.     execl(shell, tail, "-i", 0);
  213.     perror(shell);
  214.     fail();
  215. }
  216.  
  217. fail()
  218. {
  219.     kill(0, SIGTERM);
  220.     setupterm(0);
  221.     exit(0);
  222. }
  223.  
  224.  
  225. setup_master()
  226. {
  227. char line[11];
  228.  
  229.     for (linec = 'p'; linec <= 's'; linec++) {
  230.     sprintf(line, "/dev/pty%c0", linec);
  231.     if (access(line, 0) != 0)
  232.         break;
  233.     for (linen = 0; linen < 16; linen++) {
  234.         sprintf(line, "/dev/pty%c%1x", linec, linen);
  235.         master = open(line, 2);
  236.         if (master >= 0) {
  237.         return;
  238.         }
  239.     }
  240.     }
  241.     fprintf(stderr, "Can't find a pty\n");
  242.     fail();
  243. }
  244.  
  245. setup_slave()
  246. {
  247. char line[11];
  248.  
  249.     sprintf(line, "/dev/tty%c%1x", linec, linen);
  250.     slave = open(line, 2);
  251.     if (slave < 0) {
  252.     perror(line);
  253.     fail();
  254.     }
  255.     ioctl(slave, TIOCSETP, (char *)&oldb);
  256.     ioctl(slave, TIOCSETC, (char *)&oldtchars);
  257.     ioctl(slave, TIOCSLTC, (char *)&oldltchars);
  258.     ioctl(slave, TIOCLSET, (char *)&oldlb);
  259.     ioctl(slave, TIOCSETD, (char *)&oldl);
  260. }
  261. @//E*O*F vtem.c//
  262. chmod u=rw,g=r,o=r vtem.c
  263.  
  264. echo x - term.c
  265. sed 's/^@//' > "term.c" <<'@//E*O*F term.c//'
  266. /*
  267.  * vt - A termcap driven VT100 emulator for BSD Unix
  268.  *
  269.  * Version 1.0
  270.  *
  271.  * Public domain software.
  272.  * Written by Leif Samuelsson (leif@erisun) in December, 1985
  273.  */
  274.  
  275.  
  276. /* This module contains termcap and tty routines */
  277.  
  278. #include "vtem.h"
  279.  
  280. extern char *tgetstr(), *tgoto();
  281.  
  282. /* Variables for saving original terminal parameters */
  283.   struct sgttyb oldb, newb;
  284.   struct tchars oldtchars, newtchars = { -1, -1, -1, -1, -1, -1 };
  285.   struct ltchars oldltchars, newltchars = { -1, -1, -1, -1, -1, -1 };
  286.   int oldlb, newlb, oldl, newl;
  287.  
  288. /* Terminal attributes */
  289. char tbuf[1024];
  290. Bool BS;
  291. int CO, LI;
  292. char    *AL, *BC, *BL, *CD, *CL, *CE, *CM, *CR, *CS, *DL, *DO,
  293.     *KE, *KS, *MB, *MD, *ME, *MR, *ND, *NL, *SE, *SO, *SR,
  294.     *TI, *TE, *UE, *UP, *US, *MAL, *MDL;
  295.  
  296. putchar_x(c)
  297. char c;
  298. {
  299.     putchar(c);
  300. }
  301.  
  302. ttycbreak()
  303. {
  304.     ioctl(0, TIOCGETP, &oldb);
  305.     ioctl(0, TIOCGETC, &oldtchars);
  306.     ioctl(0, TIOCGETD, &oldl);
  307.     ioctl(0, TIOCGLTC, &oldltchars);
  308.     ioctl(0, TIOCLGET, &oldlb);
  309.  
  310.     newb = oldb;
  311.     newb.sg_flags |= CBREAK;
  312.     newb.sg_flags &= ~(CRMOD | ECHO);
  313.     ioctl(0, TIOCSETP, &newb);
  314.     ioctl(0, TIOCSETC, &newtchars);
  315.     ioctl(0, TIOCSLTC, &newltchars);
  316.     signal(SIGINT,SIG_IGN);
  317. }
  318.  
  319.  
  320. /* gettermtype - Finds terminal type and reads termcap entry for it.
  321.  */
  322. gettermtype()
  323. {
  324. char tptr[1024];
  325. char *termtyp;
  326. char *tbufptr;
  327.  
  328.     termtyp=getenv("TERM");
  329.     switch(tgetent(tptr,termtyp)) {
  330.     case -1:
  331.         printf("Can't read termcap\n");
  332.         exit(1);
  333.     case 0:
  334.         printf("Can't find your terminal type (%s) in termcap\n", termtyp);
  335.         exit(1);
  336.     }
  337.     tbufptr=tbuf;
  338.     AL = tgetstr("al", &tbufptr);
  339.     BC = tgetstr("bc", &tbufptr);
  340.     BL = tgetstr("bl", &tbufptr);
  341.     if (!BL)
  342.     BL = "\007";
  343.     BS = tgetflag("bs",&tbufptr);
  344.     if (!BC && BS)
  345.     BC = "\b";
  346.     CD = tgetstr("cd", &tbufptr);
  347.     CL = tgetstr("cl", &tbufptr);
  348.     CE = tgetstr("ce", &tbufptr);
  349.     CM = tgetstr("cm", &tbufptr);
  350.     CR = tgetstr("cr", &tbufptr);
  351.     if (!CR)
  352.     CR = "\r";
  353.     CS = tgetstr("cs", &tbufptr);
  354.     DL = tgetstr("dl", &tbufptr);
  355.     DO = tgetstr("do", &tbufptr);
  356.     if (!DO)
  357.     DO = "\n";
  358.     KE = tgetstr("ke", &tbufptr);
  359.     KS = tgetstr("ks", &tbufptr);
  360.     MB = tgetstr("mb", &tbufptr);
  361.     ME = tgetstr("me", &tbufptr);
  362.     MR = tgetstr("mr", &tbufptr);
  363.     ND = tgetstr("nd", &tbufptr);
  364.     NL = tgetstr("nl", &tbufptr);
  365.     if (!NL)
  366.     NL = "\n";
  367.     SO = tgetstr("so", &tbufptr);
  368.     SE = tgetstr("se", &tbufptr);
  369.     SR = tgetstr("sr", &tbufptr);
  370.     TI = tgetstr("ti", &tbufptr);
  371.     TE = tgetstr("te", &tbufptr);
  372.     UE = tgetstr("ue", &tbufptr);
  373.     UP = tgetstr("up", &tbufptr);
  374.     US = tgetstr("us", &tbufptr);
  375.     MAL = tgetstr("AL", &tbufptr);
  376.     MDL = tgetstr("DL", &tbufptr);
  377.     CO = tgetnum("co");
  378.     LI = tgetnum("li");
  379.     if(!TI) {
  380.         TI = tgetstr("vs", &tbufptr);
  381.         TE = tgetstr("ve", &tbufptr);
  382.     }
  383.  
  384.     if (CO < 80 || LI < 24) {
  385.     printf("Sorry, but vtem requires 24 by 80 lines.\r\n");
  386.     exit(1);
  387.     }
  388.     if (!CM) {
  389.     printf("Sorry, but vtem requires cursor motion capability (cm).\r\n");
  390.     exit(1);
  391.     }
  392.     if (!CL) {
  393.     printf("Sorry, but vtem requires clear screen capability (cl).\r\n");
  394.     exit(1);
  395.     }
  396.     if (!UP) {
  397.     printf("Sorry, but vtem requires cursor up capability (up).\r\n");
  398.     exit(1);
  399.     }
  400. }
  401.  
  402. setupterm(flg)            /* If flg==TRUE, set line in cbreak mode and */
  403. Bool flg;            /* initialize the terminal,otherwise restore */
  404. {
  405.     if (flg) {
  406.     ttycbreak();
  407.     if (TI)
  408.         tputs_x(TI);    /* start CM mode */
  409.     }
  410.     else {
  411.     if (KE)
  412.         tputs_x(KE);    /* Restores Keypad */
  413.     if (TE)
  414.         tputs_x(TE);    /* exit CM mode */
  415.     ioctl(0, TIOCSETP, &oldb);
  416.     ioctl(0, TIOCSETC, &oldtchars);
  417.     ioctl(0, TIOCSLTC, &oldltchars);
  418.     }
  419. }
  420.  
  421. /* clear_bos - clear from beginning of screen to cursor
  422.  */
  423. clear_bos(c,r)
  424. int c,r;
  425. {
  426. register int i;
  427.  
  428.     for (i=0; i<r; i++) {
  429.     tputs_x(tgoto(CM, 0, i));
  430.     tputs_x(CE);
  431.     }
  432.     clear_bol(c,r);
  433. }
  434.  
  435. /* clear_eos - Clear from cursor to end of screen.
  436.  */
  437. clear_eos()
  438. {
  439.     tputs_x(CD);
  440. }
  441.  
  442. /* clear_bol - Clear from beginning of line to cursor.
  443.  */
  444. clear_bol(c,r)
  445. int c,r;
  446. {
  447. register int i;
  448.  
  449.     tputs_x(tgoto(CM, 0, r));
  450.     for (i=0; i<c; i++)
  451.     putchar(' ');
  452. }
  453.  
  454. /* clear_eol - Clear from cursor to end of line.
  455.  */
  456. clear_eol(c, r)
  457. int c, r;
  458. {
  459. register int i;
  460.  
  461.     if (CE)
  462.     tputs_x(CE);
  463.     else {
  464.     for (i=c; i < ((r==23)?79:80); i++)
  465.         putchar(' ');
  466.     set_cursor(c, r);
  467.     }
  468. }
  469.  
  470.  
  471. cursor_up()
  472. {
  473.     tputs_x(UP); 
  474. }
  475.  
  476.  
  477. cursor_down()
  478. {
  479.     tputs_x(DO); 
  480. }
  481.  
  482.  
  483. cursor_right()
  484. {
  485.     tputs_x(ND); 
  486. }
  487.  
  488.  
  489. reverse_lf()
  490. {
  491.     cursor_up();        /* We hope */
  492. }
  493.  
  494.  
  495. /* start_reverse - Set terminal in reverse video mode.
  496.  */
  497. start_reverse()
  498. {
  499.     if (MR)
  500.     tputs_x(MR);
  501.     else
  502.     tputs_x(SO);
  503. }
  504.  
  505.  
  506. start_blink()
  507. {
  508.     tputs_x(MB);
  509. }
  510.  
  511.  
  512. start_underline()
  513. {
  514.     tputs_x(US);
  515. }
  516.  
  517.  
  518. start_bold()
  519. {
  520.     if (MD)
  521.     tputs_x(MD);
  522.     else
  523.     tputs_x(SO);
  524. }
  525.  
  526.  
  527. ring_bell()
  528. {
  529.     tputs_x(BL);
  530. }
  531.  
  532.  
  533. /* end_attributes - Reset terminal attributes to normal.
  534.  */
  535. end_attributes()
  536. {
  537.     if (ME)
  538.     tputs_x(ME);
  539.     else {
  540.     tputs_x(SE);
  541.     tputs_x(UE);
  542.     }
  543. }
  544.  
  545.  
  546. scroll_region(lin1, lin2, upward)      /* Scroll region between lin1 and */
  547. int lin1, lin2;                   /* lin2 inclusive one line up or down */
  548. {
  549.     /* Use scroll region if available - otherwise use insert/delete line*/
  550.     if (CS && SR) {
  551.     tputs_x(tgoto(CS,lin2,lin1));
  552.     if (upward) {
  553.         set_cursor(0,lin2);
  554.         tputs_x(NL);
  555.     }
  556.     else {
  557.         set_cursor(0,lin1);
  558.         tputs_x(SR);
  559.     }
  560.     tputs_x(tgoto(CS,23,0));
  561.     }
  562.     else if (DL && AL) {
  563.     if (upward) {
  564.         set_cursor(0,lin1);
  565.         tputs_x(DL);
  566.         set_cursor(0,lin2);
  567.         tputs_x(AL);
  568.     }
  569.     else {
  570.         set_cursor(0,lin2);
  571.         tputs_x(DL);
  572.         set_cursor(0,lin1);
  573.         tputs_x(AL);
  574.     }
  575.     }
  576. }
  577.  
  578.  
  579. @//E*O*F term.c//
  580. chmod u=rw,g=r,o=r term.c
  581.  
  582. echo x - out.c
  583. sed 's/^@//' > "out.c" <<'@//E*O*F out.c//'
  584. /*
  585.  * vt - A termcap driven VT100 emulator for BSD Unix
  586.  *
  587.  * Version 1.0
  588.  *
  589.  * Public domain software.
  590.  * Written by Leif Samuelsson (leif@erisun) in December, 1985
  591.  */
  592.  
  593. #include "vtem.h"
  594.  
  595. typedef Bool int;
  596.  
  597. static int    row, col, save_row, save_col, top_margin, bottom_margin;
  598. static Bool    blink, bold, reverse, underline, save_blink, save_bold,
  599.         save_reverse, save_underline, origin_mode, vt52_mode, wrap;
  600.  
  601. static short tabs[80];
  602. static FILE *f;
  603. static int arg[10], argno;
  604.  
  605. /* arow is absolute row, taking top_margin into account */
  606. #define arow    (row + (origin_mode ? (top_margin - 1) : 0))
  607.  
  608.  
  609. /* nextch - read output and interpret control characters.
  610.  *        Return first non-control character.
  611.  */
  612. int nextch()
  613. {
  614. register int ch;
  615.  
  616.     while ((ch = getc(f)) != EOF) {
  617.     switch (ch) {
  618.         case '\0':            /* Ignore nulls and DELs */
  619.         case '\177':
  620.             break;
  621.         case '\007':        /* Bell */
  622.         ring_bell(); break;
  623.         case '\b':            /* BackSpace */
  624.             if (col > 1) {
  625.             col--;
  626.             backspace();
  627.             } break;
  628.         case '\t':            /* Tab */
  629.         while (col < 80 && !tabs[col++]);
  630.         set_cursor(col-1, arow-1); break;
  631.  
  632.         case '\n':            /* Line Feed */
  633.             do_linefeed(); break;
  634.         case '\r':            /* Carriage Return */
  635.         if (col > 1) {
  636.             col = 1;
  637.             cr();
  638.         } break;
  639.         case '\016':        /* Ignore shift in/out */
  640.         case '\017':
  641.             break;
  642.         default:
  643.             return(ch);
  644.     }
  645.     if (f->_cnt == 0)
  646.         fflush(stdout);
  647.     }
  648.     return(ch);
  649. }
  650.  
  651. /* handle_output - Main loop of output process.
  652.  *           Reads and dispatches characters from output stream.
  653.  */
  654. handle_output()
  655. {
  656. register int ch;
  657.  
  658.     gettermtype();
  659.     (void) close(0);
  660.     if ((f = fdopen(master, "r")) == (FILE *) 0) {
  661.     fprintf(stderr, "handle_output: Can't read from shell\r\n");
  662.     exit(1);
  663.     }
  664.     do_reset();
  665.     while ((ch = nextch()) != EOF) {
  666.     if (ch == '\033') {        /* Escape character */
  667.         if (vt52_mode)
  668.         do_vt52_escape();
  669.         else
  670.         do_ansi_escape();
  671.     }
  672.     else if (ch >= ' ') {        /* Printing character */
  673.         if (col == 81) {
  674.         if (wrap) {
  675.             col = 1;
  676.             set_cursor(col-1, arow-1);
  677.             do_linefeed();
  678.         }
  679.         else {
  680.             col = 80;
  681.             set_cursor(col-1, arow-1);
  682.         }
  683.         }
  684.         if (col == 80) {
  685.         if (arow != 24)
  686.             putchar(ch);    /* Must ignore last pos */
  687.         set_cursor(col-1, arow-1);
  688.         if (wrap)
  689.             col++;
  690.         }
  691.         else {
  692.         putchar(ch);
  693.         col++;
  694.         }
  695.     }
  696.     if (f->_cnt == 0)
  697.         fflush(stdout);
  698.     }
  699.     fclose(f);
  700.     exit(0);
  701. }
  702.  
  703. /* do_ansi_escape - reads and interprets an ANSI escape sequence
  704.  */
  705.  
  706. do_ansi_escape()
  707. {
  708. register int ch;
  709.  
  710.     if ((ch = nextch()) == EOF)
  711.     return;
  712.     switch (ch) {
  713.     case '#':
  714.         do_hash();
  715.         break;
  716.     case '(':
  717.     case ')':
  718.         do_character_sets(); break;
  719.     case '7':
  720.         save_row = row;
  721.         save_col = col;
  722.         save_blink = blink;
  723.         save_bold = bold;
  724.         save_reverse = reverse;
  725.         save_underline = underline;
  726.         break;
  727.     case '8':
  728.         if (save_row > 0) {
  729.         row = save_row;
  730.         col = save_col;
  731.         set_cursor(col-1, arow-1);
  732.         if (blink = save_blink)
  733.             start_blink();
  734.         if (bold = save_bold)
  735.             start_bold();
  736.         if (reverse = save_reverse)
  737.             start_reverse();
  738.         if (underline = save_underline)
  739.             start_underline();
  740.         } break;
  741.  
  742.     case 'D':
  743.         do_linefeed(); break;
  744.  
  745.     case 'E':
  746.         if (col > 1) {
  747.         col = 1;
  748.         cr();
  749.         }
  750.         do_linefeed(); break;
  751.  
  752.     case 'H':
  753.         tabs[col-1] = 1; break;
  754.  
  755.     case 'M':
  756.         do_reverse_lf(); break;
  757.  
  758.     case '[':
  759.         do_csi(); break;
  760.  
  761.     case 'c':
  762.         do_reset(); break;
  763.     }
  764. }
  765.  
  766. /* do_csi - the real ANSI interpreter
  767.  */
  768. do_csi()
  769. {
  770. register int i, ch;
  771. int private;
  772.  
  773.     if ((ch = nextch()) == EOF)
  774.     return;
  775.  
  776.     /* Check if private VT100 esc sequence */
  777.     private = 0;
  778.     if (ch == '?') {
  779.     private++;
  780.     if ((ch = nextch()) == EOF)
  781.         return;
  782.     }
  783.  
  784.     /* Parse arguments */
  785.     argno = 0;
  786.     while ((ch >= '0' && ch <= '9') || ch == ';') {
  787.     arg[argno] = 0;
  788.     while (ch >= '0' && ch <= '9') {
  789.         arg[argno] = arg[argno] * 10 + (ch - '0');
  790.         if ((ch = nextch()) == EOF)
  791.         return;
  792.     }
  793.     if (ch == ';')
  794.         if ((ch = nextch()) == EOF)
  795.         return;
  796.     argno++;
  797.     }
  798.  
  799.     if (private) {
  800.     if (argno != 1)
  801.         return;
  802.     switch (ch) {
  803.         case 'h':
  804.         switch (arg[0]) {
  805.             case 6:
  806.             origin_mode++; break;
  807.             case 7:
  808.             wrap++; break;
  809.         } break;
  810.         case 'l':
  811.         switch (arg[0]) {
  812.             case 2:
  813.             vt52_mode = 1; break;
  814.             case 6:
  815.             origin_mode = 0; break;
  816.             case 7:
  817.             wrap = 0; break;
  818.         } break;
  819.     }
  820.     }
  821.     else {
  822.     switch (ch) {
  823.         case 'A':
  824.         i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
  825.         while (i-- && row > 1) {
  826.             cursor_up();
  827.             row--;
  828.         } break;
  829.  
  830.         case 'B':
  831.         i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
  832.         while (i-- && row < bottom_margin-top_margin+1) {
  833.             cursor_down();
  834.             row++;
  835.         } break;
  836.  
  837.         case 'C':
  838.         i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
  839.         while (i-- && col < 80) {
  840.             cursor_right();
  841.             col++;
  842.         } break;
  843.  
  844.         case 'D':
  845.         i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
  846.         while (i-- && col > 1) {
  847.             backspace();
  848.             col--;
  849.         } break;
  850.  
  851.         case 'H':
  852.         case 'f':
  853.         do_set_cursor(); break;
  854.         case 'J':
  855.         do_erase_in_display(); break;
  856.         case 'K':
  857.         do_erase_in_line(); break;
  858.         case 'L':
  859.         do_insert_line(); break;
  860.         case 'M':
  861.         do_delete_line(); break;
  862.         case 'g':
  863.             do_clear_tabs(); break;
  864.         case 'm':
  865.         do_attributes(); break;
  866.         case 'r':
  867.         do_set_scroll_region();
  868.     }
  869.     }
  870. }
  871.  
  872. /* do_vt52_escape - interprets VT52 escape sequences
  873.  */
  874. do_vt52_escape()
  875. {
  876. register int ch;
  877.  
  878.     if ((ch = nextch()) == EOF)
  879.     return;
  880.     switch (ch) {
  881.     case '<':
  882.         vt52_mode = 0; break;
  883.     case 'A':
  884.         if (row > 1) {
  885.             cursor_up();
  886.             row--;
  887.         } break;
  888.     case 'B':
  889.         if (row < bottom_margin-top_margin+1) {
  890.             cursor_down();
  891.             row++;
  892.         } break;
  893.     case 'C':
  894.         if (col < 80) {
  895.             cursor_right();
  896.             col++;
  897.         } break;
  898.     case 'D':
  899.         if (col > 1) {
  900.             backspace();
  901.             col--;
  902.         } break;
  903.     case 'H':
  904.         row = col = 1;
  905.         set_cursor(col-1, arow-1); break;
  906.     case 'I':
  907.         do_reverse_lf(); break;
  908.     case 'J':
  909.         clear_eos(); break;
  910.     case 'K':
  911.         clear_eol(col-1, arow-1); break;
  912.     case 'Y':
  913.         do_vt52_set_cursor(); break;
  914.     }
  915. }
  916.  
  917.  
  918. do_set_cursor()
  919. {
  920.     if (arg[0] == 0)
  921.     arg[0]++;
  922.     if (arg[1] == 0)
  923.     arg[1]++;
  924.     switch (argno) {
  925.     case 0:
  926.         arg[0] = 1;
  927.         argno++;
  928.         /* Fall through */
  929.  
  930.     case 1:
  931.         arg[1] = 1;        /* Correct? */
  932.         argno++;
  933.         /* Fall through... */
  934.  
  935.     case 2:
  936.         row = arg[0];
  937.         col = arg[1];
  938.         set_cursor(col-1, arow-1);
  939.         break;
  940.     }
  941. }
  942.  
  943. do_vt52_set_cursor()
  944. {
  945. register int ch1, ch2;
  946.  
  947.     if ((ch1 = nextch()) == EOF)
  948.     return;
  949.     if ((ch2 = nextch()) == EOF)
  950.     return;
  951.     ch1 -= 0x1f;
  952.     ch2 -= 0x1f;
  953.     if (ch1 >= 1 && ch1 <= 24 && ch2 >= 1 && ch2 <= 80) {
  954.         row = ch1;
  955.         col = ch2;
  956.         set_cursor(col-1, arow-1);
  957.     }
  958. }
  959.  
  960. do_erase_in_display()
  961. {
  962.     switch (argno) {
  963.     case 0:
  964.         arg[0] = 0;
  965.         argno++;
  966.         /* Fall through */
  967.     case 1:
  968.         switch (arg[0]) {
  969.         case 0:
  970.             clear_eos();
  971.             break;
  972.         case 1:
  973.             clear_bos(col-1, arow-1);
  974.             break;
  975.         case 2:
  976.             clear_screen();
  977.             set_cursor(col-1, arow-1);
  978.             break;
  979.         }
  980.         break;
  981.     }
  982. }
  983.  
  984. do_erase_in_line()
  985. {
  986.     switch(argno) {
  987.     case 0:
  988.         arg[0] = 0;
  989.         argno++;
  990.         /* fall through */
  991.     case 1:
  992.         switch (arg[0]) {
  993.         case 0:
  994.             clear_eol(col-1, arow-1);
  995.             break;
  996.         case 1:
  997.             clear_bol(col-1, arow-1);
  998.             break;
  999.         case 2:
  1000.             cr();
  1001.             clear_eol(0, arow-1);
  1002.             set_cursor(col-1, arow-1);
  1003.             break;
  1004.         } break;
  1005.     }
  1006. }
  1007.  
  1008. do_clear_tabs()
  1009. {
  1010. register int i;
  1011.  
  1012.     if (argno == 0)
  1013.     arg[argno++] = 0;
  1014.     switch (arg[0]) {
  1015.     case 0:
  1016.         tabs[col-1] = 0; break;
  1017.     case 3:
  1018.         for (i = 0; i<80; i++)
  1019.         tabs[i] = 0; break;
  1020.     } 
  1021. }
  1022.  
  1023. do_attributes()
  1024. {
  1025. register int i;
  1026.  
  1027.     if (argno == 0) {
  1028.     arg[0] = 0;
  1029.     argno++;
  1030.     }
  1031.     for (i=0; i<argno; i++) {
  1032.     switch (arg[i]) {
  1033.         case 0:
  1034.         end_attributes();
  1035.         bold = underline = blink = reverse = 0;
  1036.         break;
  1037.         case 1:
  1038.         start_bold();
  1039.         bold++; break;
  1040.  
  1041.         case 4:
  1042.         start_underline();
  1043.         underline++; break;
  1044.  
  1045.         case 5:
  1046.         start_blink();
  1047.         blink++; break;
  1048.  
  1049.         case 7:
  1050.         start_reverse();
  1051.         reverse++; break;
  1052.     }
  1053.     }
  1054. }
  1055.  
  1056. do_set_scroll_region()
  1057. {
  1058.     if (arg[0] == 0)
  1059.     arg[0]++;
  1060.     if (arg[1] == 0)
  1061.     arg[1]++;
  1062.     switch (argno) {
  1063.     case 0:
  1064.         arg[0] = 1;
  1065.         arg[1] = 24;
  1066.         argno = 2;
  1067.         /* Fall through */
  1068.  
  1069.     case 2:
  1070.         top_margin = arg[0];
  1071.         bottom_margin = arg[1];
  1072.         col = row = 1;
  1073.         set_cursor(col-1, arow-1);
  1074.         break;
  1075.     }
  1076. }
  1077.  
  1078. do_linefeed()
  1079. {
  1080.     if (arow == bottom_margin) {
  1081.     if (bottom_margin < LI) {
  1082.         scroll_region(top_margin-1, bottom_margin-1, TRUE);
  1083.         set_cursor(col-1, arow-1);
  1084.     }
  1085.     else
  1086.         linefeed();
  1087.     }
  1088.     else if (arow < 24) {
  1089.     row++;
  1090.     linefeed();
  1091.     }
  1092. }
  1093.  
  1094. do_reverse_lf()
  1095. {
  1096.     if (arow == top_margin) {
  1097.     scroll_region(top_margin-1, bottom_margin-1, FALSE);
  1098.     set_cursor(col-1, arow-1);
  1099.     }
  1100.     else if (arow > 1) {
  1101.     row--;
  1102.     reverse_lf();
  1103.     }
  1104. }
  1105.  
  1106. do_hash()
  1107. {
  1108. register int ch, i, j;
  1109.  
  1110.     if ((ch = nextch()) == EOF)
  1111.     return;
  1112.     switch(ch) {
  1113.     case '8':
  1114.         for (i=1; i<=24; i++) {
  1115.         set_cursor(0, i-1);
  1116.         for (j=1; j <= ((i==24)?79:80); j++)
  1117.             putchar('E');
  1118.         }
  1119.         row = col = 1;
  1120.         set_cursor(col-1, arow-1);        /* Correct? */
  1121.         break;
  1122.     }         
  1123. }
  1124.  
  1125. /* do_characters_sets - Not implemented
  1126.  */
  1127. do_character_sets()
  1128. {
  1129.     nextch();            /* Ignore for now */
  1130. }
  1131.  
  1132. /* do_reset - Reset emulator and screen
  1133.  */
  1134. do_reset()
  1135. {
  1136. register int i;
  1137.  
  1138.     clear_screen();
  1139.     row = 1;
  1140.     col = 1;
  1141.     top_margin = 1;
  1142.     bottom_margin = 24;
  1143.     origin_mode = 0;
  1144.     vt52_mode = 0;
  1145.     wrap = 1;
  1146.     save_row = -1;            /* So we know we haven't saved */
  1147.     for (i=0; i<80; i++)
  1148.     tabs[i] = ((i/8)*8 == i);
  1149. }
  1150.  
  1151. /* The following are routines for VT102 compatibility
  1152.  */
  1153.  
  1154. do_insert_line()
  1155. {
  1156. /* Not yet implemented */
  1157. }
  1158.  
  1159. do_delete_line()
  1160. {
  1161. /* Not yet implemented */
  1162. }
  1163. @//E*O*F out.c//
  1164. chmod u=rw,g=r,o=r out.c
  1165.  
  1166. exit 0
  1167.  
  1168.