summaryrefslogtreecommitdiffstats
path: root/contrib/ncurses/doc
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2001-05-17 08:21:06 +0000
committerpeter <peter@FreeBSD.org>2001-05-17 08:21:06 +0000
commitb7ada7f2444f41b672faef4f93e446bdf8584cf9 (patch)
treee83b2ef47811e687a6c54035c9af6d4a2b7f14e1 /contrib/ncurses/doc
parenta81407a537bfd1ab9e48c69007eb6b30e66d271b (diff)
downloadFreeBSD-src-b7ada7f2444f41b672faef4f93e446bdf8584cf9.zip
FreeBSD-src-b7ada7f2444f41b672faef4f93e446bdf8584cf9.tar.gz
Import ncurses-5.2-20010512 onto the vendor branch
Obtained from: ftp://dickey.his.com/ncurses/
Diffstat (limited to 'contrib/ncurses/doc')
-rw-r--r--contrib/ncurses/doc/hackguide.doc687
-rw-r--r--contrib/ncurses/doc/html/announce.html397
-rw-r--r--contrib/ncurses/doc/ncurses-intro.doc2502
3 files changed, 3483 insertions, 103 deletions
diff --git a/contrib/ncurses/doc/hackguide.doc b/contrib/ncurses/doc/hackguide.doc
new file mode 100644
index 0000000..e9828d2
--- /dev/null
+++ b/contrib/ncurses/doc/hackguide.doc
@@ -0,0 +1,687 @@
+
+ A Hacker's Guide to NCURSES
+
+ Contents
+
+ * Abstract
+ * Objective of the Package
+ + Why System V Curses?
+ + How to Design Extensions
+ * Portability and Configuration
+ * Documentation Conventions
+ * How to Report Bugs
+ * A Tour of the Ncurses Library
+ + Library Overview
+ + The Engine Room
+ + Keyboard Input
+ + Mouse Events
+ + Output and Screen Updating
+ * The Forms and Menu Libraries
+ * A Tour of the Terminfo Compiler
+ + Translation of Non-use Capabilities
+ + Use Capability Resolution
+ + Source-Form Translation
+ * Other Utilities
+ * Style Tips for Developers
+ * Porting Hints
+
+ Abstract
+
+ This document is a hacker's tour of the ncurses library and utilities.
+ It discusses design philosophy, implementation methods, and the
+ conventions used for coding and documentation. It is recommended
+ reading for anyone who is interested in porting, extending or
+ improving the package.
+
+ Objective of the Package
+
+ The objective of the ncurses package is to provide a free software API
+ for character-cell terminals and terminal emulators with the following
+ characteristics:
+ * Source-compatible with historical curses implementations
+ (including the original BSD curses and System V curses.
+ * Conformant with the XSI Curses standard issued as part of XPG4 by
+ X/Open.
+ * High-quality -- stable and reliable code, wide portability, good
+ packaging, superior documentation.
+ * Featureful -- should eliminate as much of the drudgery of C
+ interface programming as possible, freeing programmers to think at
+ a higher level of design.
+
+ These objectives are in priority order. So, for example, source
+ compatibility with older version must trump featurefulness -- we
+ cannot add features if it means breaking the portion of the API
+ corresponding to historical curses versions.
+
+Why System V Curses?
+
+ We used System V curses as a model, reverse-engineering their API, in
+ order to fulfill the first two objectives.
+
+ System V curses implementations can support BSD curses programs with
+ just a recompilation, so by capturing the System V API we also capture
+ BSD's.
+
+ More importantly for the future, the XSI Curses standard issued by
+ X/Open is explicitly and closely modeled on System V. So conformance
+ with System V took us most of the way to base-level XSI conformance.
+
+How to Design Extensions
+
+ The third objective (standards conformance) requires that it be easy
+ to condition source code using ncurses so that the absence of
+ nonstandard extensions does not break the code.
+
+ Accordingly, we have a policy of associating with each nonstandard
+ extension a feature macro, so that ncurses client code can use this
+ macro to condition in or out the code that requires the ncurses
+ extension.
+
+ For example, there is a macro NCURSES_MOUSE_VERSION which XSI Curses
+ does not define, but which is defined in the ncurses library header.
+ You can use this to condition the calls to the mouse API calls.
+
+ Portability and Configuration
+
+ Code written for ncurses may assume an ANSI-standard C compiler and
+ POSIX-compatible OS interface. It may also assume the presence of a
+ System-V-compatible select(2) call.
+
+ We encourage (but do not require) developers to make the code friendly
+ to less-capable UNIX environments wherever possible.
+
+ We encourage developers to support OS-specific optimizations and
+ methods not available under POSIX/ANSI, provided only that:
+ * All such code is properly conditioned so the build process does
+ not attempt to compile it under a plain ANSI/POSIX environment.
+ * Adding such implementation methods does not introduce
+ incompatibilities in the ncurses API between platforms.
+
+ We use GNU autoconf(1) as a tool to deal with portability issues. The
+ right way to leverage an OS-specific feature is to modify the autoconf
+ specification files (configure.in and aclocal.m4) to set up a new
+ feature macro, which you then use to condition your code.
+
+ Documentation Conventions
+
+ There are three kinds of documentation associated with this package.
+ Each has a different preferred format:
+ * Package-internal files (README, INSTALL, TO-DO etc.)
+ * Manual pages.
+ * Everything else (i.e., narrative documentation).
+
+ Our conventions are simple:
+ 1. Maintain package-internal files in plain text. The expected viewer
+ for them more(1) or an editor window; there's no point in
+ elaborate mark-up.
+ 2. Mark up manual pages in the man macros. These have to be viewable
+ through traditional man(1) programs.
+ 3. Write everything else in HTML.
+
+ When in doubt, HTMLize a master and use lynx(1) to generate plain
+ ASCII (as we do for the announcement document).
+
+ The reason for choosing HTML is that it's (a) well-adapted for on-line
+ browsing through viewers that are everywhere; (b) more easily readable
+ as plain text than most other mark-ups, if you don't have a viewer;
+ and (c) carries enough information that you can generate a
+ nice-looking printed version from it. Also, of course, it make
+ exporting things like the announcement document to WWW pretty trivial.
+
+ How to Report Bugs
+
+ The reporting address for bugs is bug-ncurses@gnu.org. This is a
+ majordomo list; to join, write to bug-ncurses-request@gnu.org with a
+ message containing the line:
+ subscribe <name>@<host.domain>
+
+ The ncurses code is maintained by a small group of volunteers. While
+ we try our best to fix bugs promptly, we simply don't have a lot of
+ hours to spend on elementary hand-holding. We rely on intelligent
+ cooperation from our users. If you think you have found a bug in
+ ncurses, there are some steps you can take before contacting us that
+ will help get the bug fixed quickly.
+
+ In order to use our bug-fixing time efficiently, we put people who
+ show us they've taken these steps at the head of our queue. This means
+ that if you don't, you'll probably end up at the tail end and have to
+ wait a while.
+ 1. Develop a recipe to reproduce the bug.
+ Bugs we can reproduce are likely to be fixed very quickly, often
+ within days. The most effective single thing you can do to get a
+ quick fix is develop a way we can duplicate the bad behavior --
+ ideally, by giving us source for a small, portable test program
+ that breaks the library. (Even better is a keystroke recipe using
+ one of the test programs provided with the distribution.)
+ 2. Try to reproduce the bug on a different terminal type.
+ In our experience, most of the behaviors people report as library
+ bugs are actually due to subtle problems in terminal descriptions.
+ This is especially likely to be true if you're using a traditional
+ asynchronous terminal or PC-based terminal emulator, rather than
+ xterm or a UNIX console entry.
+ It's therefore extremely helpful if you can tell us whether or not
+ your problem reproduces on other terminal types. Usually you'll
+ have both a console type and xterm available; please tell us
+ whether or not your bug reproduces on both.
+ If you have xterm available, it is also good to collect xterm
+ reports for different window sizes. This is especially true if you
+ normally use an unusual xterm window size -- a surprising number
+ of the bugs we've seen are either triggered or masked by these.
+ 3. Generate and examine a trace file for the broken behavior.
+ Recompile your program with the debugging versions of the
+ libraries. Insert a trace() call with the argument set to
+ TRACE_UPDATE. (See "Writing Programs with NCURSES" for details on
+ trace levels.) Reproduce your bug, then look at the trace file to
+ see what the library was actually doing.
+ Another frequent cause of apparent bugs is application coding
+ errors that cause the wrong things to be put on the virtual
+ screen. Looking at the virtual-screen dumps in the trace file will
+ tell you immediately if this is happening, and save you from the
+ possible embarrassment of being told that the bug is in your code
+ and is your problem rather than ours.
+ If the virtual-screen dumps look correct but the bug persists,
+ it's possible to crank up the trace level to give more and more
+ information about the library's update actions and the control
+ sequences it issues to perform them. The test directory of the
+ distribution contains a tool for digesting these logs to make them
+ less tedious to wade through.
+ Often you'll find terminfo problems at this stage by noticing that
+ the escape sequences put out for various capabilities are wrong.
+ If not, you're likely to learn enough to be able to characterize
+ any bug in the screen-update logic quite exactly.
+ 4. Report details and symptoms, not just interpretations.
+ If you do the preceding two steps, it is very likely that you'll
+ discover the nature of the problem yourself and be able to send us
+ a fix. This will create happy feelings all around and earn you
+ good karma for the first time you run into a bug you really can't
+ characterize and fix yourself.
+ If you're still stuck, at least you'll know what to tell us.
+ Remember, we need details. If you guess about what is safe to
+ leave out, you are too likely to be wrong.
+ If your bug produces a bad update, include a trace file. Try to
+ make the trace at the least voluminous level that pins down the
+ bug. Logs that have been through tracemunch are OK, it doesn't
+ throw away any information (actually they're better than
+ un-munched ones because they're easier to read).
+ If your bug produces a core-dump, please include a symbolic stack
+ trace generated by gdb(1) or your local equivalent.
+ Tell us about every terminal on which you've reproduced the bug --
+ and every terminal on which you can't. Ideally, sent us terminfo
+ sources for all of these (yours might differ from ours).
+ Include your ncurses version and your OS/machine type, of course!
+ You can find your ncurses version in the curses.h file.
+
+ If your problem smells like a logic error or in cursor movement or
+ scrolling or a bad capability, there are a couple of tiny test frames
+ for the library algorithms in the progs directory that may help you
+ isolate it. These are not part of the normal build, but do have their
+ own make productions.
+
+ The most important of these is mvcur, a test frame for the
+ cursor-movement optimization code. With this program, you can see
+ directly what control sequences will be emitted for any given cursor
+ movement or scroll/insert/delete operations. If you think you've got a
+ bad capability identified, you can disable it and test again. The
+ program is command-driven and has on-line help.
+
+ If you think the vertical-scroll optimization is broken, or just want
+ to understand how it works better, build hashmap and read the header
+ comments of hardscroll.c and hashmap.c; then try it out. You can also
+ test the hardware-scrolling optimization separately with hardscroll.
+
+ There's one other interactive tester, tctest, that exercises
+ translation between termcap and terminfo formats. If you have a
+ serious need to run this, you probably belong on our development team!
+
+ A Tour of the Ncurses Library
+
+Library Overview
+
+ Most of the library is superstructure -- fairly trivial convenience
+ interfaces to a small set of basic functions and data structures used
+ to manipulate the virtual screen (in particular, none of this code
+ does any I/O except through calls to more fundamental modules
+ described below). The files
+
+ lib_addch.c lib_bkgd.c lib_box.c lib_chgat.c lib_clear.c
+ lib_clearok.c lib_clrbot.c lib_clreol.c lib_colorset.c lib_data.c
+ lib_delch.c lib_delwin.c lib_echo.c lib_erase.c lib_gen.c
+ lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c lib_insch.c
+ lib_insdel.c lib_insstr.c lib_instr.c lib_isendwin.c lib_keyname.c
+ lib_leaveok.c lib_move.c lib_mvwin.c lib_overlay.c lib_pad.c
+ lib_printw.c lib_redrawln.c lib_scanw.c lib_screen.c lib_scroll.c
+ lib_scrollok.c lib_scrreg.c lib_set_term.c lib_slk.c
+ lib_slkatr_set.c lib_slkatrof.c lib_slkatron.c lib_slkatrset.c
+ lib_slkattr.c lib_slkclear.c lib_slkcolor.c lib_slkinit.c
+ lib_slklab.c lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c
+ lib_unctrl.c lib_vline.c lib_wattroff.c lib_wattron.c lib_window.c
+
+ are all in this category. They are very unlikely to need change,
+ barring bugs or some fundamental reorganization in the underlying data
+ structures.
+
+ These files are used only for debugging support:
+
+ lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c
+ lib_tracedmp.c lib_tracemse.c trace_buf.c
+
+ It is rather unlikely you will ever need to change these, unless you
+ want to introduce a new debug trace level for some reasoon.
+
+ There is another group of files that do direct I/O via tputs(),
+ computations on the terminal capabilities, or queries to the OS
+ environment, but nevertheless have only fairly low complexity. These
+ include:
+
+ lib_acs.c lib_beep.c lib_color.c lib_endwin.c lib_initscr.c
+ lib_longname.c lib_newterm.c lib_options.c lib_termcap.c lib_ti.c
+ lib_tparm.c lib_tputs.c lib_vidattr.c read_entry.c.
+
+ They are likely to need revision only if ncurses is being ported to an
+ environment without an underlying terminfo capability representation.
+
+ These files have serious hooks into the tty driver and signal
+ facilities:
+
+ lib_kernel.c lib_baudrate.c lib_raw.c lib_tstp.c lib_twait.c
+
+ If you run into porting snafus moving the package to another UNIX, the
+ problem is likely to be in one of these files. The file lib_print.c
+ uses sleep(2) and also falls in this category.
+
+ Almost all of the real work is done in the files
+
+ hardscroll.c hashmap.c lib_addch.c lib_doupdate.c lib_getch.c
+ lib_mouse.c lib_mvcur.c lib_refresh.c lib_setup.c lib_vidattr.c
+
+ Most of the algorithmic complexity in the library lives in these
+ files. If there is a real bug in ncurses itself, it's probably here.
+ We'll tour some of these files in detail below (see The Engine Room).
+
+ Finally, there is a group of files that is actually most of the
+ terminfo compiler. The reason this code lives in the ncurses library
+ is to support fallback to /etc/termcap. These files include
+
+ alloc_entry.c captoinfo.c comp_captab.c comp_error.c comp_hash.c
+ comp_parse.c comp_scan.c parse_entry.c read_termcap.c write_entry.c
+
+ We'll discuss these in the compiler tour.
+
+The Engine Room
+
+ Keyboard Input
+
+ All ncurses input funnels through the function wgetch(), defined in
+ lib_getch.c. This function is tricky; it has to poll for keyboard and
+ mouse events and do a running match of incoming input against the set
+ of defined special keys.
+
+ The central data structure in this module is a FIFO queue, used to
+ match multiple-character input sequences against special-key
+ capabilities; also to implement pushback via ungetch().
+
+ The wgetch() code distinguishes between function key sequences and the
+ same sequences typed manually by doing a timed wait after each input
+ character that could lead a function key sequence. If the entire
+ sequence takes less than 1 second, it is assumed to have been
+ generated by a function key press.
+
+ Hackers bruised by previous encounters with variant select(2) calls
+ may find the code in lib_twait.c interesting. It deals with the
+ problem that some BSD selects don't return a reliable time-left value.
+ The function timed_wait() effectively simulates a System V select.
+
+ Mouse Events
+
+ If the mouse interface is active, wgetch() polls for mouse events each
+ call, before it goes to the keyboard for input. It is up to
+ lib_mouse.c how the polling is accomplished; it may vary for different
+ devices.
+
+ Under xterm, however, mouse event notifications come in via the
+ keyboard input stream. They are recognized by having the kmous
+ capability as a prefix. This is kind of klugey, but trying to wire in
+ recognition of a mouse key prefix without going through the
+ function-key machinery would be just too painful, and this turns out
+ to imply having the prefix somewhere in the function-key capabilities
+ at terminal-type initialization.
+
+ This kluge only works because kmous isn't actually used by any
+ historic terminal type or curses implementation we know of. Best guess
+ is it's a relic of some forgotten experiment in-house at Bell Labs
+ that didn't leave any traces in the publicly-distributed System V
+ terminfo files. If System V or XPG4 ever gets serious about using it
+ again, this kluge may have to change.
+
+ Here are some more details about mouse event handling:
+
+ The lib_mouse()code is logically split into a lower level that accepts
+ event reports in a device-dependent format and an upper level that
+ parses mouse gestures and filters events. The mediating data structure
+ is a circular queue of event structures.
+
+ Functionally, the lower level's job is to pick up primitive events and
+ put them on the circular queue. This can happen in one of two ways:
+ either (a) _nc_mouse_event() detects a series of incoming mouse
+ reports and queues them, or (b) code in lib_getch.c detects the kmous
+ prefix in the keyboard input stream and calls _nc_mouse_inline to
+ queue up a series of adjacent mouse reports.
+
+ In either case, _nc_mouse_parse() should be called after the series is
+ accepted to parse the digested mouse reports (low-level events) into a
+ gesture (a high-level or composite event).
+
+ Output and Screen Updating
+
+ With the single exception of character echoes during a wgetnstr() call
+ (which simulates cooked-mode line editing in an ncurses window), the
+ library normally does all its output at refresh time.
+
+ The main job is to go from the current state of the screen (as
+ represented in the curscr window structure) to the desired new state
+ (as represented in the newscr window structure), while doing as little
+ I/O as possible.
+
+ The brains of this operation are the modules hashmap.c, hardscroll.c
+ and lib_doupdate.c; the latter two use lib_mvcur.c. Essentially, what
+ happens looks like this:
+
+ The hashmap.c module tries to detect vertical motion changes between
+ the real and virtual screens. This information is represented by the
+ oldindex members in the newscr structure. These are modified by
+ vertical-motion and clear operations, and both are re-initialized
+ after each update. To this change-journalling information, the hashmap
+ code adds deductions made using a modified Heckel algorithm on hash
+ values generated from the line contents.
+
+ The hardscroll.c module computes an optimum set of scroll, insertion,
+ and deletion operations to make the indices match. It calls
+ _nc_mvcur_scrolln() in lib_mvcur.c to do those motions.
+
+ Then lib_doupdate.c goes to work. Its job is to do line-by-line
+ transformations of curscr lines to newscr lines. Its main tool is the
+ routine mvcur() in lib_mvcur.c. This routine does cursor-movement
+ optimization, attempting to get from given screen location A to given
+ location B in the fewest output characters posible.
+
+ If you want to work on screen optimizations, you should use the fact
+ that (in the trace-enabled version of the library) enabling the
+ TRACE_TIMES trace level causes a report to be emitted after each
+ screen update giving the elapsed time and a count of characters
+ emitted during the update. You can use this to tell when an update
+ optimization improves efficiency.
+
+ In the trace-enabled version of the library, it is also possible to
+ disable and re-enable various optimizations at runtime by tweaking the
+ variable _nc_optimize_enable. See the file include/curses.h.in for
+ mask values, near the end.
+
+ The Forms and Menu Libraries
+
+ The forms and menu libraries should work reliably in any environment
+ you can port ncurses to. The only portability issue anywhere in them
+ is what flavor of regular expressions the built-in form field type
+ TYPE_REGEXP will recognize.
+
+ The configuration code prefers the POSIX regex facility, modeled on
+ System V's, but will settle for BSD regexps if the former isn't
+ available.
+
+ Historical note: the panels code was written primarily to assist in
+ porting u386mon 2.0 (comp.sources.misc v14i001-4) to systems lacking
+ panels support; u386mon 2.10 and beyond use it. This version has been
+ slightly cleaned up for ncurses.
+
+ A Tour of the Terminfo Compiler
+
+ The ncurses implementation of tic is rather complex internally; it has
+ to do a trying combination of missions. This starts with the fact
+ that, in addition to its normal duty of compiling terminfo sources
+ into loadable terminfo binaries, it has to be able to handle termcap
+ syntax and compile that too into terminfo entries.
+
+ The implementation therefore starts with a table-driven, dual-mode
+ lexical analyzer (in comp_scan.c). The lexer chooses its mode (termcap
+ or terminfo) based on the first `,' or `:' it finds in each entry. The
+ lexer does all the work of recognizing capability names and values;
+ the grammar above it is trivial, just "parse entries till you run out
+ of file".
+
+Translation of Non-use Capabilities
+
+ Translation of most things besides use capabilities is pretty
+ straightforward. The lexical analyzer's tokenizer hands each
+ capability name to a hash function, which drives a table lookup. The
+ table entry yields an index which is used to look up the token type in
+ another table, and controls interpretation of the value.
+
+ One possibly interesting aspect of the implementation is the way the
+ compiler tables are initialized. All the tables are generated by
+ various awk/sed/sh scripts from a master table include/Caps; these
+ scripts actually write C initializers which are linked to the
+ compiler. Furthermore, the hash table is generated in the same way, so
+ it doesn't have to be generated at compiler startup time (another
+ benefit of this organization is that the hash table can be in
+ shareable text space).
+
+ Thus, adding a new capability is usually pretty trivial, just a matter
+ of adding one line to the include/Caps file. We'll have more to say
+ about this in the section on Source-Form Translation.
+
+Use Capability Resolution
+
+ The background problem that makes tic tricky isn't the capability
+ translation itself, it's the resolution of use capabilities. Older
+ versions would not handle forward use references for this reason (that
+ is, a using terminal always had to follow its use target in the source
+ file). By doing this, they got away with a simple implementation
+ tactic; compile everything as it blows by, then resolve uses from
+ compiled entries.
+
+ This won't do for ncurses. The problem is that that the whole
+ compilation process has to be embeddable in the ncurses library so
+ that it can be called by the startup code to translate termcap entries
+ on the fly. The embedded version can't go promiscuously writing
+ everything it translates out to disk -- for one thing, it will
+ typically be running with non-root permissions.
+
+ So our tic is designed to parse an entire terminfo file into a
+ doubly-linked circular list of entry structures in-core, and then do
+ use resolution in-memory before writing everything out. This design
+ has other advantages: it makes forward and back use-references equally
+ easy (so we get the latter for free), and it makes checking for name
+ collisions before they're written out easy to do.
+
+ And this is exactly how the embedded version works. But the
+ stand-alone user-accessible version of tic partly reverts to the
+ historical strategy; it writes to disk (not keeping in core) any entry
+ with no use references.
+
+ This is strictly a core-economy kluge, implemented because the
+ terminfo master file is large enough that some core-poor systems swap
+ like crazy when you compile it all in memory...there have been reports
+ of this process taking three hours, rather than the twenty seconds or
+ less typical on the author's development box.
+
+ So. The executable tic passes the entry-parser a hook that immediately
+ writes out the referenced entry if it has no use capabilities. The
+ compiler main loop refrains from adding the entry to the in-core list
+ when this hook fires. If some other entry later needs to reference an
+ entry that got written immediately, that's OK; the resolution code
+ will fetch it off disk when it can't find it in core.
+
+ Name collisions will still be detected, just not as cleanly. The
+ write_entry() code complains before overwriting an entry that
+ postdates the time of tic's first call to write_entry(), Thus it will
+ complain about overwriting entries newly made during the tic run, but
+ not about overwriting ones that predate it.
+
+Source-Form Translation
+
+ Another use of tic is to do source translation between various termcap
+ and terminfo formats. There are more variants out there than you might
+ think; the ones we know about are described in the captoinfo(1) manual
+ page.
+
+ The translation output code (dump_entry() in ncurses/dump_entry.c) is
+ shared with the infocmp(1) utility. It takes the same internal
+ representation used to generate the binary form and dumps it to
+ standard output in a specified format.
+
+ The include/Caps file has a header comment describing ways you can
+ specify source translations for nonstandard capabilities just by
+ altering the master table. It's possible to set up capability aliasing
+ or tell the compiler to plain ignore a given capability without
+ writing any C code at all.
+
+ For circumstances where you need to do algorithmic translation, there
+ are functions in parse_entry.c called after the parse of each entry
+ that are specifically intended to encapsulate such translations. This,
+ for example, is where the AIX box1 capability get translated to an
+ acsc string.
+
+ Other Utilities
+
+ The infocmp utility is just a wrapper around the same entry-dumping
+ code used by tic for source translation. Perhaps the one interesting
+ aspect of the code is the use of a predicate function passed in to
+ dump_entry() to control which capabilities are dumped. This is
+ necessary in order to handle both the ordinary De-compilation case and
+ entry difference reporting.
+
+ The tput and clear utilities just do an entry load followed by a
+ tputs() of a selected capability.
+
+ Style Tips for Developers
+
+ See the TO-DO file in the top-level directory of the source
+ distribution for additions that would be particularly useful.
+
+ The prefix _nc_ should be used on library public functions that are
+ not part of the curses API in order to prevent pollution of the
+ application namespace. If you have to add to or modify the function
+ prototypes in curses.h.in, read ncurses/MKlib_gen.sh first so you can
+ avoid breaking XSI conformance. Please join the ncurses mailing list.
+ See the INSTALL file in the top level of the distribution for details
+ on the list.
+
+ Look for the string FIXME in source files to tag minor bugs and
+ potential problems that could use fixing.
+
+ Don't try to auto-detect OS features in the main body of the C code.
+ That's the job of the configuration system.
+
+ To hold down complexity, do make your code data-driven. Especially, if
+ you can drive logic from a table filtered out of include/Caps, do it.
+ If you find you need to augment the data in that file in order to
+ generate the proper table, that's still preferable to ad-hoc code --
+ that's why the fifth field (flags) is there.
+
+ Have fun!
+
+ Porting Hints
+
+ The following notes are intended to be a first step towards DOS and
+ Macintosh ports of the ncurses libraries.
+
+ The following library modules are `pure curses'; they operate only on
+ the curses internal structures, do all output through other curses
+ calls (not including tputs() and putp()) and do not call any other
+ UNIX routines such as signal(2) or the stdio library. Thus, they
+ should not need to be modified for single-terminal ports.
+
+ lib_addch.c lib_addstr.c lib_bkgd.c lib_box.c lib_clear.c
+ lib_clrbot.c lib_clreol.c lib_delch.c lib_delwin.c lib_erase.c
+ lib_inchstr.c lib_insch.c lib_insdel.c lib_insstr.c lib_keyname.c
+ lib_move.c lib_mvwin.c lib_newwin.c lib_overlay.c lib_pad.c
+ lib_printw.c lib_refresh.c lib_scanw.c lib_scroll.c lib_scrreg.c
+ lib_set_term.c lib_touch.c lib_tparm.c lib_tputs.c lib_unctrl.c
+ lib_window.c panel.c
+
+ This module is pure curses, but calls outstr():
+
+ lib_getstr.c
+
+ These modules are pure curses, except that they use tputs() and
+ putp():
+
+ lib_beep.c lib_color.c lib_endwin.c lib_options.c lib_slk.c
+ lib_vidattr.c
+
+ This modules assist in POSIX emulation on non-POSIX systems:
+
+ sigaction.c
+ signal calls
+
+ The following source files will not be needed for a
+ single-terminal-type port.
+
+ alloc_entry.c captoinfo.c clear.c comp_captab.c comp_error.c
+ comp_hash.c comp_main.c comp_parse.c comp_scan.c dump_entry.c
+ infocmp.c parse_entry.c read_entry.c tput.c write_entry.c
+
+ The following modules will use open()/read()/write()/close()/lseek()
+ on files, but no other OS calls.
+
+ lib_screen.c
+ used to read/write screen dumps
+
+ lib_trace.c
+ used to write trace data to the logfile
+
+ Modules that would have to be modified for a port start here:
+
+ The following modules are `pure curses' but contain assumptions
+ inappropriate for a memory-mapped port.
+
+ lib_longname.c
+ assumes there may be multiple terminals
+
+ lib_acs.c
+ assumes acs_map as a double indirection
+
+ lib_mvcur.c
+ assumes cursor moves have variable cost
+
+ lib_termcap.c
+ assumes there may be multiple terminals
+
+ lib_ti.c
+ assumes there may be multiple terminals
+
+ The following modules use UNIX-specific calls:
+
+ lib_doupdate.c
+ input checking
+
+ lib_getch.c
+ read()
+
+ lib_initscr.c
+ getenv()
+
+ lib_newterm.c
+ lib_baudrate.c
+ lib_kernel.c
+ various tty-manipulation and system calls
+
+ lib_raw.c
+ various tty-manipulation calls
+
+ lib_setup.c
+ various tty-manipulation calls
+
+ lib_restart.c
+ various tty-manipulation calls
+
+ lib_tstp.c
+ signal-manipulation calls
+
+ lib_twait.c
+ gettimeofday(), select().
+ _________________________________________________________________
+
+
+ Eric S. Raymond <esr@snark.thyrsus.com>
+
+ (Note: This is not the bug address!)
diff --git a/contrib/ncurses/doc/html/announce.html b/contrib/ncurses/doc/html/announce.html
index e7a79d6..3005e49d 100644
--- a/contrib/ncurses/doc/html/announce.html
+++ b/contrib/ncurses/doc/html/announce.html
@@ -1,15 +1,15 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN">
<!--
- $Id: announce.html,v 1.38 2000/07/04 22:41:38 tom Exp $
+ $Id: announce.html,v 1.39 2000/10/20 10:47:16 tom Exp $
-->
<HTML>
<HEAD>
-<TITLE>Announcing ncurses 5.1</TITLE>
+<TITLE>Announcing ncurses 5.2</TITLE>
<link rev=made href="mailto:bug-ncurses@gnu.org">
</HEAD>
<BODY>
-<H1>Announcing ncurses 5.1</H1>
+<H1>Announcing ncurses 5.2</H1>
The ncurses (new curses) library is a free software emulation of
curses in System V Release 4.0, and more. It uses terminfo format,
@@ -38,136 +38,327 @@ the GNU distribution site
<H1>Release Notes</H1>
-This release is designed to be upward compatible from ncurses 5.0; very few
-applications will require recompilation, depending on the platform.
-These are the highlights from the change-log since ncurses 5.0 release.
+This release is designed to be upward compatible from ncurses 5.0 and 5.1;
+very few applications will require recompilation, depending on the platform.
+These are the highlights from the change-log since ncurses 5.1 release.
<p>
Interface changes:
<ul>
- <li>made the extended terminal capabilities
- (<code>configure&nbsp;--enable-tcap-names</code>)
- a standard feature (though the configure script can disable it,
- it is built by default).
-
- <li>removed the <code>trace()</code> function and related trace support
- from the production library. This is the only interface change that
- may cause problems with existing applications linked to shared
- libraries, since not all platforms use the minor version number.
-
- <li>explicitly initialized to zero several data items which were
- implicitly initialized, e.g., cur_term. If not explicitly
- initialized, their storage type is C (common), and causes problems
- linking on some platforms.
-
- <li>modified curses.h.in, undef'ing some symbols to avoid conflict with
- C++ STL.
+ <li>change type of <code>ospeed</code> variable back to
+ <code>short</code> to match its use in legacy applications. It was
+ altered after ncurses 4.2 to <code>speed_t</code> to repair a type
+ mismatch which was introduced after 1.9.4 in 1995. The principal
+ users of termcap continued to use <code>short</code>, which is
+ not the same size.
+ <p>
+ <em>NOTE</em>: A few applications will have to be recompiled
+ (about 1% of the programs in a typical Linux distribution,
+ 10% of the programs that use ncurses). These are easy to
+ identify with <code>nm</code> or <code>strings</code>.
+
+ <li>remove a private function <code>_nc_can_clear_with()</code>, which
+ was built with the configure --enable-expanded option but not used.
+
+ <li>add several private functions (prefixed with "_nc_") for tracing
+ <code>chtype</code> values in the debug library, and for better
+ access and buffer limit checking.
</ul>
-New features:
+New features and improvements:
<ul>
- <li>added a new extension, <code>assume_default_colors()</code> to
- provide better control over the use of default colors. This is
- the principal visible difference between ncurses 5.1 and preceding
- versions. The new extension allows an application to specify what
- colors pair 0 uses.
- <p>
- <em>NOTE</em>: Pair 0 defaults to white on black unless
- you have invoked <code>use_default_colors()</code> or set it via
- <code>assume_default_colors()</code>. An application that calls
- <code>start_colors()</code> without setting the background color
- will consistently have a black background no matter what color your
- terminal's background actually is.
-
- <li>made several fixes to the terminfo-to-termcap conversion, and
- have been using the generated termcaps without further hand-tuning.
- This builds on the extension <code>use_extended_names()</code> by
- adding "obsolete" termcap strings to terminfo.src
+ <li>rewrote <code>tgoto()</code> to make it better support existing
+ termcap applications which use hardcoded strings rather than obtain
+ all of their information from the termcap file. If the string does
+ not appear to be a terminfo string (i.e., does not refer to a "%p"
+ parameter, or terminfo-style padding), and termcap support is configured, <code>tgoto()</code>
+ will interpret it as termcap. Otherwise, as before, it will use
+ <code>tparm()</code>.
+
+ <li>to ensure that the <code>tgoto()</code> changes work properly,
+ added checks to <code>tic</code> which report capabilities that do
+ not reference the expected number of parameters.
+
+ <li>new configure script options:
<ul>
- <li>modified <code>tic</code> so that if extended names (i.e.,
- configure&nbsp;--enable-tcap-names) are active, then <code>tic&nbsp;-x</code>
- will also write "obsolete" capabilities that are present in the
- terminfo source.
-
- <li>added screen's AX capability (for ECMA SGR 39 and 49) to applicable
- terminfo entries, use presence of this as a check for a small
- improvement in setting default colors.
-
- <li>add -a option to tic and infocmp, which retains commented-out
- capabilities during source translation/comparison, e.g., captoinfo
- and infotocap.
+ <li>option <code>--disable-root-environ</code> adds runtime checks
+ which tell ncurses to disregard $TERMINFO and similar environment
+ variables if the current user is root, or running setuid/setgid.
+
+ <li>option <code>--disable-assumed-color</code> allows you to use the
+ pre-5.1 convention of default colors used for color-pair 0 to be
+ configured (see assume_default_colors()).
+
+ <li>implement configure script options that transform installed
+ program names, e.g., <code>--program-prefix</code>, including the
+ manpage names and cross references.
+
+ <li>option <code>--with-database</code> allows you to specify a
+ different terminfo source-file to install. On OS/2 EMX, the
+ default is misc/emx.src, otherwise misc/terminfo.src
+
+ <li>option <code>--with-default-terminfo-dir</code> allows you to
+ specify the default terminfo database directory.
+
+ <li>option <code>--with-libtool</code> allows you to build with
+ <code>libtool</code>. <p> <em>NOTE</em>: <code>libtool</code>
+ uses a different notation for numbering shared library versions
+ from the existing ncurses configuration.
+
+ <li>option <code>--with-manpage-tbl</code> causes the manpages to be
+ preprocessed by tbl(1) prior to installation,
+
+ <li>option <code>--without-curses-h</code> causes the installation
+ process to install curses.h as ncurses.h and make appropriate
+ changes to headers and manpages.
</ul>
- <li>implemented limited support for UTF-8, useful with XFree86 xterm:
+ <li>modified configure script options:
<ul>
- <li>if the <code>configure&nbsp;--enable-widec</code> option is
- given, append 'w' to names of the generated libraries (e.g.,
- libncursesw.so) to avoid conflict with existing ncurses libraries.
- <li>add a simple UTF-8 output driver to the experimental
- wide-character support. If any of the environment variables
- LC_ALL, LC_CTYPE or LANG contain the string "UTF-8", this driver
- will be used to translate the output to UTF-8.
- <li>modified view.c to make a rudimentary viewer of UTF-8 text.
+ <li>change symbol used by the <code>--install-prefix</code> configure
+ option from <code>INSTALL_PREFIX</code> to <code>DESTDIR</code>
+ (the latter has become common usage although the name is
+ misleading).
+
+ <li>modify <code>ld -rpath</code> options (e.g., Linux, and Solaris)
+ to use an absolute pathname for the build tree's lib directory,
+ avoiding confusion with directories relative to the current one
+ with the installed programs.
+
+ <li>modified <code>misc/run_tic.in</code> to use
+ <code>tic&nbsp;-o</code>, to eliminate dependency on
+ <code>$TERMINFO</code> variable for installs.
</ul>
- <li>modify <code>raw()</code> and <code>noraw()</code> to clear/restore
- IEXTEN flag which affects <code>stty lnext</code> on systems such as FreeBSD
+ <li>terminfo database:
+ <ul>
+ <li>updated xterm terminfo entries to match XFree86 xterm patch #146.
- <li>reordered tests during mouse initialization to allow for gpm to run
- in xterm, or for xterm to be used under OS/2 EMX. Also dropped test
- for <code>$DISPLAY</code> in favor of the terminfo capability
- <code>kmous=\E[M</code> or
- if <code>$TERM</code> environment variable contains "xterm".
+ <li>added amiga-vnc,
+ Matrix Orbital, and
+ QNX qansi to misc/terminfo.src.
- <li>added configure option <code>--with-manpage-symlinks</code>, which
- provides for fully indexing manpage entries by making symbolic links
- for the aliases.
+ <li>added os2 entry to misc/emx.src.
- <li>changed <code>unctrl()</code> to render C1 characters (128-159) as
- <code>~@</code>, <code>~A</code>, etc.
+ <li>add S0 and E0 extensions to <code>screen</code>'s terminfo entry
+ since otherwise the FreeBSD port makes it pass termcap equivalents
+ to <code>tgoto</code>, which would be misinterpreted by older
+ versions of ncurses.
+ </ul>
+
+ <li>improvements to program usability:
+ <ul>
+ <li>modify programs to use <code>curses_version()</code> string to
+ report the version of ncurses with which they are compiled rather
+ than the NCURSES_VERSION string. The function returns the patch
+ level in addition to the major and minor version numbers.
- <li>add experimental configure option --enable-colorfgbg to check for
- $COLORTERM variable as set by rxvt/aterm/Eterm.
+ <li>modify <code>tput</code> program so it can be renamed or invoked via a link as
+ 'reset' or 'init', producing the same effect as <code>tput&nbsp;reset</code> or <code>tput&nbsp;init</code>.
- <li>made the <code>infocmp -F</code> option less verbose.
+ <li>add error checking to infocmp's -v and -m options to ensure that
+ the option value is indeed a number.
+ </ul>
- <li>dropped support for gnat 3.10 (gnat 3.12 is current).
+ <li>improved performance:
+ <ul>
+ <li>replace a lookup table in lib_vidattr.c used to decode
+ <code>no_color_video</code> with a logic expression which is faster.
+ </ul>
</ul>
Major bug fixes:
<ul>
- <li>modified infocmp -e, -E options to ensure that generated fallback.c
- type for Booleans agrees with term.h
+ <li>correct <code>manlinks.sed</code> script introduced in ncurses 5.1
+ to avoid using ERE "\+", which is not understood by standard versions
+ of <code>sed</code>. This happens to work with GNU <code>sed</code>,
+ but is not portable, and was the initial motivation for this release.
+
+ <li>remove "hpux10.*" case from CF_SHARED_OPTS configure script macro.
+ This differed from the "hpux*" case by using reversed symbolic
+ links, which made the 5.1 version not match the configuration of
+ 5.0 shared libraries.
+
+ <li>guard against corrupt terminfo data:
+ <ul>
+ <li>modify <code>tparm()</code> to disallow arithmetic on strings,
+ analyze the varargs list to read strings as strings and numbers as
+ numbers.
+
+ <li>modify <code>tparm()</code>'s internal function
+ <code>spop()</code> to treat a null pointer as an empty string.
+
+ <li>modify <code>parse_format()</code> in lib_tparm.c to ignore
+ precision if it is longer than 10000.
+
+ <li>rewrote limit checks in lib_mvcur.c using new functions
+ <code>_nc_safe_strcat()</code>, etc. Made other related changes to
+ check lengths used for <code>strcat()</code> and
+ <code>strcpy()</code>.
+ </ul>
+
+ <li>corrections to screen optimization:
+ <ul>
+ <li>added special case in lib_vidattr.c to reset underline and
+ standout for devices that have no sgr0 defined.
+
+ <li>change handling of <code>non_dest_scroll_region</code> in
+ tty_update.c to clear text after it is shifted in rather than before
+ shifting out. Also correct row computation.
+
+ <li>modify <code>rs2</code> capability in xterm-r6 and similar entries
+ where cursor save/restore bracketed the sequence for resetting video
+ attributes. The cursor restore would undo that.
+ </ul>
+
+ <li>UTF-8 support:
+ <ul>
+ <li>when checking LC_ALL, LC_CTYPE, and LANG environment variables
+ for UTF-8 locale, ignore those which are set to an empty value, as
+ per SUSV2.
- <li>documented a special case of incompatiblity between ncurses 4.2 and
- 5.0, added a section for this in INSTALL.
+ <li>encode 0xFFFD in UTF-8 with 3 bytes, not 2.
- <li>corrected tests for file-descriptors in OS/2 EMX mouse support. A
- negative value could be used by FD_SET, causing the select() call to
- wait indefinitely.
+ <li>modify <code>_nc_utf8_outch()</code> to avoid sign-extension when
+ checking for out-of-range value.
+ </ul>
- <li>made 'tput flash' work properly for xterm by flushing output in
- delay_output() when using napms(), and modifying xterm's terminfo to
- specify no padding character. Otherwise, xterm's reported baud rate
- could mislead ncurses into producing too few padding characters.
+ <li>other library fixes:
+ <ul>
+ <li>added checks for an empty <code>$HOME</code> environment
+ variable, to avoid retrieving terminfo descriptions from
+ <code>./.terminfo</code> .
- <li>modified lib_addch.c to allow repeated update to the lower-right
- corner, rather than displaying only the first character written until
- the cursor is moved. Recent versions of SVr4 curses can update the
- lower-right corner, and behave this way.
+ <li>change functions <code>_nc_parse_entry()</code> and
+ <code>postprocess_termcap()</code> to avoid using
+ <code>strtok()</code>, because it is non-reentrant.
- <li>modified echo() behavior of getch() to match Solaris curses for
- carriage return and backspace (reported by Neil Zanella).
+ <li>initialize <code>fds[]</code> array to 0's in
+ <code>_nc_timed_wait()</code>; apparently <code>poll()</code> only
+ sets the <code>revents</code> members of that array when there is
+ activity corresponding to the related file.
- <li>corrected offsets used for subwindows in <code>wresize()</code>
+ <li>add a check for null pointer in <code>Make_Enum_Type()</code>.
- <li>modified configure script so AC_MSG_ERROR is temporarily defined to
- a warning in AC_PROG_CXX to make it recover from a missing C++
- compiler without requiring user to add --without-cxx option
+ <li>fix a heap problem with the c++ binding.
- <li>corrected logic in lib_twait.c as used by lib_mouse.c for GPM mouse
- support when poll() is used rather than select().
+ <li>correct missing includes for &lt;string.h&gt; in several places,
+ including the C++ binding. This is not noted by gcc unless we use
+ the <code>-fno-builtin</code> option.
+ </ul>
+
+ <li>several fixes for tic:
+ <ul>
+ <li>add a check for empty buffers returned by <code>fgets()</code> in
+ comp_scan.c <code>next_char()</code> function, in case
+ <code>tic</code> is run on a non-text file (fixes a core dump).
+
+ <li>modify <code>tic</code> to verify that its inputs are really files,
+ in case someone tries to read a directory (or
+ <code>/dev/zero</code>).
+
+ <li>correct an uninitialized parameter to <code>open_tempfile()</code>
+ in tic.c which made "tic -I" give an ambiguous error message about
+ <code>tmpnam</code>.
+
+ <li>correct logic in <code>adjust_cancels()</code>, which did not check
+ both alternatives when reclassifying an extended name between
+ boolean, number and string, causing an infinite loop in
+ <code>tic</code>.
+ </ul>
+
+ <li>using new checks in <code>tic</code> for parameter counts in
+ capability strings, found/fixed several errors both in the
+ terminfo database and in the include/Caps file.
+ <ul>
+ <li>modified several terminfo capability strings, including the
+ definitions for setaf, setab, in include/Caps to indicate that the
+ entries are parameterized. This information is used to tell which
+ strings are translated when converting to termcap. This fixes a
+ problem where the generated termcap would contain a spurious "%p1"
+ for the terminfo "%p1%d".
+
+ <li>correct parameter counts in include/Caps for dclk as well as some
+ printer-specific capabilities: csnm, defc, scs, scsd, smgtp, smglp.
+ </ul>
+
+ <li>various fixes for install scripts used to support configure
+ <code>--srcdir</code> and <code>--with-install-prefix</code>.
+
+ <li>correct several mismatches between manpage filename and ".TH"
+ directives, renaming dft_fgbg.3x to default_colors.3x and
+ menu_attribs.3x to menu_attributes.3x.
+</ul>
+
+Portability:
+<ul>
+ <li>configure script:
+ <ul>
+ <li>newer config.guess, config.sub, including changes to support OS/2
+ EMX. The configure script for OS/2 EMX still relies on a patch
+ since there is no (working) support for that platform in the main
+ autoconf distribution.
+
+ <li>make configure script checks on variables <code>$GCC</code> and
+ <code>$GXX</code> consistently compare against 'yes' rather than
+ test if they are nonnull, since either may be set to the
+ corresponding name of the C or C++ compiler.
+
+ <li>change configure script to use AC_CANONICAL_SYSTEM rather than
+ AC_CANONICAL_HOST, which means that <code>configure --target</code>
+ will set a default program-prefix.
+
+ <li>modify the check for big-core to force a couple of memory
+ accesses, which may work as needed for older/less-capable machines
+ (if not, there's still the explicit configure option).
+
+ <li>modify configure test for <code>tcgetattr()</code> to allow for
+ old implementations, e.g., on BeOS, which only defined it as a
+ macro.
+
+ <li>add configure check for filesystems (such as OS/2 EMX) which do
+ not distinguish between upper/lowercase filenames, use this to fix
+ tags rules in makefiles.
+
+ <li>add MKncurses_def.sh to generate fallback definitions for
+ ncurses_cfg.h, to quiet gcc -Wundef warnings, modified ifdef's in
+ code to consistently use "#if" rather than "#ifdef".
+
+ <li>change most remaining unquoted parameters of <code>test</code> in
+ configure script to use quotes, for instance fixing a problem in the
+ <code>--disable-database</code> option.
+
+ <li>modify scripts so that "make install.data" works on OS/2 EMX.
+
+ <li>modify scripts and makefiles so the Ada95 directory builds on
+ OS/2 EMX.
+ </ul>
+
+ <li>library:
+ <ul>
+ <li>replaced case-statement in <code>_nc_tracebits()</code> for CSIZE
+ with a table to simplify working around implementations that define
+ random combinations of the related macros to zero.
+
+ <li>improved OS/2 mouse support by retrying as a 2-button mouse if code
+ fails to set up a 3-button mouse.
+
+ <li>added private entrypoint <code>_nc_basename()</code>, used to
+ consolidate related code in progs, as well as accommodating OS/2 EMX
+ pathnames.
+
+ <li>alter definition of NCURSES_CONST to make it non-empty.
+
+ <li>redefine 'TEXT' in menu.h for AMIGA, since it is reported to have
+ an (unspecified) symbol conflict.
+ </ul>
+
+ <li>programs:
+ <ul>
+ <li>modified progs/tset.c and tack/sysdep.c to build with sgttyb
+ interface if neither termio or termios is available. Tested this
+ with FreeBSD 2.1.5 (which does have termios - but the sgttyb does
+ work).
+ </ul>
- <li>made several fixes for buffer overflows, unchecked recursion,
- improvements in performance, etc. See the NEWS file for details.
</ul>
<H1>Features of Ncurses</H1>
diff --git a/contrib/ncurses/doc/ncurses-intro.doc b/contrib/ncurses/doc/ncurses-intro.doc
new file mode 100644
index 0000000..669b0b3
--- /dev/null
+++ b/contrib/ncurses/doc/ncurses-intro.doc
@@ -0,0 +1,2502 @@
+
+ Writing Programs with NCURSES
+
+ by Eric S. Raymond and Zeyd M. Ben-Halim
+ updates since release 1.9.9e by Thomas Dickey
+
+ Contents
+
+ * Introduction
+ + A Brief History of Curses
+ + Scope of This Document
+ + Terminology
+ * The Curses Library
+ + An Overview of Curses
+ o Compiling Programs using Curses
+ o Updating the Screen
+ o Standard Windows and Function Naming Conventions
+ o Variables
+ + Using the Library
+ o Starting up
+ o Output
+ o Input
+ o Using Forms Characters
+ o Character Attributes and Color
+ o Mouse Interfacing
+ o Finishing Up
+ + Function Descriptions
+ o Initialization and Wrapup
+ o Causing Output to the Terminal
+ o Low-Level Capability Access
+ o Debugging
+ + Hints, Tips, and Tricks
+ o Some Notes of Caution
+ o Temporarily Leaving ncurses Mode
+ o Using ncurses under xterm
+ o Handling Multiple Terminal Screens
+ o Testing for Terminal Capabilities
+ o Tuning for Speed
+ o Special Features of ncurses
+ + Compatibility with Older Versions
+ o Refresh of Overlapping Windows
+ o Background Erase
+ + XSI Curses Conformance
+ * The Panels Library
+ + Compiling With the Panels Library
+ + Overview of Panels
+ + Panels, Input, and the Standard Screen
+ + Hiding Panels
+ + Miscellaneous Other Facilities
+ * The Menu Library
+ + Compiling with the menu Library
+ + Overview of Menus
+ + Selecting items
+ + Menu Display
+ + Menu Windows
+ + Processing Menu Input
+ + Miscellaneous Other Features
+ * The Forms Library
+ + Compiling with the forms Library
+ + Overview of Forms
+ + Creating and Freeing Fields and Forms
+ + Fetching and Changing Field Attributes
+ o Fetching Size and Location Data
+ o Changing the Field Location
+ o The Justification Attribute
+ o Field Display Attributes
+ o Field Option Bits
+ o Field Status
+ o Field User Pointer
+ + Variable-Sized Fields
+ + Field Validation
+ o TYPE_ALPHA
+ o TYPE_ALNUM
+ o TYPE_ENUM
+ o TYPE_INTEGER
+ o TYPE_NUMERIC
+ o TYPE_REGEXP
+ + Direct Field Buffer Manipulation
+ + Attributes of Forms
+ + Control of Form Display
+ + Input Processing in the Forms Driver
+ o Page Navigation Requests
+ o Inter-Field Navigation Requests
+ o Intra-Field Navigation Requests
+ o Scrolling Requests
+ o Field Editing Requests
+ o Order Requests
+ o Application Commands
+ + Field Change Hooks
+ + Field Change Commands
+ + Form Options
+ + Custom Validation Types
+ o Union Types
+ o New Field Types
+ o Validation Function Arguments
+ o Order Functions For Custom Types
+ o Avoiding Problems
+ _________________________________________________________________
+
+ Introduction
+
+ This document is an introduction to programming with curses. It is not
+ an exhaustive reference for the curses Application Programming
+ Interface (API); that role is filled by the curses manual pages.
+ Rather, it is intended to help C programmers ease into using the
+ package.
+
+ This document is aimed at C applications programmers not yet
+ specifically familiar with ncurses. If you are already an experienced
+ curses programmer, you should nevertheless read the sections on Mouse
+ Interfacing, Debugging, Compatibility with Older Versions, and Hints,
+ Tips, and Tricks. These will bring you up to speed on the special
+ features and quirks of the ncurses implementation. If you are not so
+ experienced, keep reading.
+
+ The curses package is a subroutine library for terminal-independent
+ screen-painting and input-event handling which presents a high level
+ screen model to the programmer, hiding differences between terminal
+ types and doing automatic optimization of output to change one screen
+ full of text into another. Curses uses terminfo, which is a database
+ format that can describe the capabilities of thousands of different
+ terminals.
+
+ The curses API may seem something of an archaism on UNIX desktops
+ increasingly dominated by X, Motif, and Tcl/Tk. Nevertheless, UNIX
+ still supports tty lines and X supports xterm(1); the curses API has
+ the advantage of (a) back-portability to character-cell terminals, and
+ (b) simplicity. For an application that does not require bit-mapped
+ graphics and multiple fonts, an interface implementation using curses
+ will typically be a great deal simpler and less expensive than one
+ using an X toolkit.
+
+A Brief History of Curses
+
+ Historically, the first ancestor of curses was the routines written to
+ provide screen-handling for the game rogue; these used the
+ already-existing termcap database facility for describing terminal
+ capabilities. These routines were abstracted into a documented library
+ and first released with the early BSD UNIX versions.
+
+ System III UNIX from Bell Labs featured a rewritten and much-improved
+ curses 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, curses evolved to use more
+ facilities and offer more capabilities, going far beyond BSD curses in
+ power and flexibility.
+
+Scope of This Document
+
+ This document describes ncurses, a free implementation of the System V
+ curses API with some clearly marked extensions. It includes the
+ following System V curses features:
+ * Support for multiple screen highlights (BSD curses could only
+ handle one `standout' highlight, usually reverse-video).
+ * Support for line- and box-drawing using forms characters.
+ * Recognition of function keys on input.
+ * Color support.
+ * Support for pads (windows of larger than screen size on which the
+ screen or a subwindow defines a viewport).
+
+ 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.
+
+ The ncurses package can also capture and use event reports from a
+ mouse in some environments (notably, xterm under the X window system).
+ This document includes tips for using the mouse.
+
+ The ncurses package was originated by Pavel Curtis. The original
+ maintainer of this 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 wrote most of this introduction. Jürgen
+ Pfeifer wrote all of the menu and forms code as well as the Ada95
+ binding. Ongoing work is being done by Thomas Dickey and Jürgen
+ Pfeifer. Florian La Roche acts as the maintainer for the Free Software
+ Foundation, which holds the copyright on ncurses. Contact the current
+ maintainers at bug-ncurses@gnu.org.
+
+ This document also describes the panels 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).
+
+ Finally, this document describes in detail the menus and forms
+ extension libraries, also cloned from System V, which support easy
+ construction and sequences of menus and fill-in forms.
+
+Terminology
+
+ In this document, the following terminology is used with reasonable
+ consistency:
+
+ window
+ 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.
+
+ screens
+ 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, stdscr, is
+ automatically provided for the programmer.
+
+ terminal screen
+ The package's idea of what the terminal display currently looks
+ like, i.e., what the user sees now. This is a special screen.
+
+ The Curses Library
+
+An Overview of Curses
+
+ Compiling Programs using Curses
+
+ In order to use the library, it is necessary to have certain types and
+ variables defined. Therefore, the programmer must have a line:
+ #include <curses.h>
+
+ at the top of the program source. The screen package uses the Standard
+ I/O library, so <curses.h> includes <stdio.h>. <curses.h> also
+ includes <termios.h>, <termio.h>, or <sgtty.h> depending on your
+ system. It is redundant (but harmless) for the programmer to do these
+ includes, too. In linking with curses you need to have -lncurses in
+ your LDFLAGS or on the command line. There is no need for any other
+ libraries.
+
+ Updating the Screen
+
+ 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 curscr, for current screen) is a screen image of what
+ the terminal currently looks like. Another screen (called stdscr, for
+ standard screen) is provided 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's
+ more like a scratchpad or write buffer.
+
+ To make the section of physical screen corresponding to a window
+ reflect the contents of the window structure, the routine refresh()
+ (or wrefresh() if the window is not stdscr) is called.
+
+ 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.
+
+ Standard Windows and Function Naming Conventions
+
+ As hinted above, the routines can use several windows, but two are
+ automatically given: curscr, which knows what the terminal looks like,
+ and stdscr, which is what the programmer wants the terminal to look
+ like next. The user should never actually access curscr directly.
+ Changes should be made to through the API, and then the routine
+ refresh() (or wrefresh()) called.
+
+ Many functions are defined to use stdscr as a default screen. For
+ example, to add a character to stdscr, one calls addch() with the
+ desired character as argument. To write to a different window. use the
+ routine waddch() (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.
+
+ In order to move the current (y, x) coordinates from one point to
+ another, the routines move() and wmove() 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
+ 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 (win) comes before the added
+ (y, x) coordinates. If a function requires a window pointer, it is
+ always the first parameter passed.
+
+ Variables
+
+ The curses library sets some variables describing the terminal
+ capabilities.
+ type name description
+ ------------------------------------------------------------------
+ int LINES number of lines on the terminal
+ int COLS number of columns on the terminal
+
+ The curses.h also introduces some #define constants and types of
+ general usefulness:
+
+ bool
+ boolean type, actually a `char' (e.g., bool doneit;)
+
+ TRUE
+ boolean `true' flag (1).
+
+ FALSE
+ boolean `false' flag (0).
+
+ ERR
+ error flag returned by routines on a failure (-1).
+
+ OK
+ error flag returned by routines when things go right.
+
+Using the Library
+
+ Now we describe how to actually use the screen package. In it, we
+ assume all updating, reading, etc. is applied to stdscr. These
+ instructions will work on any window, providing you change the
+ function names and parameters as mentioned above.
+
+ Here is a sample program to motivate the discussion:
+#include <curses.h>
+#include <signal.h>
+
+static void finish(int sig);
+
+int
+main(int argc, char *argv[])
+{
+ int num = 0;
+
+ /* 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) echo(); /* echo input - in color */
+
+ if (has_colors())
+ {
+ start_color();
+
+ /*
+ * Simple color assignment, often all we need. Color pair 0 cannot
+ * be redefined. This example uses the same value for the color
+ * pair as for the foreground color, though of course that is not
+ * necessary:
+ */
+ init_pair(1, COLOR_RED, COLOR_BLACK);
+ init_pair(2, COLOR_GREEN, COLOR_BLACK);
+ init_pair(3, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(4, COLOR_BLUE, COLOR_BLACK);
+ init_pair(5, COLOR_CYAN, COLOR_BLACK);
+ init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(7, COLOR_WHITE, COLOR_BLACK);
+ }
+
+ for (;;)
+ {
+ int c = getch(); /* refresh, accept single keystroke of input */
+ attrset(COLOR_PAIR(num % 8));
+ num++;
+
+ /* process the command keystroke */
+ }
+
+ finish(0); /* we're done */
+}
+
+static void finish(int sig)
+{
+ endwin();
+
+ /* do your non-curses wrapup here */
+
+ exit(0);
+}
+
+ Starting up
+
+ In order to use the screen package, the routines must know about
+ terminal characteristics, and the space for curscr and stdscr must be
+ allocated. These function initscr() 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, initscr()
+ will terminate the program with an error message. initscr() 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
+ curscr or stdscr 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
+ nl() and cbreak() should be called after initscr().
+
+ 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
+ scrollok(). If you want the cursor to be left in place after the last
+ change, use leaveok(). If this isn't done, refresh() will move the
+ cursor to the window's current (y, x) coordinates after updating it.
+
+ You can create new windows of your own using the functions newwin(),
+ derwin(), and subwin(). The routine delwin() will allow you to get rid
+ of old windows. All the options described above can be applied to any
+ window.
+
+ Output
+
+ 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 addch() and move(). addch() adds a character at the current (y, x)
+ coordinates. move() changes the current (y, x) coordinates to whatever
+ you want them to be. It returns ERR if you try to move off the window.
+ As mentioned above, you can combine the two into mvaddch() to do both
+ things at once.
+
+ The other output functions, such as addstr() and printw(), all call
+ addch() 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 refresh(). In order to optimize finding
+ changes, refresh() assumes that any part of the window not changed
+ since the last refresh() 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
+ touchwin() is provided to make it look like the entire window has been
+ changed, thus making refresh() check the whole subsection of the
+ terminal for changes.
+
+ If you call wrefresh() with curscr as its argument, it will make the
+ screen look like curscr thinks it looks like. This is useful for
+ implementing a command which would redraw the screen in case it get
+ messed up.
+
+ Input
+
+ The complementary function to addch() is getch() which, if echo is
+ set, will call addch() 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 getch(); otherwise, the
+ program's output will be unpredictable.
+
+ When you need to accept line-oriented input in a window, the functions
+ wgetstr() and friends are available. There is even a wscanw() function
+ that can do scanf()(3)-style multi-field parsing on window input.
+ These pseudo-line-oriented functions turn on echoing while they
+ execute.
+
+ The example code above uses the call keypad(stdscr, TRUE) to enable
+ support for function-key mapping. With this feature, the getch() code
+ watches the input stream for character sequences that correspond to
+ arrow and function keys. These sequences are returned as
+ pseudo-character values. The #define values returned are listed in the
+ curses.h The mapping from sequences to #define values is determined by
+ key_ capabilities in the terminal's terminfo entry.
+
+ Using Forms Characters
+
+ The addch() function (and some others, including box() and border())
+ can accept some pseudo-character arguments which are specially defined
+ by ncurses. These are #define values set up in the curses.h header;
+ see there for a complete list (look for the prefix ACS_).
+
+ 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, curses.h will map them to
+ a recognizable (though ugly) set of ASCII defaults.
+
+ Character Attributes and Color
+
+ The ncurses package supports screen highlights including standout,
+ reverse-video, underline, and blink. It also supports color, which is
+ treated as another kind of highlight.
+
+ Highlights are encoded, internally, as high bits of the
+ pseudo-character type (chtype) that curses.h uses to represent the
+ contents of a screen cell. See the curses.h header file for a complete
+ list of highlight mask values (look for the prefix A_).
+
+ 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 addch()
+ call, or any other output call that takes a chtype argument.
+
+ 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 attron(), attroff(), and attrset(); 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 init_pair() values.
+
+ Once you've done an init_pair() that creates color-pair N, you can use
+ COLOR_PAIR(N) as a highlight that invokes that particular color
+ combination. Note that COLOR_PAIR(N), for constant N, is itself a
+ compile-time constant and can be used in initializers.
+
+ Mouse Interfacing
+
+ The ncurses library also provides a mouse interface.
+
+ NOTE: this facility is specific to ncurses, it is not part of
+ either the XSI Curses standard, nor of System V Release 4, nor BSD
+ curses. System V Release 4 curses contains code with similar
+ interface definitions, however it is not documented. Other than by
+ disassembling the library, we have no way to determine exactly how
+ that mouse code works. Thus, we recommend that you wrap
+ mouse-related code in an #ifdef using the feature macro
+ NCURSES_MOUSE_VERSION so it will not be compiled and linked on
+ non-ncurses systems.
+
+ Presently, mouse event reporting works in the following environments:
+ * xterm and similar programs such as rxvt.
+ * Linux console, when configured with gpm(1), Alessandro Rubini's
+ mouse server.
+ * OS/2 EMX
+
+ The mouse interface is very simple. To activate it, you use the
+ function mousemask(), passing it as first argument a bit-mask that
+ specifies what kinds of events you want your program to be able to
+ see. It will return the bit-mask of events that actually become
+ visible, which may differ from the argument if the mouse device is not
+ capable of reporting some of the event types you specify.
+
+ Once the mouse is active, your application's command loop should watch
+ for a return value of KEY_MOUSE from wgetch(). When you see this, a
+ mouse event report has been queued. To pick it off the queue, use the
+ function getmouse() (you must do this before the next wgetch(),
+ otherwise another mouse event might come in and make the first one
+ inaccessible).
+
+ Each call to getmouse() fills a structure (the address of which you'll
+ pass it) with mouse event data. The event data includes zero-origin,
+ screen-relative character-cell coordinates of the mouse pointer. It
+ also includes an event mask. Bits in this mask will be set,
+ corresponding to the event type being reported.
+
+ The mouse structure contains two additional fields which may be
+ significant in the future as ncurses interfaces to new kinds of
+ pointing device. In addition to x and y coordinates, there is a slot
+ for a z coordinate; this might be useful with touch-screens that can
+ return a pressure or duration parameter. There is also a device ID
+ field, which could be used to distinguish between multiple pointing
+ devices.
+
+ The class of visible events may be changed at any time via
+ mousemask(). Events that can be reported include presses, releases,
+ single-, double- and triple-clicks (you can set the maximum
+ button-down time for clicks). If you don't make clicks visible, they
+ will be reported as press-release pairs. In some environments, the
+ event mask may include bits reporting the state of shift, alt, and
+ ctrl keys on the keyboard during the event.
+
+ A function to check whether a mouse event fell within a given window
+ is also supplied. You can use this to see whether a given window
+ should consider a mouse event relevant to it.
+
+ Because mouse event reporting will not be available in all
+ environments, it would be unwise to build ncurses applications that
+ require the use of a mouse. Rather, you should use the mouse as a
+ shortcut for point-and-shoot commands your application would normally
+ accept from the keyboard. Two of the test games in the ncurses
+ distribution (bs and knight) contain code that illustrates how this
+ can be done.
+
+ See the manual page curs_mouse(3X) for full details of the
+ mouse-interface functions.
+
+ Finishing Up
+
+ In order to clean up after the ncurses routines, the routine endwin()
+ is provided. It restores tty modes to what they were when initscr()
+ was first called, and moves the cursor down to the lower-left corner.
+ Thus, anytime after the call to initscr, endwin() should be called
+ before exiting.
+
+Function Descriptions
+
+ We describe the detailed behavior of some important curses functions
+ here, as a supplement to the manual page descriptions.
+
+ Initialization and Wrapup
+
+ initscr()
+ The first function called should almost always be initscr().
+ This will determine the terminal type and initialize curses
+ data structures. initscr() also arranges that the first call to
+ refresh() will clear the screen. If an error occurs a message
+ is written to standard error and the program exits. Otherwise
+ it returns a pointer to stdscr. A few functions may be called
+ before initscr (slk_init(), filter(), ripofflines(), use_env(),
+ and, if you are using multiple terminals, newterm().)
+
+ endwin()
+ Your program should always call endwin() 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 non-visual mode. Calling
+ refresh() or doupdate() after a temporary escape from the
+ program will restore the ncurses screen from before the escape.
+
+ newterm(type, ofp, ifp)
+ A program which outputs to more than one terminal should use
+ newterm() instead of initscr(). newterm() should be called once
+ for each terminal. It returns a variable of type SCREEN * which
+ should be saved as a reference to that terminal. The arguments
+ are the type of the terminal (a string) and FILE pointers for
+ the output and input of the terminal. If type is NULL then the
+ environment variable $TERM is used. endwin() should called once
+ at wrapup time for each terminal opened using this function.
+
+ set_term(new)
+ This function is used to switch to a different terminal
+ previously opened by newterm(). 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.
+
+ delscreen(sp)
+ The inverse of newterm(); deallocates the data structures
+ associated with a given SCREEN reference.
+
+ Causing Output to the Terminal
+
+ refresh() and wrefresh(win)
+ These functions must be called to actually get any output on
+ the terminal, as other routines merely manipulate data
+ structures. wrefresh() copies the named window to the physical
+ terminal screen, taking into account what is already there in
+ order to do optimizations. refresh() does a refresh of
+ stdscr(). Unless leaveok() has been enabled, the physical
+ cursor of the terminal is left at the location of the window's
+ cursor.
+
+ doupdate() and wnoutrefresh(win)
+ 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 (wnoutrefresh()), and then calling the
+ routine to update the screen (doupdate()). If the programmer
+ wishes to output several windows at once, a series of calls to
+ wrefresh will result in alternating calls to wnoutrefresh() and
+ doupdate(), causing several bursts of output to the screen. By
+ calling wnoutrefresh() for each window, it is then possible to
+ call doupdate() once, resulting in only one burst of output,
+ with fewer total characters transmitted (this also avoids a
+ visually annoying flicker at each update).
+
+ Low-Level Capability Access
+
+ setupterm(term, filenum, errret)
+ This routine is called to initialize a terminal's description,
+ without setting up the curses screen structures or changing the
+ tty-driver mode bits. term is the character string representing
+ the name of the terminal being used. filenum is the UNIX file
+ descriptor of the terminal to be used for output. errret 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).
+
+ The value of term can be given as NULL, which will cause the
+ value of TERM in the environment to be used. The errret pointer
+ can also be given as NULL, meaning no error code is wanted. If
+ errret is defaulted, and something goes wrong, setupterm() 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.
+
+ After the call to setupterm(), the global variable cur_term is
+ set to point to the current structure of terminal capabilities.
+ By calling setupterm() for each terminal, and saving and
+ restoring cur_term, it is possible for a program to use two or
+ more terminals at once. Setupterm() also stores the names
+ section of the terminal description in the global character
+ array ttytype[]. Subsequent calls to setupterm() will overwrite
+ this array, so you'll have to save it yourself if need be.
+
+ Debugging
+
+ NOTE: These functions are not part of the standard curses API!
+
+ trace()
+ This function can be used to explicitly set a trace level. If
+ the trace level is nonzero, execution of your program will
+ generate a file called `trace' in the current working directory
+ containing a report on the library's actions. Higher trace
+ levels enable more detailed (and verbose) reporting -- see
+ comments attached to TRACE_ defines in the curses.h file for
+ details. (It is also possible to set a trace level by assigning
+ a trace level value to the environment variable NCURSES_TRACE).
+
+ _tracef()
+ 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 printf(), only it
+ outputs a newline after the end of arguments. The output goes
+ to a file called trace in the current directory.
+
+ Trace logs can be difficult to interpret due to the sheer volume of
+ data dumped in them. There is a script called tracemunch included with
+ the ncurses distribution that can alleviate this problem somewhat; it
+ compacts long sequences of similar operations into more succinct
+ single-line pseudo-operations. These pseudo-ops can be distinguished
+ by the fact that they are named in capital letters.
+
+Hints, Tips, and Tricks
+
+ The ncurses 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.
+
+ Some Notes of Caution
+
+ If you find yourself thinking you need to use noraw() or nocbreak(),
+ think again and move carefully. It's probably better design to use
+ getstr() or one of its relatives to simulate cooked mode. The noraw()
+ and nocbreak() functions try to restore cooked mode, but they may end
+ up clobbering some control bits set before you started your
+ application. Also, they have always been poorly documented, and are
+ likely to hurt your application's usability with other curses
+ libraries.
+
+ Bear in mind that refresh() is a synonym for wrefresh(stdscr). Don't
+ try to mix use of stdscr with use of windows declared by newwin(); a
+ refresh() call will blow them off the screen. The right way to handle
+ this is to use subwin(), or not touch stdscr at all and tile your
+ screen with declared windows which you then wnoutrefresh() somewhere
+ in your program event loop, with a single doupdate() call to trigger
+ actual repainting.
+
+ 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 ncurses library is not yet an
+ exception to this rule.
+
+ There is a panels library included in the ncurses distribution that
+ does a pretty good job of strengthening the overlapping-windows
+ facilities.
+
+ Try to avoid using the global variables LINES and COLS. Use getmaxyx()
+ on the stdscr 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.
+
+ Temporarily Leaving NCURSES Mode
+
+ 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 ncurses.
+
+ To leave ncurses mode, call endwin() 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
+ ncurses mode, simply call refresh() or doupdate(). This will repaint
+ the screen.
+
+ There is a boolean function, isendwin(), which code can use to test
+ whether ncurses screen mode is active. It returns TRUE in the interval
+ between an endwin() call and the following refresh(), FALSE otherwise.
+
+ Here is some sample code for shellout:
+ 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 */
+
+ Using NCURSES under XTERM
+
+ A resize operation in X sends SIGWINCH to the application running
+ under xterm. The ncurses library provides an experimental signal
+ handler, but in general does not catch this signal, because it cannot
+ know how you want the screen re-painted. You will usually have to
+ write the SIGWINCH handler yourself. Ncurses can give you some help.
+
+ The easiest way to code your SIGWINCH handler is to have it do an
+ endwin, followed by an refresh and a screen repaint you code yourself.
+ The refresh will pick up the new screen size from the xterm's
+ environment.
+
+ That is the standard way, of course (it even works with some vendor's
+ curses implementations). Its drawback is that it clears the screen to
+ reinitialize the display, and does not resize subwindows which must be
+ shrunk. Ncurses provides an extension which works better, the
+ resizeterm function. That function ensures that all windows are
+ limited to the new screen dimensions, and pads stdscr with blanks if
+ the screen is larger.
+
+ Finally, ncurses can be configured to provide its own SIGWINCH
+ handler, based on resizeterm.
+
+ Handling Multiple Terminal Screens
+
+ The initscr() function actually calls a function named newterm() to do
+ most of its work. If you are writing a program that opens multiple
+ terminals, use newterm() directly.
+
+ 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 stdscr
+ will be set to the last one allocated. You will switch between screens
+ with the set_term call. Note that you will also have to call
+ def_shell_mode and def_prog_mode on each tty yourself.
+
+ Testing for Terminal Capabilities
+
+ Sometimes you may want to write programs that test for the presence of
+ various capabilities before deciding whether to go into ncurses mode.
+ An easy way to do this is to call setupterm(), then use the functions
+ tigetflag(), tigetnum(), and tigetstr() to do your testing.
+
+ A particularly useful case of this often comes up when you want to
+ test whether a given terminal type should be treated as `smart'
+ (cursor-addressable) or `stupid'. The right way to test this is to see
+ if the return value of tigetstr("cup") is non-NULL. Alternatively, you
+ can include the term.h file and test the value of the macro
+ cursor_address.
+
+ Tuning for Speed
+
+ Use the addchstr() 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 immedok() option!
+
+ Special Features of NCURSES
+
+ The wresize() function allows you to resize a window in place. The
+ associated resizeterm() function simplifies the construction of
+ SIGWINCH handlers, for resizing all windows.
+
+ The define_key() function allows you to define at runtime function-key
+ control sequences which are not in the terminal description. The
+ keyok() function allows you to temporarily enable or disable
+ interpretation of any function-key control sequence.
+
+ The use_default_colors() function allows you to construct applications
+ which can use the terminal's default foreground and background colors
+ as an additional "default" color. Several terminal emulators support
+ this feature, which is based on ISO 6429.
+
+ Ncurses supports up 16 colors, unlike SVr4 curses which defines only
+ 8. While most terminals which provide color allow only 8 colors, about
+ a quarter (including XFree86 xterm) support 16 colors.
+
+Compatibility with Older Versions
+
+ Despite our best efforts, there are some differences between ncurses
+ and the (undocumented!) behavior of older curses implementations.
+ These arise from ambiguities or omissions in the documentation of the
+ API.
+
+ Refresh of Overlapping Windows
+
+ If you define two windows A and B that overlap, and then alternately
+ scribble on and refresh them, the changes made to the overlapping
+ region under historic curses versions were often not documented
+ precisely.
+
+ To understand why this is a problem, remember that screen updates are
+ calculated between two representations of the entire display. The
+ documentation says that when you refresh a window, it is first copied
+ to to the virtual screen, and then changes are calculated to update
+ the physical screen (and applied to the terminal). But "copied to" is
+ not very specific, and subtle differences in how copying works can
+ produce different behaviors in the case where two overlapping windows
+ are each being refreshed at unpredictable intervals.
+
+ What happens to the overlapping region depends on what wnoutrefresh()
+ does with its argument -- what portions of the argument window it
+ copies to the virtual screen. Some implementations do "change copy",
+ copying down only locations in the window that have changed (or been
+ marked changed with wtouchln() and friends). Some implementations do
+ "entire copy", copying all window locations to the virtual screen
+ whether or not they have changed.
+
+ The ncurses library itself has not always been consistent on this
+ score. Due to a bug, versions 1.8.7 to 1.9.8a did entire copy.
+ Versions 1.8.6 and older, and versions 1.9.9 and newer, do change
+ copy.
+
+ For most commercial curses implementations, it is not documented and
+ not known for sure (at least not to the ncurses maintainers) whether
+ they do change copy or entire copy. We know that System V release 3
+ curses has logic in it that looks like an attempt to do change copy,
+ but the surrounding logic and data representations are sufficiently
+ complex, and our knowledge sufficiently indirect, that it's hard to
+ know whether this is reliable. It is not clear what the SVr4
+ documentation and XSI standard intend. The XSI Curses standard barely
+ mentions wnoutrefresh(); the SVr4 documents seem to be describing
+ entire-copy, but it is possible with some effort and straining to read
+ them the other way.
+
+ It might therefore be unwise to rely on either behavior in programs
+ that might have to be linked with other curses implementations.
+ Instead, you can do an explicit touchwin() before the wnoutrefresh()
+ call to guarantee an entire-contents copy anywhere.
+
+ The really clean way to handle this is to use the panels library. If,
+ when you want a screen update, you do update_panels(), it will do all
+ the necessary wnoutrfresh() calls for whatever panel stacking order
+ you have defined. Then you can do one doupdate() and there will be a
+ single burst of physical I/O that will do all your updates.
+
+ Background Erase
+
+ If you have been using a very old versions of ncurses (1.8.7 or older)
+ you may be surprised by the behavior of the erase functions. In older
+ versions, erased areas of a window were filled with a blank modified
+ by the window's current attribute (as set by wattrset(), wattron(),
+ wattroff() and friends).
+
+ In newer versions, this is not so. Instead, the attribute of erased
+ blanks is normal unless and until it is modified by the functions
+ bkgdset() or wbkgdset().
+
+ This change in behavior conforms ncurses to System V Release 4 and the
+ XSI Curses standard.
+
+XSI Curses Conformance
+
+ The ncurses library is intended to be base-level conformant with the
+ XSI Curses standard from X/Open. Many extended-level features (in
+ fact, almost all features not directly concerned with wide characters
+ and internationalization) are also supported.
+
+ One effect of XSI conformance is the change in behavior described
+ under "Background Erase -- Compatibility with Old Versions".
+
+ Also, ncurses meets the XSI requirement that every macro entry point
+ have a corresponding function which may be linked (and will be
+ prototype-checked) if the macro definition is disabled with #undef.
+
+ The Panels Library
+
+ The ncurses 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
+ wnoutrefresh() calls followed by a doupdate(), 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.
+
+ 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.
+
+ The panel library first appeared in AT&T System V. The version
+ documented here is the panel code distributed with ncurses.
+
+Compiling With the Panels Library
+
+ Your panels-using modules must import the panels library declarations
+ with
+ #include <panel.h>
+
+ and must be linked explicitly with the panels library using an -lpanel
+ argument. Note that they must also link the ncurses library with
+ -lncurses. Many linkers are two-pass and will accept either order, but
+ it is still good practice to put -lpanel first and -lncurses second.
+
+Overview of Panels
+
+ A panel object is a window that is implicitly treated as part of a
+ deck including all other panel objects. The deck has an implicit
+ bottom-to-top visibility order. The panels library includes an update
+ function (analogous to refresh()) that displays all panels in the deck
+ in the proper order to resolve overlaps. The standard window, stdscr,
+ is considered below all panels.
+
+ Details on the panels functions are available in the man pages. We'll
+ just hit the highlights here.
+
+ You create a panel from a window by calling new_panel() on a window
+ pointer. It then becomes the top of the deck. The panel's window is
+ available as the value of panel_window() called with the panel pointer
+ as argument.
+
+ You can delete a panel (removing it from the deck) with del_panel.
+ 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 replace_window. 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.
+
+ To move a panel's window, use move_panel(). The mvwin() 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.
+
+ Two functions (top_panel(), bottom_panel()) 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.
+
+ The function update_panels() does all the wnoutrefresh() calls needed
+ to prepare for doupdate() (which you must call yourself, afterwards).
+
+ Typically, you will want to call update_panels() and doupdate() just
+ before accepting command input, once in each cycle of interaction with
+ the user. If you call update_panels() after each and every panel
+ write, you'll generate a lot of unnecessary refresh activity and
+ screen flicker.
+
+Panels, Input, and the Standard Screen
+
+ You shouldn't mix wnoutrefresh() or wrefresh() operations with panels
+ code; this will work only if the argument window is either in the top
+ panel or unobscured by any other panels.
+
+ The stsdcr window is a special case. It is considered below all
+ panels. Because changes to panels may obscure parts of stdscr, though,
+ you should call update_panels() before doupdate() even when you only
+ change stdscr.
+
+ Note that wgetch automatically calls wrefresh. Therefore, before
+ requesting input from a panel window, you need to be sure that the
+ panel is totally unobscured.
+
+ There is presently no way to display changes to one obscured panel
+ without repainting all panels.
+
+Hiding Panels
+
+ It's possible to remove a panel from the deck temporarily; use
+ hide_panel for this. Use show_panel() to render it visible again. The
+ predicate function panel_hidden tests whether or not a panel is
+ hidden.
+
+ The panel_update code ignores hidden panels. You cannot do top_panel()
+ or bottom_panel on a hidden panel(). Other panels operations are
+ applicable.
+
+Miscellaneous Other Facilities
+
+ It's possible to navigate the deck using the functions panel_above()
+ and panel_below. Handed a panel pointer, they return the panel above
+ or below that panel. Handed NULL, they return the bottom-most or
+ top-most panel.
+
+ Every panel has an associated user pointer, not used by the panel
+ code, to which you can attach application data. See the man page
+ documentation of set_panel_userptr() and panel_userptr for details.
+
+ The Menu Library
+
+ A menu is a screen display that assists the user to choose some subset
+ of a given set of items. The menu library is a curses extension that
+ supports easy programming of menu hierarchies with a uniform but
+ flexible interface.
+
+ The menu library first appeared in AT&T System V. The version
+ documented here is the menu code distributed with ncurses.
+
+Compiling With the menu Library
+
+ Your menu-using modules must import the menu library declarations with
+ #include <menu.h>
+
+ and must be linked explicitly with the menus library using an -lmenu
+ argument. Note that they must also link the ncurses library with
+ -lncurses. Many linkers are two-pass and will accept either order, but
+ it is still good practice to put -lmenu first and -lncurses second.
+
+Overview of Menus
+
+ The menus created by this library consist of collections of items
+ 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.
+
+ The menu can then by posted, 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.
+
+ A menu may also be unposted (that is, undisplayed), and finally freed
+ to make the storage associated with it and its items available for
+ re-use.
+
+ The general flow of control of a menu program looks like this:
+ 1. Initialize curses.
+ 2. Create the menu items, using new_item().
+ 3. Create the menu using new_menu().
+ 4. Post the menu using menu_post().
+ 5. Refresh the screen.
+ 6. Process user requests via an input loop.
+ 7. Unpost the menu using menu_unpost().
+ 8. Free the menu, using free_menu().
+ 9. Free the items using free_item().
+ 10. Terminate curses.
+
+Selecting items
+
+ Menus may be multi-valued or (the default) single-valued (see the
+ manual page menu_opts(3x) to see how to change the default). Both
+ types always have a current item.
+
+ 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 item_value()
+ predicate function. Your menu-processing code can use the function
+ set_item_value() to flag the items in the select set.
+
+ Menu items can be made unselectable using set_item_opts() or
+ item_opts_off() with the O_SELECTABLE 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.
+
+Menu Display
+
+ The menu library calculates a minimum display size for your window,
+ based on the following variables:
+ * The number and maximum length of the menu items
+ * Whether the O_ROWMAJOR option is enabled
+ * Whether display of descriptions is enabled
+ * Whatever menu format may have been set by the programmer
+ * The length of the menu mark string used for highlighting selected
+ items
+
+ The function set_menu_format() allows you to set the maximum size of
+ the viewport or menu page that will be used to display menu items. You
+ can retrieve any format associated with a menu with menu_format(). The
+ default format is rows=16, columns=1.
+
+ 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.
+
+ 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.
+
+ You can scroll it with requests to the menu driver, which will be
+ described in the section on menu input handling.
+
+ Each menu has a mark string used to visually tag selected items; see
+ the menu_mark(3x) manual page for details. The mark string length also
+ influences the menu page size.
+
+ The function scale_menu() 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 menu_attribs(3x) manual page.
+
+Menu Windows
+
+ 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.
+
+ 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. The inner window or subwindow is where the
+ current menu page is displayed.
+
+ By default, both windows are stdscr. You can set them with the
+ functions in menu_win(3x).
+
+ When you call menu_post(), you write the menu to its subwindow. When
+ you call menu_unpost(), you erase the subwindow, However, neither of
+ these actually modifies the screen. To do that, call wrefresh() or
+ some equivalent.
+
+Processing Menu Input
+
+ The main loop of your menu-processing code should call menu_driver()
+ 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 menu_driver(). The menu command codes are fully documented
+ in menu_driver(3x).
+
+ The simplest group of command codes is REQ_NEXT_ITEM, REQ_PREV_ITEM,
+ REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_UP_ITEM, REQ_DOWN_ITEM,
+ REQ_LEFT_ITEM, REQ_RIGHT_ITEM. These change the currently selected
+ item. These requests may cause scrolling of the menu page if it only
+ partially displayed.
+
+ 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 REQ_SCR_DLINE, REQ_SCR_ULINE,
+ REQ_SCR_DPAGE, and REQ_SCR_UPAGE.
+
+ The REQ_TOGGLE_ITEM selects or deselects the current item. It is for
+ use in multi-valued menus; if you use it with O_ONEVALUE on, you'll
+ get an error return (E_REQUEST_DENIED).
+
+ Each menu has an associated pattern buffer. The menu_driver() 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 appending a character yields no
+ new match, that character is deleted from the pattern buffer, and
+ menu_driver() returns E_NO_MATCH.
+
+ Some requests change the pattern buffer directly: REQ_CLEAR_PATTERN,
+ REQ_BACK_PATTERN, REQ_NEXT_MATCH, REQ_PREV_MATCH. The latter two are
+ useful when pattern buffer input matches more than one item in a
+ multi-valued menu.
+
+ Each successful scroll or item navigation request clears the pattern
+ buffer. It is also possible to set the pattern buffer explicitly with
+ set_menu_pattern().
+
+ Finally, menu driver requests above the constant MAX_COMMAND are
+ considered application-specific commands. The menu_driver() code
+ ignores them and returns E_UNKNOWN_COMMAND.
+
+Miscellaneous Other Features
+
+ Various menu options can affect the processing and visual appearance
+ and input processing of menus. See menu_opts(3x) for details.
+
+ 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
+ mitem_current(3x). If your application needs to change the menu
+ subwindow cursor for any reason, pos_menu_cursor() will restore it to
+ the correct location for continuing menu driver processing.
+
+ It is possible to set hooks to be called at menu initialization and
+ wrapup time, and whenever the selected item changes. See
+ menu_hook(3x).
+
+ Each item, and each menu, has an associated user pointer on which you
+ can hang application data. See mitem_userptr(3x) and menu_userptr(3x).
+
+ The Forms Library
+
+ The form library is a curses extension that supports easy programming
+ of on-screen forms for data entry and program control.
+
+ The form library first appeared in AT&T System V. The version
+ documented here is the form code distributed with ncurses.
+
+Compiling With the form Library
+
+ Your form-using modules must import the form library declarations with
+ #include <form.h>
+
+ and must be linked explicitly with the forms library using an -lform
+ argument. Note that they must also link the ncurses library with
+ -lncurses. Many linkers are two-pass and will accept either order, but
+ it is still good practice to put -lform first and -lncurses second.
+
+Overview of Forms
+
+ A form is a collection of fields; each field may be either a label
+ (explanatory text) or a data-entry location. Long forms may be
+ segmented into pages; each entry to a new page clears the screen.
+
+ To make forms, you create groups of fields and connect them with form
+ frame objects; the form library makes this relatively simple.
+
+ Once defined, a form can be posted, that is written to an associated
+ window. Actually, each form has two associated windows; a containing
+ window in which the programmer can scribble titles or borders, and a
+ subwindow in which the form fields proper are displayed.
+
+ As the form user fills out the posted form, navigation and editing
+ keys support movement between fields, editing keys support modifying
+ field, and plain text adds to or changes data in a current field. The
+ form library allows you (the forms designer) to bind each navigation
+ and editing key to any keystroke accepted by curses Fields may have
+ validation conditions on them, so that they check input data for type
+ and value. The form library supplies a rich set of pre-defined field
+ types, and makes it relatively easy to define new ones.
+
+ Once its transaction is completed (or aborted), a form may be unposted
+ (that is, undisplayed), and finally freed to make the storage
+ associated with it and its items available for re-use.
+
+ The general flow of control of a form program looks like this:
+ 1. Initialize curses.
+ 2. Create the form fields, using new_field().
+ 3. Create the form using new_form().
+ 4. Post the form using form_post().
+ 5. Refresh the screen.
+ 6. Process user requests via an input loop.
+ 7. Unpost the form using form_unpost().
+ 8. Free the form, using free_form().
+ 9. Free the fields using free_field().
+ 10. Terminate curses.
+
+ Note that this looks much like a menu program; the form library
+ handles tasks which are in many ways similar, and its interface was
+ obviously designed to resemble that of the menu library wherever
+ possible.
+
+ In forms programs, however, the `process user requests' is somewhat
+ more complicated than for menus. Besides menu-like navigation
+ operations, the menu driver loop has to support field editing and data
+ validation.
+
+Creating and Freeing Fields and Forms
+
+ The basic function for creating fields is new_field():
+FIELD *new_field(int height, int width, /* new field size */
+ int top, int left, /* upper left corner */
+ int offscreen, /* number of offscreen rows */
+ int nbuf); /* number of working buffers */
+
+ Menu items always occupy a single row, but forms fields may have
+ multiple rows. So new_field() requires you to specify a width and
+ height (the first two arguments, which mist both be greater than
+ zero).
+
+ You must also specify the location of the field's upper left corner on
+ the screen (the third and fourth arguments, which must be zero or
+ greater). Note that these coordinates are relative to the form
+ subwindow, which will coincide with stdscr by default but need not be
+ stdscr if you've done an explicit set_form_window() call.
+
+ The fifth argument allows you to specify a number of off-screen rows.
+ If this is zero, the entire field will always be displayed. If it is
+ nonzero, the form will be scrollable, with only one screen-full
+ (initially the top part) displayed at any given time. If you make a
+ field dynamic and grow it so it will no longer fit on the screen, the
+ form will become scrollable even if the offscreen argument was
+ initially zero.
+
+ The forms library allocates one working buffer per field; the size of
+ each buffer is ((height + offscreen)*width + 1, one character for each
+ position in the field plus a NUL terminator. The sixth argument is the
+ number of additional data buffers to allocate for the field; your
+ application can use them for its own purposes.
+FIELD *dup_field(FIELD *field, /* field to copy */
+ int top, int left); /* location of new copy */
+
+ The function dup_field() duplicates an existing field at a new
+ location. Size and buffering information are copied; some attribute
+ flags and status bits are not (see the form_field_new(3X) for
+ details).
+FIELD *link_field(FIELD *field, /* field to copy */
+ int top, int left); /* location of new copy */
+
+ The function link_field() also duplicates an existing field at a new
+ location. The difference from dup_field() is that it arranges for the
+ new field's buffer to be shared with the old one.
+
+ Besides the obvious use in making a field editable from two different
+ form pages, linked fields give you a way to hack in dynamic labels. If
+ you declare several fields linked to an original, and then make them
+ inactive, changes from the original will still be propagated to the
+ linked fields.
+
+ As with duplicated fields, linked fields have attribute bits separate
+ from the original.
+
+ As you might guess, all these field-allocations return NULL if the
+ field allocation is not possible due to an out-of-memory error or
+ out-of-bounds arguments.
+
+ To connect fields to a form, use
+FORM *new_form(FIELD **fields);
+
+ This function expects to see a NULL-terminated array of field
+ pointers. Said fields are connected to a newly-allocated form object;
+ its address is returned (or else NULL if the allocation fails).
+
+ Note that new_field() does not copy the pointer array into private
+ storage; if you modify the contents of the pointer array during forms
+ processing, all manner of bizarre things might happen. Also note that
+ any given field may only be connected to one form.
+
+ The functions free_field() and free_form are available to free field
+ and form objects. It is an error to attempt to free a field connected
+ to a form, but not vice-versa; thus, you will generally free your form
+ objects first.
+
+Fetching and Changing Field Attributes
+
+ Each form field has a number of location and size attributes
+ associated with it. There are other field attributes used to control
+ display and editing of the field. Some (for example, the O_STATIC bit)
+ involve sufficient complications to be covered in sections of their
+ own later on. We cover the functions used to get and set several basic
+ attributes here.
+
+ When a field is created, the attributes not specified by the new_field
+ function are copied from an invisible system default field. In
+ attribute-setting and -fetching functions, the argument NULL is taken
+ to mean this field. Changes to it persist as defaults until your forms
+ application terminates.
+
+ Fetching Size and Location Data
+
+ You can retrieve field sizes and locations through:
+int field_info(FIELD *field, /* field from which to fetch */
+ int *height, *int width, /* field size */
+ int *top, int *left, /* upper left corner */
+ int *offscreen, /* number of offscreen rows */
+ int *nbuf); /* number of working buffers */
+
+ This function is a sort of inverse of new_field(); instead of setting
+ size and location attributes of a new field, it fetches them from an
+ existing one.
+
+ Changing the Field Location
+
+ It is possible to move a field's location on the screen:
+int move_field(FIELD *field, /* field to alter */
+ int top, int left); /* new upper-left corner */
+
+ You can, of course. query the current location through field_info().
+
+ The Justification Attribute
+
+ One-line fields may be unjustified, justified right, justified left,
+ or centered. Here is how you manipulate this attribute:
+int set_field_just(FIELD *field, /* field to alter */
+ int justmode); /* mode to set */
+
+int field_just(FIELD *field); /* fetch mode of field */
+
+ The mode values accepted and returned by this functions are
+ preprocessor macros NO_JUSTIFICATION, JUSTIFY_RIGHT, JUSTIFY_LEFT, or
+ JUSTIFY_CENTER.
+
+ Field Display Attributes
+
+ For each field, you can set a foreground attribute for entered
+ characters, a background attribute for the entire field, and a pad
+ character for the unfilled portion of the field. You can also control
+ pagination of the form.
+
+ This group of four field attributes controls the visual appearance of
+ the field on the screen, without affecting in any way the data in the
+ field buffer.
+int set_field_fore(FIELD *field, /* field to alter */
+ chtype attr); /* attribute to set */
+
+chtype field_fore(FIELD *field); /* field to query */
+
+int set_field_back(FIELD *field, /* field to alter */
+ chtype attr); /* attribute to set */
+
+chtype field_back(FIELD *field); /* field to query */
+
+int set_field_pad(FIELD *field, /* field to alter */
+ int pad); /* pad character to set */
+
+chtype field_pad(FIELD *field);
+
+int set_new_page(FIELD *field, /* field to alter */
+ int flag); /* TRUE to force new page */
+
+chtype new_page(FIELD *field); /* field to query */
+
+ The attributes set and returned by the first four functions are normal
+ curses(3x) display attribute values (A_STANDOUT, A_BOLD, A_REVERSE
+ etc). The page bit of a field controls whether it is displayed at the
+ start of a new form screen.
+
+ Field Option Bits
+
+ There is also a large collection of field option bits you can set to
+ control various aspects of forms processing. You can manipulate them
+ with these functions:
+int set_field_opts(FIELD *field, /* field to alter */
+ int attr); /* attribute to set */
+
+int field_opts_on(FIELD *field, /* field to alter */
+ int attr); /* attributes to turn on */
+
+int field_opts_off(FIELD *field, /* field to alter */
+ int attr); /* attributes to turn off */
+
+int field_opts(FIELD *field); /* field to query */
+
+ By default, all options are on. Here are the available option bits:
+
+ O_VISIBLE
+ Controls whether the field is visible on the screen. Can be
+ used during form processing to hide or pop up fields depending
+ on the value of parent fields.
+
+ O_ACTIVE
+ Controls whether the field is active during forms processing
+ (i.e. visited by form navigation keys). Can be used to make
+ labels or derived fields with buffer values alterable by the
+ forms application, not the user.
+
+ O_PUBLIC
+ Controls whether data is displayed during field entry. If this
+ option is turned off on a field, the library will accept and
+ edit data in that field, but it will not be displayed and the
+ visible field cursor will not move. You can turn off the
+ O_PUBLIC bit to define password fields.
+
+ O_EDIT
+ Controls whether the field's data can be modified. When this
+ option is off, all editing requests except REQ_PREV_CHOICE and
+ REQ_NEXT_CHOICE will fail. Such read-only fields may be useful
+ for help messages.
+
+ O_WRAP
+ Controls word-wrapping in multi-line fields. Normally, when any
+ character of a (blank-separated) word reaches the end of the
+ current line, the entire word is wrapped to the next line
+ (assuming there is one). When this option is off, the word will
+ be split across the line break.
+
+ O_BLANK
+ Controls field blanking. When this option is on, entering a
+ character at the first field position erases the entire field
+ (except for the just-entered character).
+
+ O_AUTOSKIP
+ Controls automatic skip to next field when this one fills.
+ Normally, when the forms user tries to type more data into a
+ field than will fit, the editing location jumps to next field.
+ When this option is off, the user's cursor will hang at the end
+ of the field. This option is ignored in dynamic fields that
+ have not reached their size limit.
+
+ O_NULLOK
+ Controls whether validation is applied to blank fields.
+ Normally, it is not; the user can leave a field blank without
+ invoking the usual validation check on exit. If this option is
+ off on a field, exit from it will invoke a validation check.
+
+ O_PASSOK
+ Controls whether validation occurs on every exit, or only after
+ the field is modified. Normally the latter is true. Setting
+ O_PASSOK may be useful if your field's validation function may
+ change during forms processing.
+
+ O_STATIC
+ Controls whether the field is fixed to its initial dimensions.
+ If you turn this off, the field becomes dynamic and will
+ stretch to fit entered data.
+
+ A field's options cannot be changed while the field is currently
+ selected. However, options may be changed on posted fields that are
+ not current.
+
+ The option values are bit-masks and can be composed with logical-or in
+ the obvious way.
+
+Field Status
+
+ Every field has a status flag, which is set to FALSE when the field is
+ created and TRUE when the value in field buffer 0 changes. This flag
+ can be queried and set directly:
+int set_field_status(FIELD *field, /* field to alter */
+ int status); /* mode to set */
+
+int field_status(FIELD *field); /* fetch mode of field */
+
+ Setting this flag under program control can be useful if you use the
+ same form repeatedly, looking for modified fields each time.
+
+ Calling field_status() on a field not currently selected for input
+ will return a correct value. Calling field_status() on a field that is
+ currently selected for input may not necessarily give a correct field
+ status value, because entered data isn't necessarily copied to buffer
+ zero before the exit validation check. To guarantee that the returned
+ status value reflects reality, call field_status() either (1) in the
+ field's exit validation check routine, (2) from the field's or form's
+ initialization or termination hooks, or (3) just after a
+ REQ_VALIDATION request has been processed by the forms driver.
+
+Field User Pointer
+
+ Each field structure contains one character pointer slot that is not
+ used by the forms library. It is intended to be used by applications
+ to store private per-field data. You can manipulate it with:
+int set_field_userptr(FIELD *field, /* field to alter */
+ char *userptr); /* mode to set */
+
+char *field_userptr(FIELD *field); /* fetch mode of field */
+
+ (Properly, this user pointer field ought to have (void *) type. The
+ (char *) type is retained for System V compatibility.)
+
+ It is valid to set the user pointer of the default field (with a
+ set_field_userptr() call passed a NULL field pointer.) When a new
+ field is created, the default-field user pointer is copied to
+ initialize the new field's user pointer.
+
+Variable-Sized Fields
+
+ Normally, a field is fixed at the size specified for it at creation
+ time. If, however, you turn off its O_STATIC bit, it becomes dynamic
+ and will automatically resize itself to accommodate data as it is
+ entered. If the field has extra buffers associated with it, they will
+ grow right along with the main input buffer.
+
+ A one-line dynamic field will have a fixed height (1) but variable
+ width, scrolling horizontally to display data within the field area as
+ originally dimensioned and located. A multi-line dynamic field will
+ have a fixed width, but variable height (number of rows), scrolling
+ vertically to display data within the field area as originally
+ dimensioned and located.
+
+ Normally, a dynamic field is allowed to grow without limit. But it is
+ possible to set an upper limit on the size of a dynamic field. You do
+ it with this function:
+int set_max_field(FIELD *field, /* field to alter (may not be NULL) */
+ int max_size); /* upper limit on field size */
+
+ If the field is one-line, max_size is taken to be a column size limit;
+ if it is multi-line, it is taken to be a line size limit. To disable
+ any limit, use an argument of zero. The growth limit can be changed
+ whether or not the O_STATIC bit is on, but has no effect until it is.
+
+ The following properties of a field change when it becomes dynamic:
+ * If there is no growth limit, there is no final position of the
+ field; therefore O_AUTOSKIP and O_NL_OVERLOAD are ignored.
+ * Field justification will be ignored (though whatever justification
+ is set up will be retained internally and can be queried).
+ * The dup_field() and link_field() calls copy dynamic-buffer sizes.
+ If the O_STATIC option is set on one of a collection of links,
+ buffer resizing will occur only when the field is edited through
+ that link.
+ * The call field_info() will retrieve the original static size of
+ the field; use dynamic_field_info() to get the actual dynamic
+ size.
+
+Field Validation
+
+ By default, a field will accept any data that will fit in its input
+ buffer. However, it is possible to attach a validation type to a
+ field. If you do this, any attempt to leave the field while it
+ contains data that doesn't match the validation type will fail. Some
+ validation types also have a character-validity check for each time a
+ character is entered in the field.
+
+ A field's validation check (if any) is not called when
+ set_field_buffer() modifies the input buffer, nor when that buffer is
+ changed through a linked field.
+
+ The form library provides a rich set of pre-defined validation types,
+ and gives you the capability to define custom ones of your own. You
+ can examine and change field validation attributes with the following
+ functions:
+int set_field_type(FIELD *field, /* field to alter */
+ FIELDTYPE *ftype, /* type to associate */
+ ...); /* additional arguments*/
+
+FIELDTYPE *field_type(FIELD *field); /* field to query */
+
+ The validation type of a field is considered an attribute of the
+ field. As with other field attributes, Also, doing set_field_type()
+ with a NULL field default will change the system default for
+ validation of newly-created fields.
+
+ Here are the pre-defined validation types:
+
+ TYPE_ALPHA
+
+ This field type accepts alphabetic data; no blanks, no digits, no
+ special characters (this is checked at character-entry time). It is
+ set up with:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_ALPHA, /* type to associate */
+ int width); /* maximum width of field */
+
+ The width argument sets a minimum width of data. Typically you'll want
+ to set this to the field width; if it's greater than the field width,
+ the validation check will always fail. A minimum width of zero makes
+ field completion optional.
+
+ TYPE_ALNUM
+
+ This field type accepts alphabetic data and digits; no blanks, no
+ special characters (this is checked at character-entry time). It is
+ set up with:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_ALNUM, /* type to associate */
+ int width); /* maximum width of field */
+
+ The width argument sets a minimum width of data. As with TYPE_ALPHA,
+ typically you'll want to set this to the field width; if it's greater
+ than the field width, the validation check will always fail. A minimum
+ width of zero makes field completion optional.
+
+ TYPE_ENUM
+
+ This type allows you to restrict a field's values to be among a
+ specified set of string values (for example, the two-letter postal
+ codes for U.S. states). It is set up with:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_ENUM, /* type to associate */
+ char **valuelist; /* list of possible values */
+ int checkcase; /* case-sensitive? */
+ int checkunique); /* must specify uniquely? */
+
+ The valuelist parameter must point at a NULL-terminated list of valid
+ strings. The checkcase argument, if true, makes comparison with the
+ string case-sensitive.
+
+ When the user exits a TYPE_ENUM field, the validation procedure tries
+ to complete the data in the buffer to a valid entry. If a complete
+ choice string has been entered, it is of course valid. But it is also
+ possible to enter a prefix of a valid string and have it completed for
+ you.
+
+ By default, if you enter such a prefix and it matches more than one
+ value in the string list, the prefix will be completed to the first
+ matching value. But the checkunique argument, if true, requires prefix
+ matches to be unique in order to be valid.
+
+ The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests can be
+ particularly useful with these fields.
+
+ TYPE_INTEGER
+
+ This field type accepts an integer. It is set up as follows:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_INTEGER, /* type to associate */
+ int padding, /* # places to zero-pad to */
+ int vmin, int vmax); /* valid range */
+
+ Valid characters consist of an optional leading minus and digits. The
+ range check is performed on exit. If the range maximum is less than or
+ equal to the minimum, the range is ignored.
+
+ If the value passes its range check, it is padded with as many leading
+ zero digits as necessary to meet the padding argument.
+
+ A TYPE_INTEGER value buffer can conveniently be interpreted with the C
+ library function atoi(3).
+
+ TYPE_NUMERIC
+
+ This field type accepts a decimal number. It is set up as follows:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_NUMERIC, /* type to associate */
+ int padding, /* # places of precision */
+ double vmin, double vmax); /* valid range */
+
+ Valid characters consist of an optional leading minus and digits.
+ possibly including a decimal point. If your system supports locale's,
+ the decimal point character used must be the one defined by your
+ locale. The range check is performed on exit. If the range maximum is
+ less than or equal to the minimum, the range is ignored.
+
+ If the value passes its range check, it is padded with as many
+ trailing zero digits as necessary to meet the padding argument.
+
+ A TYPE_NUMERIC value buffer can conveniently be interpreted with the C
+ library function atof(3).
+
+ TYPE_REGEXP
+
+ This field type accepts data matching a regular expression. It is set
+ up as follows:
+int set_field_type(FIELD *field, /* field to alter */
+ TYPE_REGEXP, /* type to associate */
+ char *regexp); /* expression to match */
+
+ The syntax for regular expressions is that of regcomp(3). The check
+ for regular-expression match is performed on exit.
+
+Direct Field Buffer Manipulation
+
+ The chief attribute of a field is its buffer contents. When a form has
+ been completed, your application usually needs to know the state of
+ each field buffer. You can find this out with:
+char *field_buffer(FIELD *field, /* field to query */
+ int bufindex); /* number of buffer to query */
+
+ Normally, the state of the zero-numbered buffer for each field is set
+ by the user's editing actions on that field. It's sometimes useful to
+ be able to set the value of the zero-numbered (or some other) buffer
+ from your application:
+int set_field_buffer(FIELD *field, /* field to alter */
+ int bufindex, /* number of buffer to alter */
+ char *value); /* string value to set */
+
+ If the field is not large enough and cannot be resized to a
+ sufficiently large size to contain the specified value, the value will
+ be truncated to fit.
+
+ Calling field_buffer() with a null field pointer will raise an error.
+ Calling field_buffer() on a field not currently selected for input
+ will return a correct value. Calling field_buffer() on a field that is
+ currently selected for input may not necessarily give a correct field
+ buffer value, because entered data isn't necessarily copied to buffer
+ zero before the exit validation check. To guarantee that the returned
+ buffer value reflects on-screen reality, call field_buffer() either
+ (1) in the field's exit validation check routine, (2) from the field's
+ or form's initialization or termination hooks, or (3) just after a
+ REQ_VALIDATION request has been processed by the forms driver.
+
+Attributes of Forms
+
+ As with field attributes, form attributes inherit a default from a
+ system default form structure. These defaults can be queried or set by
+ of these functions using a form-pointer argument of NULL.
+
+ The principal attribute of a form is its field list. You can query and
+ change this list with:
+int set_form_fields(FORM *form, /* form to alter */
+ FIELD **fields); /* fields to connect */
+
+char *form_fields(FORM *form); /* fetch fields of form */
+
+int field_count(FORM *form); /* count connect fields */
+
+ The second argument of set_form_fields() may be a NULL-terminated
+ field pointer array like the one required by new_form(). In that case,
+ the old fields of the form are disconnected but not freed (and
+ eligible to be connected to other forms), then the new fields are
+ connected.
+
+ It may also be null, in which case the old fields are disconnected
+ (and not freed) but no new ones are connected.
+
+ The field_count() function simply counts the number of fields
+ connected to a given from. It returns -1 if the form-pointer argument
+ is NULL.
+
+Control of Form Display
+
+ In the overview section, you saw that to display a form you normally
+ start by defining its size (and fields), posting it, and refreshing
+ the screen. There is an hidden step before posting, which is the
+ association of the form with a frame window (actually, a pair of
+ windows) within which it will be displayed. By default, the forms
+ library associates every form with the full-screen window stdscr.
+
+ By making this step explicit, you can associate a form with a declared
+ frame window on your screen display. This can be useful if you want to
+ adapt the form display to different screen sizes, dynamically tile
+ forms on the screen, or use a form as part of an interface layout
+ managed by panels.
+
+ The two windows associated with each form have the same functions as
+ their analogues in the menu library. Both these windows are painted
+ when the form is posted and erased when the form is unposted.
+
+ The outer or frame window is not otherwise touched by the form
+ routines. It exists so the programmer can associate a title, a border,
+ or perhaps help text with the form and have it properly refreshed or
+ erased at post/unpost time. The inner window or subwindow is where the
+ current form page is actually displayed.
+
+ In order to declare your own frame window for a form, you'll need to
+ know the size of the form's bounding rectangle. You can get this
+ information with:
+int scale_form(FORM *form, /* form to query */
+ int *rows, /* form rows */
+ int *cols); /* form cols */
+
+ The form dimensions are passed back in the locations pointed to by the
+ arguments. Once you have this information, you can use it to declare
+ of windows, then use one of these functions:
+int set_form_win(FORM *form, /* form to alter */
+ WINDOW *win); /* frame window to connect */
+
+WINDOW *form_win(FORM *form); /* fetch frame window of form */
+
+int set_form_sub(FORM *form, /* form to alter */
+ WINDOW *win); /* form subwindow to connect */
+
+WINDOW *form_sub(FORM *form); /* fetch form subwindow of form */
+
+ Note that curses operations, including refresh(), on the form, should
+ be done on the frame window, not the form subwindow.
+
+ It is possible to check from your application whether all of a
+ scrollable field is actually displayed within the menu subwindow. Use
+ these functions:
+int data_ahead(FORM *form); /* form to be queried */
+
+int data_behind(FORM *form); /* form to be queried */
+
+ The function data_ahead() returns TRUE if (a) the current field is
+ one-line and has undisplayed data off to the right, (b) the current
+ field is multi-line and there is data off-screen below it.
+
+ The function data_behind() returns TRUE if the first (upper left hand)
+ character position is off-screen (not being displayed).
+
+ Finally, there is a function to restore the form window's cursor to
+ the value expected by the forms driver:
+int pos_form_cursor(FORM *) /* form to be queried */
+
+ If your application changes the form window cursor, call this function
+ before handing control back to the forms driver in order to
+ re-synchronize it.
+
+Input Processing in the Forms Driver
+
+ The function form_driver() handles virtualized input requests for form
+ navigation, editing, and validation requests, just as menu_driver does
+ for menus (see the section on menu input handling).
+int form_driver(FORM *form, /* form to pass input to */
+ int request); /* form request code */
+
+ Your input virtualization function needs to take input and then
+ convert it to either an alphanumeric character (which is treated as
+ data to be entered in the currently-selected field), or a forms
+ processing request.
+
+ The forms driver provides hooks (through input-validation and
+ field-termination functions) with which your application code can
+ check that the input taken by the driver matched what was expected.
+
+ Page Navigation Requests
+
+ These requests cause page-level moves through the form, triggering
+ display of a new form screen.
+
+ REQ_NEXT_PAGE
+ Move to the next form page.
+
+ REQ_PREV_PAGE
+ Move to the previous form page.
+
+ REQ_FIRST_PAGE
+ Move to the first form page.
+
+ REQ_LAST_PAGE
+ Move to the last form page.
+
+ These requests treat the list as cyclic; that is, REQ_NEXT_PAGE from
+ the last page goes to the first, and REQ_PREV_PAGE from the first page
+ goes to the last.
+
+ Inter-Field Navigation Requests
+
+ These requests handle navigation between fields on the same page.
+
+ REQ_NEXT_FIELD
+ Move to next field.
+
+ REQ_PREV_FIELD
+ Move to previous field.
+
+ REQ_FIRST_FIELD
+ Move to the first field.
+
+ REQ_LAST_FIELD
+ Move to the last field.
+
+ REQ_SNEXT_FIELD
+ Move to sorted next field.
+
+ REQ_SPREV_FIELD
+ Move to sorted previous field.
+
+ REQ_SFIRST_FIELD
+ Move to the sorted first field.
+
+ REQ_SLAST_FIELD
+ Move to the sorted last field.
+
+ REQ_LEFT_FIELD
+ Move left to field.
+
+ REQ_RIGHT_FIELD
+ Move right to field.
+
+ REQ_UP_FIELD
+ Move up to field.
+
+ REQ_DOWN_FIELD
+ Move down to field.
+
+ These requests treat the list of fields on a page as cyclic; that is,
+ REQ_NEXT_FIELD from the last field goes to the first, and
+ REQ_PREV_FIELD from the first field goes to the last. The order of the
+ fields for these (and the REQ_FIRST_FIELD and REQ_LAST_FIELD requests)
+ is simply the order of the field pointers in the form array (as set up
+ by new_form() or set_form_fields()
+
+ It is also possible to traverse the fields as if they had been sorted
+ in screen-position order, so the sequence goes left-to-right and
+ top-to-bottom. To do this, use the second group of four
+ sorted-movement requests.
+
+ Finally, it is possible to move between fields using visual directions
+ up, down, right, and left. To accomplish this, use the third group of
+ four requests. Note, however, that the position of a form for purposes
+ of these requests is its upper-left corner.
+
+ For example, suppose you have a multi-line field B, and two
+ single-line fields A and C on the same line with B, with A to the left
+ of B and C to the right of B. A REQ_MOVE_RIGHT from A will go to B
+ only if A, B, and C all share the same first line; otherwise it will
+ skip over B to C.
+
+ Intra-Field Navigation Requests
+
+ These requests drive movement of the edit cursor within the currently
+ selected field.
+
+ REQ_NEXT_CHAR
+ Move to next character.
+
+ REQ_PREV_CHAR
+ Move to previous character.
+
+ REQ_NEXT_LINE
+ Move to next line.
+
+ REQ_PREV_LINE
+ Move to previous line.
+
+ REQ_NEXT_WORD
+ Move to next word.
+
+ REQ_PREV_WORD
+ Move to previous word.
+
+ REQ_BEG_FIELD
+ Move to beginning of field.
+
+ REQ_END_FIELD
+ Move to end of field.
+
+ REQ_BEG_LINE
+ Move to beginning of line.
+
+ REQ_END_LINE
+ Move to end of line.
+
+ REQ_LEFT_CHAR
+ Move left in field.
+
+ REQ_RIGHT_CHAR
+ Move right in field.
+
+ REQ_UP_CHAR
+ Move up in field.
+
+ REQ_DOWN_CHAR
+ Move down in field.
+
+ Each word is separated from the previous and next characters by
+ whitespace. The commands to move to beginning and end of line or field
+ look for the first or last non-pad character in their ranges.
+
+ Scrolling Requests
+
+ Fields that are dynamic and have grown and fields explicitly created
+ with offscreen rows are scrollable. One-line fields scroll
+ horizontally; multi-line fields scroll vertically. Most scrolling is
+ triggered by editing and intra-field movement (the library scrolls the
+ field to keep the cursor visible). It is possible to explicitly
+ request scrolling with the following requests:
+
+ REQ_SCR_FLINE
+ Scroll vertically forward a line.
+
+ REQ_SCR_BLINE
+ Scroll vertically backward a line.
+
+ REQ_SCR_FPAGE
+ Scroll vertically forward a page.
+
+ REQ_SCR_BPAGE
+ Scroll vertically backward a page.
+
+ REQ_SCR_FHPAGE
+ Scroll vertically forward half a page.
+
+ REQ_SCR_BHPAGE
+ Scroll vertically backward half a page.
+
+ REQ_SCR_FCHAR
+ Scroll horizontally forward a character.
+
+ REQ_SCR_BCHAR
+ Scroll horizontally backward a character.
+
+ REQ_SCR_HFLINE
+ Scroll horizontally one field width forward.
+
+ REQ_SCR_HBLINE
+ Scroll horizontally one field width backward.
+
+ REQ_SCR_HFHALF
+ Scroll horizontally one half field width forward.
+
+ REQ_SCR_HBHALF
+ Scroll horizontally one half field width backward.
+
+ For scrolling purposes, a page of a field is the height of its visible
+ part.
+
+ Editing Requests
+
+ When you pass the forms driver an ASCII character, it is treated as a
+ request to add the character to the field's data buffer. Whether this
+ is an insertion or a replacement depends on the field's edit mode
+ (insertion is the default.
+
+ The following requests support editing the field and changing the edit
+ mode:
+
+ REQ_INS_MODE
+ Set insertion mode.
+
+ REQ_OVL_MODE
+ Set overlay mode.
+
+ REQ_NEW_LINE
+ New line request (see below for explanation).
+
+ REQ_INS_CHAR
+ Insert space at character location.
+
+ REQ_INS_LINE
+ Insert blank line at character location.
+
+ REQ_DEL_CHAR
+ Delete character at cursor.
+
+ REQ_DEL_PREV
+ Delete previous word at cursor.
+
+ REQ_DEL_LINE
+ Delete line at cursor.
+
+ REQ_DEL_WORD
+ Delete word at cursor.
+
+ REQ_CLR_EOL
+ Clear to end of line.
+
+ REQ_CLR_EOF
+ Clear to end of field.
+
+ REQ_CLEAR_FIELD
+ Clear entire field.
+
+ The behavior of the REQ_NEW_LINE and REQ_DEL_PREV requests is
+ complicated and partly controlled by a pair of forms options. The
+ special cases are triggered when the cursor is at the beginning of a
+ field, or on the last line of the field.
+
+ First, we consider REQ_NEW_LINE:
+
+ The normal behavior of REQ_NEW_LINE in insert mode is to break the
+ current line at the position of the edit cursor, inserting the portion
+ of the current line after the cursor as a new line following the
+ current and moving the cursor to the beginning of that new line (you
+ may think of this as inserting a newline in the field buffer).
+
+ The normal behavior of REQ_NEW_LINE in overlay mode is to clear the
+ current line from the position of the edit cursor to end of line. The
+ cursor is then moved to the beginning of the next line.
+
+ However, REQ_NEW_LINE at the beginning of a field, or on the last line
+ of a field, instead does a REQ_NEXT_FIELD. O_NL_OVERLOAD option is
+ off, this special action is disabled.
+
+ Now, let us consider REQ_DEL_PREV:
+
+ The normal behavior of REQ_DEL_PREV is to delete the previous
+ character. If insert mode is on, and the cursor is at the start of a
+ line, and the text on that line will fit on the previous one, it
+ instead appends the contents of the current line to the previous one
+ and deletes the current line (you may think of this as deleting a
+ newline from the field buffer).
+
+ However, REQ_DEL_PREV at the beginning of a field is instead treated
+ as a REQ_PREV_FIELD.
+
+ If the O_BS_OVERLOAD option is off, this special action is disabled
+ and the forms driver just returns E_REQUEST_DENIED.
+
+ See Form Options for discussion of how to set and clear the overload
+ options.
+
+ Order Requests
+
+ If the type of your field is ordered, and has associated functions for
+ getting the next and previous values of the type from a given value,
+ there are requests that can fetch that value into the field buffer:
+
+ REQ_NEXT_CHOICE
+ Place the successor value of the current value in the buffer.
+
+ REQ_PREV_CHOICE
+ Place the predecessor value of the current value in the buffer.
+
+ Of the built-in field types, only TYPE_ENUM has built-in successor and
+ predecessor functions. When you define a field type of your own (see
+ Custom Validation Types), you can associate our own ordering
+ functions.
+
+ Application Commands
+
+ Form requests are represented as integers above the curses value
+ greater than KEY_MAX and less than or equal to the constant
+ MAX_COMMAND. If your input-virtualization routine returns a value
+ above MAX_COMMAND, the forms driver will ignore it.
+
+Field Change Hooks
+
+ It is possible to set function hooks to be executed whenever the
+ current field or form changes. Here are the functions that support
+ this:
+typedef void (*HOOK)(); /* pointer to function returning void */
+
+int set_form_init(FORM *form, /* form to alter */
+ HOOK hook); /* initialization hook */
+
+HOOK form_init(FORM *form); /* form to query */
+
+int set_form_term(FORM *form, /* form to alter */
+ HOOK hook); /* termination hook */
+
+HOOK form_term(FORM *form); /* form to query */
+
+int set_field_init(FORM *form, /* form to alter */
+ HOOK hook); /* initialization hook */
+
+HOOK field_init(FORM *form); /* form to query */
+
+int set_field_term(FORM *form, /* form to alter */
+ HOOK hook); /* termination hook */
+
+HOOK field_term(FORM *form); /* form to query */
+
+ These functions allow you to either set or query four different hooks.
+ In each of the set functions, the second argument should be the
+ address of a hook function. These functions differ only in the timing
+ of the hook call.
+
+ form_init
+ This hook is called when the form is posted; also, just after
+ each page change operation.
+
+ field_init
+ This hook is called when the form is posted; also, just after
+ each field change
+
+ field_term
+ This hook is called just after field validation; that is, just
+ before the field is altered. It is also called when the form is
+ unposted.
+
+ form_term
+ This hook is called when the form is unposted; also, just
+ before each page change operation.
+
+ Calls to these hooks may be triggered
+ 1. When user editing requests are processed by the forms driver
+ 2. When the current page is changed by set_current_field() call
+ 3. When the current field is changed by a set_form_page() call
+
+ See Field Change Commands for discussion of the latter two cases.
+
+ You can set a default hook for all fields by passing one of the set
+ functions a NULL first argument.
+
+ You can disable any of these hooks by (re)setting them to NULL, the
+ default value.
+
+Field Change Commands
+
+ Normally, navigation through the form will be driven by the user's
+ input requests. But sometimes it is useful to be able to move the
+ focus for editing and viewing under control of your application, or
+ ask which field it currently is in. The following functions help you
+ accomplish this:
+int set_current_field(FORM *form, /* form to alter */
+ FIELD *field); /* field to shift to */
+
+FIELD *current_field(FORM *form); /* form to query */
+
+int field_index(FORM *form, /* form to query */
+ FIELD *field); /* field to get index of */
+
+ The function field_index() returns the index of the given field in the
+ given form's field array (the array passed to new_form() or
+ set_form_fields()).
+
+ The initial current field of a form is the first active field on the
+ first page. The function set_form_fields() resets this.
+
+ It is also possible to move around by pages.
+int set_form_page(FORM *form, /* form to alter */
+ int page); /* page to go to (0-origin) */
+
+int form_page(FORM *form); /* return form's current page */
+
+ The initial page of a newly-created form is 0. The function
+ set_form_fields() resets this.
+
+Form Options
+
+ Like fields, forms may have control option bits. They can be changed
+ or queried with these functions:
+int set_form_opts(FORM *form, /* form to alter */
+ int attr); /* attribute to set */
+
+int form_opts_on(FORM *form, /* form to alter */
+ int attr); /* attributes to turn on */
+
+int form_opts_off(FORM *form, /* form to alter */
+ int attr); /* attributes to turn off */
+
+int form_opts(FORM *form); /* form to query */
+
+ By default, all options are on. Here are the available option bits:
+
+ O_NL_OVERLOAD
+ Enable overloading of REQ_NEW_LINE as described in Editing
+ Requests. The value of this option is ignored on dynamic fields
+ that have not reached their size limit; these have no last
+ line, so the circumstances for triggering a REQ_NEXT_FIELD
+ never arise.
+
+ O_BS_OVERLOAD
+ Enable overloading of REQ_DEL_PREV as described in Editing
+ Requests.
+
+ The option values are bit-masks and can be composed with logical-or in
+ the obvious way.
+
+Custom Validation Types
+
+ The form library gives you the capability to define custom validation
+ types of your own. Further, the optional additional arguments of
+ set_field_type effectively allow you to parameterize validation types.
+ Most of the complications in the validation-type interface have to do
+ with the handling of the additional arguments within custom validation
+ functions.
+
+ Union Types
+
+ The simplest way to create a custom data type is to compose it from
+ two preexisting ones:
+FIELD *link_fieldtype(FIELDTYPE *type1,
+ FIELDTYPE *type2);
+
+ This function creates a field type that will accept any of the values
+ legal for either of its argument field types (which may be either
+ predefined or programmer-defined). If a set_field_type() call later
+ requires arguments, the new composite type expects all arguments for
+ the first type, than all arguments for the second. Order functions
+ (see Order Requests) associated with the component types will work on
+ the composite; what it does is check the validation function for the
+ first type, then for the second, to figure what type the buffer
+ contents should be treated as.
+
+ New Field Types
+
+ To create a field type from scratch, you need to specify one or both
+ of the following things:
+ * A character-validation function, to check each character as it is
+ entered.
+ * A field-validation function to be applied on exit from the field.
+
+ Here's how you do that:
+typedef int (*HOOK)(); /* pointer to function returning int */
+
+FIELDTYPE *new_fieldtype(HOOK f_validate, /* field validator */
+ HOOK c_validate) /* character validator */
+
+
+int free_fieldtype(FIELDTYPE *ftype); /* type to free */
+
+ At least one of the arguments of new_fieldtype() must be non-NULL. The
+ forms driver will automatically call the new type's validation
+ functions at appropriate points in processing a field of the new type.
+
+ The function free_fieldtype() deallocates the argument fieldtype,
+ freeing all storage associated with it.
+
+ Normally, a field validator is called when the user attempts to leave
+ the field. Its first argument is a field pointer, from which it can
+ get to field buffer 0 and test it. If the function returns TRUE, the
+ operation succeeds; if it returns FALSE, the edit cursor stays in the
+ field.
+
+ A character validator gets the character passed in as a first
+ argument. It too should return TRUE if the character is valid, FALSE
+ otherwise.
+
+ Validation Function Arguments
+
+ Your field- and character- validation functions will be passed a
+ second argument as well. This second argument is the address of a
+ structure (which we'll call a pile) built from any of the
+ field-type-specific arguments passed to set_field_type(). If no such
+ arguments are defined for the field type, this pile pointer argument
+ will be NULL.
+
+ In order to arrange for such arguments to be passed to your validation
+ functions, you must associate a small set of storage-management
+ functions with the type. The forms driver will use these to synthesize
+ a pile from the trailing arguments of each set_field_type() argument,
+ and a pointer to the pile will be passed to the validation functions.
+
+ Here is how you make the association:
+typedef char *(*PTRHOOK)(); /* pointer to function returning (char *) */
+typedef void (*VOIDHOOK)(); /* pointer to function returning void */
+
+int set_fieldtype_arg(FIELDTYPE *type, /* type to alter */
+ PTRHOOK make_str, /* make structure from args */
+ PTRHOOK copy_str, /* make copy of structure */
+ VOIDHOOK free_str); /* free structure storage */
+
+ Here is how the storage-management hooks are used:
+
+ make_str
+ This function is called by set_field_type(). It gets one
+ argument, a va_list of the type-specific arguments passed to
+ set_field_type(). It is expected to return a pile pointer to a
+ data structure that encapsulates those arguments.
+
+ copy_str
+ This function is called by form library functions that allocate
+ new field instances. It is expected to take a pile pointer,
+ copy the pile to allocated storage, and return the address of
+ the pile copy.
+
+ free_str
+ This function is called by field- and type-deallocation
+ routines in the library. It takes a pile pointer argument, and
+ is expected to free the storage of that pile.
+
+ The make_str and copy_str functions may return NULL to signal
+ allocation failure. The library routines will that call them will
+ return error indication when this happens. Thus, your validation
+ functions should never see a NULL file pointer and need not check
+ specially for it.
+
+ Order Functions For Custom Types
+
+ Some custom field types are simply ordered in the same well-defined
+ way that TYPE_ENUM is. For such types, it is possible to define
+ successor and predecessor functions to support the REQ_NEXT_CHOICE and
+ REQ_PREV_CHOICE requests. Here's how:
+typedef int (*INTHOOK)(); /* pointer to function returning int */
+
+int set_fieldtype_arg(FIELDTYPE *type, /* type to alter */
+ INTHOOK succ, /* get successor value */
+ INTHOOK pred); /* get predecessor value */
+
+ The successor and predecessor arguments will each be passed two
+ arguments; a field pointer, and a pile pointer (as for the validation
+ functions). They are expected to use the function field_buffer() to
+ read the current value, and set_field_buffer() on buffer 0 to set the
+ next or previous value. Either hook may return TRUE to indicate
+ success (a legal next or previous value was set) or FALSE to indicate
+ failure.
+
+ Avoiding Problems
+
+ The interface for defining custom types is complicated and tricky.
+ Rather than attempting to create a custom type entirely from scratch,
+ you should start by studying the library source code for whichever of
+ the pre-defined types seems to be closest to what you want.
+
+ Use that code as a model, and evolve it towards what you really want.
+ You will avoid many problems and annoyances that way. The code in the
+ ncurses library has been specifically exempted from the package
+ copyright to support this.
+
+ If your custom type defines order functions, have do something
+ intuitive with a blank field. A useful convention is to make the
+ successor of a blank field the types minimum value, and its
+ predecessor the maximum.
OpenPOWER on IntegriCloud