home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
gnu
/
foo123
/
curses.doc
next >
Wrap
Text File
|
1993-07-29
|
95KB
|
2,461 lines
Screen Updating and Cursor Movement Optimization:
A Library Package
_✓K_✓e_✓n_✓n_✓e_✓t_✓h _✓C. _✓R. _✓C. _✓A_✓r_✓n_✓o_✓l_✓d
Computer Science Division
Department of Electrical Engineering and Computer Science
University of California, Berkeley
Berkeley, California 94720
_✓A_✓B_✓S_✓T_✓R_✓A_✓C_✓T
This document describes a package of C library
functions which allow the user to:
1) update a screen with reasonable optimization,
2) get input from the terminal in a screen-oriented
fashion, and
3) independent from the above, move the cursor op-
timally from one point to another.
These routines all use the _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) database to
describe the capabilities of the terminal.
_✓A_✓c_✓k_✓n_✓o_✓w_✓l_✓e_✓d_✓g_✓e_✓m_✓e_✓n_✓t_✓s
This package would not exist without the work of Bill
Joy, who, in writing his editor, created the capability to
generally describe terminals, wrote the routines which read
this database, and, most importantly, those which implement
optimal cursor movement, which routines I have simply lifted
nearly intact. Doug Merritt and Kurt Shoens also were ex-
tremely important, as were both willing to waste time
listening to me rant and rave. The help and/or support of
Ken Abrams, Alan Char, Mark Horton, and Joe Kalash, was, and
is, also greatly appreciated.
Revised 16 April 1986
Screen Package PS1:18-3
_✓1. _✓O_✓v_✓e_✓r_✓v_✓i_✓e_✓w
In making available the generalized terminal descrip-
tions in _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5), much information was made available to
the programmer, but little work was taken out of one's
hands. The purpose of this package is to allow the C pro-
grammer to do the most common type of terminal dependent
functions, those of movement optimization and optimal screen
updating, without doing any of the dirty work, and (hopeful-
ly) with nearly as much ease as is necessary to simply print
or read things.
The package is split into three parts: (1) Screen up-
dating; (2) Screen updating with user input; and (3) Cursor
motion optimization.
It is possible to use the motion optimization without
using either of the other two, and screen updating and input
can be done without any programmer knowledge of the motion
optimization, or indeed the database itself.
_✓1._✓1. _✓T_✓e_✓r_✓m_✓i_✓n_✓o_✓l_✓o_✓g_✓y (_✓o_✓r, _✓W_✓o_✓r_✓d_✓s _✓Y_✓o_✓u _✓C_✓a_✓n _✓S_✓a_✓y _✓t_✓o _✓S_✓o_✓u_✓n_✓d _✓B_✓r_✓i_✓l_✓l_✓i_✓-
_✓a_✓n_✓t)
In this document, the following terminology is kept to
with reasonable consistency:
_✓w_✓i_✓n_✓d_✓o_✓w: An internal representation containing an image of
what a section of the terminal screen may look like at
some point in time. This subsection can either encom-
pass the entire terminal screen, or any smaller portion
down to a single character within that screen.
_✓t_✓e_✓r_✓m_✓i_✓n_✓a_✓l: Sometimes called _✓t_✓e_✓r_✓m_✓i_✓n_✓a_✓l _✓s_✓c_✓r_✓e_✓e_✓n. The package's
idea of what the terminal's screen currently looks
like, _✓i._✓e., what the user sees now. This is a special
_✓s_✓c_✓r_✓e_✓e_✓n:
_✓s_✓c_✓r_✓e_✓e_✓n: This is a subset of windows which are as large as
the terminal screen, _✓i._✓e., they start at the upper left
hand corner and encompass the lower right hand corner.
One of these, _✓s_✓t_✓d_✓s_✓c_✓r, is automatically provided for the
programmer.
_✓1._✓2. _✓C_✓o_✓m_✓p_✓i_✓l_✓i_✓n_✓g _✓T_✓h_✓i_✓n_✓g_✓s
In order to use the library, it is necessary to have
certain types and variables defined. Therefore, the pro-
grammer must have a line:
#_✓i_✓n_✓c_✓l_✓u_✓d_✓e <_✓c_✓u_✓r_✓s_✓e_✓s._✓h>
at the top of the program source. The header file
PS1:18-4 Screen Package
<_✓c_✓u_✓r_✓s_✓e_✓s._✓h> needs to include <_✓s_✓g_✓t_✓t_✓y._✓h>, so the one should not
do so oneself[1]. Also, compilations should have the fol-
lowing form:
_✓c_✓c [ flags ] file ... -_✓l_✓c_✓u_✓r_✓s_✓e_✓s -_✓l_✓t_✓e_✓r_✓m_✓c_✓a_✓p
_✓1._✓3. _✓S_✓c_✓r_✓e_✓e_✓n _✓U_✓p_✓d_✓a_✓t_✓i_✓n_✓g
In order to update the screen optimally, it is neces-
sary for the routines to know what the screen currently
looks like and what the programmer wants it to look like
next. For this purpose, a data type (structure) named _✓W_✓I_✓N_✓-
_✓D_✓O_✓W is defined which describes a window image to the rou-
tines, including its starting position on the screen (the
(y, x) co-ordinates of the upper left hand corner) and its
size. One of these (called _✓c_✓u_✓r_✓s_✓c_✓r for _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓s_✓c_✓r_✓e_✓e_✓n) is a
screen image of what the terminal currently looks like.
Another screen (called _✓s_✓t_✓d_✓s_✓c_✓r, for _✓s_✓t_✓a_✓n_✓d_✓a_✓r_✓d _✓s_✓c_✓r_✓e_✓e_✓n) is pro-
vided by default to make changes on.
A window is a purely internal representation. It is
used to build and store a potential image of a portion of
the terminal. It doesn't bear any necessary relation to
what is really on the terminal screen. It is more like an
array of characters on which to make changes.
When one has a window which describes what some part
the terminal should look like, the routine _✓r_✓e_✓f_✓r_✓e_✓s_✓h() (or
_✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h() if the window is not _✓s_✓t_✓d_✓s_✓c_✓r) is called. _✓r_✓e_✓-
_✓f_✓r_✓e_✓s_✓h() makes the terminal, in the area covered by the win-
dow, look like that window. Note, therefore, that changing
something on a window _✓d_✓o_✓e_✓s _✓n_✓o_✓t _✓c_✓h_✓a_✓n_✓g_✓e _✓t_✓h_✓e _✓t_✓e_✓r_✓m_✓i_✓n_✓a_✓l. Actual
updates to the terminal screen are made only by calling _✓r_✓e_✓-
_✓f_✓r_✓e_✓s_✓h() or _✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h(). This allows the programmer to main-
tain several different ideas of what a portion of the termi-
nal screen should look like. Also, changes can be made to
windows in any order, without regard to motion efficiency.
Then, at will, the programmer can effectively say "make it
look like this", and let the package worry about the best
way to do this.
_✓1._✓4. _✓N_✓a_✓m_✓i_✓n_✓g _✓C_✓o_✓n_✓v_✓e_✓n_✓t_✓i_✓o_✓n_✓s
As hinted above, the routines can use several windows,
but two are automatically given: _✓c_✓u_✓r_✓s_✓c_✓r, which knows what
the terminal looks like, and _✓s_✓t_✓d_✓s_✓c_✓r, which is what the pro-
____________________
[1] The screen package also uses the Standard I/O li-
brary, so <_✓c_✓u_✓r_✓s_✓e_✓s._✓h> includes <_✓s_✓t_✓d_✓i_✓o._✓h>. It is redundant
(but harmless) for the programmer to do it, too.
Screen Package PS1:18-5
grammer wants the terminal to look like next. The user
should never really access _✓c_✓u_✓r_✓s_✓c_✓r directly. Changes should
be made to the appropriate screen, and then the routine _✓r_✓e_✓-
_✓f_✓r_✓e_✓s_✓h() (or _✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h()) should be called.
Many functions are set up to deal with _✓s_✓t_✓d_✓s_✓c_✓r as a de-
fault screen. For example, to add a character to _✓s_✓t_✓d_✓s_✓c_✓r,
one calls _✓a_✓d_✓d_✓c_✓h() with the desired character. If a dif-
ferent window is to be used, the routine _✓w_✓a_✓d_✓d_✓c_✓h() (for
_✓window-specific _✓a_✓d_✓d_✓c_✓h()) is provided[2]. This convention of
prepending function names with a "_✓w" when they are to be ap-
plied to specific windows is consistent. The only routines
which do _✓n_✓o_✓t do this are those to which a window must always
be specified.
In order to move the current (y, x) co-ordinates from
one point to another, the routines _✓m_✓o_✓v_✓e() and _✓w_✓m_✓o_✓v_✓e() are
provided. However, it is often desirable to first move and
then perform some I/O operation. In order to avoid clumsy-
ness, most I/O routines can be preceded by the prefix "_✓m_✓v"
and the desired (y, x) co-ordinates then can be added to the
arguments to the function. For example, the calls
move(y, x);
addch(ch);
can be replaced by
mvaddch(y, x, ch);
and
wmove(win, y, x);
waddch(win, ch);
can be replaced by
mvwaddch(win, y, x, ch);
Note that the window description pointer (_✓w_✓i_✓n) comes before
the added (y, x) co-ordinates. If such pointers are need,
they are always the first parameters passed.
_✓2. _✓V_✓a_✓r_✓i_✓a_✓b_✓l_✓e_✓s
Many variables which are used to describe the terminal
environment are available to the programmer. They are:
____________________
[2] Actually, _✓a_✓d_✓d_✓c_✓h() is really a "#define" macro with
arguments, as are most of the "functions" which deal with
_✓s_✓t_✓d_✓s_✓c_✓r as a default.
PS1:18-6 Screen Package
type name description
________________________________________________________________________
WINDOW * curscr
current version of the screen (terminal screen).
WINDOW * stdscr
standard screen. Most updates are usually done
here.
char * Def_term
default terminal type if type cannot be determined
bool My_term
use the terminal specification in _✓D_✓e_✓f__✓t_✓e_✓r_✓m as ter-
minal, irrelevant of real terminal type
char * ttytype
full name of the current terminal.
int LINES
number of lines on the terminal
int COLS
number of columns on the terminal
int ERR
error flag returned by routines on a fail.
int OK
error flag returned by routines when things go
right.
There are also several "#define" constants and types
which are of general usefulness:
reg storage class ``register'' (_✓e._✓g., _✓r_✓e_✓g _✓i_✓n_✓t _✓i;)
bool boolean type, actually a ``char'' (_✓e._✓g., _✓b_✓o_✓o_✓l _✓d_✓o_✓n_✓e_✓i_✓t;)
TRUE boolean ``true'' flag (1).
FALSE boolean ``false'' flag (0).
_✓3. _✓U_✓s_✓a_✓g_✓e
This is a description of how to actually use the screen
package. In it, we assume all updating, reading, etc. is
applied to _✓s_✓t_✓d_✓s_✓c_✓r. All instructions will work on any win-
dow, with changing the function name and parameters as men-
tioned above.
_✓3._✓1. _✓S_✓t_✓a_✓r_✓t_✓i_✓n_✓g _✓u_✓p
In order to use the screen package, the routines must
know about terminal characteristics, and the space for
_✓c_✓u_✓r_✓s_✓c_✓r and _✓s_✓t_✓d_✓s_✓c_✓r must be allocated. These functions are
performed by _✓i_✓n_✓i_✓t_✓s_✓c_✓r(). Since it must allocate space for
the windows, it can overflow core when attempting to do so.
On this rather rare occasion, _✓i_✓n_✓i_✓t_✓s_✓c_✓r() returns ERR. _✓i_✓n_✓-
_✓i_✓t_✓s_✓c_✓r() must _✓a_✓l_✓w_✓a_✓y_✓s be called before any of the routines
which affect windows are used. If it is not, the program
will core dump as soon as either _✓c_✓u_✓r_✓s_✓c_✓r or _✓s_✓t_✓d_✓s_✓c_✓r are refer-
enced. However, it is usually best to wait to call it until
after you are sure you will need it, like after checking for
startup errors. Terminal status changing routines like _✓n_✓l()
and _✓c_✓b_✓r_✓e_✓a_✓k() should be called after _✓i_✓n_✓i_✓t_✓s_✓c_✓r().
Now that the screen windows have been allocated, you
can set them up for the run. If you want to, say, allow the
window to scroll, use _✓s_✓c_✓r_✓o_✓l_✓l_✓o_✓k(). If you want the cursor to
Screen Package PS1:18-7
be left after the last change, use _✓l_✓e_✓a_✓v_✓e_✓o_✓k(). If this isn't
done, _✓r_✓e_✓f_✓r_✓e_✓s_✓h() will move the cursor to the window's current
(y, x) co-ordinates after updating it. New windows of your
own can be created, too, by using the functions _✓n_✓e_✓w_✓w_✓i_✓n() and
_✓s_✓u_✓b_✓w_✓i_✓n(). _✓d_✓e_✓l_✓w_✓i_✓n() will allow you to get rid of old win-
dows. If you wish to change the official size of the termi-
nal by hand, just set the variables _✓L_✓I_✓N_✓E_✓S and _✓C_✓O_✓L_✓S to be
what you want, and then call _✓i_✓n_✓i_✓t_✓s_✓c_✓r(). This is best done
before, but can be done either before or after, the first
call to _✓i_✓n_✓i_✓t_✓s_✓c_✓r(), as it will always delete any existing
_✓s_✓t_✓d_✓s_✓c_✓r and/or _✓c_✓u_✓r_✓s_✓c_✓r before creating new ones.
_✓3._✓2. _✓T_✓h_✓e _✓N_✓i_✓t_✓t_✓y-_✓G_✓r_✓i_✓t_✓t_✓y
_✓3._✓2._✓1. _✓O_✓u_✓t_✓p_✓u_✓t
Now that we have set things up, we will want to actual-
ly update the terminal. The basic functions used to change
what will go on a window are _✓a_✓d_✓d_✓c_✓h() and _✓m_✓o_✓v_✓e(). _✓a_✓d_✓d_✓c_✓h()
adds a character at the current (y, x) co-ordinates, return-
ing ERR if it would cause the window to illegally scroll,
_✓i._✓e., printing a character in the lower right-hand corner of
a terminal which automatically scrolls if scrolling is not
allowed. _✓m_✓o_✓v_✓e() changes the current (y, x) co-ordinates to
whatever you want them to be. It returns ERR if you try to
move off the window when scrolling is not allowed. As men-
tioned above, you can combine the two into _✓m_✓v_✓a_✓d_✓d_✓c_✓h() to do
both things in one fell swoop.
The other output functions, such as _✓a_✓d_✓d_✓s_✓t_✓r() and
_✓p_✓r_✓i_✓n_✓t_✓w(), all call _✓a_✓d_✓d_✓c_✓h() to add characters to the window.
After you have put on the window what you want there,
when you want the portion of the terminal covered by the
window to be made to look like it, you must call _✓r_✓e_✓f_✓r_✓e_✓s_✓h().
In order to optimize finding changes, _✓r_✓e_✓f_✓r_✓e_✓s_✓h() assumes that
any part of the window not changed since the last _✓r_✓e_✓f_✓r_✓e_✓s_✓h()
of that window has not been changed on the terminal, _✓i._✓e.,
that you have not refreshed a portion of the terminal with
an overlapping window. If this is not the case, the rou-
tines _✓t_✓o_✓u_✓c_✓h_✓w_✓i_✓n(), _✓t_✓o_✓u_✓c_✓h_✓l_✓i_✓n_✓e(), and _✓t_✓o_✓u_✓c_✓h_✓o_✓v_✓e_✓r_✓l_✓a_✓p() are pro-
vided to make it look like a desired part of window has been
changed, thus forcing _✓r_✓e_✓f_✓r_✓e_✓s_✓h() check that whole subsection
of the terminal for changes.
If you call _✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h() with _✓c_✓u_✓r_✓s_✓c_✓r, it will make the
screen look like _✓c_✓u_✓r_✓s_✓c_✓r thinks it looks like. This is use-
ful for implementing a command which would redraw the screen
in case it get messed up.
PS1:18-8 Screen Package
_✓3._✓2._✓2. _✓I_✓n_✓p_✓u_✓t
Input is essentially a mirror image of output. The
complementary function to _✓a_✓d_✓d_✓c_✓h() is _✓g_✓e_✓t_✓c_✓h() which, if echo
is set, will call _✓a_✓d_✓d_✓c_✓h() to echo the character. Since the
screen package needs to know what is on the terminal at all
times, if characters are to be echoed, the tty must be in
raw or cbreak mode. If it is not, _✓g_✓e_✓t_✓c_✓h() sets it to be
cbreak, and then reads in the character.
_✓3._✓2._✓3. _✓M_✓i_✓s_✓c_✓e_✓l_✓l_✓a_✓n_✓e_✓o_✓u_✓s
All sorts of fun functions exists for maintaining and
changing information about the windows. For the most part,
the descriptions in section 5.4. should suffice.
_✓3._✓3. _✓F_✓i_✓n_✓i_✓s_✓h_✓i_✓n_✓g _✓u_✓p
In order to do certain optimizations, and, on some ter-
minals, to work at all, some things must be done before the
screen routines start up. These functions are performed in
_✓g_✓e_✓t_✓t_✓t_✓m_✓o_✓d_✓e() and _✓s_✓e_✓t_✓t_✓e_✓r_✓m(), which are called by _✓i_✓n_✓i_✓t_✓s_✓c_✓r().
In order to clean up after the routines, the routine
_✓e_✓n_✓d_✓w_✓i_✓n() is provided. It restores tty modes to what they
were when _✓i_✓n_✓i_✓t_✓s_✓c_✓r() was first called. Thus, anytime after
the call to initscr, _✓e_✓n_✓d_✓w_✓i_✓n() should be called before exit-
ing.
_✓4. _✓C_✓u_✓r_✓s_✓o_✓r _✓M_✓o_✓t_✓i_✓o_✓n _✓O_✓p_✓t_✓i_✓m_✓i_✓z_✓a_✓t_✓i_✓o_✓n: _✓S_✓t_✓a_✓n_✓d_✓i_✓n_✓g _✓A_✓l_✓o_✓n_✓e
It is possible to use the cursor optimization functions
of this screen package without the overhead and additional
size of the screen updating functions. The screen updating
functions are designed for uses where parts of the screen
are changed, but the overall image remains the same. This
includes such programs as _✓r_✓o_✓g_✓u_✓e and _✓v_✓i[3]. Certain other
programs will find it difficult to use these functions in
this manner without considerable unnecessary program over-
head. For such applications, such as some "_✓c_✓r_✓t _✓h_✓a_✓c_✓k_✓s"[4]
and optimizing _✓m_✓o_✓r_✓e(1)-type programs, all that is needed is
the motion optimizations. This, therefore, is a description
of what some of what goes on at the lower levels of this
screen package. The descriptions assume a certain amount of
familiarity with programming problems and some finer points
of C. None of it is terribly difficult, but you should be
____________________
[3] _✓r_✓o_✓g_✓u_✓e actually uses these functions, _✓v_✓i does not.
[4] Graphics programs designed to run on character-
oriented terminals. I could name many, but they come and
go, so the list would be quickly out of date. Recently,
there have been programs such as _✓r_✓a_✓i_✓n, _✓r_✓o_✓c_✓k_✓e_✓t, and _✓g_✓u_✓n.
Screen Package PS1:18-9
forewarned.
_✓4._✓1. _✓T_✓e_✓r_✓m_✓i_✓n_✓a_✓l _✓I_✓n_✓f_✓o_✓r_✓m_✓a_✓t_✓i_✓o_✓n
In order to use a terminal's features to the best of a
program's abilities, it must first know what they are[5].
The _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) database describes these, but a certain
amount of decoding is necessary, and there are, of course,
both efficient and inefficient ways of reading them in. The
algorithm that the uses is taken from _✓v_✓i and is hideously
efficient. It reads them in a tight loop into a set of
variables whose names are two uppercase letters with some
mnemonic value. For example, _✓H_✓O is a string which moves the
cursor to the "home" position[6]. As there are two types of
variables involving ttys, there are two routines. The
first, _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e(), sets some variables based upon the tty
modes accessed by _✓g_✓t_✓t_✓y(2) and _✓s_✓t_✓t_✓y(2) The second, _✓s_✓e_✓t_✓t_✓e_✓r_✓m(),
a larger task by reading in the descriptions from the
_✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) database. This is the way these routines are
used by _✓i_✓n_✓i_✓t_✓s_✓c_✓r():
_✓i_✓f (isatty(0)) {
gettmode();
_✓i_✓f ((sp=getenv("TERM")) != NULL)
setterm(sp);
_✓e_✓l_✓s_✓e
setterm(Def_term);
}
_✓e_✓l_✓s_✓e
setterm(Def_term);
_puts(TI);
_puts(VS);
_✓i_✓s_✓a_✓t_✓t_✓y() checks to see if file descriptor 0 is a termi-
nal[7]. If it is, _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e() sets the terminal description
modes from a _✓g_✓t_✓t_✓y(2) _✓g_✓e_✓t_✓e_✓n_✓v() is then called to get the name
of the terminal, and that value (if there is one) is passed
____________________
[5] If this comes as any surprise to you, there's this
tower in Paris they're thinking of junking that I can let
you have for a song.
[6] These names are identical to those variables used in
the _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) database to describe each capability. See
Appendix A for a complete list of those read, and the
_✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) manual page for a full description.
[7] _✓i_✓s_✓a_✓t_✓t_✓y() is defined in the default C library function
routines. It does a _✓g_✓t_✓t_✓y(2) on the descriptor and checks
the return value.
PS1:18-10 Screen Package
to _✓s_✓e_✓t_✓t_✓e_✓r_✓m(), which reads in the variables from _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5)
associated with that terminal. (_✓g_✓e_✓t_✓e_✓n_✓v() returns a pointer
to a string containing the name of the terminal, which we
save in the character pointer _✓s_✓p.) If _✓i_✓s_✓a_✓t_✓t_✓y() returns
false, the default terminal _✓D_✓e_✓f__✓t_✓e_✓r_✓m is used. The _✓T_✓I and _✓V_✓S
sequences initialize the terminal (__✓p_✓u_✓t_✓s() is a macro which
uses _✓t_✓p_✓u_✓t_✓s() (see _✓t_✓e_✓r_✓m_✓c_✓a_✓p(3)) and __✓p_✓u_✓t_✓c_✓h_✓a_✓r() to put out a
string). _✓e_✓n_✓d_✓w_✓i_✓n() undoes these things.
_✓4._✓2. _✓M_✓o_✓v_✓e_✓m_✓e_✓n_✓t _✓O_✓p_✓t_✓i_✓m_✓i_✓z_✓a_✓t_✓i_✓o_✓n_✓s, _✓o_✓r, _✓G_✓e_✓t_✓t_✓i_✓n_✓g _✓O_✓v_✓e_✓r _✓Y_✓o_✓n_✓d_✓e_✓r
Now that we have all this useful information, it would
be nice to do something with it[8]. The most difficult
thing to do properly is motion optimization. When you con-
sider how many different features various terminals have
(tabs, backtabs, non-destructive space, home sequences, ab-
solute tabs, .....) you can see that deciding how to get
from here to there can be a decidedly non-trivial task. The
editor _✓v_✓i uses many of these features, and the routines it
uses to do this take up many pages of code. Fortunately, I
was able to liberate them with the author's permission, and
use them here.
After using _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e() and _✓s_✓e_✓t_✓t_✓e_✓r_✓m() to get the termi-
nal descriptions, the function _✓m_✓v_✓c_✓u_✓r() deals with this task.
It usage is simple: you simply tell it where you are now and
where you want to go. For example
mvcur(0, 0, LINES/2, COLS/2)
would move the cursor from the home position (0, 0) to the
middle of the screen. If you wish to force absolute ad-
dressing, you can use the function _✓t_✓g_✓o_✓t_✓o() from the _✓t_✓e_✓r_✓m_✓-
_✓l_✓i_✓b(7) routines, or you can tell _✓m_✓v_✓c_✓u_✓r() that you are impos-
sibly far away, like Cleveland. For example, to absolutely
address the lower left hand corner of the screen from any-
where just claim that you are in the upper right hand
corner:
mvcur(0, COLS-1, LINES-1, 0)
_✓5. _✓T_✓h_✓e _✓F_✓u_✓n_✓c_✓t_✓i_✓o_✓n_✓s
In the following definitions, "[*]" means that the
"function" is really a "#define" macro with arguments. This
____________________
[8] Actually, it _✓c_✓a_✓n be emotionally fulfilling just to
get the information. This is usually only true, however, if
you have the social life of a kumquat.
Screen Package PS1:18-11
means that it will not show up in stack traces in the de-
bugger, or, in the case of such functions as _✓a_✓d_✓d_✓c_✓h(), it
will show up as it's "_✓w" counterpart. The arguments are
given to show the order and type of each. Their names are
not mandatory, just suggestive.
_✓5._✓1. _✓O_✓u_✓t_✓p_✓u_✓t _✓F_✓u_✓n_✓c_✓t_✓i_✓o_✓n_✓s
_✓a_✓d_✓d_✓c_✓h(_✓c_✓h) [*]
_✓c_✓h_✓a_✓r _✓c_✓h;
_✓w_✓a_✓d_✓d_✓c_✓h(_✓w_✓i_✓n, _✓c_✓h)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r _✓c_✓h;
Add the character _✓c_✓h on the window at the current
(y, x) co-ordinates. If the character is a newline
('\n') the line will be cleared to the end, and the
current (y, x) co-ordinates will be changed to the be-
ginning off the next line if newline mapping is on, or
to the next line at the same x co-ordinate if it is
off. A return ('\r') will move to the beginning of the
line on the window. Tabs ('\t') will be expanded into
spaces in the normal tabstop positions of every eight
characters. This returns ERR if it would cause the
screen to scroll illegally.
_✓a_✓d_✓d_✓s_✓t_✓r(_✓s_✓t_✓r) [*]
_✓c_✓h_✓a_✓r *_✓s_✓t_✓r;
_✓w_✓a_✓d_✓d_✓s_✓t_✓r(_✓w_✓i_✓n, _✓s_✓t_✓r)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r *_✓s_✓t_✓r;
Add the string pointed to by _✓s_✓t_✓r on the window at the
current (y, x) co-ordinates. This returns ERR if it
would cause the screen to scroll illegally. In this
case, it will put on as much as it can.
_✓b_✓o_✓x(_✓w_✓i_✓n, _✓v_✓e_✓r_✓t, _✓h_✓o_✓r)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r _✓v_✓e_✓r_✓t, _✓h_✓o_✓r;
Draws a box around the window using _✓v_✓e_✓r_✓t as the charac-
ter for drawing the vertical sides, and _✓h_✓o_✓r for drawing
the horizontal lines. If scrolling is not allowed, and
the window encompasses the lower right-hand corner of
PS1:18-12 Screen Package
the terminal, the corners are left blank to avoid a
scroll.
_✓c_✓l_✓e_✓a_✓r() [*]
_✓w_✓c_✓l_✓e_✓a_✓r(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Resets the entire window to blanks. If _✓w_✓i_✓n is a
screen, this sets the clear flag, which will cause a
clear-screen sequence to be sent on the next _✓r_✓e_✓f_✓r_✓e_✓s_✓h()
call. This also moves the current (y, x) co-ordinates
to (0, 0).
_✓c_✓l_✓e_✓a_✓r_✓o_✓k(_✓s_✓c_✓r, _✓b_✓o_✓o_✓l_✓f) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓s_✓c_✓r;
_✓b_✓o_✓o_✓l _✓b_✓o_✓o_✓l_✓f;
Sets the clear flag for the screen _✓s_✓c_✓r. If _✓b_✓o_✓o_✓l_✓f is
TRUE, this will force a clear-screen to be printed on
the next _✓r_✓e_✓f_✓r_✓e_✓s_✓h(), or stop it from doing so if _✓b_✓o_✓o_✓l_✓f
is FALSE. This only works on screens, and, unlike
_✓c_✓l_✓e_✓a_✓r(), does not alter the contents of the screen. If
_✓s_✓c_✓r is _✓c_✓u_✓r_✓s_✓c_✓r, the next _✓r_✓e_✓f_✓r_✓e_✓s_✓h() call will cause a
clear-screen, even if the window passed to _✓r_✓e_✓f_✓r_✓e_✓s_✓h() is
not a screen.
_✓c_✓l_✓r_✓t_✓o_✓b_✓o_✓t() [*]
_✓w_✓c_✓l_✓r_✓t_✓o_✓b_✓o_✓t(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Wipes the window clear from the current (y, x) co-
ordinates to the bottom. This does not force a clear-
screen sequence on the next refresh under any cir-
cumstances. This has no associated "mv" command.
_✓c_✓l_✓r_✓t_✓o_✓e_✓o_✓l() [*]
_✓w_✓c_✓l_✓r_✓t_✓o_✓e_✓o_✓l(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Wipes the window clear from the current (y, x) co-
ordinates to the end of the line. This has no associ-
ated "mv" command.
Screen Package PS1:18-13
_✓d_✓e_✓l_✓c_✓h()
_✓w_✓d_✓e_✓l_✓c_✓h(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Delete the character at the current (y, x) co-
ordinates. Each character after it on the line shifts
to the left, and the last character becomes blank.
_✓d_✓e_✓l_✓e_✓t_✓e_✓l_✓n()
_✓w_✓d_✓e_✓l_✓e_✓t_✓e_✓l_✓n(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Delete the current line. Every line below the current
one will move up, and the bottom line will become
blank. The current (y, x) co-ordinates will remain un-
changed.
_✓e_✓r_✓a_✓s_✓e() [*]
_✓w_✓e_✓r_✓a_✓s_✓e(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Erases the window to blanks without setting the clear
flag. This is analagous to _✓c_✓l_✓e_✓a_✓r(), except that it
never causes a clear-screen sequence to be generated on
a _✓r_✓e_✓f_✓r_✓e_✓s_✓h(). This has no associated "mv" command.
_✓f_✓l_✓u_✓s_✓h_✓o_✓k(_✓w_✓i_✓n, _✓b_✓o_✓o_✓l_✓f) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓b_✓o_✓o_✓l _✓b_✓o_✓o_✓l_✓f;
Normally, _✓r_✓e_✓f_✓r_✓e_✓s_✓h() _✓f_✓f_✓l_✓u_✓s_✓h()'s _✓s_✓t_✓d_✓o_✓u_✓t when it is fin-
ished. _✓f_✓l_✓u_✓s_✓h_✓o_✓k() allows you to control this. if _✓b_✓o_✓o_✓l_✓f
is TRUE (_✓i._✓e., non-zero) it will do the _✓f_✓f_✓l_✓u_✓s_✓h(); if it
is FALSE. it will not.
_✓i_✓d_✓l_✓o_✓k(_✓w_✓i_✓n, _✓b_✓o_✓o_✓l_✓f)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓b_✓o_✓o_✓l _✓b_✓o_✓o_✓l_✓f;
Reserved for future use. This will eventually signal
to _✓r_✓e_✓f_✓r_✓e_✓s_✓h() that it is all right to use the insert and
PS1:18-14 Screen Package
delete line sequences when updating the window.
_✓i_✓n_✓s_✓c_✓h(_✓c)
_✓c_✓h_✓a_✓r _✓c;
_✓w_✓i_✓n_✓s_✓c_✓h(_✓w_✓i_✓n, _✓c)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r _✓c;
Insert _✓c at the current (y, x) co-ordinates Each char-
acter after it shifts to the right, and the last char-
acter disappears. This returns ERR if it would cause
the screen to scroll illegally.
_✓i_✓n_✓s_✓e_✓r_✓t_✓l_✓n()
_✓w_✓i_✓n_✓s_✓e_✓r_✓t_✓l_✓n(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Insert a line above the current one. Every line below
the current line will be shifted down, and the bottom
line will disappear. The current line will become
blank, and the current (y, x) co-ordinates will remain
unchanged.
_✓m_✓o_✓v_✓e(_✓y, _✓x) [*]
_✓i_✓n_✓t _✓y, _✓x;
_✓w_✓m_✓o_✓v_✓e(_✓w_✓i_✓n, _✓y, _✓x)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓i_✓n_✓t _✓y, _✓x;
Change the current (y, x) co-ordinates of the window to
(_✓y, _✓x). This returns ERR if it would cause the screen
to scroll illegally.
_✓o_✓v_✓e_✓r_✓l_✓a_✓y(_✓w_✓i_✓n_✓1, _✓w_✓i_✓n_✓2)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n_✓1, *_✓w_✓i_✓n_✓2;
Overlay _✓w_✓i_✓n_✓1 on _✓w_✓i_✓n_✓2. The contents of _✓w_✓i_✓n_✓1, insofar as
they fit, are placed on _✓w_✓i_✓n_✓2 at their starting (y, x)
co-ordinates. This is done non-destructively, i.e.,
blanks on _✓w_✓i_✓n_✓1 leave the contents of the space on _✓w_✓i_✓n_✓2
untouched.
Screen Package PS1:18-15
_✓o_✓v_✓e_✓r_✓w_✓r_✓i_✓t_✓e(_✓w_✓i_✓n_✓1, _✓w_✓i_✓n_✓2)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n_✓1, *_✓w_✓i_✓n_✓2;
Overwrite _✓w_✓i_✓n_✓1 on _✓w_✓i_✓n_✓2. The contents of _✓w_✓i_✓n_✓1, insofar
as they fit, are placed on _✓w_✓i_✓n_✓2 at their starting
(y, x) co-ordinates. This is done destructively, _✓i._✓e.,
blanks on _✓w_✓i_✓n_✓1 become blank on _✓w_✓i_✓n_✓2.
_✓p_✓r_✓i_✓n_✓t_✓w(_✓f_✓m_✓t, _✓a_✓r_✓g_✓1, _✓a_✓r_✓g_✓2, ...)
_✓c_✓h_✓a_✓r *_✓f_✓m_✓t;
_✓w_✓p_✓r_✓i_✓n_✓t_✓w(_✓w_✓i_✓n, _✓f_✓m_✓t, _✓a_✓r_✓g_✓1, _✓a_✓r_✓g_✓2, ...)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r *_✓f_✓m_✓t;
Performs a _✓p_✓r_✓i_✓n_✓t_✓f() on the window starting at the
current (y, x) co-ordinates. It uses _✓a_✓d_✓d_✓s_✓t_✓r() to add
the string on the window. It is often advisable to use
the field width options of _✓p_✓r_✓i_✓n_✓t_✓f() to avoid leaving
things on the window from earlier calls. This returns
ERR if it would cause the screen to scroll illegally.
_✓r_✓e_✓f_✓r_✓e_✓s_✓h() [*]
_✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Synchronize the terminal screen with the desired win-
dow. If the window is not a screen, only that part
covered by it is updated. This returns ERR if it would
cause the screen to scroll illegally. In this case, it
will update whatever it can without causing the scroll.
As a special case, if _✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h() is called with the
window _✓c_✓u_✓r_✓s_✓c_✓r the screen is cleared and repainted as it
is currently. This is very useful for allowing the
redrawing of the screen when the user has garbage
dumped on his terminal.
_✓s_✓t_✓a_✓n_✓d_✓o_✓u_✓t() [*]
_✓w_✓s_✓t_✓a_✓n_✓d_✓o_✓u_✓t(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓s_✓t_✓a_✓n_✓d_✓e_✓n_✓d() [*]
PS1:18-16 Screen Package
_✓w_✓s_✓t_✓a_✓n_✓d_✓e_✓n_✓d(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Start and stop putting characters onto _✓w_✓i_✓n in standout
mode. _✓s_✓t_✓a_✓n_✓d_✓o_✓u_✓t() causes any characters added to the
window to be put in standout mode on the terminal (if
it has that capability). _✓s_✓t_✓a_✓n_✓d_✓e_✓n_✓d() stops this. The
sequences _✓S_✓O and _✓S_✓E (or _✓U_✓S and _✓U_✓E if they are not de-
fined) are used (see Appendix A).
_✓5._✓2. _✓I_✓n_✓p_✓u_✓t _✓F_✓u_✓n_✓c_✓t_✓i_✓o_✓n_✓s
_✓c_✓b_✓r_✓e_✓a_✓k() [*]
_✓n_✓o_✓c_✓b_✓r_✓e_✓a_✓k() [*]
_✓c_✓r_✓m_✓o_✓d_✓e() [*]
_✓n_✓o_✓c_✓r_✓m_✓o_✓d_✓e() [*]
Set or unset the terminal to/from cbreak mode. The
misnamed macros _✓c_✓r_✓m_✓o_✓d_✓e() and _✓n_✓o_✓c_✓r_✓m_✓o_✓d_✓e() are retained
for backwards compatibility with ealier versions of the
library.
_✓e_✓c_✓h_✓o() [*]
_✓n_✓o_✓e_✓c_✓h_✓o() [*]
Sets the terminal to echo or not echo characters.
_✓g_✓e_✓t_✓c_✓h() [*]
_✓w_✓g_✓e_✓t_✓c_✓h(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Gets a character from the terminal and (if necessary)
echos it on the window. This returns ERR if it would
cause the screen to scroll illegally. Otherwise, the
character gotten is returned. If _✓n_✓o_✓e_✓c_✓h_✓o has been set,
then the window is left unaltered. In order to retain
control of the terminal, it is necessary to have one of
_✓n_✓o_✓e_✓c_✓h_✓o, _✓c_✓b_✓r_✓e_✓a_✓k, or _✓r_✓a_✓w_✓m_✓o_✓d_✓e set. If you do not set one,
whatever routine you call to read characters will set
_✓c_✓b_✓r_✓e_✓a_✓k for you, and then reset to the original mode
when finished.
Screen Package PS1:18-17
_✓g_✓e_✓t_✓s_✓t_✓r(_✓s_✓t_✓r) [*]
_✓c_✓h_✓a_✓r *_✓s_✓t_✓r;
_✓w_✓g_✓e_✓t_✓s_✓t_✓r(_✓w_✓i_✓n, _✓s_✓t_✓r)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r *_✓s_✓t_✓r;
Get a string through the window and put it in the loca-
tion pointed to by _✓s_✓t_✓r, which is assumed to be large
enough to handle it. It sets tty modes if necessary,
and then calls _✓g_✓e_✓t_✓c_✓h() (or _✓w_✓g_✓e_✓t_✓c_✓h(_✓w_✓i_✓n)) to get the
characters needed to fill in the string until a newline
or EOF is encountered. The newline stripped off the
string. This returns ERR if it would cause the screen
to scroll illegally.
__✓p_✓u_✓t_✓c_✓h_✓a_✓r(_✓c)
_✓c_✓h_✓a_✓r _✓c;
Put out a character using the _✓p_✓u_✓t_✓c_✓h_✓a_✓r() macro. This
function is used to output every character that _✓c_✓u_✓r_✓s_✓e_✓s
generates. Thus, it can be redefined by the user who
wants to do non-standard things with the output. It is
named with an initial "_" because it usually should be
invisible to the programmer.
_✓r_✓a_✓w() [*]
_✓n_✓o_✓r_✓a_✓w() [*]
Set or unset the terminal to/from raw mode. On version
7 _✓U_✓N_✓I_✓X[_✓9] this also turns of newline mapping (see
_✓n_✓l()).
_✓s_✓c_✓a_✓n_✓w(_✓f_✓m_✓t, _✓a_✓r_✓g_✓1, _✓a_✓r_✓g_✓2, ...)
_✓c_✓h_✓a_✓r *_✓f_✓m_✓t;
_✓w_✓s_✓c_✓a_✓n_✓w(_✓w_✓i_✓n, _✓f_✓m_✓t, _✓a_✓r_✓g_✓1, _✓a_✓r_✓g_✓2, ...)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓c_✓h_✓a_✓r *_✓f_✓m_✓t;
____________________
[9] _✓U_✓N_✓I_✓X is a trademark of Bell Laboratories.
PS1:18-18 Screen Package
Perform a _✓s_✓c_✓a_✓n_✓f() through the window using _✓f_✓m_✓t. It
does this using consecutive _✓g_✓e_✓t_✓c_✓h()'s (or
_✓w_✓g_✓e_✓t_✓c_✓h(_✓w_✓i_✓n)'s). This returns ERR if it would cause the
screen to scroll illegally.
_✓5._✓3. _✓M_✓i_✓s_✓c_✓e_✓l_✓l_✓a_✓n_✓e_✓o_✓u_✓s _✓F_✓u_✓n_✓c_✓t_✓i_✓o_✓n_✓s
_✓b_✓a_✓u_✓d_✓r_✓a_✓t_✓e() [*]
Returns the output baud rate of the terminal. This is
a system dependent constant (defined in <_✓s_✓y_✓s/_✓t_✓t_✓y._✓h> on
BSD systems, which is included by <_✓c_✓u_✓r_✓s_✓e_✓s._✓h>).
_✓d_✓e_✓l_✓w_✓i_✓n(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Deletes the window from existence. All resources are
freed for future use by _✓c_✓a_✓l_✓l_✓o_✓c(3). If a window has a
_✓s_✓u_✓b_✓w_✓i_✓n() allocated window inside of it, deleting the
outer window the subwindow is not affected, even though
this does invalidate it. Therefore, subwindows should
be deleted before their outer windows are.
_✓e_✓n_✓d_✓w_✓i_✓n()
Finish up window routines before exit. This restores
the terminal to the state it was before _✓i_✓n_✓i_✓t_✓s_✓c_✓r() (or
_✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e() and _✓s_✓e_✓t_✓t_✓e_✓r_✓m()) was called. It should always
be called before exiting. It does not exit. This is
especially useful for resetting tty stats when trapping
rubouts via _✓s_✓i_✓g_✓n_✓a_✓l(2).
_✓e_✓r_✓a_✓s_✓e_✓c_✓h_✓a_✓r() [*]
Returns the erase character for the terminal, _✓i._✓e., the
character used by the user to erase a single character
from the input.
_✓c_✓h_✓a_✓r *
_✓g_✓e_✓t_✓c_✓a_✓p(_✓s_✓t_✓r)
_✓c_✓h_✓a_✓r *_✓s_✓t_✓r;
Return a pointer to the _✓t_✓e_✓r_✓m_✓c_✓a_✓p capability described by
_✓s_✓t_✓r (see _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5) for details).
Screen Package PS1:18-19
_✓g_✓e_✓t_✓y_✓x(_✓w_✓i_✓n, _✓y, _✓x) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓i_✓n_✓t _✓y, _✓x;
Puts the current (y, x) co-ordinates of _✓w_✓i_✓n in the
variables _✓y and _✓x. Since it is a macro, not a func-
tion, you do not pass the address of _✓y and _✓x.
_✓i_✓n_✓c_✓h() [*]
_✓w_✓i_✓n_✓c_✓h(_✓w_✓i_✓n) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Returns the character at the current (y, x) co-
ordinates on the given window. This does not make any
changes to the window.
_✓i_✓n_✓i_✓t_✓s_✓c_✓r()
Initialize the screen routines. This must be called
before any of the screen routines are used. It ini-
tializes the terminal-type data and such, and without
it none of the routines can operate. If standard input
is not a tty, it sets the specifications to the termi-
nal whose name is pointed to by _✓D_✓e_✓f__✓t_✓e_✓r_✓m (initialy
"dumb"). If the boolean _✓M_✓y__✓t_✓e_✓r_✓m is true, _✓D_✓e_✓f__✓t_✓e_✓r_✓m is
always used. If the system supports the _✓T_✓I_✓O_✓C_✓G_✓W_✓I_✓N_✓S_✓Z
_✓i_✓o_✓c_✓t_✓l(_✓2) call, it is used to get the number of lines
and columns for the terminal, otherwise it is taken
from the _✓t_✓e_✓r_✓m_✓c_✓a_✓p description.
_✓k_✓i_✓l_✓l_✓c_✓h_✓a_✓r() [*]
Returns the line kill character for the terminal, _✓i._✓e.,
the character used by the user to erase an entire line
from the input.
_✓l_✓e_✓a_✓v_✓e_✓o_✓k(_✓w_✓i_✓n, _✓b_✓o_✓o_✓l_✓f) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓b_✓o_✓o_✓l _✓b_✓o_✓o_✓l_✓f;
Sets the boolean flag for leaving the cursor after the
last change. If _✓b_✓o_✓o_✓l_✓f is TRUE, the cursor will be left
after the last update on the terminal, and the current
PS1:18-20 Screen Package
(y, x) co-ordinates for _✓w_✓i_✓n will be changed according-
ly. If it is FALSE, it will be moved to the current
(y, x) co-ordinates. This flag (initialy FALSE) re-
tains its value until changed by the user.
_✓l_✓o_✓n_✓g_✓n_✓a_✓m_✓e(_✓t_✓e_✓r_✓m_✓b_✓u_✓f, _✓n_✓a_✓m_✓e)
_✓c_✓h_✓a_✓r *_✓t_✓e_✓r_✓m_✓b_✓u_✓f, *_✓n_✓a_✓m_✓e;
_✓f_✓u_✓l_✓l_✓n_✓a_✓m_✓e(_✓t_✓e_✓r_✓m_✓b_✓u_✓f, _✓n_✓a_✓m_✓e)
_✓c_✓h_✓a_✓r *_✓t_✓e_✓r_✓m_✓b_✓u_✓f, *_✓n_✓a_✓m_✓e;
_✓l_✓o_✓n_✓g_✓n_✓a_✓m_✓e() fills in _✓n_✓a_✓m_✓e with the long name of the ter-
minal described by the _✓t_✓e_✓r_✓m_✓c_✓a_✓p entry in _✓t_✓e_✓r_✓m_✓b_✓u_✓f. It is
generally of little use, but is nice for telling the
user in a readable format what terminal we think he
has. This is available in the global variable _✓t_✓t_✓y_✓t_✓y_✓p_✓e.
_✓t_✓e_✓r_✓m_✓b_✓u_✓f is usually set via the termlib routine
_✓t_✓g_✓e_✓t_✓e_✓n_✓t(). _✓f_✓u_✓l_✓l_✓n_✓a_✓m_✓e() is the same as _✓l_✓o_✓n_✓g_✓n_✓a_✓m_✓e(), ex-
cept that it gives the fullest name given in the entry,
which can be quite verbose.
_✓m_✓v_✓w_✓i_✓n(_✓w_✓i_✓n, _✓y, _✓x)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓i_✓n_✓t _✓y, _✓x;
Move the home position of the window _✓w_✓i_✓n from its
current starting coordinates to (_✓y, _✓x). If that would
put part or all of the window off the edge of the ter-
minal screen, _✓m_✓v_✓w_✓i_✓n() returns ERR and does not change
anything. For subwindows, _✓m_✓v_✓w_✓i_✓n() also returns ERR if
you attempt to move it off its main window. If you
move a main window, all subwindows are moved along with
it.
_✓W_✓I_✓N_✓D_✓O_✓W *
_✓n_✓e_✓w_✓w_✓i_✓n(_✓l_✓i_✓n_✓e_✓s, _✓c_✓o_✓l_✓s, _✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x)
_✓i_✓n_✓t _✓l_✓i_✓n_✓e_✓s, _✓c_✓o_✓l_✓s, _✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x;
Create a new window with _✓l_✓i_✓n_✓e_✓s lines and _✓c_✓o_✓l_✓s columns
starting at position (_✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x). If either
_✓l_✓i_✓n_✓e_✓s or _✓c_✓o_✓l_✓s is 0 (zero), that dimension will be set
to (_✓L_✓I_✓N_✓E_✓S - _✓b_✓e_✓g_✓i_✓n__✓y) or (_✓C_✓O_✓L_✓S - _✓b_✓e_✓g_✓i_✓n__✓x) respectively.
Thus, to get a new window of dimensions _✓L_✓I_✓N_✓E_✓S x _✓C_✓O_✓L_✓S,
use _✓n_✓e_✓w_✓w_✓i_✓n(_✓0, _✓0, _✓0, _✓0).
_✓n_✓l() [*]
Screen Package PS1:18-21
_✓n_✓o_✓n_✓l() [*]
Set or unset the terminal to/from nl mode, _✓i._✓e.,
start/stop the system from mapping <_✓R_✓E_✓T_✓U_✓R_✓N> to <_✓L_✓I_✓N_✓E-
_✓F_✓E_✓E_✓D>. If the mapping is not done, _✓r_✓e_✓f_✓r_✓e_✓s_✓h() can do
more optimization, so it is recommended, but not re-
quired, to turn it off.
_✓s_✓c_✓r_✓o_✓l_✓l_✓o_✓k(_✓w_✓i_✓n, _✓b_✓o_✓o_✓l_✓f) [*]
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓b_✓o_✓o_✓l _✓b_✓o_✓o_✓l_✓f;
Set the scroll flag for the given window. If _✓b_✓o_✓o_✓l_✓f is
FALSE, scrolling is not allowed. This is its default
setting.
_✓t_✓o_✓u_✓c_✓h_✓l_✓i_✓n_✓e(_✓w_✓i_✓n, _✓y, _✓s_✓t_✓a_✓r_✓t_✓x, _✓e_✓n_✓d_✓x)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓i_✓n_✓t _✓y, _✓s_✓t_✓a_✓r_✓t_✓x, _✓e_✓n_✓d_✓x;
This function performs a function similar to _✓t_✓o_✓u_✓c_✓h_✓w_✓i_✓n()
on a single line. It marks the first change for the
given line to be _✓s_✓t_✓a_✓r_✓t_✓x, if it is before the current
first change mark, and the last change mark is set to
be _✓e_✓n_✓d_✓x if it is currently less than _✓e_✓n_✓d_✓x.
_✓t_✓o_✓u_✓c_✓h_✓o_✓v_✓e_✓r_✓l_✓a_✓p(_✓w_✓i_✓n_✓1, _✓w_✓i_✓n_✓2)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n_✓1, *_✓w_✓i_✓n_✓2;
Touch the window _✓w_✓i_✓n_✓2 in the area which overlaps with
_✓w_✓i_✓n_✓1. If they do not overlap, no changes are made.
_✓t_✓o_✓u_✓c_✓h_✓w_✓i_✓n(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Make it appear that the every location on the window
has been changed. This is usually only needed for re-
freshes with overlapping windows.
_✓W_✓I_✓N_✓D_✓O_✓W *
_✓s_✓u_✓b_✓w_✓i_✓n(_✓w_✓i_✓n, _✓l_✓i_✓n_✓e_✓s, _✓c_✓o_✓l_✓s, _✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
_✓i_✓n_✓t _✓l_✓i_✓n_✓e_✓s, _✓c_✓o_✓l_✓s, _✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x;
PS1:18-22 Screen Package
Create a new window with _✓l_✓i_✓n_✓e_✓s lines and _✓c_✓o_✓l_✓s columns
starting at position (_✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x) inside the win-
dow _✓w_✓i_✓n. This means that any change made to either
window in the area covered by the subwindow will be
made on both windows. _✓b_✓e_✓g_✓i_✓n__✓y, _✓b_✓e_✓g_✓i_✓n__✓x are specified
relative to the overall screen, not the relative (0, 0)
of _✓w_✓i_✓n. If either _✓l_✓i_✓n_✓e_✓s or _✓c_✓o_✓l_✓s is 0 (zero), that di-
mension will be set to (_✓L_✓I_✓N_✓E_✓S - _✓b_✓e_✓g_✓i_✓n__✓y) or (_✓C_✓O_✓L_✓S -
_✓b_✓e_✓g_✓i_✓n__✓x) respectively.
_✓u_✓n_✓c_✓t_✓r_✓l(_✓c_✓h) [*]
_✓c_✓h_✓a_✓r _✓c_✓h;
This is actually a debug function for the library, but
it is of general usefulness. It returns a string which
is a representation of _✓c_✓h. Control characters become
their upper-case equivalents preceded by a "^". Other
letters stay just as they are. To use _✓u_✓n_✓c_✓t_✓r_✓l(), you
may have to have #_✓i_✓n_✓c_✓l_✓u_✓d_✓e <_✓u_✓n_✓c_✓t_✓r_✓l._✓h> in your file.
_✓5._✓4. _✓D_✓e_✓t_✓a_✓i_✓l_✓s
_✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e()
Get the tty stats. This is normally called by _✓i_✓n_✓-
_✓i_✓t_✓s_✓c_✓r().
_✓m_✓v_✓c_✓u_✓r(_✓l_✓a_✓s_✓t_✓y, _✓l_✓a_✓s_✓t_✓x, _✓n_✓e_✓w_✓y, _✓n_✓e_✓w_✓x)
_✓i_✓n_✓t _✓l_✓a_✓s_✓t_✓y, _✓l_✓a_✓s_✓t_✓x, _✓n_✓e_✓w_✓y, _✓n_✓e_✓w_✓x;
Moves the terminal's cursor from (_✓l_✓a_✓s_✓t_✓y, _✓l_✓a_✓s_✓t_✓x) to
(_✓n_✓e_✓w_✓y, _✓n_✓e_✓w_✓x) in an approximation of optimal fashion.
This routine uses the functions borrowed from _✓e_✓x ver-
sion 2.6. It is possible to use this optimization
without the benefit of the screen routines. With the
screen routines, this should not be called by the user.
_✓m_✓o_✓v_✓e() and _✓r_✓e_✓f_✓r_✓e_✓s_✓h() should be used to move the cursor
position, so that the routines know what's going on.
_✓s_✓c_✓r_✓o_✓l_✓l(_✓w_✓i_✓n)
_✓W_✓I_✓N_✓D_✓O_✓W *_✓w_✓i_✓n;
Scroll the window upward one line. This is normally
not used by the user.
Screen Package PS1:18-23
_✓s_✓a_✓v_✓e_✓t_✓t_✓y() [*]
_✓r_✓e_✓s_✓e_✓t_✓t_✓y() [*]
_✓s_✓a_✓v_✓e_✓t_✓t_✓y() saves the current tty characteristic flags.
_✓r_✓e_✓s_✓e_✓t_✓t_✓y() restores them to what _✓s_✓a_✓v_✓e_✓t_✓t_✓y() stored.
These functions are performed automatically by _✓i_✓n_✓-
_✓i_✓t_✓s_✓c_✓r() and _✓e_✓n_✓d_✓w_✓i_✓n().
_✓s_✓e_✓t_✓t_✓e_✓r_✓m(_✓n_✓a_✓m_✓e)
_✓c_✓h_✓a_✓r *_✓n_✓a_✓m_✓e;
Set the terminal characteristics to be those of the
terminal named _✓n_✓a_✓m_✓e, getting the terminal size from the
_✓T_✓I_✓O_✓C_✓G_✓W_✓I_✓N_✓S_✓Z _✓i_✓o_✓c_✓t_✓l(_✓2) if it exists, otherwise from the
environment. This is normally called by _✓i_✓n_✓i_✓t_✓s_✓c_✓r().
_✓t_✓s_✓t_✓p()
If the new _✓t_✓t_✓y(4) driver is in use, this function will
save the current tty state and then put the process to
sleep. When the process gets restarted, it restores
the tty state and then calls _✓w_✓r_✓e_✓f_✓r_✓e_✓s_✓h(_✓c_✓u_✓r_✓s_✓c_✓r) to redraw
the screen. _✓i_✓n_✓i_✓t_✓s_✓c_✓r() sets the signal SIGTSTP to trap
to this routine.
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓A
_✓1. _✓C_✓a_✓p_✓a_✓b_✓i_✓l_✓i_✓t_✓i_✓e_✓s _✓f_✓r_✓o_✓m _✓t_✓e_✓r_✓m_✓c_✓a_✓p
_✓1._✓1. _✓D_✓i_✓s_✓c_✓l_✓a_✓i_✓m_✓e_✓r
The description of terminals is a difficult business,
and we only attempt to summarize the capabilities here: for
a full description see _✓t_✓e_✓r_✓m_✓c_✓a_✓p(5).
_✓1._✓2. _✓O_✓v_✓e_✓r_✓v_✓i_✓e_✓w
Capabilities from _✓t_✓e_✓r_✓m_✓c_✓a_✓p are of three kinds: string
valued options, numeric valued options, and boolean options.
The string valued options are the most complicated, since
they may include padding information, which we describe now.
Intelligent terminals often require padding on intelli-
gent operations at high (and sometimes even low) speed.
This is specified by a number before the string in the capa-
bility, and has meaning for the capabilities which have a _✓P
at the front of their comment. This normally is a number of
milliseconds to pad the operation. In the current system
which has no true programmable delays, we do this by sending
a sequence of pad characters (normally nulls, but can be
changed (specified by _✓P_✓C)). In some cases, the pad is
better computed as some number of milliseconds times the
number of affected lines (to the bottom of the screen usual-
ly, except when terminals have insert modes which will shift
several lines.) This is specified as, i e.g. , _✓1_✓2*. before
the capability, to say 12 milliseconds per affected whatever
(currently always line). Capabilities where this makes
sense say _✓P*.
_✓1._✓3. _✓V_✓a_✓r_✓i_✓a_✓b_✓l_✓e_✓s _✓S_✓e_✓t _✓B_✓y _✓s_✓e_✓t_✓t_✓e_✓r_✓m()
variables set by _✓s_✓e_✓t_✓t_✓e_✓r_✓m()
Type Name Pad Description
_____________________________________________________________
char * AL P* Add new blank Line
bool AM Automatic Margins
char * BC Back Cursor movement
bool BS BackSpace works
char * BT P Back Tab
bool CA Cursor Addressable
char * CD P* Clear to end of Display
char * CE P Clear to End of line
char * CL P* CLear screen
char * CM P Cursor Motion
char * DC P* Delete Character
char * DL P* Delete Line sequence
char * DM Delete Mode (enter)
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓A
variables set by _✓s_✓e_✓t_✓t_✓e_✓r_✓m()
Type Name Pad Description
_____________________________________________________________
char * DO DOwn line sequence
char * ED End Delete mode
bool EO can Erase Overstrikes with ' '
char * EI End Insert mode
char * HO HOme cursor
bool HZ HaZeltine ~ braindamage
char * IC P Insert Character
bool IN Insert-Null blessing
char * IM enter Insert Mode (IC usually set, too)
char * IP P* Pad after char Inserted using IM+IE
char * LL quick to Last Line, column 0
char * MA ctrl character MAp for cmd mode
bool MI can Move in Insert mode
bool NC No Cr: \r sends \r\n then eats \n
char * ND Non-Destructive space
bool OS OverStrike works
char PC Pad Character
char * SE Standout End (may leave space)
char * SF P Scroll Forwards
char * SO Stand Out begin (may leave space)
char * SR P Scroll in Reverse
char * TA P TAb (not ^I or with padding)
char * TE Terminal address enable Ending sequence
char * TI Terminal address enable Initialization
char * UC Underline a single Character
char * UE Underline Ending sequence
bool UL UnderLining works even though !OS
char * UP UPline
char * US Underline Starting sequence
char * VB Visible Bell
char * VE Visual End sequence
char * VS Visual Start sequence
bool XN a Newline gets eaten after wrap
Names starting with _✓X are reserved for severely nauseous
glitches
For purposes of _✓s_✓t_✓a_✓n_✓d_✓o_✓u_✓t(), if _✓S_✓G() is not 0, _✓S_✓O() is
set to _✓N_✓U_✓L_✓L(), and if _✓U_✓G() is not _✓0(), _✓U_✓S() is set to
_✓N_✓U_✓L_✓L(). If, after this, _✓S_✓O() is _✓N_✓U_✓L_✓L(), and _✓U_✓S() is not,
_✓S_✓O() is set to be _✓U_✓S(), and _✓S_✓E() is set to be _✓U_✓E().
_✓1._✓4. _✓V_✓a_✓r_✓i_✓a_✓b_✓l_✓e_✓s _✓S_✓e_✓t _✓B_✓y _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e()
variables set by _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e()
type name description
____________________________________________________________
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓A
variables set by _✓g_✓e_✓t_✓t_✓m_✓o_✓d_✓e()
type name description
____________________________________________________________
bool NONL Term can't hack linefeeds doing a CR
bool GT Gtty indicates Tabs
bool UPPERCASE Terminal generates only uppercase letters
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓B
_✓1.
_✓T_✓h_✓e _✓W_✓I_✓N_✓D_✓O_✓W _✓s_✓t_✓r_✓u_✓c_✓t_✓u_✓r_✓e
The WINDOW structure is defined as follows:
/*
* _✓C_✓o_✓p_✓y_✓r_✓i_✓g_✓h_✓t _✓1_✓9_✓8_✓0 _✓K_✓e_✓n_✓n_✓e_✓t_✓h _✓C. _✓R. _✓C. _✓A_✓r_✓n_✓o_✓l_✓d _✓a_✓n_✓d _✓T_✓h_✓e _✓R_✓e_✓g_✓e_✓n_✓t_✓s _✓o_✓f _✓t_✓h_✓e
* _✓U_✓n_✓i_✓v_✓e_✓r_✓s_✓i_✓t_✓y _✓o_✓f _✓C_✓a_✓l_✓i_✓f_✓o_✓r_✓n_✓i_✓a. _✓P_✓e_✓r_✓m_✓i_✓s_✓s_✓i_✓o_✓n _✓i_✓s _✓g_✓r_✓a_✓n_✓t_✓e_✓d _✓t_✓o _✓f_✓r_✓e_✓e_✓l_✓y
* _✓d_✓i_✓s_✓t_✓r_✓i_✓b_✓u_✓t_✓e _✓c_✓u_✓r_✓s_✓e_✓s _✓a_✓n_✓d _✓i_✓t_✓s _✓d_✓o_✓c_✓u_✓m_✓e_✓n_✓t_✓a_✓t_✓i_✓o_✓n _✓p_✓r_✓o_✓v_✓i_✓d_✓e_✓d _✓t_✓h_✓a_✓t _✓t_✓h_✓i_✓s
* _✓n_✓o_✓t_✓i_✓c_✓e _✓i_✓s _✓l_✓e_✓f_✓t _✓i_✓n_✓t_✓a_✓c_✓t.
*
* @(#)_✓w_✓i_✓n__✓s_✓t._✓c _✓6._✓1 (_✓B_✓e_✓r_✓k_✓e_✓l_✓e_✓y) _✓4/_✓2_✓4/_✓8_✓6";
*/
# _✓d_✓e_✓f_✓i_✓n_✓e WINDOW _✓s_✓t_✓r_✓u_✓c_✓t _win_st
_✓s_✓t_✓r_✓u_✓c_✓t _win_st {
_✓s_✓h_✓o_✓r_✓t _cury, _curx;
_✓s_✓h_✓o_✓r_✓t _maxy, _maxx;
_✓s_✓h_✓o_✓r_✓t _begy, _begx;
_✓s_✓h_✓o_✓r_✓t _flags;
_✓s_✓h_✓o_✓r_✓t _ch_off;
bool _clear;
bool _leave;
bool _scroll;
_✓c_✓h_✓a_✓r **_y;
_✓s_✓h_✓o_✓r_✓t *_firstch;
_✓s_✓h_✓o_✓r_✓t *_lastch;
_✓s_✓t_✓r_✓u_✓c_✓t _win_st *_nextp, *_orig;
};
# _✓d_✓e_✓f_✓i_✓n_✓e _ENDLINE 001
# _✓d_✓e_✓f_✓i_✓n_✓e _FULLWIN 002
# _✓d_✓e_✓f_✓i_✓n_✓e _SCROLLWIN 004
# _✓d_✓e_✓f_✓i_✓n_✓e _FLUSH 010
# _✓d_✓e_✓f_✓i_✓n_✓e _FULLLINE 020
# _✓d_✓e_✓f_✓i_✓n_✓e _IDLINE 040
# _✓d_✓e_✓f_✓i_✓n_✓e _STANDOUT 0200
# _✓d_✓e_✓f_✓i_✓n_✓e _NOCHANGE -1
__✓c_✓u_✓r_✓y and __✓c_✓u_✓r_✓x are the current (y, x) co-ordinates for
the window. New characters added to the screen are added at
this point. __✓m_✓a_✓x_✓y and __✓m_✓a_✓x_✓x are the maximum values allowed
for (__✓c_✓u_✓r_✓y, __✓c_✓u_✓r_✓x). __✓b_✓e_✓g_✓y and __✓b_✓e_✓g_✓x are the starting (y, x)
co-ordinates on the terminal for the window, _✓i._✓e., the
window's home. __✓c_✓u_✓r_✓y, __✓c_✓u_✓r_✓x, __✓m_✓a_✓x_✓y, and __✓m_✓a_✓x_✓x are measured
____________________
[10] All variables not normally accessed directly by the
user are named with an initial "_" to avoid conflicts with
the user's variables.
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓B
relative to (__✓b_✓e_✓g_✓y, __✓b_✓e_✓g_✓x), not the terminal's home.
__✓c_✓l_✓e_✓a_✓r tells if a clear-screen sequence is to be gen-
erated on the next _✓r_✓e_✓f_✓r_✓e_✓s_✓h() call. This is only meaningful
for screens. The initial clear-screen for the first _✓r_✓e_✓-
_✓f_✓r_✓e_✓s_✓h() call is generated by initially setting clear to be
TRUE for _✓c_✓u_✓r_✓s_✓c_✓r, which always generates a clear-screen if
set, irrelevant of the dimensions of the window involved.
__✓l_✓e_✓a_✓v_✓e is TRUE if the current (y, x) co-ordinates and the
cursor are to be left after the last character changed on
the terminal, or not moved if there is no change. __✓s_✓c_✓r_✓o_✓l_✓l
is TRUE if scrolling is allowed.
__✓y is a pointer to an array of lines which describe the
terminal. Thus:
_y[i]
is a pointer to the _✓ith line, and
_y[i][j]
is the _✓jth character on the _✓ith line. __✓f_✓l_✓a_✓g_✓s can have one
or more values or'd into it.
For windows that are not subwindows, __✓o_✓r_✓i_✓g is NULL .
For subwindows, it points to the main window to which the
window is subsidiary. __✓n_✓e_✓x_✓t_✓p is a pointer in a circularly
linked list of all the windows which are subwindows of the
same main window, plus the main window itself.
__✓f_✓i_✓r_✓s_✓t_✓c_✓h and __✓l_✓a_✓s_✓t_✓c_✓h are _✓m_✓a_✓l_✓l_✓o_✓c()ed arrays which con-
tain the index of the first and last changed characters on
the line. __✓c_✓h__✓o_✓f_✓f is the x offset for the window in the
__✓f_✓i_✓r_✓s_✓t_✓c_✓h and __✓l_✓a_✓s_✓t_✓c_✓h arrays for this window. For main win-
dows, this is always 0; for subwindows it is the difference
between the starting point of the main window and that of
the subindow, so that change markers can be set relative to
the main window. This makes these markers global in scope.
All subwindows share the appropriate portions of __✓y,
__✓f_✓i_✓r_✓s_✓t_✓c_✓h, __✓l_✓a_✓s_✓t_✓c_✓h, and __✓i_✓n_✓s_✓d_✓e_✓l with their main window.
__✓E_✓N_✓D_✓L_✓I_✓N_✓E says that the end of the line for this window
is also the end of a screen. __✓F_✓U_✓L_✓L_✓W_✓I_✓N says that this window
is a screen. __✓S_✓C_✓R_✓O_✓L_✓L_✓W_✓I_✓N indicates that the last character
of this screen is at the lower right-hand corner of the ter-
minal; _✓i._✓e., if a character was put there, the terminal
would scroll. __✓F_✓U_✓L_✓L_✓L_✓I_✓N_✓E says that the width of a line is
the same as the width of the terminal. If __✓F_✓L_✓U_✓S_✓H is set, it
says that _✓f_✓f_✓l_✓u_✓s_✓h(_✓s_✓t_✓d_✓o_✓u_✓t) should be called at the end of each
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓B
_✓r_✓e_✓f_✓r_✓e_✓s_✓h() __✓S_✓T_✓A_✓N_✓D_✓O_✓U_✓T says that all characters added to the
screen are in standout mode. __✓I_✓N_✓S_✓D_✓E_✓L is reserved for future
use, and is set by _✓i_✓d_✓l_✓o_✓k(). __✓f_✓i_✓r_✓s_✓t_✓c_✓h is set to __✓N_✓O_✓C_✓H_✓A_✓N_✓G_✓E
for lines on which there has been no change since the last
_✓r_✓e_✓f_✓r_✓e_✓s_✓h().
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
_✓1. _✓E_✓x_✓a_✓m_✓p_✓l_✓e_✓s
Here we present a few examples of how to use the pack-
age. They attempt to be representative, though not
comprehensive.
_✓2. _✓S_✓c_✓r_✓e_✓e_✓n _✓U_✓p_✓d_✓a_✓t_✓i_✓n_✓g
The following examples are intended to demonstrate the
basic structure of a program using the screen updating sec-
tions of the package. Several of the programs require cal-
culational sections which are irrelevant of to the example,
and are therefore usually not included. It is hoped that
the data structure definitions give enough of an idea to al-
low understanding of what the relevant portions do. The
rest is left as an exercise to the reader, and will not be
on the final.
_✓2._✓1. _✓T_✓w_✓i_✓n_✓k_✓l_✓e
This is a moderately simple program which prints pretty
patterns on the screen that might even hold your interest
for 30 seconds or more. It switches between patterns of as-
terisks, putting them on one by one in random order, and
then taking them off in the same fashion. It is more effi-
cient to write this using only the motion optimization, as
is demonstrated below.
/*
* _✓C_✓o_✓p_✓y_✓r_✓i_✓g_✓h_✓t _✓1_✓9_✓8_✓0 _✓K_✓e_✓n_✓n_✓e_✓t_✓h _✓C. _✓R. _✓C. _✓A_✓r_✓n_✓o_✓l_✓d _✓a_✓n_✓d _✓T_✓h_✓e _✓R_✓e_✓g_✓e_✓n_✓t_✓s _✓o_✓f _✓t_✓h_✓e
* _✓U_✓n_✓i_✓v_✓e_✓r_✓s_✓i_✓t_✓y _✓o_✓f _✓C_✓a_✓l_✓i_✓f_✓o_✓r_✓n_✓i_✓a. _✓P_✓e_✓r_✓m_✓i_✓s_✓s_✓i_✓o_✓n _✓i_✓s _✓g_✓r_✓a_✓n_✓t_✓e_✓d _✓t_✓o _✓f_✓r_✓e_✓e_✓l_✓y
* _✓d_✓i_✓s_✓t_✓r_✓i_✓b_✓u_✓t_✓e _✓c_✓u_✓r_✓s_✓e_✓s _✓a_✓n_✓d _✓i_✓t_✓s _✓d_✓o_✓c_✓u_✓m_✓e_✓n_✓t_✓a_✓t_✓i_✓o_✓n _✓p_✓r_✓o_✓v_✓i_✓d_✓e_✓d _✓t_✓h_✓a_✓t _✓t_✓h_✓i_✓s
* _✓n_✓o_✓t_✓i_✓c_✓e _✓i_✓s _✓l_✓e_✓f_✓t _✓i_✓n_✓t_✓a_✓c_✓t.
*/
#_✓i_✓f_✓n_✓d_✓e_✓f lint
_✓s_✓t_✓a_✓t_✓i_✓c _✓c_✓h_✓a_✓r sccsid[] = "@(#)twinkle1.c 6.1 (Berkeley) 4/24/86";
#_✓e_✓n_✓d_✓i_✓f not lint
# _✓i_✓n_✓c_✓l_✓u_✓d_✓e <curses.h>
# _✓i_✓n_✓c_✓l_✓u_✓d_✓e <signal.h>
/*
* _✓t_✓h_✓e _✓i_✓d_✓e_✓a _✓f_✓o_✓r _✓t_✓h_✓i_✓s _✓p_✓r_✓o_✓g_✓r_✓a_✓m _✓w_✓a_✓s _✓a _✓p_✓r_✓o_✓d_✓u_✓c_✓t _✓o_✓f _✓t_✓h_✓e _✓i_✓m_✓a_✓g_✓i_✓n_✓a_✓t_✓i_✓o_✓n _✓o_✓f
* _✓K_✓u_✓r_✓t _✓S_✓c_✓h_✓o_✓e_✓n_✓s. _✓N_✓o_✓t _✓r_✓e_✓s_✓p_✓o_✓n_✓s_✓i_✓b_✓l_✓e _✓f_✓o_✓r _✓m_✓i_✓n_✓d_✓s _✓l_✓o_✓s_✓t _✓o_✓r _✓s_✓t_✓o_✓l_✓e_✓n.
*/
# _✓d_✓e_✓f_✓i_✓n_✓e NCOLS 80
# _✓d_✓e_✓f_✓i_✓n_✓e NLINES 24
# _✓d_✓e_✓f_✓i_✓n_✓e MAXPATTERNS 4
_✓t_✓y_✓p_✓e_✓d_✓e_✓f _✓s_✓t_✓r_✓u_✓c_✓t {
_✓i_✓n_✓t y, x;
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
} LOCS;
LOCS Layout[NCOLS * NLINES]; /* _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓b_✓o_✓a_✓r_✓d _✓l_✓a_✓y_✓o_✓u_✓t */
_✓i_✓n_✓t Pattern, /* _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓p_✓a_✓t_✓t_✓e_✓r_✓n _✓n_✓u_✓m_✓b_✓e_✓r */
Numstars; /* _✓n_✓u_✓m_✓b_✓e_✓r _✓o_✓f _✓s_✓t_✓a_✓r_✓s _✓i_✓n _✓p_✓a_✓t_✓t_✓e_✓r_✓n */
_✓c_✓h_✓a_✓r *getenv();
_✓i_✓n_✓t die();
main()
{
srand(getpid()); /* _✓i_✓n_✓i_✓t_✓i_✓a_✓l_✓i_✓z_✓e _✓r_✓a_✓n_✓d_✓o_✓m _✓s_✓e_✓q_✓u_✓e_✓n_✓c_✓e */
initscr();
signal(SIGINT, die);
noecho();
nonl();
leaveok(stdscr, TRUE);
scrollok(stdscr, FALSE);
_✓f_✓o_✓r (;;) {
makeboard(); /* _✓m_✓a_✓k_✓e _✓t_✓h_✓e _✓b_✓o_✓a_✓r_✓d _✓s_✓e_✓t_✓u_✓p */
puton('*'); /* _✓p_✓u_✓t _✓o_✓n '*'_✓s */
puton(' '); /* _✓c_✓o_✓v_✓e_✓r _✓u_✓p _✓w_✓i_✓t_✓h ' '_✓s */
}
}
/*
* _✓O_✓n _✓p_✓r_✓o_✓g_✓r_✓a_✓m _✓e_✓x_✓i_✓t, _✓m_✓o_✓v_✓e _✓t_✓h_✓e _✓c_✓u_✓r_✓s_✓o_✓r _✓t_✓o _✓t_✓h_✓e _✓l_✓o_✓w_✓e_✓r _✓l_✓e_✓f_✓t _✓c_✓o_✓r_✓n_✓e_✓r _✓b_✓y
* _✓d_✓i_✓r_✓e_✓c_✓t _✓a_✓d_✓d_✓r_✓e_✓s_✓s_✓i_✓n_✓g, _✓s_✓i_✓n_✓c_✓e _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓l_✓o_✓c_✓a_✓t_✓i_✓o_✓n _✓i_✓s _✓n_✓o_✓t _✓g_✓u_✓a_✓r_✓a_✓n_✓t_✓e_✓e_✓d.
* _✓W_✓e _✓l_✓i_✓e _✓a_✓n_✓d _✓s_✓a_✓y _✓w_✓e _✓u_✓s_✓e_✓d _✓t_✓o _✓b_✓e _✓a_✓t _✓t_✓h_✓e _✓u_✓p_✓p_✓e_✓r _✓r_✓i_✓g_✓h_✓t _✓c_✓o_✓r_✓n_✓e_✓r _✓t_✓o _✓g_✓u_✓a_✓r_✓a_✓n_✓t_✓e_✓e
* _✓a_✓b_✓s_✓o_✓l_✓u_✓t_✓e _✓a_✓d_✓d_✓r_✓e_✓s_✓s_✓i_✓n_✓g.
*/
die()
{
signal(SIGINT, SIG_IGN);
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
exit(0);
}
/*
* _✓M_✓a_✓k_✓e _✓t_✓h_✓e _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓b_✓o_✓a_✓r_✓d _✓s_✓e_✓t_✓u_✓p. _✓I_✓t _✓p_✓i_✓c_✓k_✓s _✓a _✓r_✓a_✓n_✓d_✓o_✓m _✓p_✓a_✓t_✓t_✓e_✓r_✓n _✓a_✓n_✓d
* _✓c_✓a_✓l_✓l_✓s _✓i_✓s_✓o_✓n() _✓t_✓o _✓d_✓e_✓t_✓e_✓r_✓m_✓i_✓n_✓e _✓i_✓f _✓t_✓h_✓e _✓c_✓h_✓a_✓r_✓a_✓c_✓t_✓e_✓r _✓i_✓s _✓o_✓n _✓t_✓h_✓a_✓t _✓p_✓a_✓t_✓t_✓e_✓r_✓n
* _✓o_✓r _✓n_✓o_✓t.
*/
makeboard()
{
reg _✓i_✓n_✓t y, x;
reg LOCS *lp;
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
Pattern = rand() % MAXPATTERNS;
lp = Layout;
_✓f_✓o_✓r (y = 0; y < NLINES; y++)
_✓f_✓o_✓r (x = 0; x < NCOLS; x++)
_✓i_✓f (ison(y, x)) {
lp->y = y;
lp->x = x;
lp++;
}
Numstars = lp - Layout;
}
/*
* _✓R_✓e_✓t_✓u_✓r_✓n _✓T_✓R_✓U_✓E _✓i_✓f (_✓y, _✓x) _✓i_✓s _✓o_✓n _✓t_✓h_✓e _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓p_✓a_✓t_✓t_✓e_✓r_✓n.
*/
ison(y, x)
reg _✓i_✓n_✓t y, x; {
_✓s_✓w_✓i_✓t_✓c_✓h (Pattern) {
_✓c_✓a_✓s_✓e 0: /* _✓a_✓l_✓t_✓e_✓r_✓n_✓a_✓t_✓i_✓n_✓g _✓l_✓i_✓n_✓e_✓s */
_✓r_✓e_✓t_✓u_✓r_✓n !(y & 01);
_✓c_✓a_✓s_✓e 1: /* _✓b_✓o_✓x */
_✓i_✓f (x >= LINES && y >= NCOLS)
_✓r_✓e_✓t_✓u_✓r_✓n FALSE;
_✓i_✓f (y < 3 || y >= NLINES - 3)
_✓r_✓e_✓t_✓u_✓r_✓n TRUE;
_✓r_✓e_✓t_✓u_✓r_✓n (x < 3 || x >= NCOLS - 3);
_✓c_✓a_✓s_✓e 2: /* _✓h_✓o_✓l_✓y _✓p_✓a_✓t_✓t_✓e_✓r_✓n! */
_✓r_✓e_✓t_✓u_✓r_✓n ((x + y) & 01);
_✓c_✓a_✓s_✓e 3: /* _✓b_✓a_✓r _✓a_✓c_✓r_✓o_✓s_✓s _✓c_✓e_✓n_✓t_✓e_✓r */
_✓r_✓e_✓t_✓u_✓r_✓n (y >= 9 && y <= 15);
}
/* _✓N_✓O_✓T_✓R_✓E_✓A_✓C_✓H_✓E_✓D */
}
puton(ch)
reg _✓c_✓h_✓a_✓r ch;
{
reg LOCS *lp;
reg _✓i_✓n_✓t r;
reg LOCS *end;
LOCS temp;
end = &Layout[Numstars];
_✓f_✓o_✓r (lp = Layout; lp < end; lp++) {
r = rand() % Numstars;
temp = *lp;
*lp = Layout[r];
Layout[r] = temp;
}
_✓f_✓o_✓r (lp = Layout; lp < end; lp++) {
mvaddch(lp->y, lp->x, ch);
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
refresh();
}
}
_✓2._✓2. _✓L_✓i_✓f_✓e
This program fragment models the famous computer pat-
tern game of life (Scientific American, May, 1974). The
calculational routines create a linked list of structures
defining where each piece is. Nothing here claims to be op-
timal, merely demonstrative. This code, however, is a very
good place to use the screen updating routines, as it allows
them to worry about what the last position looked like, so
you don't have to. It also demonstrates some of the input
routines.
/*
* _✓C_✓o_✓p_✓y_✓r_✓i_✓g_✓h_✓t _✓1_✓9_✓8_✓0 _✓K_✓e_✓n_✓n_✓e_✓t_✓h _✓C. _✓R. _✓C. _✓A_✓r_✓n_✓o_✓l_✓d _✓a_✓n_✓d _✓T_✓h_✓e _✓R_✓e_✓g_✓e_✓n_✓t_✓s _✓o_✓f _✓t_✓h_✓e
* _✓U_✓n_✓i_✓v_✓e_✓r_✓s_✓i_✓t_✓y _✓o_✓f _✓C_✓a_✓l_✓i_✓f_✓o_✓r_✓n_✓i_✓a. _✓P_✓e_✓r_✓m_✓i_✓s_✓s_✓i_✓o_✓n _✓i_✓s _✓g_✓r_✓a_✓n_✓t_✓e_✓d _✓t_✓o _✓f_✓r_✓e_✓e_✓l_✓y
* _✓d_✓i_✓s_✓t_✓r_✓i_✓b_✓u_✓t_✓e _✓c_✓u_✓r_✓s_✓e_✓s _✓a_✓n_✓d _✓i_✓t_✓s _✓d_✓o_✓c_✓u_✓m_✓e_✓n_✓t_✓a_✓t_✓i_✓o_✓n _✓p_✓r_✓o_✓v_✓i_✓d_✓e_✓d _✓t_✓h_✓a_✓t _✓t_✓h_✓i_✓s
* _✓n_✓o_✓t_✓i_✓c_✓e _✓i_✓s _✓l_✓e_✓f_✓t _✓i_✓n_✓t_✓a_✓c_✓t.
*/
#_✓i_✓f_✓n_✓d_✓e_✓f lint
_✓s_✓t_✓a_✓t_✓i_✓c _✓c_✓h_✓a_✓r sccsid[] = "@(#)life.c 6.1 (Berkeley) 4/23/86";
#_✓e_✓n_✓d_✓i_✓f not lint
# _✓i_✓n_✓c_✓l_✓u_✓d_✓e <curses.h>
# _✓i_✓n_✓c_✓l_✓u_✓d_✓e <signal.h>
/*
* _✓R_✓u_✓n _✓a _✓l_✓i_✓f_✓e _✓g_✓a_✓m_✓e. _✓T_✓h_✓i_✓s _✓i_✓s _✓a _✓d_✓e_✓m_✓o_✓n_✓s_✓t_✓r_✓a_✓t_✓i_✓o_✓n _✓p_✓r_✓o_✓g_✓r_✓a_✓m _✓f_✓o_✓r
* _✓t_✓h_✓e _✓S_✓c_✓r_✓e_✓e_✓n _✓U_✓p_✓d_✓a_✓t_✓i_✓n_✓g _✓s_✓e_✓c_✓t_✓i_✓o_✓n _✓o_✓f _✓t_✓h_✓e -_✓l_✓c_✓u_✓r_✓s_✓e_✓s _✓c_✓u_✓r_✓s_✓o_✓r _✓p_✓a_✓c_✓k_✓a_✓g_✓e.
*/
_✓t_✓y_✓p_✓e_✓d_✓e_✓f _✓s_✓t_✓r_✓u_✓c_✓t lst_st { /* _✓l_✓i_✓n_✓k_✓e_✓d _✓l_✓i_✓s_✓t _✓e_✓l_✓e_✓m_✓e_✓n_✓t */
_✓i_✓n_✓t y, x; /* (_✓y, _✓x) _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n _✓o_✓f _✓p_✓i_✓e_✓c_✓e */
_✓s_✓t_✓r_✓u_✓c_✓t lst_st *next, *last; /* _✓d_✓o_✓u_✓b_✓l_✓y _✓l_✓i_✓n_✓k_✓e_✓d */
} LIST;
LIST *Head; /* _✓h_✓e_✓a_✓d _✓o_✓f _✓l_✓i_✓n_✓k_✓e_✓d _✓l_✓i_✓s_✓t */
_✓i_✓n_✓t die();
main(ac, av)
_✓i_✓n_✓t ac;
_✓c_✓h_✓a_✓r *av[];
{
evalargs(ac, av); /* _✓e_✓v_✓a_✓l_✓u_✓a_✓t_✓e _✓a_✓r_✓g_✓u_✓m_✓e_✓n_✓t_✓s */
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
initscr(); /* _✓i_✓n_✓i_✓t_✓i_✓a_✓l_✓i_✓z_✓e _✓s_✓c_✓r_✓e_✓e_✓n _✓p_✓a_✓c_✓k_✓a_✓g_✓e */
signal(SIGINT, die); /* _✓s_✓e_✓t _✓t_✓o _✓r_✓e_✓s_✓t_✓o_✓r_✓e _✓t_✓t_✓y _✓s_✓t_✓a_✓t_✓s */
cbreak(); /* _✓s_✓e_✓t _✓f_✓o_✓r _✓c_✓h_✓a_✓r-_✓b_✓y-_✓c_✓h_✓a_✓r */
noecho(); /* _✓i_✓n_✓p_✓u_✓t */
nonl(); /* _✓f_✓o_✓r _✓o_✓p_✓t_✓i_✓m_✓i_✓z_✓a_✓t_✓i_✓o_✓n */
getstart(); /* _✓g_✓e_✓t _✓s_✓t_✓a_✓r_✓t_✓i_✓n_✓g _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n */
_✓f_✓o_✓r (;;) {
prboard(); /* _✓p_✓r_✓i_✓n_✓t _✓o_✓u_✓t _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓b_✓o_✓a_✓r_✓d */
update(); /* _✓u_✓p_✓d_✓a_✓t_✓e _✓b_✓o_✓a_✓r_✓d _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n */
}
}
/*
* _✓T_✓h_✓i_✓s _✓i_✓s _✓t_✓h_✓e _✓r_✓o_✓u_✓t_✓i_✓n_✓e _✓w_✓h_✓i_✓c_✓h _✓i_✓s _✓c_✓a_✓l_✓l_✓e_✓d _✓w_✓h_✓e_✓n _✓r_✓u_✓b_✓o_✓u_✓t _✓i_✓s _✓h_✓i_✓t.
* _✓I_✓t _✓r_✓e_✓s_✓e_✓t_✓s _✓t_✓h_✓e _✓t_✓t_✓y _✓s_✓t_✓a_✓t_✓s _✓t_✓o _✓t_✓h_✓e_✓i_✓r _✓o_✓r_✓i_✓g_✓i_✓n_✓a_✓l _✓v_✓a_✓l_✓u_✓e_✓s. _✓T_✓h_✓i_✓s
* _✓i_✓s _✓t_✓h_✓e _✓n_✓o_✓r_✓m_✓a_✓l _✓w_✓a_✓y _✓o_✓f _✓l_✓e_✓a_✓v_✓i_✓n_✓g _✓t_✓h_✓e _✓p_✓r_✓o_✓g_✓r_✓a_✓m.
*/
die()
{
signal(SIGINT, SIG_IGN); /* _✓i_✓g_✓n_✓o_✓r_✓e _✓r_✓u_✓b_✓o_✓u_✓t_✓s */
mvcur(0, COLS - 1, LINES - 1, 0); /* _✓g_✓o _✓t_✓o _✓b_✓o_✓t_✓t_✓o_✓m _✓o_✓f _✓s_✓c_✓r_✓e_✓e_✓n */
endwin(); /* _✓s_✓e_✓t _✓t_✓e_✓r_✓m_✓i_✓n_✓a_✓l _✓t_✓o _✓g_✓o_✓o_✓d _✓s_✓t_✓a_✓t_✓e */
exit(0);
}
/*
* _✓G_✓e_✓t _✓t_✓h_✓e _✓s_✓t_✓a_✓r_✓t_✓i_✓n_✓g _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n _✓f_✓r_✓o_✓m _✓t_✓h_✓e _✓u_✓s_✓e_✓r. _✓T_✓h_✓e_✓y _✓k_✓e_✓y_✓s _✓u, _✓i, _✓o, _✓j, _✓l,
* _✓m, ,, _✓a_✓n_✓d . _✓a_✓r_✓e _✓u_✓s_✓e_✓d _✓f_✓o_✓r _✓m_✓o_✓v_✓i_✓n_✓g _✓t_✓h_✓e_✓i_✓r _✓r_✓e_✓l_✓a_✓t_✓i_✓v_✓e _✓d_✓i_✓r_✓e_✓c_✓t_✓i_✓o_✓n_✓s _✓f_✓r_✓o_✓m _✓t_✓h_✓e
* _✓k _✓k_✓e_✓y. _✓T_✓h_✓u_✓s, _✓u _✓m_✓o_✓v_✓e _✓d_✓i_✓a_✓g_✓o_✓n_✓a_✓l_✓l_✓y _✓u_✓p _✓t_✓o _✓t_✓h_✓e _✓l_✓e_✓f_✓t, , _✓m_✓o_✓v_✓e_✓s _✓d_✓i_✓r_✓e_✓c_✓t_✓l_✓y _✓d_✓o_✓w_✓n,
* _✓e_✓t_✓c. _✓x _✓p_✓l_✓a_✓c_✓e_✓s _✓a _✓p_✓i_✓e_✓c_✓e _✓a_✓t _✓t_✓h_✓e _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n, " " _✓t_✓a_✓k_✓e_✓s _✓i_✓t _✓a_✓w_✓a_✓y.
* _✓T_✓h_✓e _✓i_✓n_✓p_✓u_✓t _✓c_✓a_✓n _✓a_✓l_✓s_✓o _✓b_✓e _✓f_✓r_✓o_✓m _✓a _✓f_✓i_✓l_✓e. _✓T_✓h_✓e _✓l_✓i_✓s_✓t _✓i_✓s _✓b_✓u_✓i_✓l_✓t _✓a_✓f_✓t_✓e_✓r _✓t_✓h_✓e
* _✓b_✓o_✓a_✓r_✓d _✓s_✓e_✓t_✓u_✓p _✓i_✓s _✓r_✓e_✓a_✓d_✓y.
*/
getstart()
{
reg _✓c_✓h_✓a_✓r c;
reg _✓i_✓n_✓t x, y;
_✓a_✓u_✓t_✓o _✓c_✓h_✓a_✓r buf[100];
box(stdscr, '|', '_'); /* _✓b_✓o_✓x _✓i_✓n _✓t_✓h_✓e _✓s_✓c_✓r_✓e_✓e_✓n */
move(1, 1); /* _✓m_✓o_✓v_✓e _✓t_✓o _✓u_✓p_✓p_✓e_✓r _✓l_✓e_✓f_✓t _✓c_✓o_✓r_✓n_✓e_✓r */
_✓f_✓o_✓r (;;) {
refresh(); /* _✓p_✓r_✓i_✓n_✓t _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n */
_✓i_✓f ((c = getch()) == 'q')
_✓b_✓r_✓e_✓a_✓k;
_✓s_✓w_✓i_✓t_✓c_✓h (c) {
_✓c_✓a_✓s_✓e 'u':
_✓c_✓a_✓s_✓e 'i':
_✓c_✓a_✓s_✓e 'o':
_✓c_✓a_✓s_✓e 'j':
_✓c_✓a_✓s_✓e 'l':
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
_✓c_✓a_✓s_✓e 'm':
_✓c_✓a_✓s_✓e ',':
_✓c_✓a_✓s_✓e '.':
adjustyx(c);
_✓b_✓r_✓e_✓a_✓k;
_✓c_✓a_✓s_✓e 'f':
mvaddstr(0, 0, "File name: ");
getstr(buf);
readfile(buf);
_✓b_✓r_✓e_✓a_✓k;
_✓c_✓a_✓s_✓e 'x':
addch('X');
_✓b_✓r_✓e_✓a_✓k;
_✓c_✓a_✓s_✓e ' ':
addch(' ');
_✓b_✓r_✓e_✓a_✓k;
}
}
_✓i_✓f (Head != NULL) /* _✓s_✓t_✓a_✓r_✓t _✓n_✓e_✓w _✓l_✓i_✓s_✓t */
dellist(Head);
Head = malloc(_✓s_✓i_✓z_✓e_✓o_✓f (LIST));
/*
* _✓l_✓o_✓o_✓p _✓t_✓h_✓r_✓o_✓u_✓g_✓h _✓t_✓h_✓e _✓s_✓c_✓r_✓e_✓e_✓n _✓l_✓o_✓o_✓k_✓i_✓n_✓g _✓f_✓o_✓r '_✓x'_✓s, _✓a_✓n_✓d _✓a_✓d_✓d _✓a _✓l_✓i_✓s_✓t
* _✓e_✓l_✓e_✓m_✓e_✓n_✓t _✓f_✓o_✓r _✓e_✓a_✓c_✓h _✓o_✓n_✓e
*/
_✓f_✓o_✓r (y = 1; y < LINES - 1; y++)
_✓f_✓o_✓r (x = 1; x < COLS - 1; x++) {
move(y, x);
_✓i_✓f (inch() == 'x')
addlist(y, x);
}
}
/*
* _✓P_✓r_✓i_✓n_✓t _✓o_✓u_✓t _✓t_✓h_✓e _✓c_✓u_✓r_✓r_✓e_✓n_✓t _✓b_✓o_✓a_✓r_✓d _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n _✓f_✓r_✓o_✓m _✓t_✓h_✓e _✓l_✓i_✓n_✓k_✓e_✓d _✓l_✓i_✓s_✓t
*/
prboard() {
reg LIST *hp;
erase(); /* _✓c_✓l_✓e_✓a_✓r _✓o_✓u_✓t _✓l_✓a_✓s_✓t _✓p_✓o_✓s_✓i_✓t_✓i_✓o_✓n */
box(stdscr, '|', '_'); /* _✓b_✓o_✓x _✓i_✓n _✓t_✓h_✓e _✓s_✓c_✓r_✓e_✓e_✓n */
/*
* _✓g_✓o _✓t_✓h_✓r_✓o_✓u_✓g_✓h _✓t_✓h_✓e _✓l_✓i_✓s_✓t _✓a_✓d_✓d_✓i_✓n_✓g _✓e_✓a_✓c_✓h _✓p_✓i_✓e_✓c_✓e _✓t_✓o _✓t_✓h_✓e _✓n_✓e_✓w_✓l_✓y
* _✓b_✓l_✓a_✓n_✓k _✓b_✓o_✓a_✓r_✓d
*/
_✓f_✓o_✓r (hp = Head; hp; hp = hp->next)
mvaddch(hp->y, hp->x, 'X');
refresh();
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
}
_✓3. _✓M_✓o_✓t_✓i_✓o_✓n _✓o_✓p_✓t_✓i_✓m_✓i_✓z_✓a_✓t_✓i_✓o_✓n
The following example shows how motion optimization is
written on its own. Programs which flit from one place to
another without regard for what is already there usually do
not need the overhead of both space and time associated with
screen updating. They should instead use motion optimiza-
tion.
_✓3._✓1. _✓T_✓w_✓i_✓n_✓k_✓l_✓e
The _✓t_✓w_✓i_✓n_✓k_✓l_✓e program is a good candidate for simple mo-
tion optimization. Here is how it could be written (only
the routines that have been changed are shown):
/*
* _✓C_✓o_✓p_✓y_✓r_✓i_✓g_✓h_✓t _✓1_✓9_✓8_✓0 _✓K_✓e_✓n_✓n_✓e_✓t_✓h _✓C. _✓R. _✓C. _✓A_✓r_✓n_✓o_✓l_✓d _✓a_✓n_✓d _✓T_✓h_✓e _✓R_✓e_✓g_✓e_✓n_✓t_✓s _✓o_✓f _✓t_✓h_✓e
* _✓U_✓n_✓i_✓v_✓e_✓r_✓s_✓i_✓t_✓y _✓o_✓f _✓C_✓a_✓l_✓i_✓f_✓o_✓r_✓n_✓i_✓a. _✓P_✓e_✓r_✓m_✓i_✓s_✓s_✓i_✓o_✓n _✓i_✓s _✓g_✓r_✓a_✓n_✓t_✓e_✓d _✓t_✓o _✓f_✓r_✓e_✓e_✓l_✓y
* _✓d_✓i_✓s_✓t_✓r_✓i_✓b_✓u_✓t_✓e _✓c_✓u_✓r_✓s_✓e_✓s _✓a_✓n_✓d _✓i_✓t_✓s _✓d_✓o_✓c_✓u_✓m_✓e_✓n_✓t_✓a_✓t_✓i_✓o_✓n _✓p_✓r_✓o_✓v_✓i_✓d_✓e_✓d _✓t_✓h_✓a_✓t _✓t_✓h_✓i_✓s
* _✓n_✓o_✓t_✓i_✓c_✓e _✓i_✓s _✓l_✓e_✓f_✓t _✓i_✓n_✓t_✓a_✓c_✓t.
*/
#_✓i_✓f_✓n_✓d_✓e_✓f lint
_✓s_✓t_✓a_✓t_✓i_✓c _✓c_✓h_✓a_✓r sccsid[] = "@(#)twinkle2.c 6.1 (Berkeley) 4/24/86";
#_✓e_✓n_✓d_✓i_✓f not lint
_✓e_✓x_✓t_✓e_✓r_✓n _✓i_✓n_✓t _putchar();
main()
{
reg _✓c_✓h_✓a_✓r *sp;
srand(getpid()); /* _✓i_✓n_✓i_✓t_✓i_✓a_✓l_✓i_✓z_✓e _✓r_✓a_✓n_✓d_✓o_✓m _✓s_✓e_✓q_✓u_✓e_✓n_✓c_✓e */
_✓i_✓f (isatty(0)) {
gettmode();
_✓i_✓f ((sp = getenv("TERM")) != NULL)
setterm(sp);
signal(SIGINT, die);
}
_✓e_✓l_✓s_✓e {
printf("Need a terminal on %d\n", _tty_ch);
exit(1);
}
_puts(TI);
_puts(VS);
noecho();
nonl();
tputs(CL, NLINES, _putchar);
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C
_✓f_✓o_✓r (;;) {
makeboard(); /* _✓m_✓a_✓k_✓e _✓t_✓h_✓e _✓b_✓o_✓a_✓r_✓d _✓s_✓e_✓t_✓u_✓p */
puton('*'); /* _✓p_✓u_✓t _✓o_✓n '*'_✓s */
puton(' '); /* _✓c_✓o_✓v_✓e_✓r _✓u_✓p _✓w_✓i_✓t_✓h ' '_✓s */
}
}
puton(ch)
_✓c_✓h_✓a_✓r ch;
{
reg LOCS *lp;
reg _✓i_✓n_✓t r;
reg LOCS *end;
LOCS temp;
_✓s_✓t_✓a_✓t_✓i_✓c _✓i_✓n_✓t lasty, lastx;
end = &Layout[Numstars];
_✓f_✓o_✓r (lp = Layout; lp < end; lp++) {
r = rand() % Numstars;
temp = *lp;
*lp = Layout[r];
Layout[r] = temp;
}
_✓f_✓o_✓r (lp = Layout; lp < end; lp++)
/* _✓p_✓r_✓e_✓v_✓e_✓n_✓t _✓s_✓c_✓r_✓o_✓l_✓l_✓i_✓n_✓g */
_✓i_✓f (!AM || (lp->y < NLINES - 1 || lp->x < NCOLS - 1)) {
mvcur(lasty, lastx, lp->y, lp->x);
putchar(ch);
lasty = lp->y;
_✓i_✓f ((lastx = lp->x + 1) >= NCOLS)
_✓i_✓f (AM) {
lastx = 0;
lasty++;
}
_✓e_✓l_✓s_✓e
lastx = NCOLS - 1;
}
}
PS1:18-2 Screen Package
_✓C_✓o_✓n_✓t_✓e_✓n_✓t_✓s
1 Overview ............................................ 3
1.1 Terminology (or, Words You Can Say to Sound
Brilliant) ......................................... 3
1.2 Compiling Things ............................... 3
1.3 Screen Updating ................................ 4
1.4 Naming Conventions ............................. 4
2 Variables ........................................... 5
3 Usage ............................................... 6
3.1 Starting up .................................... 6
3.2 The Nitty-Gritty ............................... 7
3.2.1 Output .................................... 7
3.2.2 Input ..................................... 8
3.2.3 Miscellaneous ............................. 8
3.3 Finishing up ................................... 8
4 Cursor Motion Optimization: Standing Alone .......... 8
4.1 Terminal Information ........................... 9
4.2 Movement Optimizations, or, Getting Over
Yonder ............................................. 10
5 The Functions ....................................... 10
5.1 Output Functions ............................... 11
5.2 Input Functions ................................ 16
5.3 Miscellaneous Functions ........................ 18
5.4 Details ........................................ 22
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x_✓e_✓s
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓A ............................................ 24
1 Capabilities from termcap ........................... 24
1.1 Disclaimer ..................................... 24
1.2 Overview ....................................... 24
1.3 Variables Set By setterm() ..................... 24
1.4 Variables Set By gettmode() .................... 25
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓B ............................................ 27
1 The WINDOW structure ................................ 27
_✓A_✓p_✓p_✓e_✓n_✓d_✓i_✓x _✓C ............................................ 30
1 Examples ............................................ 30
2 Screen Updating ..................................... 30
2.1 Twinkle ........................................ 30
2.2 Life ........................................... 33
3 Motion optimization ................................. 36
3.1 Twinkle ........................................ 36