diff options
author | Peter Wemm <peter@FreeBSD.org> | 2001-05-17 08:21:06 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2001-05-17 08:21:06 +0000 |
commit | 7a69bbfb278952228c9aa1eca241e65fcdef425e (patch) | |
tree | e83b2ef47811e687a6c54035c9af6d4a2b7f14e1 /contrib/ncurses/doc | |
parent | 18259542b2f8fa7e3f76f4bb0dd37995dfd424aa (diff) | |
download | src-7a69bbfb278952228c9aa1eca241e65fcdef425e.tar.gz src-7a69bbfb278952228c9aa1eca241e65fcdef425e.zip |
Import ncurses-5.2-20010512 onto the vendor branch
Obtained from: ftp://dickey.his.com/ncurses/
Notes
Notes:
svn path=/vendor/ncurses/dist/; revision=76726
Diffstat (limited to 'contrib/ncurses/doc')
-rw-r--r-- | contrib/ncurses/doc/hackguide.doc | 687 | ||||
-rw-r--r-- | contrib/ncurses/doc/html/announce.html | 397 | ||||
-rw-r--r-- | contrib/ncurses/doc/ncurses-intro.doc | 2502 |
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 000000000000..e9828d2919fa --- /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 e7a79d6c899d..3005e49d5889 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 --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 --enable-tcap-names) are active, then <code>tic -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 --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 -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 reset</code> or <code>tput 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 <string.h> 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 000000000000..669b0b391705 --- /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. |