xref: /csrg-svn/usr.bin/window/README (revision 32343)
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