1035 lines
46 KiB
HTML
1035 lines
46 KiB
HTML
<TITLE>mitem_attribs(3x)</TITLE>
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>Writing Programs with NCURSES</TITLE>
|
|
<link rev="made" href="mailto:esr@snark.thyrsus.com">
|
|
</HEAD>
|
|
<BODY>
|
|
|
|
<H1>Writing Programs with NCURSES</H1>
|
|
|
|
<BLOCKQUOTE>
|
|
by Zeyd M. ben-Halim and Eric S. Raymond<BR>
|
|
(version 1.9, 1 May 1995)
|
|
</BLOCKQUOTE>
|
|
|
|
<H1>Contents</H1>
|
|
<UL>
|
|
<LI> <A HREF="#introduction">Introduction</A>
|
|
<LI> <A HREF="#overview">An Overview of Curses</A>
|
|
<UL>
|
|
<LI> <A HREF="#terminology">Terminology</A>
|
|
<LI> <A HREF="#compiling">Compiling Programs using Curses</A>
|
|
<LI> <A HREF="#updating">Updating the Screen</A>
|
|
<LI> <A HREF="#stdscr">Standard Windows and Function Naming Conventions</A>
|
|
<LI> <A HREF="#variables">Variables</A>
|
|
</UL>
|
|
<LI> <A HREF="#using">Using the Library</A>
|
|
<UL>
|
|
<LI> <A HREF="#starting">Starting up</A>
|
|
<LI> <A HREF="#output">Output</A>
|
|
<LI> <A HREF="#input">Input</A>
|
|
<LI> <A HREF="#formschars">Using Forms Characters</A>
|
|
<LI> <A HREF="#attributes">Character Attributes and Color</A>
|
|
<LI> <A HREF="#finishing">Finishing Up</A>
|
|
</UL>
|
|
<LI> <A HREF="#functions">Function Descriptions</A>
|
|
<UL>
|
|
<LI> <A HREF="#init">Initialization and Wrapup</A>
|
|
<LI> <A HREF="#flush">Causing Output to the Terminal</A>
|
|
<LI> <A HREF="#lowlevel">Low-Level Capability Access</A>
|
|
<LI> <A HREF="#debugging">Debugging</A>
|
|
</UL>
|
|
<LI> <A HREF="#hints">Hints, Tips, and Tricks</A>
|
|
<UL>
|
|
<LI> <A HREF="#caution">Some Notes of Caution</A>
|
|
<LI> <A HREF="#leaving">Temporarily Leaving ncurses Mode</A>
|
|
<LI> <A HREF="#xterm">Using <TT>ncurses</TT> under <TT>xterm</TT></A>
|
|
<LI> <A HREF="#screens">Handling Multiple Terminal Screens</A>
|
|
<LI> <A HREF="#testing">Testing for Terminal Capabilities</A>
|
|
<LI> <A HREF="#tuning">Tuning for Speed</A>
|
|
<LI> <A HREF="#special">Special Features of <TT>ncurses</TT></A>
|
|
</UL>
|
|
<LI> <A HREF="#panels">The <CODE>panels</CODE> Library</A>
|
|
<UL>
|
|
<LI> <A HREF="#pcompile">Compiling With the panels Library</A>
|
|
<LI> <A HREF="#poverview">Overview of panels</A>
|
|
<LI> <A HREF="#pstsdcr">Panels, Input, and the Standard Screen</A>
|
|
<LI> <A HREF="#hiding">Hiding Panels</A>
|
|
<LI> <A HREF="#pmisc">Miscellaneous Other Facilities</A>
|
|
</UL>
|
|
<LI> <A HREF="#menu">The Menu Library</A>
|
|
<LI> <A HREF="#mcompile">Compiling With the menu Library</A>
|
|
<LI> <A HREF="#moverview">Overview of Menus</A>
|
|
<LI> <A HREF="#select">Selecting items</A>
|
|
<LI> <A HREF="#mdisplay">Menu Display</A>
|
|
<LI> <A HREF="#mwindows">Menu Windows</A>
|
|
<LI> <A HREF="#minput">Processing Menu Input</A>
|
|
<LI> <A HREF="#mmisc">Miscellaneous Other Features</A>
|
|
</UL>
|
|
|
|
<HR>
|
|
<H1><A NAME="introduction">Introduction</A></H1>
|
|
|
|
This document is an introduction to programming with <TT>curses</TT>. It is
|
|
not an exhaustive reference for the curses Application Programming Interface
|
|
(API); that role is filled by the <TT>curses</TT> manual pages. Rather, it
|
|
is intended to help C programmers ease into using the package. <P>
|
|
|
|
The <TT>curses</TT> package is a subroutine library which presents a high level
|
|
screen model to the programmer, hiding differences between terminal types and
|
|
doing automatic optimization of output to change one screenfull of text into
|
|
another. <TT>Curses</TT> uses terminfo, which is a database format that can
|
|
describe the capabilities of thousands of different terminals. <P>
|
|
|
|
Historically, the first ancestor of <TT>curses</TT> was the routines written to
|
|
provide screen-handling for the game <TT>rogue</TT>; these used the already-
|
|
existing <TT>termcap</TT> database facility for describing terminal
|
|
capabilities. These routines were abstracted into a documented library and
|
|
first released with the early BSD UNIX versions. <P>
|
|
|
|
System III UNIX from Bell Labs featured a rewritten and much-improved
|
|
<TT>curses</TT> library. It introduced the terminfo format. Terminfo is based
|
|
on Berkeley's termcap database, but contains a number of improvements and
|
|
extensions. Parameterized capabilities strings were introduced, making it
|
|
possible to describe multiple video attributes, and colors and to handle far
|
|
more unusual terminals than possible with termcap. In the later AT&T
|
|
System V releases, <TT>curses</TT> evolved to use more facilities and offer
|
|
more capabilities, going far beyond BSD curses in power and flexibility.<P>
|
|
|
|
This document describes <TT>ncurses</TT>, a freeware implementation of the
|
|
System V <TT>curses</TT> API. It includes the following System V curses
|
|
features: <P>
|
|
<UL>
|
|
<LI> Support for multiple screen highlights (BSD curses could only
|
|
handle one `standout' highlight, usually reverse-video). <P>
|
|
<LI> Support for line- and box-drawing using forms characters. <P>
|
|
<LI> Recognition of function keys on input. <P>
|
|
<LI> Color support. <P>
|
|
<LI> Support for pads (windows of larger than screen size on which the
|
|
screen or a subwindow defines a viewport). <P>
|
|
</UL>
|
|
|
|
Also, this package makes use of the insert and delete line and character
|
|
features of terminals so equipped, and determines how to optimally use these
|
|
features with no help from the programmer. It allows arbitrary combinations of
|
|
video attributes to be displayed, even on terminals that leave ``magic
|
|
cookies'' on the screen to mark changes in attributes. <P>
|
|
|
|
The <TT>ncurses</TT> package was originated by Pavel Curtis. The primary
|
|
maintainer of the package is Zeyd ben-Halim <zmbenhal@netcom.com>.
|
|
Eric S. Raymond <esr@snark.thyrsus.com> wrote many of the new
|
|
features in versions after 1.8.1 and coauthored this introduction. <P>
|
|
|
|
This document also describes the <A HREF="panels"></A> extension library,
|
|
similarly modeled on the SVr4 panels facility. This library allows you to
|
|
associate backing store with each of a stack or deck of overlapping windows,
|
|
and provides operations for moving windows around in the stack that change
|
|
their visibility in the natural way (handling window overlaps). <P>
|
|
|
|
Finally, this document describes the <A HREF="#menus">menu</A> extension
|
|
library, also cloned from System V, which provides easy construction and
|
|
sequences of menus. <P>
|
|
|
|
<H1><A NAME="overview">An Overview of Curses</A></H1>
|
|
|
|
<H2><A NAME="terminology">Terminology</A></H2>
|
|
|
|
In this document, the following terminology is used with reasonable
|
|
consistency:
|
|
|
|
<DL>
|
|
<DT> window
|
|
<DD>
|
|
A data structure describing a sub-rectangle of the screen (possibly the
|
|
entire screen). You can write to a window as though it were a miniature
|
|
screen, scrolling independently of other windows on the physical screen.
|
|
<DT> screens
|
|
<DD>
|
|
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, <TT>stdscr</TT>, is automatically provided for the programmer.
|
|
<DT> terminal screen
|
|
<DD>
|
|
The package's idea of what the terminal display currently looks like, i.e.,
|
|
what the user sees now. This is a special screen.
|
|
</DL>
|
|
|
|
<H2><A NAME="compiling">Compiling Programs using Curses</A></H2>
|
|
|
|
In order to use the library, it is necessary to have certain types and
|
|
variables defined. Therefore, the programmer must have a line:
|
|
|
|
<PRE>
|
|
#include <TT><curses.h></TT>
|
|
</PRE>
|
|
|
|
at the top of the program source. The screen package uses the Standard I/O
|
|
library, so <TT><curses.h></TT> includes
|
|
<TT><stdio.h></TT>. <TT><curses.h></TT> also includes
|
|
<TT><termios.h></TT>, <TT><termio.h></TT>, or
|
|
<TT><sgtty.h></TT> depending on your system. It is redundant (but
|
|
harmless) for the programmer to do these includes, too. In linking with
|
|
<TT>curses</TT> you need to have <TT>-lncurses</TT> in your LDFLAGS or on the
|
|
command line. There is no need for any other libraries.
|
|
|
|
<H2><A NAME="updating">Updating the Screen</A></H2>
|
|
|
|
In order to update the screen optimally, it is necessary 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 WINDOW is
|
|
defined which describes a window image to the routines, including its starting
|
|
position on the screen (the (y, x) coordinates of the upper left hand corner)
|
|
and its size. One of these (called <TT>curscr</TT>, for current screen) is a
|
|
screen image of what the terminal currently looks like. Another screen (called
|
|
<TT>stdscr</TT>, for standard screen) is provided by default to make changes
|
|
on. <P>
|
|
|
|
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's more like a
|
|
scratchpad or write buffer. <P>
|
|
|
|
To make the section of physical screen corresponding to a window reflect the
|
|
contents of the window structure, the routine <TT>refresh()</TT> (or
|
|
<TT>wrefresh()</TT> if the window is not <TT>stdscr</TT>) is called. <P>
|
|
|
|
A given physical screen section may be within the scope of any number of
|
|
overlapping windows. 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 implementation
|
|
determine the most efficient way to repaint the screen. <P>
|
|
|
|
<H2><A NAME="stdscr">Standard Windows and Function Naming Conventions</A></H2>
|
|
|
|
As hinted above, the routines can use several windows, but two are
|
|
automatically given: <TT>curscr</TT>, which knows what the terminal looks like,
|
|
and <TT>stdscr</TT>, which is what the pro- grammer wants the terminal to look
|
|
like next. The user should never actually access <TT>curscr</TT> directly.
|
|
Changes should be made to through the API, and then the routine
|
|
<TT>refresh()</TT> (or <TT>wrefresh()</TT>) called. <P>
|
|
|
|
Many functions are defined to use <TT>stdscr</TT> as a default screen. For
|
|
example, to add a character to <TT>stdscr</TT>, one calls <TT>addch()</TT> with
|
|
the desired character as argument. To write to a different window. use the
|
|
routine <TT>waddch()</TT> (for `w'indow-specific addch()) is provided. This
|
|
convention of prepending function names with a `w' when they are to be
|
|
applied to specific windows is consistent. The only routines which do not
|
|
follow it are those for which a window must always be specified. <P>
|
|
|
|
In order to move the current (y, x) coordinates from one point to another, the
|
|
routines <TT>move()</TT> and <TT>wmove()</TT> are provided. However, it is
|
|
often desirable to first move and then perform some I/O operation. In order to
|
|
avoid clumsiness, most I/O routines can be preceded by the prefix 'mv' and
|
|
the desired (y, x) coordinates prepended to the arguments to the function. For
|
|
example, the calls
|
|
|
|
<PRE>
|
|
move(y, x);
|
|
addch(ch);
|
|
</PRE>
|
|
|
|
can be replaced by
|
|
|
|
<PRE>
|
|
mvaddch(y, x, ch);
|
|
</PRE>
|
|
|
|
and
|
|
|
|
<PRE>
|
|
wmove(win, y, x);
|
|
waddch(win, ch);
|
|
</PRE>
|
|
|
|
can be replaced by
|
|
|
|
<PRE>
|
|
mvwaddch(win, y, x, ch);
|
|
</PRE>
|
|
|
|
Note that the window description pointer (win) comes before the added (y, x)
|
|
coordinates. If a function requires a window pointer, it is always the first
|
|
parameter passed. <P>
|
|
|
|
<H2><A NAME="variables">Variables</A></H2>
|
|
|
|
The <TT>curses</TT> library sets some variables describing the terminal
|
|
capabilities.
|
|
|
|
<PRE>
|
|
type name description
|
|
------------------------------------------------------------------
|
|
int LINES number of lines on the terminal
|
|
int COLS number of columns on the terminal
|
|
</PRE>
|
|
|
|
The <TT>curses.h</TT> also introduces some <TT>#define</TT> constants and types
|
|
of general usefulness:
|
|
|
|
<DL>
|
|
<DT> <TT>bool</TT>
|
|
<DD> boolean type, actually a `char' (e.g., <TT>bool doneit;</TT>)
|
|
<DT> <TT>TRUE</TT>
|
|
<DD> boolean `true' flag (1).
|
|
<DT> <TT>FALSE</TT>
|
|
<DD> boolean `false' flag (0).
|
|
<DT> <TT>ERR</TT>
|
|
<DD> error flag returned by routines on a fail (-1).
|
|
<DT> <TT>OK</TT>
|
|
<DD> error flag returned by routines when things go right.
|
|
</DL>
|
|
|
|
<H1><A NAME="using">Using the Library</A></H1>
|
|
|
|
Now we describe how to actually use the screen package. In it, we assume all
|
|
updating, reading, etc. is applied to <TT>stdscr</TT>. These instructions will
|
|
work on any window, providing you change the function names and parameters as
|
|
mentioned above. <P>
|
|
|
|
Here is a sample program to motivate the discussion: <P>
|
|
|
|
<PRE>
|
|
#include <curses.h>
|
|
#include <signal.h>
|
|
|
|
static void finish(int sig);
|
|
|
|
main(int argc, char *argv[])
|
|
{
|
|
/* initialize your non-curses data structures here */
|
|
|
|
(void) signal(SIGINT, finish); /* arrange interrupts to terminate */
|
|
|
|
(void) initscr(); /* initialize the curses library */
|
|
keypad(stdscr, TRUE); /* enable keyboard mapping */
|
|
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
|
|
(void) cbreak(); /* take input chars one at a time, no wait for \n */
|
|
(void) noecho(); /* don't echo input */
|
|
|
|
if (has_colors())
|
|
{
|
|
start_color();
|
|
|
|
/*
|
|
* Simple color assignment, often all we need.
|
|
*/
|
|
init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
|
|
init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
|
|
init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
|
|
init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
|
|
init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
|
|
init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
int c = getch(); /* refresh, accept single keystroke of input */
|
|
|
|
/* process the command keystroke */
|
|
}
|
|
|
|
finish(0); /* we're done */
|
|
}
|
|
|
|
static void finish(int sig)
|
|
{
|
|
endwin();
|
|
|
|
/* do your non-curses wrapup here */
|
|
|
|
exit(0);
|
|
}
|
|
</PRE>
|
|
|
|
<H2><A NAME="starting">Starting up</A></H2>
|
|
|
|
In order to use the screen package, the routines must know about terminal
|
|
characteristics, and the space for <TT>curscr</TT> and <TT>stdscr</TT> must be
|
|
allocated. These function <TT>initscr()</TT> does both these things. Since it
|
|
must allocate space for the windows, it can overflow memory when attempting to
|
|
do so. On the rare occasions this happens, <TT>initscr()</TT> will terminate
|
|
the program with an error message. <TT>initscr()</TT> must always 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 <TT>curscr</TT> or <TT>stdscr</TT> are
|
|
referenced. 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 <TT>nl()</TT> and <TT>cbreak()</TT> should be called
|
|
after <TT>initscr()</TT>. <P>
|
|
|
|
Once the screen windows have been allocated, you can set them up for
|
|
your program. If you want to, say, allow a screen to scroll, use
|
|
<TT>scrollok()</TT>. If you want the cursor to be left in place after
|
|
the last change, use <TT>leaveok()</TT>. If this isn't done,
|
|
<TT>refresh()</TT> will move the cursor to the window's current (y, x)
|
|
coordinates after updating it. <P>
|
|
|
|
You can create new windows of your own using the functions <TT>newwin()</TT>,
|
|
<TT>derwin()</TT>, and <TT>subwin()</TT>. The routine <TT>delwin()</TT> will
|
|
allow you to get rid of old windows. All the options described above can be
|
|
applied to any window. <P>
|
|
|
|
<H2><A NAME="output">Output</A></H2>
|
|
|
|
Now that we have set things up, we will want to actually update the terminal.
|
|
The basic functions used to change what will go on a window are
|
|
<TT>addch()</TT> and <TT>move()</TT>. <TT>addch()</TT> adds a character at the
|
|
current (y, x) coordinates. <TT>move()</TT> changes the current (y, x)
|
|
coordinates to whatever you want them to be. It returns <TT>ERR</TT> if you
|
|
try to move off the window. As mentioned above, you can combine the two into
|
|
<TT>mvaddch()</TT> to do both things at once. <P>
|
|
|
|
The other output functions, such as <TT>addstr()</TT> and <TT>printw()</TT>,
|
|
all call <TT>addch()</TT> to add characters to the window. <P>
|
|
|
|
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
|
|
<TT>refresh()</TT>. In order to optimize finding changes, <TT>refresh()</TT>
|
|
assumes that any part of the window not changed since the last
|
|
<TT>refresh()</TT> 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 routine <TT>touchwin()</TT> is provided
|
|
to make it look like the entire window has been changed, thus making
|
|
<TT>refresh()</TT> check the whole subsection of the terminal for changes. <P>
|
|
|
|
If you call <TT>wrefresh()</TT> with <TT>curscr</TT> as its argument, it will
|
|
make the screen look like <TT>curscr</TT> thinks it looks like. This is useful
|
|
for implementing a command which would redraw the screen in case it get messed
|
|
up. <P>
|
|
|
|
<H2><A NAME="input">Input</A></H2>
|
|
|
|
The complementary function to <TT>addch()</TT> is <TT>getch()</TT> which, if
|
|
echo is set, will call <TT>addch()</TT> 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. Since
|
|
initially the terminal has echoing enabled and is in ordinary ``cooked'' mode,
|
|
one or the other has to changed before calling <TT>getch()</TT>; otherwise,
|
|
the program's output will be unpredictable. <P>
|
|
|
|
When you need to accept line-oriented input in a window, the functions
|
|
<TT>wgetstr</TT> and friends are available. There is even a <TT>wscanw</TT>
|
|
function that can do <TT>scanf</TT>(3)-style multi-field parsing on window
|
|
input. These pseudo-line-oriented functions turn on echoing while they
|
|
execute. <P>
|
|
|
|
The example code above uses the call <TT>keypad(stdscr, TRUE)</TT> to enable
|
|
support for function-key mapping. With this feature, the <TT>getch()</TT> code
|
|
watches the input stream for character sequences that correspond to arrow and
|
|
function keys. These sequences are returned as pseudo-character values. The
|
|
<TT>#define</TT> values returned are listed in the <TT>ncurses.h</TT> The
|
|
mapping from sequences to <TT>#define</TT> values is determined by
|
|
<TT>key_</TT> capabilities in the terminal's terminfo entry. <P>
|
|
|
|
<H2><A NAME="formschars">Using Forms Characters</A></H2>
|
|
|
|
The <TT>addch</TT> function (and some others, including <TT>box</TT> and
|
|
<TT>border</TT>) can accept some pseudo-character arguments which are specially
|
|
defined by <TT>ncurses</TT>. These are <TT>#define</TT> values set up in
|
|
the <TT>ncurses.h</TT> header; see there for a complete list (look for
|
|
the prefix <TT>ACS_</TT>). <P>
|
|
|
|
The most useful of the ACS defines are the forms-drawing characters. You can
|
|
use these to draw boxes and simple graphs on the screen. If the terminal
|
|
does not have such characters, <TT>ncurses.h</TT> will map them to a
|
|
recognizable (though ugly) set of ASCII defaults. <P>
|
|
|
|
<H2><A NAME="attributes">Character Attributes and Color</A></H2>
|
|
|
|
The <TT>ncurses</TT> package supports screen highlights including standout,
|
|
reverse-video, underline, and blink. It also supports color, which is treated
|
|
as another kind of highlight. <P>
|
|
|
|
Highlights are encoded, internally, as high bits of the pseudo-character type
|
|
(<TT>chtype</TT>) that <TT>ncurses.h</TT> uses to represent the contents of a
|
|
screen cell. See the <TT>ncurses.h</TT> header file for a complete list of
|
|
highlight mask values (look for the prefix <TT>A_</TT>).<P>
|
|
|
|
There are two ways to make highlights. One is to logical-or the value of the
|
|
highlights you want into the character argument of an <TT>addch</TT> call,
|
|
or any other output call that takes a <TT>chtype</TT> argument. <P>
|
|
|
|
The other is to set the current-highlight value. This is logical-or'ed with
|
|
any highlight you specify the first way. You do this with the functions
|
|
<TT>attron</TT>, <TT>attroff</TT>, and <TT>attrset</TT>; see the manual
|
|
pages for details.
|
|
|
|
Color is a special kind of highlight. The package actually thinks in terms
|
|
of color pairs, combinations of foreground and background colors. The sample
|
|
code above sets up eight color pairs, all of the guaranteed-available colors
|
|
on black. Note that each color pair is, in effect, given the name of its
|
|
foreground color. Any other range of eight non-conflicting values could
|
|
have been used as the first arguments of the <TT>init_pair</TT> values. <P>
|
|
|
|
Once you've done an <TT>init_pair</TT> that creates color-pair N, you can
|
|
use <TT>COLOR_PAIR(N)</TT> as a highlight that invokes that particular
|
|
color combination. Note that <TT>COLOR_PAIR(N)</TT>, for constant N,
|
|
is itself a compile-time constant and can be used in initializers. <P>
|
|
|
|
<H2><A NAME="finishing">Finishing Up</A></H2>
|
|
|
|
In order to clean up after the <TT>ncurses</TT> routines, the routine
|
|
<TT>endwin()</TT> is provided. It restores tty modes to what they were when
|
|
<TT>initscr()</TT> was first called, and moves the cursor down to the
|
|
lower-left corner. Thus, anytime after the call to initscr, <TT>endwin()</TT>
|
|
should be called before exiting. <P>
|
|
|
|
<H1><A NAME="functions">Function Descriptions</A></H1>
|
|
|
|
We describe the detailed behavior of some important curses functions here, as a
|
|
supplement to the manual page descriptions.
|
|
|
|
<H2><A NAME="init">Initialization and Wrapup</A></H2>
|
|
|
|
<DL>
|
|
<DT> <TT>initscr()</TT>
|
|
<DD> The first function called should almost always be
|
|
<TT>initscr</TT>. This will determine the terminal type and
|
|
initialize curses data structures. <TT>initscr</TT> also arranges that
|
|
the first call to <TT>refresh</TT> will clear the screen. If an error
|
|
occurs a message is writen to standard error and the program
|
|
exits. Otherwise it returns a pointer to stdscr. A few functions may be
|
|
called before initscr (<TT>slk_init</TT>, <TT>filter</TT>,
|
|
<TT>ripofflines</TT>, <TT>use_env</TT>, and, if you are using multiple
|
|
terminals, <TT>newterm</TT>.)
|
|
<DT> <TT>endwin()</TT>
|
|
<DD> Your program should always call <TT>endwin</TT> before exiting or
|
|
shelling out of the program. This function will restore tty modes,
|
|
move the cursor to the lower left corner of the screen, reset the
|
|
terminal into the proper nonvisual mode. Calling <TT>refresh()</TT>
|
|
or <TT>doupdate()</TT> after a temporary escape from the program will
|
|
restore the ncurses screen from before the escape.
|
|
<DT> <TT>newterm(type, ofp, ifp)</TT>
|
|
<DD> A program which outputs to more than one terminal should use
|
|
<TT>newterm</TT> instead of <TT>initscr</TT>. <TT>newterm</TT> should
|
|
be called once for each terminal. It returns a variable of type
|
|
<TT>SCREEN *</TT> which should be saved as a reference to that
|
|
terminal. The arguments are the type of the terminal (a string) and
|
|
<TT>FILE</TT> pointers for the output and input of the terminal. If
|
|
type is NULL then the environment variable <TT>$TERM</TT> is used.
|
|
<TT>endwin</TT> should called once at wrapup time for each terminal
|
|
opened using this function.
|
|
<DT> <TT>set_term(new)</TT>
|
|
<DD> This function is used to switch to a different terminal previously
|
|
opened by <TT>newterm</TT>. The screen reference for the new terminal
|
|
is passed as the parameter. The previous terminal is returned by the
|
|
function. All other calls affect only the current terminal.
|
|
<DT> <TT>delscreen(sp)</TT>
|
|
<DD> The inverse of <TT>newterm</TT>; deallocates the data structures
|
|
associated with a given <TT>SCREEN</TT> reference.
|
|
</DL>
|
|
|
|
<H2><A NAME="flush">Causing Output to the Terminal</A></H2>
|
|
|
|
<DL>
|
|
<DT> <TT>refresh()</TT> and <TT>wrefresh(win)</TT>
|
|
<DD> These functions must be called to actually get any output on
|
|
the terminal, as other routines merely manipulate data
|
|
structures. <TT>wrefresh</TT> copies the named window to the physi-
|
|
cal terminal screen, taking into account what is already
|
|
there in order to do optimizations. <TT>refresh</TT> does a
|
|
refresh of <TT>stdscr</TT>. Unless <TT>leaveok</TT> has been
|
|
enabled, the physical cursor of the terminal is left at the
|
|
location of the window's cursor.
|
|
<DT> <TT>doupdate()</TT> and <TT>wnoutrefresh(win)</TT>
|
|
<DD> These two functions allow multiple updates with more efficiency
|
|
than wrefresh. To use them, it is important to understand how curses
|
|
works. In addition to all the window structures, curses keeps two
|
|
data structures representing the terminal screen: a physical screen,
|
|
describing what is actually on the screen, and a virtual screen,
|
|
describing what the programmer wants to have on the screen. wrefresh
|
|
works by first copying the named window to the virtual screen
|
|
(<TT>wnoutrefresh</TT>), and then calling the routine to update the
|
|
screen (<TT>doupdate</TT>). If the programmer wishes to output
|
|
several windows at once, a series of calls to wre- fresh will result
|
|
in alternating calls to <TT>wnoutrefresh</TT> and <TT>doupdate</TT>,
|
|
causing several bursts of output to the screen. By calling
|
|
<TT>wnoutrefresh</TT> for each window, it is then possible to call
|
|
<TT>doupdate once</TT>, resulting in only one burst of output, with
|
|
probably fewer total characters transmitted.
|
|
</DL>
|
|
|
|
<H2><A NAME="init">Low-Level Capability Access</A></H2>
|
|
|
|
<DL>
|
|
<DT> <TT>setupterm(term, filenum, errret)</TT>
|
|
This routine is called to initialize a terminal's description, without setting
|
|
up the curses screen structures or changing the tty-driver mode bits.
|
|
<TT>term</TT> is the character string representing the name of the terminal
|
|
being used. <TT>filenum</TT> is the UNIX file descriptor of the ter- minal to
|
|
be used for output. <TT>errret</TT> is a pointer to an integer, in which a
|
|
success or failure indication is returned. The values returned can be 1 (all
|
|
is well), 0 (no such terminal), or -1 (some problem locating the terminfo
|
|
database). <P>
|
|
|
|
The value of <TT>term</TT> can be given as NULL, which will cause the value of
|
|
<TT>TERM</TT> in the environment to be used. The <TT>errret</TT> pointer can
|
|
also be given as NULL, meaning no error code is wanted. If <TT>errret</TT> is
|
|
defaulted, and something goes wrong, <TT>setupterm</TT> will print an
|
|
appropriate error message and exit, rather than returning. Thus, a simple
|
|
program can call setupterm(0, 1, 0) and not worry about initialization
|
|
errors. <P>
|
|
|
|
After the call to <TT>setupterm</TT>, the global variable <TT>cur_term</TT> is
|
|
set to point to the current structure of terminal capabilities. By calling
|
|
<TT>setupterm</TT> for each terminal, and saving and restoring
|
|
<TT>cur_term</TT>, it is possible for a program to use two or more terminals at
|
|
once. <TT>Setupterm</TT> also stores the names section of the terminal
|
|
description in the global character array <TT>ttytype[]</TT>. Subsequent calls
|
|
to <TT>setupterm</TT> will overwrite this array, so you'll have to save it
|
|
yourself if need be. <P>
|
|
<DD>
|
|
</DL>
|
|
|
|
<H2><A NAME="debugging">Debugging</A></H2>
|
|
|
|
<DL>
|
|
<DT> <TT>_tracef()</TT>
|
|
<DD>
|
|
NOTE: THIS FUNCTION IS NOT PART OF THE STANDARD CURSES API!
|
|
This function can be used to output your own debugging information. It is only
|
|
available only if you link with -lncurses_g. It can be used the same way as
|
|
<TT>printf</TT>, only it outputs a newline after the end of arguments.
|
|
The output goes to a file called <TT>trace</TT> in the current directory.
|
|
</DL>
|
|
|
|
<H1><A NAME="hints">Hints, Tips, and Tricks</A></H1>
|
|
|
|
The <TT>ncurses</TT> manual pages are a complete reference for this library.
|
|
In the remainder of this document, we discuss various useful methods that
|
|
may not be obvious from the manual page descriptions. <P>
|
|
|
|
<H2><A NAME="caution">Some Notes of Caution</A></H2>
|
|
|
|
Bear in mind that <TT>refresh()</TT> is a synonym for
|
|
<TT>wrefresh(stdscr)</TT>,
|
|
and don't try to mix use of <TT>stdscr</TT> with use of windows declared
|
|
by <TT>newwin</TT>; a <TT>refresh()</TT> call will blow them off the
|
|
screen. The right way to handle this is to use <TT>subwin</TT>, or
|
|
not touch <TT>stdscr</TT> at all and tile your screen with declared
|
|
windows which you then <TT>wnoutrefresh</TT> somewhere in your program
|
|
event loop, with a single <TT>doupdate</TT> call to trigger actual
|
|
repainting. <P>
|
|
|
|
You are much less likely to run into problems if you design your screen
|
|
layouts to use tiled rather than overlapping windows. Historically,
|
|
curses support for overlapping windows has been weak, fragile, and poorly
|
|
documented. The <TT>ncurses</TT> library is not yet an exception to this
|
|
rule. <P>
|
|
|
|
There is a freeware panels library included in the <TT>ncurses</TT>
|
|
distribution that does a pretty good job of strengthening the
|
|
overlapping-windows facilities. <P>
|
|
|
|
Try to avoid using the global variables LINES and COLS. Use
|
|
<TT>getmaxyx()</TT> on the <TT>stdscr</TT> context instead. Reason:
|
|
your code may be ported to run in an environment with window resizes,
|
|
in which case several screens could be open with different sizes. <P>
|
|
|
|
<H2><A NAME="leaving">Temporarily Leaving <TT>ncurses</TT> Mode</A></H2>
|
|
|
|
Sometimes you will want to write a program that spends most of its time in
|
|
screen mode, but occasionally returns to ordinary `cooked' mode. A common
|
|
reason for this is to support shell-out. This behavior is simple to arrange
|
|
in <TT>ncurses</TT>. <P>
|
|
|
|
To leave <TT>ncurses</TT> mode, call <TT>endwin()</TT> as you would if you
|
|
were intending to terminate the program. This will take the screen back to
|
|
cooked mode; you can do your shell-out. When you want to return to
|
|
<TT>ncurses</TT> mode, simply call <TT>refresh()</TT> or <TT>doupdate()</TT>.
|
|
This will repaint the screen. <P>
|
|
|
|
There is a boolean function, <TT>isendwin()</TT>, which code can use to
|
|
test whether <TT>ncurses</TT> screen mode is active. It returns <TT>TRUE</TT>
|
|
in the interval between an <TT>endwin()</TT> call and the following
|
|
<TT>refresh()</TT>, <TT>FALSE</TT> otherwise. <P>
|
|
|
|
Here is some sample code for shellout:
|
|
|
|
<PRE>
|
|
addstr("Shelling out...");
|
|
def_prog_mode(); /* save current tty modes */
|
|
endwin(); /* restore original tty modes */
|
|
system("sh"); /* run shell */
|
|
addstr("returned.\n"); /* prepare return message */
|
|
refresh(); /* restore save modes, repaint screen */
|
|
</PRE>
|
|
|
|
<H2><A NAME="xterm">Using <TT>ncurses</TT> Under <TT>xterm</TT></A></H2>
|
|
|
|
A resize operation in X sends SIGWINCH to the application running under xterm.
|
|
The <TT>ncurses</TT> library does not catch this signal, because it cannot in
|
|
general know how you want the screen re-painted. You will have to write the
|
|
SIGWINCH handler yourself. <P>
|
|
|
|
The easiest way to code your SIGWINCH handler is to have it do an
|
|
<TT>endwin</TT>, followed by an <TT>initscr</TT> and a screen repaint you code
|
|
yourself. The <TT>initscr</TT> will pick up the new screen size from the
|
|
xterm's environment.
|
|
|
|
<H2><A NAME="screens">Handling Multiple Terminal Screens</A></H2>
|
|
|
|
The <TT>initscr()</TT> function actually calls a function named
|
|
<TT>newterm()</TT> to do most of its work. If you are writing a program that
|
|
opens multiple terminals, use <TT>newterm()</TT> directly. <P>
|
|
|
|
For each call, you will have to specify a terminal type and a pair of file
|
|
pointers; each call will return a screen reference, and <TT>stdscr</TT> will be
|
|
set to the last one allocated. You will switch between screens with the
|
|
<TT>set_term</TT> call. Note that you will also have to call
|
|
<TT>def_shell_mode</TT> and <TT>def_prog_mode</TT> on each tty yourself. <P>
|
|
|
|
<H2><A NAME="testing">Testing for Terminal Capabilities</A></H2>
|
|
|
|
Sometimes you may want to write programs that test for the presence of various
|
|
capabilities before deciding whether to go into <TT>ncurses</TT> mode. An easy
|
|
way to do this is to call <TT>setupterm()</TT>, then use the functions
|
|
<TT>tigetflag()</TT>, <TT>tigetnum()</TT>, and <TT>tigetstr()</TT> to do your
|
|
testing. <P>
|
|
|
|
<H2><A NAME="tuning">Tuning for Speed</A></H2>
|
|
|
|
Use the <TT>addchstr()</TT> family of functions for fast
|
|
screen-painting of text when you know the text doesn't contain any
|
|
control characters. Try to make attribute changes infrequent on your
|
|
screens. Don't use the <TT>immedok()</TT> option! <P>
|
|
|
|
<H2><A NAME="special">Special Features of <TT>ncurses</TT></A></H2>
|
|
|
|
When running on PC-clones, <TT>ncurses</TT> has enhanced support for the
|
|
IBM high-half and ROM characters. A new highlight, <TT>A_PCCHARSET</TT>,
|
|
enables display of the PC ROM graphics 0-31 that are normally interpreted
|
|
as control characters.
|
|
|
|
<H1><A NAME="panels">The <CODE>panels</CODE> Library</A></H1>
|
|
|
|
The <TT>ncurses</TT> library by itself provides good support for screen
|
|
displays in which the windows are tiled (non-overlapping). In the more
|
|
general case that windows may overlap, you have to use a series of
|
|
<CODE>wnoutrefresh()</CODE> calls followd by a <CODE>doupdate()</CODE>, and be
|
|
careful about the order you do the window refreshes in. It has to be
|
|
bottom-upwards, otherwise parts of windows that should be obscured will
|
|
show through. <P>
|
|
|
|
When your interface design is such that windows may dive deeper into the
|
|
visibility stack or pop to the top at runtime, the resulting book-keeping
|
|
can be tedious and difficult to get right. Hence the panels library. <P>
|
|
|
|
The <CODE>panel</CODE> library first appeared in AT&T System V. The
|
|
version documented here is the freeware <CODE>panel</CODE> code distributed
|
|
with <CODE>ncurses</CODE>.
|
|
|
|
<H2><A NAME="pcompile">Compiling With the panels Library</A></H2>
|
|
|
|
Your panels-using modules must import the panels library declarations with
|
|
|
|
<PRE>
|
|
#include <TT>≶panel.h&tg;</TT>
|
|
</PRE>
|
|
|
|
and must be linked explicitly with the panels library using an
|
|
<CODE>-lpanel</CODE> argument. Note that they must also link the
|
|
<TT>ncurses</TT> library with <CODE>-lcurses</CODE>. Most modern linkers
|
|
are two-pass and will accept either order, but it is still good practice
|
|
to put <CODE>-lpanel</CODE> first and <CODE>-lcurses</CODE> second.
|
|
|
|
<H2><A NAME="poverview">Overview of panels</A></H2>
|
|
|
|
A panel object is a window that is implicitly treated as part of a
|
|
<DFN>deck</DFN> including all other panel objects. The deck has an implicit
|
|
bottom-to-top visibility order. The panels library includes an update
|
|
function (analogous to <CODE>refresh()</CODE>) that displays all panels in the
|
|
deck in the proper order to resolve overlaps. The standard window,
|
|
<CODE>stdscr</CODE>, is considered below all panels. <P>
|
|
|
|
Details on the panels functions are available in the man pages. We'll just
|
|
hit the highlights here. <P>
|
|
|
|
You create a panel from a window by calling <CODE>new_panel()</CODE> on a
|
|
window pointer. It then becomes the top of the deck. The panel's window
|
|
is available as the value of <CODE>pnel_windo()</CODE> called with the
|
|
panel pointer as argument.<P>
|
|
|
|
You can delete a panel (removing it from the deck) with <CODE>del_panel</CODE>.
|
|
This will not deallocate the associated window; you have to do that yourself.
|
|
|
|
You can replace a panel's window with a different window by calling
|
|
<CODE>replace_window</CODE>. The new window may be of different size;
|
|
the panel code will re-compute all overlaps. This operation doesn't
|
|
change the panel's position in the deck. <P>
|
|
|
|
To move a panel's window, use <CODE>move_panel()</CODE>. The
|
|
<CODE>mvwin()</CODE> function on the panel's window isn't sufficient because it
|
|
doesn't update the panels library's representation of where the windows are.
|
|
This operation leaves the panel's depth, contents, and size unchanged. <P>
|
|
|
|
Two functions (<CODE>top_panel()</CODE>, <CODE>bottom_panel()</CODE>) are
|
|
provided for rearranging the deck. The first pops its argument window to the
|
|
top of the deck; the second sends it to the bottom. Either operation leaves
|
|
the panel's screen location, contents, and size unchanged. <P>
|
|
|
|
The function <CODE>update_panels()</CODE> does all the
|
|
<CODE>wnoutrefresh()</CODE> calls needed to prepare for
|
|
<CODE>doupdate()</CODE> (which you must call yourself, afterwards). <P>
|
|
|
|
<H2><A HREF="pstsdcr">Panels, Input, and the Standard Screen</A></H2>
|
|
|
|
You shouldn't mix <CODE>wnoutrefresh()</CODE> or <CODE>wrefresh()</CODE>
|
|
operations with panels code; this will work only if the argument window
|
|
is either in the top panel or un-obscured by any other panels. <P>
|
|
|
|
The <CODE>stsdcr</CODE> window is a special case. It is considered below all
|
|
panels. Because changes to panels may obscure parts of <CODE>stdscr</CODE>,
|
|
though, you should call <CODE>update_panels()</CODE> before
|
|
<CODE>doupdate()</CODE> even when you only change <CODE>stdscr</CODE>. <P>
|
|
|
|
Note that <CODE>wgetch</CODE> automatically calls <CODE>wrefresh</CODE>.
|
|
Therefore, before requesting input from a panel window, you need to be sure
|
|
that the panel is totally unobscured. <P>
|
|
|
|
There is presently no way to display changes to one obscured panel without
|
|
repainting all panels. <P>
|
|
|
|
<H2><A NAME="hiding">Hiding Panels</A></H2>
|
|
|
|
It's possible to remove a panel from the deck temporarily; use
|
|
<CODE>hide_panel</CODE> for this. You can un-hide a panel with
|
|
<CODE>show_panel()</CODE>. The predicate function <CODE>panel_hidden</CODE>
|
|
tests whether or not a panel is hidden. <P>
|
|
|
|
The <CODE>panel_update</CODE> code ignores hidden panels. You cannot do
|
|
<CODE>top_panel()</CODE> or <CODE>bottom_panel</CODE> on a hiddlen panel().
|
|
Other panels operations are applicable. <P>
|
|
|
|
<H2><A NAME="pmisc">Miscellaneous Other Facilities</A></H2>
|
|
|
|
It's possible to navigate the deck using the functions
|
|
<CODE>panel_above()</CODE> and <CODE>panel_below</CODE>. Handed a panel
|
|
pointer, they return the panel above or below that panel. Handed
|
|
<CODE>NULL</CODE>, they return the bottom-most or top-most panel. <P>
|
|
|
|
Every panel has an associated user pointer, not used by the panel code, to
|
|
whicch you can attach application data. See the man page documentation
|
|
of <CODE>set_panel_userptr()</CODE> and <CODE>panel_userptr</CODE> for
|
|
details. <P>
|
|
|
|
<H1><A HREF="menus">The Menu Library</A></H1>
|
|
|
|
A menu is a screen display that assists the user to choose some subset
|
|
of a given set of items. The <CODE>menu</CODE> library is a curses
|
|
extension that supports easy programming of menu hierarchies with a
|
|
uniform but flexible interface.
|
|
|
|
The <CODE>menu</CODE> library first appeared in AT&T System V. The
|
|
version documented here is the freeware <CODE>menu</CODE> code distributed
|
|
with <CODE>ncurses</CODE>.
|
|
|
|
<H2><A NAME="mcompile">Compiling With the menu Library</A></H2>
|
|
|
|
Your menu-using modules must import the menu library declarations with
|
|
|
|
<PRE>
|
|
#include <TT>≶menu.h&tg;</TT>
|
|
</PRE>
|
|
|
|
and must be linked explicitly with the menus library using an
|
|
<CODE>-lmenu</CODE> argument. Note that they must also link the
|
|
<TT>ncurses</TT> library with <CODE>-lcurses</CODE>. Most modern linkers
|
|
are two-pass and will accept either order, but it is still good practice
|
|
to put <CODE>-lmenu</CODE> first and <CODE>-lcurses</CODE> second.
|
|
|
|
<H2><A NAME="moverview">Overview of Menus</A></H2>
|
|
|
|
The menus created by this library consist of collections of
|
|
<DFN>items</DFN> including a name string part and a description string
|
|
part. To make menus, you create groups of these items and connect
|
|
them with menu frame objects. <P>
|
|
|
|
The menu can then by <DFN>posted</DFN>, that is written to an
|
|
associated window. Actually, each menu has two associated windows; a
|
|
containing window in which the programmer can scribble titles or
|
|
borders, and a subwindow in which the menu items proper are displayed.
|
|
If this subwindow is too small to display all the items, it will be a
|
|
scrollable viewport on the collection of items. <P>
|
|
|
|
A menu may also be <DFN>unposted</DFN> (that is, undisplayed), and finally
|
|
freed to make the storage associated with it and its items available for
|
|
re-use. <P>
|
|
|
|
The general flow of control of a menu program looks like this:
|
|
|
|
<OL>
|
|
<LI> Initialize <CODE>curses</CODE>.
|
|
<LI> Create the menu items, using <CODE>new_item()</CODE>.
|
|
<LI> Create the menu using <CODE>new_menu()</CODE>.
|
|
<LI> Post the menu using <CODE>menu_post()</CODE>.
|
|
<LI> Refresh the screen.
|
|
<LI> Process user requests via an input loop.
|
|
<LI> Unpost the menu using <CODE>menu_unpost()</CODE>.
|
|
<LI> Free the menu, using <CODE>free_menu()</CODE>.
|
|
<LI> Free the items using <CODE>free_item()</CODE>.
|
|
<LI> Terminate <CODE>curses</CODE>.
|
|
</OL>
|
|
|
|
<H2><A NAME="select">Selecting items</A></H2>
|
|
|
|
Menus may be multi-valued or (the default) single-valued (see the manual
|
|
page <CODE>mitem_opts(3x)</CODE> to see how to change the default).
|
|
Both types always have a <DFN>current item</DFN>. <P>
|
|
|
|
From a single-valued menu you can read the selected value simply by looking
|
|
at the current item. From a multi-valued menu, you get the selected set
|
|
by looping through the items applying the <CODE>item_value()</CODE>
|
|
predicate function. Your menu-processing code can use the function
|
|
<CODE>set_item_value()</CODE> to flag the items in the select set. <P>
|
|
|
|
Menu items can be made un-selectable using <CODE>set_item_opts()</CODE>
|
|
or <CODE>item_opts_off()</CODE> with the <CODE>O_SELECTABLE</CODE>
|
|
argument. This is the only option so far defined for menus, but it
|
|
is good practice to code as though other option bits might be on. <P>
|
|
|
|
<H2><A NAME="mdisplay">Menu Display</A></H2>
|
|
|
|
The menu library calculates a minimum display size for your window, based
|
|
on the following variables: <P>
|
|
|
|
<UL>
|
|
<LI> The number and maximum length of the menu items
|
|
<LI> Whether the O_ROWMAJOR option is enabled
|
|
<LI> Whether display of descriptions is enabled
|
|
<LI> Whatever menu format may have been set by the programmer
|
|
<LI> The length of the menu mark string used for highlighting selected items
|
|
</UL>
|
|
|
|
The function <CODE>set_menu_format()</CODE> allows you to set the
|
|
maximum size of the viewport or <DFN>menu page</DFN> that will be used
|
|
to display menu items. You can retrieve any format associated with a
|
|
menu with <CODE>menu_format()</CODE>. The default format is rows=16,
|
|
columns=1. <P>
|
|
|
|
The actual menu page may be smaller than the format size. This depends
|
|
on the item number and size and whether O_ROWMAJOR is on. This option
|
|
(on by default) causes menu items to be displayed in a `raster-scan'
|
|
pattern, so that if more than one item will fit horizontally the first
|
|
couple of items are side-by-side in the top row. The alternative is
|
|
column-major display, which tries to put the first several items in
|
|
the first column. <P>
|
|
|
|
As mentioned above, a menu format not large enough to allow all items to fit
|
|
on-screen will result in a menu display that is vertically scrollable. <P>
|
|
You can scroll it with requests to the menu driver, which will be described
|
|
in the section on <A HREF="#minput">menu input handling</A>. <P>
|
|
|
|
Each menu has a <DFN>mark string</DFN> used to visually tag selected items;
|
|
see the <CODE>menu_mark(3x)</CODE> manual page for details. The mark
|
|
string length also influences the menu page size. <P>
|
|
|
|
The function <CODE>scale_menu()</CODE> returns the minimum display size
|
|
that the menu code computes from all these factors.
|
|
|
|
There are other menu display attributes including a select attribute,
|
|
an attribute for selectable items, an attribute for unselectable items,
|
|
and a pad character used to separate item name text from description
|
|
text. These have reasonable defaults which the library allows you to
|
|
change (see the <CODE>menu_attribs(3x)</CODE>manual page. <P>
|
|
|
|
<H2><A NAME="mwindows">Menu Windows</A></H2>
|
|
|
|
Each menu has, as mentioned previously, a pair of associated windows.
|
|
Both these windows are painted when the menu is posted and erased when
|
|
the menu is unposted. <P>
|
|
|
|
The outer or frame window is not otherwise touched by the menu routines.
|
|
It exists so the programmer can associate a title, a border, or
|
|
perhaps help text with the menu and have it properly refreshed or erased
|
|
at post/unpost time. <P>
|
|
|
|
The inner window or <DFN>subwindow</DFN> is where the current menu page is
|
|
displayed. <P>
|
|
|
|
By default, both windows are <CODE>stdscr</CODE>. You can set them with the
|
|
functions in <CODE>menu_win(3x)</CODE>. <P>
|
|
|
|
When you call <CODE>menu_post()</CODE>, you write the menu to its
|
|
subwindow. When you call <CODE>menu_unpost()</CODE>, you erase the
|
|
subwindow, However, neither of these actually modifies the screen. To
|
|
do that, call <CODE>wrefresh()</CODE> or some equivalent. <P>
|
|
|
|
<H2><A NAME="minput">Processing Menu Input</A></H2>
|
|
|
|
The main loop of your menu-processing code should call
|
|
<CODE>menu_driver()</CODE> repeatedly. The first argument of this routine
|
|
is a menu pointer; the second is a menu command code. You should write an
|
|
input-fetching routine that maps input characters to menu command codes, and
|
|
pass its output to <CODE>menu_driver()</CODE>. The menu command codes are
|
|
fully documented in <CODE>menu_driver(3x)</CODE>. <P>
|
|
|
|
The simplest group of command codes is <CODE>REQ_NEXT_ITEM</CODE>,
|
|
<CODE>REQ_PREV_ITEM</CODE>, <CODE>REQ_FIRST_ITEM</CODE>,
|
|
<CODE>REQ_LAST_ITEM</CODE>, <CODE>REQ_UP_ITEM</CODE>,
|
|
<CODE>REQ_DOWN_ITEM</CODE>, <CODE>REQ_LEFT_ITEM</CODE>,
|
|
<CODE>REQ_RIGHT_ITEM</CODE>. These change the currently selected
|
|
item. These requests may cause scrolling of the menu page if it only
|
|
partially displayed. <P>
|
|
|
|
There are explicit requests for scrolling which also change the
|
|
current item (because the select location does not change, but the
|
|
item there does). These are <CODE>REQ_SCR_DLINE</CODE>,
|
|
<CODE>REQ_SCR_ULINE</CODE>, <CODE>REQ_SCR_DPAGE</CODE>, and
|
|
<CODE>REQ_SCR_UPAGE</CODE>. <P>
|
|
|
|
The <CODE>REQ_TOGGLE_ITEM</CODE> selects or deselects the current item.
|
|
It is for use in multi-valued menus; if you use it with <CODE>O_ONEVALUE</CODE>
|
|
on, you'll get an error return (<CODE>E_REQUEST_DENIED</CODE>). <P>
|
|
|
|
Each menu has an associated pattern buffer. The
|
|
<CODE>menu_driver()</CODE> logic tries to accumulate printable ASCII
|
|
characters passed in in that buffer; when it matches a prefix of an
|
|
item name, that item (or the next matching item) is selected. If
|
|
apopending a character yields no new match, that character is deleted
|
|
from the pattern buffer, and <CODE>menu_driver()</CODE> returns
|
|
<CODE>E_NO_MATCH</CODE>. <P>
|
|
|
|
Some requests change the pattern buffer directly:
|
|
<CODE>REQ_CLEAR_PATTERN</CODE>, <CODE>REQ_BACK_PATTERN</CODE>,
|
|
<CODE>REQ_NEXT_MATCH</CODE>, <CODE>REQ_PREV_MATCH</CODE>. The latter
|
|
two are useful when pattern buffer input matches more than one item
|
|
in a multi-valued menu. <P>
|
|
|
|
Each successful scroll or item navigation request clears the pattern
|
|
buffer. It is also possible to set the pattern buffer explicitly
|
|
with <CODE>set_menu_pattern()</CODE>. <P>
|
|
|
|
Finally, menu driver requests above the constant <CODE>MAX_COMMAND</CODE>
|
|
are considered application-specific commands. The <CODE>menu_driver()</CODE>
|
|
code ignores them and returns <CODE>E_UNKNOWN_COMMAND</CODE>.
|
|
|
|
<H2><A NAME="mmisc">Miscellaneous Other Features</A></H2>
|
|
|
|
Various menu options can affect the processing and visual appearance
|
|
and input processing of menus. See <CODE>menu_opts(3x) for
|
|
details.</CODE> <P>
|
|
|
|
It is possible to change the current item from application code; this
|
|
is useful if you want to write your own navigation requests. It is
|
|
also possible to explicitly set the top row of the menu display. See
|
|
<CODE>mitem_current(3x)</CODE>.
|
|
|
|
If your application needs to change the menu subwindow cursor for
|
|
any reason, <CODE>pos_menu_cursor()</CODE> will restore it to the
|
|
correct location for continuing menu driver processing. <P>
|
|
|
|
It is possible to set hooks to be called at menu initialization and
|
|
wrapup time, and whenever the selected item changes. See
|
|
<CODE>menu_hook(3x)</CODE>. <P>
|
|
|
|
Each item, and each menu, has an associated user pointer on which you
|
|
can hang application data. See <CODE>mitem_userptr(3x)</CODE> and
|
|
<CODE>menu_userptr(3x)</CODE>. <P>
|
|
|
|
<HR>
|
|
<ADDRESS>Eric S. Raymond <esr@snark.thyrsus.com></ADDRESS> </BODY>
|
|
</HTML>
|