attach Berkeley specific copyright
[unix-history] / usr / src / usr.bin / window / README
CommitLineData
2514c570 1@(#)README 3.8 %G%
60de5df9
EW
2
3/*
4 * Copyright (c) 1983 Regents of the University of California,
5 * All rights reserved. Redistribution permitted subject to
6 * the terms of the Berkeley Software License Agreement.
7 */
84a5ea18 8
533eb3f8
EW
9Compilation notes:
10
7c38ad4d 11 There is only one compiler option:
84a5ea18 12
2514c570 13 vax use Vax byte ordering (found in ww.h)
115fa6f8 14 It should already be defined in the preprocessor.
2514c570
EW
15 It turns out that all of the other machines that
16 I know are running window (68000, CCI, MIPS) are
17 big endians, so the single "#ifdef vax" suffices.
18
19 Ok, there's another one, STR_DEBUG. It turns on consistency checks
20 in the string allocator. It's been left on since performace doesn't
21 seem to suffer. There's an abort() somewhere when an inconsistency
22 is found. It hasn't happened in years.
84a5ea18 23
7c38ad4d 24 The file local.h contains locally tunable constants.
84a5ea18 25
2514c570
EW
26 The makefile used to be updated with mkmf; it has been changed
27at various times to use cpp -M and, currently, mkdep. The only library
28it needs is termcap.
84a5ea18 29
113b73b6
EW
30 Window, as is, only runs on 4.3 machines.
31
32 On 4.2 machines, at least these modifications must be done:
33
34 delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ,
35 struct winsize
36 add to ww.h
37 typedef int fd_set;
38 #define FD_ZERO(s) (*(s) = 0)
39 #define FD_SET(b, s) (*(s) |= 1 << (b))
40 #define FD_ISSET(b, s) (*(s) & 1 << (b))
41 add to ww.h
42 #define sigmask(s) (1 << (s) - 1)
84a5ea18 43
84a5ea18 44
533eb3f8
EW
45A few notes about the internals:
46
47 The window package. Windows are opened by calling wwopen().
48Wwwrite() is the primitive for writing to windows. Wwputc(), wwputs(),
49and wwprintf() are also supported. Some of the outputs to windows are
50delayed. Wwupdate() updates the terminal to match the internal screen
51buffer. Wwspawn() spawns a child process on the other end of a window,
2514c570 52with its environment tailored to the window. Visible windows are
533eb3f8 53doubly linked in the order of their overlap. Wwadd() inserts a window
115fa6f8 54into the list at a given place. Wwdelete() deletes it. Windows not in
2514c570
EW
55the list are not visible, though wwwrite() still works. Window was
56written before the days of X and Sunview, so some of the terminology
57is not standard.
533eb3f8
EW
58
59 Most functions return -1 on error. Wwopen() returns the null
115fa6f8
EW
60pointer. An error number is saved in wwerrno. Wwerror() returns an
61error string based on wwerrno suitable for printing.
533eb3f8
EW
62
63 The terminal drivers perform all output to the physical terminal,
64including special functions like character and line insertion and
65deletion. The window package keeps a list of known terminals. At
66initialization time, the terminal type is matched against the list to
67find the right terminal driver to use. The last driver, the generic
68driver, matches all terminals and uses the termcap database. The
69interface between the window package the terminal driver is the `tt'
70structure. It contains pointers to functions to perform special
71functions and terminal output, as well as flags about the
2514c570
EW
72characteristics of the terminal. Most of these ideas are borrowed
73from the Maryland window package, which in turn is based on Goslin's
74Emacs.
533eb3f8 75
115fa6f8
EW
76 The IO system is semi-synchronous. Terminal input is signal
77driven, and everything else is done synchronously with a single
2514c570 78select(). It is roughly event-driven, though not in a clean way.
533eb3f8 79
115fa6f8
EW
80 Normally, in both conversation mode and command mode, window
81sleeps in a select() in wwiomux() waiting for data from the
82pseudo-terminals. At the same time, terminal input causes SIGIO which
83is caught by wwrint(). The select() returns when at least one of the
84pseudo-terminals becomes ready for reading.
533eb3f8 85
115fa6f8
EW
86 Wwrint() is the interrupt handler for tty input. It reads input
87into a linear buffer accessed through four pointers:
533eb3f8
EW
88
89 +-------+--------------+----------------+
90 | empty | data | empty |
91 +-------+--------------+----------------+
92 ^ ^ ^ ^
93 | | | |
94 wwib wwibp wwibq wwibe
95
2514c570
EW
96Wwrint() appends characters at the end and increments wwibq (*wwibq++
97= c), and characters are taken off the buffer at wwibp using the
98wwgetc() and wwpeekc() macros. As is the convention in C, wwibq
99and wwibe point to one position beyond the end. In addition,
100wwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is
101used by wwiomux() to interrupt the select() which would otherwise
102resume after the interrupt. (Actually, I hear this is not true,
103but the longjmp feature is used to avoid a race condition as well.
104Anyway, it means I didn't have to depend on a feature in a
105daily-changing kernel, but that's another story.) The macro
106wwinterrupt() returns true if the input buffer is non-empty.
107Wwupdate(), wwwrite(), and wwiomux() check this condition and will
108return at the first convenient opportunity when it becomes true.
109In the case of wwwrite(), the flag ww_nointr in the window structure
110overrides this. This feature allows the user to interrupt lengthy
111outputs safely. The structure of the input buffer is designed to
112avoid race conditions without blocking interrupts.
113
114 Actually, wwsetjmp and wwinterrupt() are part of a software
115interrupt scheme used by the two interrupt catchers wwrint() and
116wwchild(). Asserting the interrupt lets the synchronous parts of
117the program know that there's an interesting asynchronous condition
118(i.e., got a keyboard character, or a child process died) that they
119might want to process before anything else. The synchronous routines
120can check for this condition with wwinterrupt() or by arranging
121that a longjmp() be done.
122
123 Wwiomux() copies pseudo-terminal output into their corresponding
533eb3f8
EW
124windows. Without anything to do, it blocks in a select(), waiting for
125read ready on pseudo-terminals. Reads are done into per-window buffers
126in the window structures. When there is at least one buffer non-empty,
127wwiomux() finds the top most of these windows and writes it using
115fa6f8
EW
128wwwrite(). Then the process is repeated. A non-blocking select() is
129done after a wwwrite() to pick up any output that may have come in
130during the write, which may take a long time. Specifically, we use
131this to stop output or flush buffer when a pseudo-terminal tells us to
132(we use pty packet mode). The select() blocks only when all of the
133windows' buffers are empty. A wwupdate() is done prior to this, which
134is the only time the screen is guaranteed to be completely up to date.
135Wwiomux() loops until wwinterrupt() becomes true.
136
137 The top level routine for all this is mloop(). In conversation
138mode, it simply calls wwiomux(), which only returns when input is
139available. The input buffer is then written to the pseudo-terminal of
140the current window. If the escape character is found in the input,
141command mode is entered. Otherwise, the process is repeated. In
142command mode, control is transferred to docmd() which returns only when
143conversation mode is reentered. Docmd() and other command processing
144routines typically wait for input in a loop:
145
146 while (wwpeekc() < 0)
533eb3f8
EW
147 wwiomux();
148
115fa6f8 149When the loop terminates, wwgetc() is used to read the input buffer.
533eb3f8
EW
150
151 Output to the physical terminal is handled by the lowest level
152routines of the window package, in the files ttoutput.c and tt.h. The
115fa6f8
EW
153standard IO package is not used, to get better control over buffering
154and to use non-blocking reads in wwrint(). The buffer size is set to
533eb3f8
EW
155approximately one second of output time, based on the baudrate.
156
157 The result of all this complexity is faster response time,
158especially in output stopping and flushing. Wwwrite() checks
159wwinterrupt() after every line. It also calls wwupdate() for each line
160it writes. The output buffer is limited to one second of output time.
161Thus, there is usually only a delay of one to two lines plus one second
162after a ^C or ^S. Also, commands that produce lengthy output can be
163aborted without actually showing all of it on the terminal. (Try the
115fa6f8 164'?' command followed by escape immediately.)