2.11BSD/src/ucb/window/README

@(#)README	3.6 4/24/85

/*
 * Copyright (c) 1983 Regents of the University of California,
 * All rights reserved.  Redistribution permitted subject to
 * the terms of the Berkeley Software License Agreement.
 */

Compilation notes:

     There is only one compiler option:

	mc68000		use 68000 byte ordering
			It should already be defined in the preprocessor.

     The file local.h contains locally tunable constants.

     The makefile should be updated with mkmf.  The only library it needs
is termcap (and jobs for 4.1).

     Window only runs on 4.2 machines.


A few notes about the internals:

     The window package.  Windows are opened by calling wwopen().
Wwwrite() is the primitive for writing to windows.  Wwputc(), wwputs(),
and wwprintf() are also supported.  Some of the outputs to windows are
delayed.  Wwupdate() updates the terminal to match the internal screen
buffer.  Wwspawn() spawns a child process on the other end of a window,
with it's environment tailored to the window.  Visible windows are
doubly linked in the order of their overlap.  Wwadd() inserts a window
into the list at a given place.  Wwdelete() deletes it.  Windows not in
the list are not visible, though wwwrite() still works.

     Most functions return -1 on error.  Wwopen() returns the null
pointer.  An error number is saved in wwerrno.  Wwerror() returns an
error string based on wwerrno suitable for printing.

     The terminal drivers perform all output to the physical terminal,
including special functions like character and line insertion and
deletion.  The window package keeps a list of known terminals.  At
initialization time, the terminal type is matched against the list to
find the right terminal driver to use.  The last driver, the generic
driver, matches all terminals and uses the termcap database.  The
interface between the window package the terminal driver is the `tt'
structure.  It contains pointers to functions to perform special
functions and terminal output, as well as flags about the
characteristics of the terminal.

     The IO system is semi-synchronous.  Terminal input is signal
driven, and everything else is done synchronously with a single
select().

     Normally, in both conversation mode and command mode, window
sleeps in a select() in wwiomux() waiting for data from the
pseudo-terminals.  At the same time, terminal input causes SIGIO which
is caught by wwrint().  The select() returns when at least one of the
pseudo-terminals becomes ready for reading.

     Wwrint() is the interrupt handler for tty input.  It reads input
into a linear buffer accessed through four pointers:

	+-------+--------------+----------------+
	| empty |    data      |   empty	|
	+-------+--------------+----------------+
	^	^		^		 ^
	|	|		|		 |
       wwib    wwibp	       wwibq		wwibe

Wwrint() appends characters at the end and increments wwibq (*wwibq++ =
c), and characters are taken from the buffer at wwibp using the
wwgetc() and wwpeekc() macros.  As is the convention in C, wwibq and
wwibe point to one position beyond the end.  In addition, wwrint() will
do a longjmp(wwjmpbuf) if wwsetjmp is true.  This is used by wwiomux()
to interrupt the select() which would otherwise resume after the
interrupt.  The macro wwinterrupt() returns true if the input buffer is
non-empty.  Wwupdate(), wwwrite(), and wwiomux() check this condition
and will return at the first convenient opportunity when it becomes
true.  In the case of wwwrite(), the flag ww_nointr in the window
structure overrides this.  This feature allows the user to interrupt
lengthy outputs safely.  The structure of the input buffer is designed
to avoid race conditions without blocking interrupts.

     Wwiomux() copies pseudo-terminal outputs into their corresponding
windows.  Without anything to do, it blocks in a select(), waiting for
read ready on pseudo-terminals.  Reads are done into per-window buffers
in the window structures.  When there is at least one buffer non-empty,
wwiomux() finds the top most of these windows and writes it using
wwwrite().  Then the process is repeated.  A non-blocking select() is
done after a wwwrite() to pick up any output that may have come in
during the write, which may take a long time.  Specifically, we use
this to stop output or flush buffer when a pseudo-terminal tells us to
(we use pty packet mode).  The select() blocks only when all of the
windows' buffers are empty.  A wwupdate() is done prior to this, which
is the only time the screen is guaranteed to be completely up to date.
Wwiomux() loops until wwinterrupt() becomes true.

     The top level routine for all this is mloop().  In conversation
mode, it simply calls wwiomux(), which only returns when input is
available.  The input buffer is then written to the pseudo-terminal of
the current window.  If the escape character is found in the input,
command mode is entered.  Otherwise, the process is repeated.  In
command mode, control is transferred to docmd() which returns only when
conversation mode is reentered.  Docmd() and other command processing
routines typically wait for input in a loop:

	while (wwpeekc() < 0)
		wwiomux();

When the loop terminates, wwgetc() is used to read the input buffer.

     Output to the physical terminal is handled by the lowest level
routines of the window package, in the files ttoutput.c and tt.h.  The
standard IO package is not used, to get better control over buffering
and to use non-blocking reads in wwrint().  The buffer size is set to
approximately one second of output time, based on the baudrate.

     The result of all this complexity is faster response time,
especially in output stopping and flushing.  Wwwrite() checks
wwinterrupt() after every line.  It also calls wwupdate() for each line
it writes.  The output buffer is limited to one second of output time.
Thus, there is usually only a delay of one to two lines plus one second
after a ^C or ^S.  Also, commands that produce lengthy output can be
aborted without actually showing all of it on the terminal.  (Try the
'?' command followed by escape immediately.)