1*32343Sedward@(#)README 3.8 10/06/87 215556Sedward 318742Sedward/* 418742Sedward * Copyright (c) 1983 Regents of the University of California, 518742Sedward * All rights reserved. Redistribution permitted subject to 618742Sedward * the terms of the Berkeley Software License Agreement. 718742Sedward */ 818742Sedward 916284SedwardCompilation notes: 1015556Sedward 1116398Sedward There is only one compiler option: 1216284Sedward 13*32343Sedward vax use Vax byte ordering (found in ww.h) 1416535Sedward It should already be defined in the preprocessor. 15*32343Sedward It turns out that all of the other machines that 16*32343Sedward I know are running window (68000, CCI, MIPS) are 17*32343Sedward big endians, so the single "#ifdef vax" suffices. 1815556Sedward 19*32343Sedward Ok, there's another one, STR_DEBUG. It turns on consistency checks 20*32343Sedward in the string allocator. It's been left on since performace doesn't 21*32343Sedward seem to suffer. There's an abort() somewhere when an inconsistency 22*32343Sedward is found. It hasn't happened in years. 23*32343Sedward 2416398Sedward The file local.h contains locally tunable constants. 2515556Sedward 26*32343Sedward The makefile used to be updated with mkmf; it has been changed 27*32343Sedwardat various times to use cpp -M and, currently, mkdep. The only library 28*32343Sedwardit needs is termcap. 2915556Sedward 3029718Sedward Window, as is, only runs on 4.3 machines. 3115556Sedward 3229718Sedward On 4.2 machines, at least these modifications must be done: 3315556Sedward 3429718Sedward delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ, 3529718Sedward struct winsize 3629718Sedward add to ww.h 3729718Sedward typedef int fd_set; 3829718Sedward #define FD_ZERO(s) (*(s) = 0) 3929718Sedward #define FD_SET(b, s) (*(s) |= 1 << (b)) 4029718Sedward #define FD_ISSET(b, s) (*(s) & 1 << (b)) 4129718Sedward add to ww.h 4229718Sedward #define sigmask(s) (1 << (s) - 1) 4329718Sedward 4429718Sedward 4516284SedwardA few notes about the internals: 4616284Sedward 4716284Sedward The window package. Windows are opened by calling wwopen(). 4816284SedwardWwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), 4916284Sedwardand wwprintf() are also supported. Some of the outputs to windows are 5016284Sedwarddelayed. Wwupdate() updates the terminal to match the internal screen 5116284Sedwardbuffer. Wwspawn() spawns a child process on the other end of a window, 52*32343Sedwardwith its environment tailored to the window. Visible windows are 5316284Sedwarddoubly linked in the order of their overlap. Wwadd() inserts a window 5416535Sedwardinto the list at a given place. Wwdelete() deletes it. Windows not in 55*32343Sedwardthe list are not visible, though wwwrite() still works. Window was 56*32343Sedwardwritten before the days of X and Sunview, so some of the terminology 57*32343Sedwardis not standard. 5816284Sedward 5916284Sedward Most functions return -1 on error. Wwopen() returns the null 6016535Sedwardpointer. An error number is saved in wwerrno. Wwerror() returns an 6116535Sedwarderror string based on wwerrno suitable for printing. 6216284Sedward 6316284Sedward The terminal drivers perform all output to the physical terminal, 6416284Sedwardincluding special functions like character and line insertion and 6516284Sedwarddeletion. The window package keeps a list of known terminals. At 6616284Sedwardinitialization time, the terminal type is matched against the list to 6716284Sedwardfind the right terminal driver to use. The last driver, the generic 6816284Sedwarddriver, matches all terminals and uses the termcap database. The 6916284Sedwardinterface between the window package the terminal driver is the `tt' 7016284Sedwardstructure. It contains pointers to functions to perform special 7116284Sedwardfunctions and terminal output, as well as flags about the 72*32343Sedwardcharacteristics of the terminal. Most of these ideas are borrowed 73*32343Sedwardfrom the Maryland window package, which in turn is based on Goslin's 74*32343SedwardEmacs. 7516284Sedward 7616535Sedward The IO system is semi-synchronous. Terminal input is signal 7716535Sedwarddriven, and everything else is done synchronously with a single 78*32343Sedwardselect(). It is roughly event-driven, though not in a clean way. 7916284Sedward 8016535Sedward Normally, in both conversation mode and command mode, window 8116535Sedwardsleeps in a select() in wwiomux() waiting for data from the 8216535Sedwardpseudo-terminals. At the same time, terminal input causes SIGIO which 8316535Sedwardis caught by wwrint(). The select() returns when at least one of the 8416535Sedwardpseudo-terminals becomes ready for reading. 8516284Sedward 8616535Sedward Wwrint() is the interrupt handler for tty input. It reads input 8716535Sedwardinto a linear buffer accessed through four pointers: 8816284Sedward 8916284Sedward +-------+--------------+----------------+ 9016284Sedward | empty | data | empty | 9116284Sedward +-------+--------------+----------------+ 9216284Sedward ^ ^ ^ ^ 9316284Sedward | | | | 9416284Sedward wwib wwibp wwibq wwibe 9516284Sedward 96*32343SedwardWwrint() appends characters at the end and increments wwibq (*wwibq++ 97*32343Sedward= c), and characters are taken off the buffer at wwibp using the 98*32343Sedwardwwgetc() and wwpeekc() macros. As is the convention in C, wwibq 99*32343Sedwardand wwibe point to one position beyond the end. In addition, 100*32343Sedwardwwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is 101*32343Sedwardused by wwiomux() to interrupt the select() which would otherwise 102*32343Sedwardresume after the interrupt. (Actually, I hear this is not true, 103*32343Sedwardbut the longjmp feature is used to avoid a race condition as well. 104*32343SedwardAnyway, it means I didn't have to depend on a feature in a 105*32343Sedwarddaily-changing kernel, but that's another story.) The macro 106*32343Sedwardwwinterrupt() returns true if the input buffer is non-empty. 107*32343SedwardWwupdate(), wwwrite(), and wwiomux() check this condition and will 108*32343Sedwardreturn at the first convenient opportunity when it becomes true. 109*32343SedwardIn the case of wwwrite(), the flag ww_nointr in the window structure 110*32343Sedwardoverrides this. This feature allows the user to interrupt lengthy 111*32343Sedwardoutputs safely. The structure of the input buffer is designed to 112*32343Sedwardavoid race conditions without blocking interrupts. 11316284Sedward 114*32343Sedward Actually, wwsetjmp and wwinterrupt() are part of a software 115*32343Sedwardinterrupt scheme used by the two interrupt catchers wwrint() and 116*32343Sedwardwwchild(). Asserting the interrupt lets the synchronous parts of 117*32343Sedwardthe program know that there's an interesting asynchronous condition 118*32343Sedward(i.e., got a keyboard character, or a child process died) that they 119*32343Sedwardmight want to process before anything else. The synchronous routines 120*32343Sedwardcan check for this condition with wwinterrupt() or by arranging 121*32343Sedwardthat a longjmp() be done. 122*32343Sedward 123*32343Sedward Wwiomux() copies pseudo-terminal output into their corresponding 12416284Sedwardwindows. Without anything to do, it blocks in a select(), waiting for 12516284Sedwardread ready on pseudo-terminals. Reads are done into per-window buffers 12616284Sedwardin the window structures. When there is at least one buffer non-empty, 12716284Sedwardwwiomux() finds the top most of these windows and writes it using 12816535Sedwardwwwrite(). Then the process is repeated. A non-blocking select() is 12916535Sedwarddone after a wwwrite() to pick up any output that may have come in 13016535Sedwardduring the write, which may take a long time. Specifically, we use 13116535Sedwardthis to stop output or flush buffer when a pseudo-terminal tells us to 13216535Sedward(we use pty packet mode). The select() blocks only when all of the 13316535Sedwardwindows' buffers are empty. A wwupdate() is done prior to this, which 13416535Sedwardis the only time the screen is guaranteed to be completely up to date. 13516535SedwardWwiomux() loops until wwinterrupt() becomes true. 13616284Sedward 13716535Sedward The top level routine for all this is mloop(). In conversation 13816535Sedwardmode, it simply calls wwiomux(), which only returns when input is 13916535Sedwardavailable. The input buffer is then written to the pseudo-terminal of 14016535Sedwardthe current window. If the escape character is found in the input, 14116535Sedwardcommand mode is entered. Otherwise, the process is repeated. In 14216535Sedwardcommand mode, control is transferred to docmd() which returns only when 14316535Sedwardconversation mode is reentered. Docmd() and other command processing 14416535Sedwardroutines typically wait for input in a loop: 14516284Sedward 14616535Sedward while (wwpeekc() < 0) 14716284Sedward wwiomux(); 14816284Sedward 14916535SedwardWhen the loop terminates, wwgetc() is used to read the input buffer. 15016284Sedward 15116284Sedward Output to the physical terminal is handled by the lowest level 15216284Sedwardroutines of the window package, in the files ttoutput.c and tt.h. The 15316535Sedwardstandard IO package is not used, to get better control over buffering 15416535Sedwardand to use non-blocking reads in wwrint(). The buffer size is set to 15516284Sedwardapproximately one second of output time, based on the baudrate. 15616284Sedward 15716284Sedward The result of all this complexity is faster response time, 15816284Sedwardespecially in output stopping and flushing. Wwwrite() checks 15916284Sedwardwwinterrupt() after every line. It also calls wwupdate() for each line 16016284Sedwardit writes. The output buffer is limited to one second of output time. 16116284SedwardThus, there is usually only a delay of one to two lines plus one second 16216284Sedwardafter a ^C or ^S. Also, commands that produce lengthy output can be 16316284Sedwardaborted without actually showing all of it on the terminal. (Try the 16416535Sedward'?' command followed by escape immediately.) 165