home *** CD-ROM | disk | FTP | other *** search
- /* thisterm terminal emulator
- By Troy Rollo 1989
-
- The thisterm terminal emulator is a minimum terminal
- emulator for the apollo domains. This version has only
- two control sequences:
- Ctrl-L (ascii 0xc) clears the screen (pad)
- An escape character followed by x+' ', y+' ' moves
- to the given location in the pad.
-
- Additional control sequences can be created by modifying
- the xfread routine. The ones already installed can, of course
- be modified.
-
- Thisterm uses the pseudo tty device entries /dev/ptypb and
- /dev/ttypb. An improved version would start at [pt]typ0 and work
- up towards [pt]typf, allowing more than one thisterm
- terminal emulator to run at once. It might also remove borders,
- and use pad_$set_full_window and the current scale factor to
- set the size of the window to match the size of the pseudo
- screen.
-
- avenger@runx.ips.oz.au
- s8730679@spectrum.eecs.unsw.oz.au (sometimes)
- 8730679@elec70a.eecs.unsw.oz.au (sometimes)
- troy_rollo@712.502@fidogate.fido.oz.au (can't reply)
- */
-
- #include <netdb.h>
- #include <stdio.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <apollo/base.h>
- #include <apollo/pad.h>
- #include <apollo/error.h>
-
- #define COLUMNS 80
- #define ROWS 25
-
- /* I think fd2p is a relic from a previous life. This program evolved
- from an rexec patron */
- int fd2p = 1;
- status_$t status;
- stream_$sk_t sk = {
- 0l,
- 0l,
- 0l
- };
-
- /* Hmm... interesting... I don't actually use argc or argv */
- main(int argc, char **argv)
- {
- char c[256];
- int cc;
- int n;
- int pn, pid;
- int rem, proc;
-
-
- /* put the pad in raw mode. This is a requirement for any terminal
- emulator */
- pad_$raw(1, &status);
- /* Now open the master side of the pseudo tty */
- rem=open("/dev/ptypb", O_RDWR);
- /* And the slave side */
- proc=open("/dev/ttypb", O_RDWR);
- if (rem==-1 || proc==-1)
- /* Complain if unable to open either - probably should
- try to find another one */
- exit(1);
- if((pid=fork())==-1) {
- fprintf(stderr, "%s: can't fork\n", argv[0]);
- exit(1);
- }
- if (pid==0) {
- /* This process lives on the slave side of the pseudo tty
- Make the pseudo tty stdin, stdout and stderr */
- close(0);
- close(1);
- close(2);
- dup(proc);
- dup(proc);
- dup(proc);
- close(proc);
- close(rem);
- /* I use ksh - you might prefer another shell */
- execl("/bin/ksh", "ksh", "-i", 0);
- }
- close(proc);
- /* Close the slave side so that when the last slave side process dies
- or closes its last file descriptor we hear about it on the master side */
- if ((pn=fork())==-1) {
- fprintf(stderr, "%s: Can't fork\n", argv[0]);
- kill(pid,9);
- exit(1);
- }
- /* Create a frame to allow the cursor to roam around the pseudo screen */
- pad_$create_frame(1, COLUMNS, ROWS, &status);
- /* The parent reads on the master side (output of the slace side) until
- there are no more processes writing on the pseudo tty. At this point
- it enters a suicide pact - killing the child with a machine gun (signal
- 9) and dieing itself.
- Intil it dies, the slave side transfers all stdin to the pseudo tty */
- if (pn!=0) {
- while (xfread(rem) !=-1);
- pad_$cooked(1, &status);
- pad_$delete_frame(1, &status);
- kill(pn, 9);
- exit(0);
- }
- else {
- while ((n=read(0, c, 255)) != 0)
- write(rem, c, n);
- }
- }
-
-
- /* xfread reads from the pseudo tty, and decides what to do about the output.
- It's fairly straight forward - checks for any specified control character.
- There is a bug in the newline sequence - if the user presses the page up or
- shift-uparrow keys, you can't get back on the current frame.... perhaps these
- keys should be redefined within the region of the pad.
- Some enhancements might be:
- A partial screen clearing option.
- Scroll forward and back on demand.
- Changing font (perhaps loading an inverse font and using it for highlight.
- the following fonts could also prove useful as built-ins:
- italics
- bold
- times_roman
- as well as a pure graphics font (say, a 7x1 font with each character
- representing a sequence of pixels in a vertical line)
- This routine doesn't return until there are no more slaves using the pseudo
- tty
- */
- int xfread(f)
- int f;
- {
- char b;
- short x, y;
- long line, eof;
- short xo, yo;
-
- while (kread(f,&b)!=-1)
- if (b=='\033') {
- kread(f,&b);
- x=(short) (b-' '+1);
- kread(f,&b);
- y=(short) (b-' '+1);
- pad_$inq_view(1, 1, &line, &eof, &xo, &yo, &status);
- pad_$move(1,pad_$absolute,x,y+yo-1,&status);
- write(1,"\0",2);
- }
- else if (b=='\014') {
- pad_$clear_frame(1, sk, &status);
- write(1,"\0",2);
- }
- else {
- write(1,&b,1);
- if (b=='\n') {
- pad_$inq_view(1, 1, &line, &eof, &xo, &yo, &status);
- pad_$inq_position(1, &x, &y, &status);
- if (y-yo+1==25) {
- pad_$set_view(1, 1, line, 1, yo+2, &status);
- pad_$create_frame(1, COLUMNS, ROWS, &status);
- }
- }
- }
- return (-1);
- }
-
- /* A buffered read - returns 1 on success, -1 on failure (just to be difficult for
- anybody using it as the argument to if! And also for compatibility with the
- values returned by Domain/IX
- returns one character at a time, buffering them in a static 2048 byte buffer.
- interesting things would happen if two different files were used as arguments
- int different parts of the program, but it's probably not worth fixing */
- int kread(file, buffer)
- int file;
- char *buffer;
- {
- static char BIGBUF[2048];
- static int bbcnt = 0;
- static int bbptr = 0;
-
- if (bbptr>=bbcnt) {
- bbcnt=read(file, BIGBUF, 2048);
- if (bbcnt==-1)
- return(-1);
- bbptr=0;
- }
- *buffer=BIGBUF[bbptr];
- ++bbptr;
- return(1);
- }
-