xref: /csrg-svn/usr.bin/window/README (revision 33514)
118742Sedward/*
2*33514Sbostic * Copyright (c) 1983 Regents of the University of California.
3*33514Sbostic * All rights reserved.
4*33514Sbostic *
5*33514Sbostic * Redistribution and use in source and binary forms are permitted
6*33514Sbostic * provided that this notice is preserved and that due credit is given
7*33514Sbostic * to the University of California at Berkeley. The name of the University
8*33514Sbostic * may not be used to endorse or promote products derived from this
9*33514Sbostic * software without specific prior written permission. This software
10*33514Sbostic * is provided ``as is'' without express or implied warranty.
11*33514Sbostic *
12*33514Sbostic *	@(#)README	3.9 (Berkeley) 02/21/88
1318742Sedward */
1418742Sedward
1516284SedwardCompilation notes:
1615556Sedward
1716398Sedward     There is only one compiler option:
1816284Sedward
1932343Sedward	vax		use Vax byte ordering (found in ww.h)
2016535Sedward			It should already be defined in the preprocessor.
2132343Sedward			It turns out that all of the other machines that
2232343Sedward			I know are running window (68000, CCI, MIPS) are
2332343Sedward			big endians, so the single "#ifdef vax" suffices.
2415556Sedward
2532343Sedward     Ok, there's another one, STR_DEBUG.  It turns on consistency checks
2632343Sedward     in the string allocator.  It's been left on since performace doesn't
2732343Sedward     seem to suffer.  There's an abort() somewhere when an inconsistency
2832343Sedward     is found.  It hasn't happened in years.
2932343Sedward
3016398Sedward     The file local.h contains locally tunable constants.
3115556Sedward
3232343Sedward     The makefile used to be updated with mkmf; it has been changed
3332343Sedwardat various times to use cpp -M and, currently, mkdep.  The only library
3432343Sedwardit needs is termcap.
3515556Sedward
3629718Sedward     Window, as is, only runs on 4.3 machines.
3715556Sedward
3829718Sedward     On 4.2 machines, at least these modifications must be done:
3915556Sedward
4029718Sedward	delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ,
4129718Sedward		struct winsize
4229718Sedward	add to ww.h
4329718Sedward		typedef int fd_set;
4429718Sedward		#define FD_ZERO(s) (*(s) = 0)
4529718Sedward		#define FD_SET(b, s) (*(s) |= 1 << (b))
4629718Sedward		#define FD_ISSET(b, s) (*(s) & 1 << (b))
4729718Sedward	add to ww.h
4829718Sedward		#define sigmask(s) (1 << (s) - 1)
4929718Sedward
5029718Sedward
5116284SedwardA few notes about the internals:
5216284Sedward
5316284Sedward     The window package.  Windows are opened by calling wwopen().
5416284SedwardWwwrite() is the primitive for writing to windows.  Wwputc(), wwputs(),
5516284Sedwardand wwprintf() are also supported.  Some of the outputs to windows are
5616284Sedwarddelayed.  Wwupdate() updates the terminal to match the internal screen
5716284Sedwardbuffer.  Wwspawn() spawns a child process on the other end of a window,
5832343Sedwardwith its environment tailored to the window.  Visible windows are
5916284Sedwarddoubly linked in the order of their overlap.  Wwadd() inserts a window
6016535Sedwardinto the list at a given place.  Wwdelete() deletes it.  Windows not in
6132343Sedwardthe list are not visible, though wwwrite() still works.  Window was
6232343Sedwardwritten before the days of X and Sunview, so some of the terminology
6332343Sedwardis not standard.
6416284Sedward
6516284Sedward     Most functions return -1 on error.  Wwopen() returns the null
6616535Sedwardpointer.  An error number is saved in wwerrno.  Wwerror() returns an
6716535Sedwarderror string based on wwerrno suitable for printing.
6816284Sedward
6916284Sedward     The terminal drivers perform all output to the physical terminal,
7016284Sedwardincluding special functions like character and line insertion and
7116284Sedwarddeletion.  The window package keeps a list of known terminals.  At
7216284Sedwardinitialization time, the terminal type is matched against the list to
7316284Sedwardfind the right terminal driver to use.  The last driver, the generic
7416284Sedwarddriver, matches all terminals and uses the termcap database.  The
7516284Sedwardinterface between the window package the terminal driver is the `tt'
7616284Sedwardstructure.  It contains pointers to functions to perform special
7716284Sedwardfunctions and terminal output, as well as flags about the
7832343Sedwardcharacteristics of the terminal.  Most of these ideas are borrowed
7932343Sedwardfrom the Maryland window package, which in turn is based on Goslin's
8032343SedwardEmacs.
8116284Sedward
8216535Sedward     The IO system is semi-synchronous.  Terminal input is signal
8316535Sedwarddriven, and everything else is done synchronously with a single
8432343Sedwardselect().  It is roughly event-driven, though not in a clean way.
8516284Sedward
8616535Sedward     Normally, in both conversation mode and command mode, window
8716535Sedwardsleeps in a select() in wwiomux() waiting for data from the
8816535Sedwardpseudo-terminals.  At the same time, terminal input causes SIGIO which
8916535Sedwardis caught by wwrint().  The select() returns when at least one of the
9016535Sedwardpseudo-terminals becomes ready for reading.
9116284Sedward
9216535Sedward     Wwrint() is the interrupt handler for tty input.  It reads input
9316535Sedwardinto a linear buffer accessed through four pointers:
9416284Sedward
9516284Sedward	+-------+--------------+----------------+
9616284Sedward	| empty |    data      |   empty	|
9716284Sedward	+-------+--------------+----------------+
9816284Sedward	^	^		^		 ^
9916284Sedward	|	|		|		 |
10016284Sedward       wwib    wwibp	       wwibq		wwibe
10116284Sedward
10232343SedwardWwrint() appends characters at the end and increments wwibq (*wwibq++
10332343Sedward= c), and characters are taken off the buffer at wwibp using the
10432343Sedwardwwgetc() and wwpeekc() macros.  As is the convention in C, wwibq
10532343Sedwardand wwibe point to one position beyond the end.  In addition,
10632343Sedwardwwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true.  This is
10732343Sedwardused by wwiomux() to interrupt the select() which would otherwise
10832343Sedwardresume after the interrupt.  (Actually, I hear this is not true,
10932343Sedwardbut the longjmp feature is used to avoid a race condition as well.
11032343SedwardAnyway, it means I didn't have to depend on a feature in a
11132343Sedwarddaily-changing kernel, but that's another story.) The macro
11232343Sedwardwwinterrupt() returns true if the input buffer is non-empty.
11332343SedwardWwupdate(), wwwrite(), and wwiomux() check this condition and will
11432343Sedwardreturn at the first convenient opportunity when it becomes true.
11532343SedwardIn the case of wwwrite(), the flag ww_nointr in the window structure
11632343Sedwardoverrides this.  This feature allows the user to interrupt lengthy
11732343Sedwardoutputs safely.  The structure of the input buffer is designed to
11832343Sedwardavoid race conditions without blocking interrupts.
11916284Sedward
12032343Sedward     Actually, wwsetjmp and wwinterrupt() are part of a software
12132343Sedwardinterrupt scheme used by the two interrupt catchers wwrint() and
12232343Sedwardwwchild().  Asserting the interrupt lets the synchronous parts of
12332343Sedwardthe program know that there's an interesting asynchronous condition
12432343Sedward(i.e., got a keyboard character, or a child process died) that they
12532343Sedwardmight want to process before anything else.  The synchronous routines
12632343Sedwardcan check for this condition with wwinterrupt() or by arranging
12732343Sedwardthat a longjmp() be done.
12832343Sedward
12932343Sedward     Wwiomux() copies pseudo-terminal output into their corresponding
13016284Sedwardwindows.  Without anything to do, it blocks in a select(), waiting for
13116284Sedwardread ready on pseudo-terminals.  Reads are done into per-window buffers
13216284Sedwardin the window structures.  When there is at least one buffer non-empty,
13316284Sedwardwwiomux() finds the top most of these windows and writes it using
13416535Sedwardwwwrite().  Then the process is repeated.  A non-blocking select() is
13516535Sedwarddone after a wwwrite() to pick up any output that may have come in
13616535Sedwardduring the write, which may take a long time.  Specifically, we use
13716535Sedwardthis to stop output or flush buffer when a pseudo-terminal tells us to
13816535Sedward(we use pty packet mode).  The select() blocks only when all of the
13916535Sedwardwindows' buffers are empty.  A wwupdate() is done prior to this, which
14016535Sedwardis the only time the screen is guaranteed to be completely up to date.
14116535SedwardWwiomux() loops until wwinterrupt() becomes true.
14216284Sedward
14316535Sedward     The top level routine for all this is mloop().  In conversation
14416535Sedwardmode, it simply calls wwiomux(), which only returns when input is
14516535Sedwardavailable.  The input buffer is then written to the pseudo-terminal of
14616535Sedwardthe current window.  If the escape character is found in the input,
14716535Sedwardcommand mode is entered.  Otherwise, the process is repeated.  In
14816535Sedwardcommand mode, control is transferred to docmd() which returns only when
14916535Sedwardconversation mode is reentered.  Docmd() and other command processing
15016535Sedwardroutines typically wait for input in a loop:
15116284Sedward
15216535Sedward	while (wwpeekc() < 0)
15316284Sedward		wwiomux();
15416284Sedward
15516535SedwardWhen the loop terminates, wwgetc() is used to read the input buffer.
15616284Sedward
15716284Sedward     Output to the physical terminal is handled by the lowest level
15816284Sedwardroutines of the window package, in the files ttoutput.c and tt.h.  The
15916535Sedwardstandard IO package is not used, to get better control over buffering
16016535Sedwardand to use non-blocking reads in wwrint().  The buffer size is set to
16116284Sedwardapproximately one second of output time, based on the baudrate.
16216284Sedward
16316284Sedward     The result of all this complexity is faster response time,
16416284Sedwardespecially in output stopping and flushing.  Wwwrite() checks
16516284Sedwardwwinterrupt() after every line.  It also calls wwupdate() for each line
16616284Sedwardit writes.  The output buffer is limited to one second of output time.
16716284SedwardThus, there is usually only a delay of one to two lines plus one second
16816284Sedwardafter a ^C or ^S.  Also, commands that produce lengthy output can be
16916284Sedwardaborted without actually showing all of it on the terminal.  (Try the
17016535Sedward'?' command followed by escape immediately.)
171