xref: /csrg-svn/usr.bin/window/README (revision 36258)
118742Sedward/*
233514Sbostic * Copyright (c) 1983 Regents of the University of California.
333514Sbostic * All rights reserved.
433514Sbostic *
533514Sbostic * Redistribution and use in source and binary forms are permitted
634988Sbostic * provided that the above copyright notice and this paragraph are
734988Sbostic * duplicated in all such forms and that any documentation,
834988Sbostic * advertising materials, and other materials related to such
934988Sbostic * distribution and use acknowledge that the software was developed
1034988Sbostic * by the University of California, Berkeley.  The name of the
1134988Sbostic * University may not be used to endorse or promote products derived
1234988Sbostic * from this software without specific prior written permission.
1334988Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434988Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534988Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1633514Sbostic *
17*36258Sedward *	@(#)README	3.12 (Berkeley) 11/23/88
1818742Sedward */
1918742Sedward
2016284SedwardCompilation notes:
2115556Sedward
2216398Sedward     There is only one compiler option:
2316284Sedward
24*36258Sedward	BYTE_ORDER (used only in ww.h)
25*36258Sedward		It should already be defined in machine/endian.h.
26*36258Sedward		The code knows about BIG_ENDIAN, LITTLE_ENDIAN, and PDP_ENDIAN.
27*36258Sedward		It only cares about byte order in words, so PDP_ENDIAN
28*36258Sedward		is the same as LITTLE_ENDIAN.
2915556Sedward
3032343Sedward     Ok, there's another one, STR_DEBUG.  It turns on consistency checks
3132343Sedward     in the string allocator.  It's been left on since performace doesn't
3232343Sedward     seem to suffer.  There's an abort() somewhere when an inconsistency
3332343Sedward     is found.  It hasn't happened in years.
3432343Sedward
3516398Sedward     The file local.h contains locally tunable constants.
3615556Sedward
3732343Sedward     The makefile used to be updated with mkmf; it has been changed
3832343Sedwardat various times to use cpp -M and, currently, mkdep.  The only library
3932343Sedwardit needs is termcap.
4015556Sedward
4129718Sedward     Window, as is, only runs on 4.3 machines.
4215556Sedward
4329718Sedward     On 4.2 machines, at least these modifications must be done:
4415556Sedward
4529718Sedward	delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ,
4629718Sedward		struct winsize
4729718Sedward	add to ww.h
4829718Sedward		typedef int fd_set;
4929718Sedward		#define FD_ZERO(s) (*(s) = 0)
5029718Sedward		#define FD_SET(b, s) (*(s) |= 1 << (b))
5129718Sedward		#define FD_ISSET(b, s) (*(s) & 1 << (b))
5229718Sedward	add to ww.h
5329718Sedward		#define sigmask(s) (1 << (s) - 1)
5429718Sedward
5529718Sedward
5616284SedwardA few notes about the internals:
5716284Sedward
5816284Sedward     The window package.  Windows are opened by calling wwopen().
5916284SedwardWwwrite() is the primitive for writing to windows.  Wwputc(), wwputs(),
6016284Sedwardand wwprintf() are also supported.  Some of the outputs to windows are
6116284Sedwarddelayed.  Wwupdate() updates the terminal to match the internal screen
6216284Sedwardbuffer.  Wwspawn() spawns a child process on the other end of a window,
6332343Sedwardwith its environment tailored to the window.  Visible windows are
6416284Sedwarddoubly linked in the order of their overlap.  Wwadd() inserts a window
6516535Sedwardinto the list at a given place.  Wwdelete() deletes it.  Windows not in
6632343Sedwardthe list are not visible, though wwwrite() still works.  Window was
6732343Sedwardwritten before the days of X and Sunview, so some of the terminology
6832343Sedwardis not standard.
6916284Sedward
7016284Sedward     Most functions return -1 on error.  Wwopen() returns the null
7116535Sedwardpointer.  An error number is saved in wwerrno.  Wwerror() returns an
7216535Sedwarderror string based on wwerrno suitable for printing.
7316284Sedward
7416284Sedward     The terminal drivers perform all output to the physical terminal,
7516284Sedwardincluding special functions like character and line insertion and
7616284Sedwarddeletion.  The window package keeps a list of known terminals.  At
7716284Sedwardinitialization time, the terminal type is matched against the list to
7816284Sedwardfind the right terminal driver to use.  The last driver, the generic
7916284Sedwarddriver, matches all terminals and uses the termcap database.  The
8016284Sedwardinterface between the window package the terminal driver is the `tt'
8116284Sedwardstructure.  It contains pointers to functions to perform special
8216284Sedwardfunctions and terminal output, as well as flags about the
8332343Sedwardcharacteristics of the terminal.  Most of these ideas are borrowed
8432343Sedwardfrom the Maryland window package, which in turn is based on Goslin's
8532343SedwardEmacs.
8616284Sedward
8716535Sedward     The IO system is semi-synchronous.  Terminal input is signal
8816535Sedwarddriven, and everything else is done synchronously with a single
8932343Sedwardselect().  It is roughly event-driven, though not in a clean way.
9016284Sedward
9116535Sedward     Normally, in both conversation mode and command mode, window
9216535Sedwardsleeps in a select() in wwiomux() waiting for data from the
9316535Sedwardpseudo-terminals.  At the same time, terminal input causes SIGIO which
9416535Sedwardis caught by wwrint().  The select() returns when at least one of the
9516535Sedwardpseudo-terminals becomes ready for reading.
9616284Sedward
9716535Sedward     Wwrint() is the interrupt handler for tty input.  It reads input
9816535Sedwardinto a linear buffer accessed through four pointers:
9916284Sedward
10016284Sedward	+-------+--------------+----------------+
10116284Sedward	| empty |    data      |   empty	|
10216284Sedward	+-------+--------------+----------------+
10316284Sedward	^	^		^		 ^
10416284Sedward	|	|		|		 |
10516284Sedward       wwib    wwibp	       wwibq		wwibe
10616284Sedward
10732343SedwardWwrint() appends characters at the end and increments wwibq (*wwibq++
10832343Sedward= c), and characters are taken off the buffer at wwibp using the
10932343Sedwardwwgetc() and wwpeekc() macros.  As is the convention in C, wwibq
11032343Sedwardand wwibe point to one position beyond the end.  In addition,
11132343Sedwardwwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true.  This is
11232343Sedwardused by wwiomux() to interrupt the select() which would otherwise
11332343Sedwardresume after the interrupt.  (Actually, I hear this is not true,
11432343Sedwardbut the longjmp feature is used to avoid a race condition as well.
11532343SedwardAnyway, it means I didn't have to depend on a feature in a
11632343Sedwarddaily-changing kernel, but that's another story.) The macro
11732343Sedwardwwinterrupt() returns true if the input buffer is non-empty.
11832343SedwardWwupdate(), wwwrite(), and wwiomux() check this condition and will
11932343Sedwardreturn at the first convenient opportunity when it becomes true.
12032343SedwardIn the case of wwwrite(), the flag ww_nointr in the window structure
12132343Sedwardoverrides this.  This feature allows the user to interrupt lengthy
12232343Sedwardoutputs safely.  The structure of the input buffer is designed to
12332343Sedwardavoid race conditions without blocking interrupts.
12416284Sedward
12532343Sedward     Actually, wwsetjmp and wwinterrupt() are part of a software
12632343Sedwardinterrupt scheme used by the two interrupt catchers wwrint() and
12732343Sedwardwwchild().  Asserting the interrupt lets the synchronous parts of
12832343Sedwardthe program know that there's an interesting asynchronous condition
12932343Sedward(i.e., got a keyboard character, or a child process died) that they
13032343Sedwardmight want to process before anything else.  The synchronous routines
13132343Sedwardcan check for this condition with wwinterrupt() or by arranging
13232343Sedwardthat a longjmp() be done.
13332343Sedward
13432343Sedward     Wwiomux() copies pseudo-terminal output into their corresponding
13516284Sedwardwindows.  Without anything to do, it blocks in a select(), waiting for
13616284Sedwardread ready on pseudo-terminals.  Reads are done into per-window buffers
13716284Sedwardin the window structures.  When there is at least one buffer non-empty,
13816284Sedwardwwiomux() finds the top most of these windows and writes it using
13916535Sedwardwwwrite().  Then the process is repeated.  A non-blocking select() is
14016535Sedwarddone after a wwwrite() to pick up any output that may have come in
14116535Sedwardduring the write, which may take a long time.  Specifically, we use
14216535Sedwardthis to stop output or flush buffer when a pseudo-terminal tells us to
14316535Sedward(we use pty packet mode).  The select() blocks only when all of the
14416535Sedwardwindows' buffers are empty.  A wwupdate() is done prior to this, which
14516535Sedwardis the only time the screen is guaranteed to be completely up to date.
14616535SedwardWwiomux() loops until wwinterrupt() becomes true.
14716284Sedward
14816535Sedward     The top level routine for all this is mloop().  In conversation
14916535Sedwardmode, it simply calls wwiomux(), which only returns when input is
15016535Sedwardavailable.  The input buffer is then written to the pseudo-terminal of
15116535Sedwardthe current window.  If the escape character is found in the input,
15216535Sedwardcommand mode is entered.  Otherwise, the process is repeated.  In
15316535Sedwardcommand mode, control is transferred to docmd() which returns only when
15416535Sedwardconversation mode is reentered.  Docmd() and other command processing
15516535Sedwardroutines typically wait for input in a loop:
15616284Sedward
15716535Sedward	while (wwpeekc() < 0)
15816284Sedward		wwiomux();
15916284Sedward
16016535SedwardWhen the loop terminates, wwgetc() is used to read the input buffer.
16116284Sedward
16216284Sedward     Output to the physical terminal is handled by the lowest level
16316284Sedwardroutines of the window package, in the files ttoutput.c and tt.h.  The
16416535Sedwardstandard IO package is not used, to get better control over buffering
16516535Sedwardand to use non-blocking reads in wwrint().  The buffer size is set to
16616284Sedwardapproximately one second of output time, based on the baudrate.
16716284Sedward
16816284Sedward     The result of all this complexity is faster response time,
16916284Sedwardespecially in output stopping and flushing.  Wwwrite() checks
17016284Sedwardwwinterrupt() after every line.  It also calls wwupdate() for each line
17116284Sedwardit writes.  The output buffer is limited to one second of output time.
17216284SedwardThus, there is usually only a delay of one to two lines plus one second
17316284Sedwardafter a ^C or ^S.  Also, commands that produce lengthy output can be
17416284Sedwardaborted without actually showing all of it on the terminal.  (Try the
17516535Sedward'?' command followed by escape immediately.)
176