home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume7 / tm / tm.c < prev   
C/C++ Source or Header  |  1989-07-02  |  6KB  |  196 lines

  1. /* thisterm terminal emulator
  2.     By Troy Rollo 1989
  3.  
  4.     The thisterm terminal emulator is a minimum terminal
  5.     emulator for the apollo domains. This version has only
  6.     two control sequences:
  7.         Ctrl-L (ascii 0xc) clears the screen (pad)
  8.         An escape character followed by x+' ', y+' ' moves
  9.     to the given location in the pad.
  10.  
  11.     Additional control sequences can be created by modifying
  12.     the xfread routine. The ones already installed can, of course
  13.     be modified.
  14.  
  15.     Thisterm uses the pseudo tty device entries /dev/ptypb and
  16.     /dev/ttypb. An improved version would start at [pt]typ0 and work
  17.     up towards [pt]typf, allowing more than one thisterm
  18.     terminal emulator to run at once. It might also remove borders,
  19.     and use pad_$set_full_window and the current scale factor to
  20.     set the size of the window to match the size of the pseudo
  21.     screen.
  22.  
  23.     avenger@runx.ips.oz.au
  24.     s8730679@spectrum.eecs.unsw.oz.au (sometimes)
  25.     8730679@elec70a.eecs.unsw.oz.au (sometimes)
  26.     troy_rollo@712.502@fidogate.fido.oz.au (can't reply)
  27. */
  28.  
  29. #include <netdb.h>
  30. #include <stdio.h>
  31. #include <signal.h> 
  32. #include <fcntl.h>
  33. #include <apollo/base.h>
  34. #include <apollo/pad.h>
  35. #include <apollo/error.h>
  36.  
  37. #define COLUMNS 80
  38. #define ROWS 25
  39.  
  40. /* I think fd2p is a relic from a previous life. This program evolved
  41.     from an rexec patron */
  42. int fd2p = 1;
  43. status_$t status;
  44. stream_$sk_t sk = {
  45.         0l,
  46.         0l,
  47.         0l
  48.     };
  49.  
  50. /* Hmm... interesting... I don't actually use argc or argv */
  51. main(int argc, char **argv)
  52. {
  53.         char c[256];    
  54.         int cc;
  55.         int n;
  56.         int pn, pid;
  57.     int rem, proc;
  58.         
  59.  
  60.     /* put the pad in raw mode. This is a requirement for any terminal
  61.        emulator */
  62.     pad_$raw(1, &status);
  63.     /* Now open the master side of the pseudo tty */
  64.     rem=open("/dev/ptypb", O_RDWR);
  65.     /* And the slave side */
  66.     proc=open("/dev/ttypb", O_RDWR);
  67.         if (rem==-1 || proc==-1)
  68.         /* Complain if unable to open either - probably should
  69.            try to find another one */
  70.         exit(1);
  71.     if((pid=fork())==-1) {
  72.         fprintf(stderr, "%s: can't fork\n", argv[0]);
  73.         exit(1);
  74.     }
  75.     if (pid==0) {
  76.         /* This process lives on the slave side of the pseudo tty
  77.            Make the pseudo tty stdin, stdout and stderr */
  78.         close(0);
  79.         close(1);
  80.         close(2);
  81.         dup(proc);
  82.         dup(proc);
  83.         dup(proc);
  84.         close(proc);
  85.         close(rem);
  86.         /* I use ksh - you might prefer another shell */
  87.         execl("/bin/ksh", "ksh", "-i", 0);
  88.     }
  89.     close(proc);
  90.     /* Close the slave side so that when the last slave side process dies
  91.        or closes its last file descriptor we hear about it on the master side */
  92.         if ((pn=fork())==-1) {
  93.         fprintf(stderr, "%s: Can't fork\n", argv[0]);
  94.         kill(pid,9);
  95.         exit(1);
  96.         }
  97.     /* Create a frame to allow the cursor to roam around the pseudo screen */
  98.     pad_$create_frame(1, COLUMNS, ROWS, &status);
  99.     /* The parent reads on the master side (output of the slace side) until
  100.        there are no more processes writing on the pseudo tty. At this point
  101.        it enters a suicide pact - killing the child with a machine gun (signal
  102.        9) and dieing itself.
  103.        Intil it dies, the slave side transfers all stdin to the pseudo tty    */
  104.         if (pn!=0) {
  105.         while (xfread(rem) !=-1);
  106.         pad_$cooked(1, &status);
  107.         pad_$delete_frame(1, &status);
  108.         kill(pn, 9);
  109.         exit(0);
  110.         }
  111.         else {
  112.             while ((n=read(0, c, 255)) != 0)
  113.             write(rem, c, n);
  114.         }
  115. }
  116.  
  117.  
  118. /* xfread reads from the pseudo tty, and decides what to do about the output.
  119.    It's fairly straight forward - checks for any specified control character.
  120.    There is a bug in the newline sequence - if the user presses the page up or
  121.    shift-uparrow keys, you can't get back on the current frame.... perhaps these
  122.    keys should be redefined within the region of the pad.
  123.     Some enhancements might be:
  124.    A partial screen clearing option.
  125.    Scroll forward and back on demand.
  126.    Changing font (perhaps loading an inverse font and using it for highlight.
  127.     the following fonts could also prove useful as built-ins:
  128.       italics
  129.       bold
  130.       times_roman
  131.     as well as a pure graphics font (say, a 7x1 font with each character
  132.     representing a sequence of pixels in a vertical line)
  133.    This routine doesn't return until there are no more slaves using the pseudo
  134.    tty
  135. */
  136. int xfread(f)
  137. int f;
  138. {
  139.     char b;
  140.     short x, y;
  141.     long line, eof;
  142.     short xo, yo;
  143.  
  144.     while (kread(f,&b)!=-1)
  145.         if (b=='\033') {
  146.             kread(f,&b);
  147.             x=(short) (b-' '+1);
  148.             kread(f,&b);
  149.             y=(short) (b-' '+1);
  150.             pad_$inq_view(1, 1, &line, &eof, &xo, &yo, &status);
  151.             pad_$move(1,pad_$absolute,x,y+yo-1,&status);
  152.             write(1,"\0",2);
  153.         }
  154.         else if (b=='\014') {
  155.             pad_$clear_frame(1, sk, &status);
  156.             write(1,"\0",2);
  157.         }
  158.         else {
  159.             write(1,&b,1);
  160.             if (b=='\n') {
  161.                 pad_$inq_view(1, 1, &line, &eof, &xo, &yo, &status);
  162.                 pad_$inq_position(1, &x, &y, &status);
  163.                 if (y-yo+1==25) {
  164.                     pad_$set_view(1, 1, line, 1, yo+2, &status);
  165.                     pad_$create_frame(1, COLUMNS, ROWS, &status);
  166.                 }
  167.             }
  168.         }
  169.     return (-1);
  170. }
  171.  
  172. /* A buffered read - returns 1 on success, -1 on failure (just to be difficult for
  173.    anybody using it as the argument to if! And also for compatibility with the
  174.    values returned by Domain/IX
  175.    returns one character at a time, buffering them in a static 2048 byte buffer.
  176.    interesting things would happen if two different files were used as arguments
  177.    int different parts of the program, but it's probably not worth fixing */
  178. int kread(file, buffer)
  179. int file;
  180. char *buffer;
  181. {
  182.     static char BIGBUF[2048];
  183.     static int bbcnt = 0;
  184.     static int bbptr = 0;
  185.  
  186.     if (bbptr>=bbcnt) {
  187.         bbcnt=read(file, BIGBUF, 2048);
  188.         if (bbcnt==-1)
  189.             return(-1);
  190.         bbptr=0;
  191.     }
  192.     *buffer=BIGBUF[bbptr];
  193.     ++bbptr;
  194.     return(1);
  195. }
  196.