home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / window / README < prev    next >
Encoding:
Text File  |  1991-04-18  |  9.4 KB  |  195 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  *  Edward Wang at The University of California, Berkeley.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)README    3.13 (Berkeley) 6/6/90
  37.  */
  38.  
  39. Compilation notes:
  40.  
  41.      There is only one compiler option:
  42.  
  43.     BYTE_ORDER (used only in ww.h)
  44.         It should already be defined in machine/endian.h.
  45.         The code knows about BIG_ENDIAN, LITTLE_ENDIAN, and PDP_ENDIAN.
  46.         It only cares about byte order in words, so PDP_ENDIAN
  47.         is the same as LITTLE_ENDIAN.
  48.  
  49.      Ok, there's another one, STR_DEBUG.  It turns on consistency checks
  50.      in the string allocator.  It's been left on since performace doesn't
  51.      seem to suffer.  There's an abort() somewhere when an inconsistency
  52.      is found.  It hasn't happened in years.
  53.  
  54.      The file local.h contains locally tunable constants.
  55.  
  56.      The makefile used to be updated with mkmf; it has been changed
  57. at various times to use cpp -M and, currently, mkdep.  The only library
  58. it needs is termcap.
  59.  
  60.      Window, as is, only runs on 4.3 machines.
  61.  
  62.      On 4.2 machines, at least these modifications must be done:
  63.  
  64.     delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ,
  65.         struct winsize
  66.     add to ww.h
  67.         typedef int fd_set;
  68.         #define FD_ZERO(s) (*(s) = 0)
  69.         #define FD_SET(b, s) (*(s) |= 1 << (b))
  70.         #define FD_ISSET(b, s) (*(s) & 1 << (b))
  71.     add to ww.h
  72.         #define sigmask(s) (1 << (s) - 1)
  73.  
  74.  
  75. A few notes about the internals:
  76.  
  77.      The window package.  Windows are opened by calling wwopen().
  78. Wwwrite() is the primitive for writing to windows.  Wwputc(), wwputs(),
  79. and wwprintf() are also supported.  Some of the outputs to windows are
  80. delayed.  Wwupdate() updates the terminal to match the internal screen
  81. buffer.  Wwspawn() spawns a child process on the other end of a window,
  82. with its environment tailored to the window.  Visible windows are
  83. doubly linked in the order of their overlap.  Wwadd() inserts a window
  84. into the list at a given place.  Wwdelete() deletes it.  Windows not in
  85. the list are not visible, though wwwrite() still works.  Window was
  86. written before the days of X and Sunview, so some of the terminology
  87. is not standard.
  88.  
  89.      Most functions return -1 on error.  Wwopen() returns the null
  90. pointer.  An error number is saved in wwerrno.  Wwerror() returns an
  91. error string based on wwerrno suitable for printing.
  92.  
  93.      The terminal drivers perform all output to the physical terminal,
  94. including special functions like character and line insertion and
  95. deletion.  The window package keeps a list of known terminals.  At
  96. initialization time, the terminal type is matched against the list to
  97. find the right terminal driver to use.  The last driver, the generic
  98. driver, matches all terminals and uses the termcap database.  The
  99. interface between the window package the terminal driver is the `tt'
  100. structure.  It contains pointers to functions to perform special
  101. functions and terminal output, as well as flags about the
  102. characteristics of the terminal.  Most of these ideas are borrowed
  103. from the Maryland window package, which in turn is based on Goslin's
  104. Emacs.
  105.  
  106.      The IO system is semi-synchronous.  Terminal input is signal
  107. driven, and everything else is done synchronously with a single
  108. select().  It is roughly event-driven, though not in a clean way.
  109.  
  110.      Normally, in both conversation mode and command mode, window
  111. sleeps in a select() in wwiomux() waiting for data from the
  112. pseudo-terminals.  At the same time, terminal input causes SIGIO which
  113. is caught by wwrint().  The select() returns when at least one of the
  114. pseudo-terminals becomes ready for reading.
  115.  
  116.      Wwrint() is the interrupt handler for tty input.  It reads input
  117. into a linear buffer accessed through four pointers:
  118.  
  119.     +-------+--------------+----------------+
  120.     | empty |    data      |   empty    |
  121.     +-------+--------------+----------------+
  122.     ^    ^        ^         ^
  123.     |    |        |         |
  124.        wwib    wwibp           wwibq        wwibe
  125.  
  126. Wwrint() appends characters at the end and increments wwibq (*wwibq++
  127. = c), and characters are taken off the buffer at wwibp using the
  128. wwgetc() and wwpeekc() macros.  As is the convention in C, wwibq
  129. and wwibe point to one position beyond the end.  In addition,
  130. wwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true.  This is
  131. used by wwiomux() to interrupt the select() which would otherwise
  132. resume after the interrupt.  (Actually, I hear this is not true,
  133. but the longjmp feature is used to avoid a race condition as well.
  134. Anyway, it means I didn't have to depend on a feature in a
  135. daily-changing kernel, but that's another story.) The macro
  136. wwinterrupt() returns true if the input buffer is non-empty.
  137. Wwupdate(), wwwrite(), and wwiomux() check this condition and will
  138. return at the first convenient opportunity when it becomes true.
  139. In the case of wwwrite(), the flag ww_nointr in the window structure
  140. overrides this.  This feature allows the user to interrupt lengthy
  141. outputs safely.  The structure of the input buffer is designed to
  142. avoid race conditions without blocking interrupts.
  143.  
  144.      Actually, wwsetjmp and wwinterrupt() are part of a software
  145. interrupt scheme used by the two interrupt catchers wwrint() and
  146. wwchild().  Asserting the interrupt lets the synchronous parts of
  147. the program know that there's an interesting asynchronous condition
  148. (i.e., got a keyboard character, or a child process died) that they
  149. might want to process before anything else.  The synchronous routines
  150. can check for this condition with wwinterrupt() or by arranging
  151. that a longjmp() be done.
  152.  
  153.      Wwiomux() copies pseudo-terminal output into their corresponding
  154. windows.  Without anything to do, it blocks in a select(), waiting for
  155. read ready on pseudo-terminals.  Reads are done into per-window buffers
  156. in the window structures.  When there is at least one buffer non-empty,
  157. wwiomux() finds the top most of these windows and writes it using
  158. wwwrite().  Then the process is repeated.  A non-blocking select() is
  159. done after a wwwrite() to pick up any output that may have come in
  160. during the write, which may take a long time.  Specifically, we use
  161. this to stop output or flush buffer when a pseudo-terminal tells us to
  162. (we use pty packet mode).  The select() blocks only when all of the
  163. windows' buffers are empty.  A wwupdate() is done prior to this, which
  164. is the only time the screen is guaranteed to be completely up to date.
  165. Wwiomux() loops until wwinterrupt() becomes true.
  166.  
  167.      The top level routine for all this is mloop().  In conversation
  168. mode, it simply calls wwiomux(), which only returns when input is
  169. available.  The input buffer is then written to the pseudo-terminal of
  170. the current window.  If the escape character is found in the input,
  171. command mode is entered.  Otherwise, the process is repeated.  In
  172. command mode, control is transferred to docmd() which returns only when
  173. conversation mode is reentered.  Docmd() and other command processing
  174. routines typically wait for input in a loop:
  175.  
  176.     while (wwpeekc() < 0)
  177.         wwiomux();
  178.  
  179. When the loop terminates, wwgetc() is used to read the input buffer.
  180.  
  181.      Output to the physical terminal is handled by the lowest level
  182. routines of the window package, in the files ttoutput.c and tt.h.  The
  183. standard IO package is not used, to get better control over buffering
  184. and to use non-blocking reads in wwrint().  The buffer size is set to
  185. approximately one second of output time, based on the baudrate.
  186.  
  187.      The result of all this complexity is faster response time,
  188. especially in output stopping and flushing.  Wwwrite() checks
  189. wwinterrupt() after every line.  It also calls wwupdate() for each line
  190. it writes.  The output buffer is limited to one second of output time.
  191. Thus, there is usually only a delay of one to two lines plus one second
  192. after a ^C or ^S.  Also, commands that produce lengthy output can be
  193. aborted without actually showing all of it on the terminal.  (Try the
  194. '?' command followed by escape immediately.)
  195.