ncurses-intro.html revision 166124
162449Speter<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> 262449Speter<!-- 3166124Srafan $Id: ncurses-intro.html,v 1.41 2005/12/24 15:47:05 tom Exp $ 4166124Srafan **************************************************************************** 5166124Srafan * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * 6166124Srafan * * 7166124Srafan * Permission is hereby granted, free of charge, to any person obtaining a * 8166124Srafan * copy of this software and associated documentation files (the * 9166124Srafan * "Software"), to deal in the Software without restriction, including * 10166124Srafan * without limitation the rights to use, copy, modify, merge, publish, * 11166124Srafan * distribute, distribute with modifications, sublicense, and/or sell * 12166124Srafan * copies of the Software, and to permit persons to whom the Software is * 13166124Srafan * furnished to do so, subject to the following conditions: * 14166124Srafan * * 15166124Srafan * The above copyright notice and this permission notice shall be included * 16166124Srafan * in all copies or substantial portions of the Software. * 17166124Srafan * * 18166124Srafan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 19166124Srafan * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 20166124Srafan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 21166124Srafan * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 22166124Srafan * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 23166124Srafan * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 24166124Srafan * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 25166124Srafan * * 26166124Srafan * Except as contained in this notice, the name(s) of the above copyright * 27166124Srafan * holders shall not be used in advertising or otherwise to promote the * 28166124Srafan * sale, use or other dealings in this Software without prior written * 29166124Srafan * authorization. * 30166124Srafan **************************************************************************** 3162449Speter--> 3262449Speter<HTML> 3362449Speter<HEAD> 3462449Speter<TITLE>Writing Programs with NCURSES</TITLE> 3562449Speter<link rev="made" href="mailto:bugs-ncurses@gnu.org"> 36166124Srafan<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 3762449Speter</HEAD> 3862449Speter<BODY> 3962449Speter 4062449Speter<H1>Writing Programs with NCURSES</H1> 4162449Speter 4262449Speter<BLOCKQUOTE> 4362449Speterby Eric S. Raymond and Zeyd M. Ben-Halim<BR> 4462449Speterupdates since release 1.9.9e by Thomas Dickey 4562449Speter</BLOCKQUOTE> 4662449Speter 4762449Speter<H1>Contents</H1> 4862449Speter<UL> 4962449Speter<LI><A HREF="#introduction">Introduction</A> 5062449Speter<UL> 5162449Speter<LI><A HREF="#history">A Brief History of Curses</A> 5262449Speter<LI><A HREF="#scope">Scope of This Document</A> 5362449Speter<LI><A HREF="#terminology">Terminology</A> 5462449Speter</UL> 5562449Speter<LI><A HREF="#curses">The Curses Library</A> 5662449Speter<UL> 5762449Speter<LI><A HREF="#overview">An Overview of Curses</A> 5862449Speter<UL> 5962449Speter<LI><A HREF="#compiling">Compiling Programs using Curses</A> 6062449Speter<LI><A HREF="#updating">Updating the Screen</A> 6162449Speter<LI><A HREF="#stdscr">Standard Windows and Function Naming Conventions</A> 6262449Speter<LI><A HREF="#variables">Variables</A> 6362449Speter</UL> 6462449Speter<LI><A HREF="#using">Using the Library</A> 6562449Speter<UL> 6662449Speter<LI><A HREF="#starting">Starting up</A> 6762449Speter<LI><A HREF="#output">Output</A> 6862449Speter<LI><A HREF="#input">Input</A> 6962449Speter<LI><A HREF="#formschars">Using Forms Characters</A> 7062449Speter<LI><A HREF="#attributes">Character Attributes and Color</A> 7162449Speter<LI><A HREF="#mouse">Mouse Interfacing</A> 7262449Speter<LI><A HREF="#finishing">Finishing Up</A> 7362449Speter</UL> 7462449Speter<LI><A HREF="#functions">Function Descriptions</A> 7562449Speter<UL> 7662449Speter<LI><A HREF="#init">Initialization and Wrapup</A> 7762449Speter<LI><A HREF="#flush">Causing Output to the Terminal</A> 7862449Speter<LI><A HREF="#lowlevel">Low-Level Capability Access</A> 7962449Speter<LI><A HREF="#debugging">Debugging</A> 8062449Speter</UL> 8162449Speter<LI><A HREF="#hints">Hints, Tips, and Tricks</A> 8262449Speter<UL> 8362449Speter<LI><A HREF="#caution">Some Notes of Caution</A> 8462449Speter<LI><A HREF="#leaving">Temporarily Leaving ncurses Mode</A> 8562449Speter<LI><A HREF="#xterm">Using <CODE>ncurses</CODE> under <CODE>xterm</CODE></A> 8662449Speter<LI><A HREF="#screens">Handling Multiple Terminal Screens</A> 8762449Speter<LI><A HREF="#testing">Testing for Terminal Capabilities</A> 8862449Speter<LI><A HREF="#tuning">Tuning for Speed</A> 8962449Speter<LI><A HREF="#special">Special Features of <CODE>ncurses</CODE></A> 9062449Speter</UL> 9162449Speter<LI><A HREF="#compat">Compatibility with Older Versions</A> 9262449Speter<UL> 9362449Speter<LI><A HREF="#refbug">Refresh of Overlapping Windows</A> 9462449Speter<LI><A HREF="#backbug">Background Erase</A> 9562449Speter</UL> 9662449Speter<LI><A HREF="#xsifuncs">XSI Curses Conformance</A> 9762449Speter</UL> 9862449Speter<LI><A HREF="#panels">The Panels Library</A> 9962449Speter<UL> 10062449Speter<LI><A HREF="#pcompile">Compiling With the Panels Library</A> 10162449Speter<LI><A HREF="#poverview">Overview of Panels</A> 10262449Speter<LI><A HREF="#pstdscr">Panels, Input, and the Standard Screen</A> 10362449Speter<LI><A HREF="#hiding">Hiding Panels</A> 10462449Speter<LI><A HREF="#pmisc">Miscellaneous Other Facilities</A> 10562449Speter</UL> 10662449Speter<LI><A HREF="#menu">The Menu Library</A> 10762449Speter<UL> 10862449Speter<LI><A HREF="#mcompile">Compiling with the menu Library</A> 10962449Speter<LI><A HREF="#moverview">Overview of Menus</A> 11062449Speter<LI><A HREF="#mselect">Selecting items</A> 11162449Speter<LI><A HREF="#mdisplay">Menu Display</A> 11262449Speter<LI><A HREF="#mwindows">Menu Windows</A> 11362449Speter<LI><A HREF="#minput">Processing Menu Input</A> 11462449Speter<LI><A HREF="#mmisc">Miscellaneous Other Features</A> 11562449Speter</UL> 11662449Speter<LI><A HREF="#form">The Forms Library</A> 11762449Speter<UL> 11862449Speter<LI><A HREF="#fcompile">Compiling with the forms Library</A> 11962449Speter<LI><A HREF="#foverview">Overview of Forms</A> 12062449Speter<LI><A HREF="#fcreate">Creating and Freeing Fields and Forms</A> 12162449Speter<LI><A HREF="#fattributes">Fetching and Changing Field Attributes</A> 12262449Speter<UL> 12362449Speter<LI><A HREF="#fsizes">Fetching Size and Location Data</A> 12462449Speter<LI><A HREF="#flocation">Changing the Field Location</A> 12562449Speter<LI><A HREF="#fjust">The Justification Attribute</A> 12662449Speter<LI><A HREF="#fdispatts">Field Display Attributes</A> 12762449Speter<LI><A HREF="#foptions">Field Option Bits</A> 12862449Speter<LI><A HREF="#fstatus">Field Status</A> 12962449Speter<LI><A HREF="#fuser">Field User Pointer</A> 13062449Speter</UL> 13162449Speter<LI><A HREF="#fdynamic">Variable-Sized Fields</A> 13262449Speter<LI><A HREF="#fvalidation">Field Validation</A> 13362449Speter<UL> 13462449Speter<LI><A HREF="#ftype_alpha">TYPE_ALPHA</A> 13562449Speter<LI><A HREF="#ftype_alnum">TYPE_ALNUM</A> 13662449Speter<LI><A HREF="#ftype_enum">TYPE_ENUM</A> 13762449Speter<LI><A HREF="#ftype_integer">TYPE_INTEGER</A> 13862449Speter<LI><A HREF="#ftype_numeric">TYPE_NUMERIC</A> 13962449Speter<LI><A HREF="#ftype_regexp">TYPE_REGEXP</A> 14062449Speter</UL> 14162449Speter<LI><A HREF="#fbuffer">Direct Field Buffer Manipulation</A> 14262449Speter<LI><A HREF="#formattrs">Attributes of Forms</A> 14362449Speter<LI><A HREF="#fdisplay">Control of Form Display</A> 14462449Speter<LI><A HREF="#fdriver">Input Processing in the Forms Driver</A> 14562449Speter<UL> 14662449Speter<LI><A HREF="#fpage">Page Navigation Requests</A> 14762449Speter<LI><A HREF="#ffield">Inter-Field Navigation Requests</A> 14862449Speter<LI><A HREF="#fifield">Intra-Field Navigation Requests</A> 14962449Speter<LI><A HREF="#fscroll">Scrolling Requests</A> 15062449Speter<LI><A HREF="#fedit">Field Editing Requests</A> 15162449Speter<LI><A HREF="#forder">Order Requests</A> 15262449Speter<LI><A HREF="#fappcmds">Application Commands</A> 15362449Speter</UL> 15462449Speter<LI><A HREF="#fhooks">Field Change Hooks</A> 15562449Speter<LI><A HREF="#ffocus">Field Change Commands</A> 15662449Speter<LI><A HREF="#frmoptions">Form Options</A> 15762449Speter<LI><A HREF="#fcustom">Custom Validation Types</A> 15862449Speter<UL> 15962449Speter<LI><A HREF="#flinktypes">Union Types</A> 16062449Speter<LI><A HREF="#fnewtypes">New Field Types</A> 16162449Speter<LI><A HREF="#fcheckargs">Validation Function Arguments</A> 16262449Speter<LI><A HREF="#fcustorder">Order Functions For Custom Types</A> 16362449Speter<LI><A HREF="#fcustprobs">Avoiding Problems</A> 16462449Speter</UL> 16562449Speter</UL> 16662449Speter</UL> 16762449Speter 16862449Speter<HR> 16962449Speter<H1><A NAME="introduction">Introduction</A></H1> 17062449Speter 17162449SpeterThis document is an introduction to programming with <CODE>curses</CODE>. It is 17262449Speternot an exhaustive reference for the curses Application Programming Interface 17362449Speter(API); that role is filled by the <CODE>curses</CODE> manual pages. Rather, it 17462449Speteris intended to help C programmers ease into using the package. <P> 17562449Speter 17662449SpeterThis document is aimed at C applications programmers not yet specifically 17762449Speterfamiliar with ncurses. If you are already an experienced <CODE>curses</CODE> 17862449Speterprogrammer, you should nevertheless read the sections on 17962449Speter<A HREF="#mouse">Mouse Interfacing</A>, <A HREF="#debugging">Debugging</A>, 18062449Speter<A HREF="#compat">Compatibility with Older Versions</A>, 18162449Speterand <A HREF="#hints">Hints, Tips, and Tricks</A>. These will bring you up 18262449Speterto speed on the special features and quirks of the <CODE>ncurses</CODE> 18362449Speterimplementation. If you are not so experienced, keep reading. <P> 18462449Speter 18562449SpeterThe <CODE>curses</CODE> package is a subroutine library for 18662449Speterterminal-independent screen-painting and input-event handling which 18762449Speterpresents a high level screen model to the programmer, hiding differences 18862449Speterbetween terminal types and doing automatic optimization of output to change 18962449Speterone screen full of text into another. <CODE>Curses</CODE> uses terminfo, which 19062449Speteris a database format that can describe the capabilities of thousands of 19162449Speterdifferent terminals. <P> 19262449Speter 19362449SpeterThe <CODE>curses</CODE> API may seem something of an archaism on UNIX desktops 19462449Speterincreasingly dominated by X, Motif, and Tcl/Tk. Nevertheless, UNIX still 19562449Spetersupports tty lines and X supports <EM>xterm(1)</EM>; the <CODE>curses</CODE> 19662449SpeterAPI has the advantage of (a) back-portability to character-cell terminals, 19762449Speterand (b) simplicity. For an application that does not require bit-mapped 19862449Spetergraphics and multiple fonts, an interface implementation using <CODE>curses</CODE> 19962449Speterwill typically be a great deal simpler and less expensive than one using an 20062449SpeterX toolkit. 20162449Speter 20262449Speter<H2><A NAME="history">A Brief History of Curses</A></H2> 20362449Speter 20462449SpeterHistorically, the first ancestor of <CODE>curses</CODE> was the routines written to 20562449Speterprovide screen-handling for the game <CODE>rogue</CODE>; these used the 20662449Speteralready-existing <CODE>termcap</CODE> database facility for describing terminal 20762449Spetercapabilities. These routines were abstracted into a documented library and 20862449Speterfirst released with the early BSD UNIX versions. <P> 20962449Speter 21062449SpeterSystem III UNIX from Bell Labs featured a rewritten and much-improved 21162449Speter<CODE>curses</CODE> library. It introduced the terminfo format. Terminfo is based 21262449Speteron Berkeley's termcap database, but contains a number of improvements and 21362449Speterextensions. Parameterized capabilities strings were introduced, making it 21462449Speterpossible to describe multiple video attributes, and colors and to handle far 21562449Spetermore unusual terminals than possible with termcap. In the later AT&T 21662449SpeterSystem V releases, <CODE>curses</CODE> evolved to use more facilities and offer 21762449Spetermore capabilities, going far beyond BSD curses in power and flexibility. 21862449Speter 21962449Speter<H2><A NAME="scope">Scope of This Document</A></H2> 22062449Speter 22162449SpeterThis document describes <CODE>ncurses</CODE>, a free implementation of 22262449Speterthe System V <CODE>curses</CODE> API with some clearly marked extensions. 22362449SpeterIt includes the following System V curses features: 22462449Speter<UL> 22562449Speter<LI>Support for multiple screen highlights (BSD curses could only 22662449Speterhandle one `standout' highlight, usually reverse-video). 22762449Speter<LI>Support for line- and box-drawing using forms characters. 22862449Speter<LI>Recognition of function keys on input. 22962449Speter<LI>Color support. 23062449Speter<LI>Support for pads (windows of larger than screen size on which the 23162449Speterscreen or a subwindow defines a viewport). 23262449Speter</UL> 23362449Speter 23462449SpeterAlso, this package makes use of the insert and delete line and character 23562449Speterfeatures of terminals so equipped, and determines how to optimally use these 23662449Speterfeatures with no help from the programmer. It allows arbitrary combinations of 23762449Spetervideo attributes to be displayed, even on terminals that leave ``magic 23862449Spetercookies'' on the screen to mark changes in attributes. <P> 23962449Speter 24062449SpeterThe <CODE>ncurses</CODE> package can also capture and use event reports from a 24162449Spetermouse in some environments (notably, xterm under the X window system). This 24262449Speterdocument includes tips for using the mouse. <P> 24362449Speter 24462449SpeterThe <CODE>ncurses</CODE> package was originated by Pavel Curtis. The original 24562449Spetermaintainer of this package is 24662449Speter<A HREF="mailto:zmbenhal@netcom.com">Zeyd Ben-Halim</A> 24762449Speter<zmbenhal@netcom.com>. 24862449Speter<A HREF="mailto:esr@snark.thyrsus.com">Eric S. Raymond</A> 24962449Speter<esr@snark.thyrsus.com> 25062449Speterwrote many of the new features in versions after 1.8.1 25162449Speterand wrote most of this introduction. 252166124SrafanJürgen Pfeifer 25362449Speterwrote all of the menu and forms code as well as the 25462449Speter<A HREF="http://www.adahome.com">Ada95</A> binding. 25562449SpeterOngoing work is being done by 256166124Srafan<A HREF="mailto:dickey@invisible-island.net">Thomas Dickey</A> (maintainer). 25762449SpeterContact the current maintainers at 25862449Speter<A HREF="mailto:bug-ncurses@gnu.org">bug-ncurses@gnu.org</A>. 25962449Speter<P> 26062449Speter 26162449SpeterThis document also describes the <A HREF="#panels">panels</A> extension library, 26262449Spetersimilarly modeled on the SVr4 panels facility. This library allows you to 26362449Speterassociate backing store with each of a stack or deck of overlapping windows, 26462449Speterand provides operations for moving windows around in the stack that change 26562449Spetertheir visibility in the natural way (handling window overlaps). <P> 26662449Speter 26762449SpeterFinally, this document describes in detail the <A HREF="#menu">menus</A> and <A 26862449SpeterHREF="#form">forms</A> extension libraries, also cloned from System V, 26962449Speterwhich support easy construction and sequences of menus and fill-in 27062449Speterforms. 27162449Speter 27262449Speter 27362449Speter<H2><A NAME="terminology">Terminology</A></H2> 27462449Speter 27562449SpeterIn this document, the following terminology is used with reasonable 27662449Speterconsistency: 27762449Speter 27862449Speter<DL> 27962449Speter<DT> window 28062449Speter<DD> 28162449SpeterA data structure describing a sub-rectangle of the screen (possibly the 28262449Speterentire screen). You can write to a window as though it were a miniature 28362449Speterscreen, scrolling independently of other windows on the physical screen. 28462449Speter<DT> screens 28562449Speter<DD> 28662449SpeterA subset of windows which are as large as the terminal screen, i.e., they start 28762449Speterat the upper left hand corner and encompass the lower right hand corner. One 28862449Speterof these, <CODE>stdscr</CODE>, is automatically provided for the programmer. 28962449Speter<DT> terminal screen 29062449Speter<DD> 29162449SpeterThe package's idea of what the terminal display currently looks like, i.e., 29262449Speterwhat the user sees now. This is a special screen. 29362449Speter</DL> 29462449Speter 29562449Speter<H1><A NAME="curses">The Curses Library</A></H1> 29662449Speter 29762449Speter<H2><A NAME="overview">An Overview of Curses</A></H2> 29862449Speter 29962449Speter<H3><A NAME="compiling">Compiling Programs using Curses</A></H3> 30062449Speter 30162449SpeterIn order to use the library, it is necessary to have certain types and 30262449Spetervariables defined. Therefore, the programmer must have a line: 30362449Speter 30462449Speter<PRE> 30562449Speter #include <curses.h> 30662449Speter</PRE> 30762449Speter 30862449Speterat the top of the program source. The screen package uses the Standard I/O 30962449Speterlibrary, so <CODE><curses.h></CODE> includes 31062449Speter<CODE><stdio.h></CODE>. <CODE><curses.h></CODE> also includes 31162449Speter<CODE><termios.h></CODE>, <CODE><termio.h></CODE>, or 31262449Speter<CODE><sgtty.h></CODE> depending on your system. It is redundant (but 31362449Speterharmless) for the programmer to do these includes, too. In linking with 31462449Speter<CODE>curses</CODE> you need to have <CODE>-lncurses</CODE> in your LDFLAGS or on the 31562449Spetercommand line. There is no need for any other libraries. 31662449Speter 31762449Speter<H3><A NAME="updating">Updating the Screen</A></H3> 31862449Speter 31962449SpeterIn order to update the screen optimally, it is necessary for the routines to 32062449Speterknow what the screen currently looks like and what the programmer wants it to 32162449Speterlook like next. For this purpose, a data type (structure) named WINDOW is 32262449Speterdefined which describes a window image to the routines, including its starting 32362449Speterposition on the screen (the (y, x) coordinates of the upper left hand corner) 32462449Speterand its size. One of these (called <CODE>curscr</CODE>, for current screen) is a 32562449Speterscreen image of what the terminal currently looks like. Another screen (called 32662449Speter<CODE>stdscr</CODE>, for standard screen) is provided by default to make changes 32762449Speteron. <P> 32862449Speter 32962449SpeterA window is a purely internal representation. It is used to build and store a 33062449Speterpotential image of a portion of the terminal. It doesn't bear any necessary 33162449Speterrelation to what is really on the terminal screen; it's more like a 33262449Speterscratchpad or write buffer. <P> 33362449Speter 33462449SpeterTo make the section of physical screen corresponding to a window reflect the 33562449Spetercontents of the window structure, the routine <CODE>refresh()</CODE> (or 33662449Speter<CODE>wrefresh()</CODE> if the window is not <CODE>stdscr</CODE>) is called. <P> 33762449Speter 33862449SpeterA given physical screen section may be within the scope of any number of 33962449Speteroverlapping windows. Also, changes can be made to windows in any order, 34062449Speterwithout regard to motion efficiency. Then, at will, the programmer can 34162449Spetereffectively say ``make it look like this,'' and let the package implementation 34262449Speterdetermine the most efficient way to repaint the screen. 34362449Speter 34462449Speter<H3><A NAME="stdscr">Standard Windows and Function Naming Conventions</A></H3> 34562449Speter 34662449SpeterAs hinted above, the routines can use several windows, but two are 34762449Speterautomatically given: <CODE>curscr</CODE>, which knows what the terminal looks like, 34862449Speterand <CODE>stdscr</CODE>, which is what the programmer wants the terminal to look 34962449Speterlike next. The user should never actually access <CODE>curscr</CODE> directly. 35062449SpeterChanges should be made to through the API, and then the routine 35162449Speter<CODE>refresh()</CODE> (or <CODE>wrefresh()</CODE>) called. <P> 35262449Speter 35362449SpeterMany functions are defined to use <CODE>stdscr</CODE> as a default screen. For 35462449Speterexample, to add a character to <CODE>stdscr</CODE>, one calls <CODE>addch()</CODE> with 35562449Speterthe desired character as argument. To write to a different window. use the 35662449Speterroutine <CODE>waddch()</CODE> (for `w'indow-specific addch()) is provided. This 35762449Speterconvention of prepending function names with a `w' when they are to be 35862449Speterapplied to specific windows is consistent. The only routines which do not 35962449Speterfollow it are those for which a window must always be specified. <P> 36062449Speter 36162449SpeterIn order to move the current (y, x) coordinates from one point to another, the 36262449Speterroutines <CODE>move()</CODE> and <CODE>wmove()</CODE> are provided. However, it is 36362449Speteroften desirable to first move and then perform some I/O operation. In order to 36462449Speteravoid clumsiness, most I/O routines can be preceded by the prefix 'mv' and 36562449Speterthe desired (y, x) coordinates prepended to the arguments to the function. For 36662449Speterexample, the calls 36762449Speter 36862449Speter<PRE> 36962449Speter move(y, x); 37062449Speter addch(ch); 37162449Speter</PRE> 37262449Speter 37362449Spetercan be replaced by 37462449Speter 37562449Speter<PRE> 37662449Speter mvaddch(y, x, ch); 37762449Speter</PRE> 37862449Speter 37962449Speterand 38062449Speter 38162449Speter<PRE> 38262449Speter wmove(win, y, x); 38362449Speter waddch(win, ch); 38462449Speter</PRE> 38562449Speter 38662449Spetercan be replaced by 38762449Speter 38862449Speter<PRE> 38962449Speter mvwaddch(win, y, x, ch); 39062449Speter</PRE> 39162449Speter 39262449SpeterNote that the window description pointer (win) comes before the added (y, x) 39362449Spetercoordinates. If a function requires a window pointer, it is always the first 39462449Speterparameter passed. 39562449Speter 39662449Speter<H3><A NAME="variables">Variables</A></H3> 39762449Speter 39862449SpeterThe <CODE>curses</CODE> library sets some variables describing the terminal 39962449Spetercapabilities. 40062449Speter 40162449Speter<PRE> 40262449Speter type name description 40362449Speter ------------------------------------------------------------------ 40462449Speter int LINES number of lines on the terminal 40562449Speter int COLS number of columns on the terminal 40662449Speter</PRE> 40762449Speter 40862449SpeterThe <CODE>curses.h</CODE> also introduces some <CODE>#define</CODE> constants and types 40962449Speterof general usefulness: 41062449Speter 41162449Speter<DL> 41262449Speter<DT> <CODE>bool</CODE> 41362449Speter<DD> boolean type, actually a `char' (e.g., <CODE>bool doneit;</CODE>) 41462449Speter<DT> <CODE>TRUE</CODE> 41562449Speter<DD> boolean `true' flag (1). 41662449Speter<DT> <CODE>FALSE</CODE> 41762449Speter<DD> boolean `false' flag (0). 41862449Speter<DT> <CODE>ERR</CODE> 41962449Speter<DD> error flag returned by routines on a failure (-1). 42062449Speter<DT> <CODE>OK</CODE> 42162449Speter<DD> error flag returned by routines when things go right. 42262449Speter</DL> 42362449Speter 42462449Speter<H2><A NAME="using">Using the Library</A></H2> 42562449Speter 42662449SpeterNow we describe how to actually use the screen package. In it, we assume all 42762449Speterupdating, reading, etc. is applied to <CODE>stdscr</CODE>. These instructions will 42862449Speterwork on any window, providing you change the function names and parameters as 42962449Spetermentioned above. <P> 43062449Speter 43162449SpeterHere is a sample program to motivate the discussion: 43262449Speter 43362449Speter<PRE> 43462449Speter#include <curses.h> 43562449Speter#include <signal.h> 43662449Speter 43762449Speterstatic void finish(int sig); 43862449Speter 43962449Speterint 44062449Spetermain(int argc, char *argv[]) 44162449Speter{ 44262449Speter int num = 0; 44362449Speter 44462449Speter /* initialize your non-curses data structures here */ 44562449Speter 44662449Speter (void) signal(SIGINT, finish); /* arrange interrupts to terminate */ 44762449Speter 44862449Speter (void) initscr(); /* initialize the curses library */ 44962449Speter keypad(stdscr, TRUE); /* enable keyboard mapping */ 45062449Speter (void) nonl(); /* tell curses not to do NL->CR/NL on output */ 45162449Speter (void) cbreak(); /* take input chars one at a time, no wait for \n */ 45262449Speter (void) echo(); /* echo input - in color */ 45362449Speter 45462449Speter if (has_colors()) 45562449Speter { 45662449Speter start_color(); 45762449Speter 45862449Speter /* 45962449Speter * Simple color assignment, often all we need. Color pair 0 cannot 46062449Speter * be redefined. This example uses the same value for the color 46162449Speter * pair as for the foreground color, though of course that is not 46262449Speter * necessary: 46362449Speter */ 46462449Speter init_pair(1, COLOR_RED, COLOR_BLACK); 46562449Speter init_pair(2, COLOR_GREEN, COLOR_BLACK); 46662449Speter init_pair(3, COLOR_YELLOW, COLOR_BLACK); 46762449Speter init_pair(4, COLOR_BLUE, COLOR_BLACK); 46862449Speter init_pair(5, COLOR_CYAN, COLOR_BLACK); 46962449Speter init_pair(6, COLOR_MAGENTA, COLOR_BLACK); 47062449Speter init_pair(7, COLOR_WHITE, COLOR_BLACK); 47162449Speter } 47262449Speter 47362449Speter for (;;) 47462449Speter { 47562449Speter int c = getch(); /* refresh, accept single keystroke of input */ 47662449Speter attrset(COLOR_PAIR(num % 8)); 47762449Speter num++; 47862449Speter 47962449Speter /* process the command keystroke */ 48062449Speter } 48162449Speter 48262449Speter finish(0); /* we're done */ 48362449Speter} 48462449Speter 48562449Speterstatic void finish(int sig) 48662449Speter{ 48762449Speter endwin(); 48862449Speter 48962449Speter /* do your non-curses wrapup here */ 49062449Speter 49162449Speter exit(0); 49262449Speter} 49362449Speter</PRE> 49462449Speter 49562449Speter<H3><A NAME="starting">Starting up</A></H3> 49662449Speter 49762449SpeterIn order to use the screen package, the routines must know about terminal 49862449Spetercharacteristics, and the space for <CODE>curscr</CODE> and <CODE>stdscr</CODE> must be 49962449Speterallocated. These function <CODE>initscr()</CODE> does both these things. Since it 50062449Spetermust allocate space for the windows, it can overflow memory when attempting to 50162449Speterdo so. On the rare occasions this happens, <CODE>initscr()</CODE> will terminate 50262449Speterthe program with an error message. <CODE>initscr()</CODE> must always be called 50362449Speterbefore any of the routines which affect windows are used. If it is not, the 50462449Speterprogram will core dump as soon as either <CODE>curscr</CODE> or <CODE>stdscr</CODE> are 50562449Speterreferenced. However, it is usually best to wait to call it until after you are 50662449Spetersure you will need it, like after checking for startup errors. Terminal status 50762449Speterchanging routines like <CODE>nl()</CODE> and <CODE>cbreak()</CODE> should be called 50862449Speterafter <CODE>initscr()</CODE>. <P> 50962449Speter 51062449SpeterOnce the screen windows have been allocated, you can set them up for 51162449Speteryour program. If you want to, say, allow a screen to scroll, use 51262449Speter<CODE>scrollok()</CODE>. If you want the cursor to be left in place after 51362449Speterthe last change, use <CODE>leaveok()</CODE>. If this isn't done, 51462449Speter<CODE>refresh()</CODE> will move the cursor to the window's current (y, x) 51562449Spetercoordinates after updating it. <P> 51662449Speter 51762449SpeterYou can create new windows of your own using the functions <CODE>newwin()</CODE>, 51862449Speter<CODE>derwin()</CODE>, and <CODE>subwin()</CODE>. The routine <CODE>delwin()</CODE> will 51962449Speterallow you to get rid of old windows. All the options described above can be 52062449Speterapplied to any window. 52162449Speter 52262449Speter<H3><A NAME="output">Output</A></H3> 52362449Speter 52462449SpeterNow that we have set things up, we will want to actually update the terminal. 52562449SpeterThe basic functions used to change what will go on a window are 52662449Speter<CODE>addch()</CODE> and <CODE>move()</CODE>. <CODE>addch()</CODE> adds a character at the 52762449Spetercurrent (y, x) coordinates. <CODE>move()</CODE> changes the current (y, x) 52862449Spetercoordinates to whatever you want them to be. It returns <CODE>ERR</CODE> if you 52962449Spetertry to move off the window. As mentioned above, you can combine the two into 53062449Speter<CODE>mvaddch()</CODE> to do both things at once. <P> 53162449Speter 53262449SpeterThe other output functions, such as <CODE>addstr()</CODE> and <CODE>printw()</CODE>, 53362449Speterall call <CODE>addch()</CODE> to add characters to the window. <P> 53462449Speter 53562449SpeterAfter you have put on the window what you want there, when you want the portion 53662449Speterof the terminal covered by the window to be made to look like it, you must call 53762449Speter<CODE>refresh()</CODE>. In order to optimize finding changes, <CODE>refresh()</CODE> 53862449Speterassumes that any part of the window not changed since the last 53962449Speter<CODE>refresh()</CODE> of that window has not been changed on the terminal, i.e., 54062449Speterthat you have not refreshed a portion of the terminal with an overlapping 54162449Speterwindow. If this is not the case, the routine <CODE>touchwin()</CODE> is provided 54262449Speterto make it look like the entire window has been changed, thus making 54362449Speter<CODE>refresh()</CODE> check the whole subsection of the terminal for changes. <P> 54462449Speter 54562449SpeterIf you call <CODE>wrefresh()</CODE> with <CODE>curscr</CODE> as its argument, it will 54662449Spetermake the screen look like <CODE>curscr</CODE> thinks it looks like. This is useful 54762449Speterfor implementing a command which would redraw the screen in case it get messed 54862449Speterup. 54962449Speter 55062449Speter<H3><A NAME="input">Input</A></H3> 55162449Speter 55262449SpeterThe complementary function to <CODE>addch()</CODE> is <CODE>getch()</CODE> which, if 55362449Speterecho is set, will call <CODE>addch()</CODE> to echo the character. Since the 55462449Speterscreen package needs to know what is on the terminal at all times, if 55562449Spetercharacters are to be echoed, the tty must be in raw or cbreak mode. Since 55662449Speterinitially the terminal has echoing enabled and is in ordinary ``cooked'' mode, 55762449Speterone or the other has to changed before calling <CODE>getch()</CODE>; otherwise, 55862449Speterthe program's output will be unpredictable. <P> 55962449Speter 56062449SpeterWhen you need to accept line-oriented input in a window, the functions 56162449Speter<CODE>wgetstr()</CODE> and friends are available. There is even a <CODE>wscanw()</CODE> 56262449Speterfunction that can do <CODE>scanf()</CODE>(3)-style multi-field parsing on window 56362449Speterinput. These pseudo-line-oriented functions turn on echoing while they 56462449Speterexecute. <P> 56562449Speter 56662449SpeterThe example code above uses the call <CODE>keypad(stdscr, TRUE)</CODE> to enable 56762449Spetersupport for function-key mapping. With this feature, the <CODE>getch()</CODE> code 56862449Speterwatches the input stream for character sequences that correspond to arrow and 56962449Speterfunction keys. These sequences are returned as pseudo-character values. The 57062449Speter<CODE>#define</CODE> values returned are listed in the <CODE>curses.h</CODE> The 57162449Spetermapping from sequences to <CODE>#define</CODE> values is determined by 57262449Speter<CODE>key_</CODE> capabilities in the terminal's terminfo entry. 57362449Speter 57462449Speter<H3><A NAME="formschars">Using Forms Characters</A></H3> 57562449Speter 57662449SpeterThe <CODE>addch()</CODE> function (and some others, including <CODE>box()</CODE> and 57762449Speter<CODE>border()</CODE>) can accept some pseudo-character arguments which are specially 57862449Speterdefined by <CODE>ncurses</CODE>. These are <CODE>#define</CODE> values set up in 57962449Speterthe <CODE>curses.h</CODE> header; see there for a complete list (look for 58062449Speterthe prefix <CODE>ACS_</CODE>). <P> 58162449Speter 58262449SpeterThe most useful of the ACS defines are the forms-drawing characters. You can 58362449Speteruse these to draw boxes and simple graphs on the screen. If the terminal 58462449Speterdoes not have such characters, <CODE>curses.h</CODE> will map them to a 58562449Speterrecognizable (though ugly) set of ASCII defaults. 58662449Speter 58762449Speter<H3><A NAME="attributes">Character Attributes and Color</A></H3> 58862449Speter 58962449SpeterThe <CODE>ncurses</CODE> package supports screen highlights including standout, 59062449Speterreverse-video, underline, and blink. It also supports color, which is treated 59162449Speteras another kind of highlight. <P> 59262449Speter 59362449SpeterHighlights are encoded, internally, as high bits of the pseudo-character type 59462449Speter(<CODE>chtype</CODE>) that <CODE>curses.h</CODE> uses to represent the contents of a 59562449Speterscreen cell. See the <CODE>curses.h</CODE> header file for a complete list of 59662449Speterhighlight mask values (look for the prefix <CODE>A_</CODE>).<P> 59762449Speter 59862449SpeterThere are two ways to make highlights. One is to logical-or the value of the 59962449Speterhighlights you want into the character argument of an <CODE>addch()</CODE> call, 60062449Speteror any other output call that takes a <CODE>chtype</CODE> argument. <P> 60162449Speter 60262449SpeterThe other is to set the current-highlight value. This is logical-or'ed with 60362449Speterany highlight you specify the first way. You do this with the functions 60462449Speter<CODE>attron()</CODE>, <CODE>attroff()</CODE>, and <CODE>attrset()</CODE>; see the manual 60562449Speterpages for details. 60662449Speter 60762449SpeterColor is a special kind of highlight. The package actually thinks in terms 60862449Speterof color pairs, combinations of foreground and background colors. The sample 60962449Spetercode above sets up eight color pairs, all of the guaranteed-available colors 61062449Speteron black. Note that each color pair is, in effect, given the name of its 61162449Speterforeground color. Any other range of eight non-conflicting values could 61262449Speterhave been used as the first arguments of the <CODE>init_pair()</CODE> values. <P> 61362449Speter 61462449SpeterOnce you've done an <CODE>init_pair()</CODE> that creates color-pair N, you can 61562449Speteruse <CODE>COLOR_PAIR(N)</CODE> as a highlight that invokes that particular 61662449Spetercolor combination. Note that <CODE>COLOR_PAIR(N)</CODE>, for constant N, 61762449Speteris itself a compile-time constant and can be used in initializers. 61862449Speter 61962449Speter<H3><A NAME="mouse">Mouse Interfacing</A></H3> 62062449Speter 62162449SpeterThe <CODE>ncurses</CODE> library also provides a mouse interface. 62262449Speter<!-- The 'note' tag is not portable enough --> 62362449Speter<blockquote> 62462449Speter<strong>NOTE:</strong> this facility is specific to <CODE>ncurses</CODE>, it is not part of either 62562449Speterthe XSI Curses standard, nor of System V Release 4, nor BSD curses. 62662449SpeterSystem V Release 4 curses contains code with similar interface definitions, 62762449Speterhowever it is not documented. Other than by disassembling the library, we 62862449Speterhave no way to determine exactly how that mouse code works. 62962449SpeterThus, we recommend that you wrap mouse-related code in an #ifdef using the 63062449Speterfeature macro NCURSES_MOUSE_VERSION so it will not be compiled and linked 63162449Speteron non-ncurses systems. 63262449Speter</blockquote> 63362449Speter 63462449SpeterPresently, mouse event reporting works in the following environments: 63562449Speter<ul> 63662449Speter<li>xterm and similar programs such as rxvt. 63762449Speter<li>Linux console, when configured with <CODE>gpm</CODE>(1), Alessandro 63862449SpeterRubini's mouse server. 639166124Srafan<li>FreeBSD sysmouse (console) 64062449Speter<li>OS/2 EMX 64162449Speter</ul> 64262449Speter<P> 64362449SpeterThe mouse interface is very simple. To activate it, you use the function 64462449Speter<CODE>mousemask()</CODE>, passing it as first argument a bit-mask that specifies 64562449Speterwhat kinds of events you want your program to be able to see. It will 64662449Speterreturn the bit-mask of events that actually become visible, which may differ 64762449Speterfrom the argument if the mouse device is not capable of reporting some of 64862449Speterthe event types you specify. <P> 64962449Speter 65062449SpeterOnce the mouse is active, your application's command loop should watch 65162449Speterfor a return value of <CODE>KEY_MOUSE</CODE> from <CODE>wgetch()</CODE>. When 65262449Speteryou see this, a mouse event report has been queued. To pick it off 65362449Speterthe queue, use the function <CODE>getmouse()</CODE> (you must do this before 65462449Speterthe next <CODE>wgetch()</CODE>, otherwise another mouse event might come 65562449Speterin and make the first one inaccessible). <P> 65662449Speter 65762449SpeterEach call to <CODE>getmouse()</CODE> fills a structure (the address of which you'll 65862449Speterpass it) with mouse event data. The event data includes zero-origin, 65962449Speterscreen-relative character-cell coordinates of the mouse pointer. It also 66062449Speterincludes an event mask. Bits in this mask will be set, corresponding 66162449Speterto the event type being reported. <P> 66262449Speter 66362449SpeterThe mouse structure contains two additional fields which may be 66462449Spetersignificant in the future as ncurses interfaces to new kinds of 66562449Speterpointing device. In addition to x and y coordinates, there is a slot 66662449Speterfor a z coordinate; this might be useful with touch-screens that can 66762449Speterreturn a pressure or duration parameter. There is also a device ID 66862449Speterfield, which could be used to distinguish between multiple pointing 66962449Speterdevices. <P> 67062449Speter 67162449SpeterThe class of visible events may be changed at any time via <CODE>mousemask()</CODE>. 67262449SpeterEvents that can be reported include presses, releases, single-, double- and 67362449Spetertriple-clicks (you can set the maximum button-down time for clicks). If 67462449Speteryou don't make clicks visible, they will be reported as press-release 67562449Speterpairs. In some environments, the event mask may include bits reporting 67662449Speterthe state of shift, alt, and ctrl keys on the keyboard during the event. <P> 67762449Speter 67862449SpeterA function to check whether a mouse event fell within a given window is 67962449Speteralso supplied. You can use this to see whether a given window should 68062449Speterconsider a mouse event relevant to it. <P> 68162449Speter 68262449SpeterBecause mouse event reporting will not be available in all 68362449Speterenvironments, it would be unwise to build <CODE>ncurses</CODE> 68462449Speterapplications that <EM>require</EM> the use of a mouse. Rather, you should 68562449Speteruse the mouse as a shortcut for point-and-shoot commands your application 68662449Speterwould normally accept from the keyboard. Two of the test games in the 68762449Speter<CODE>ncurses</CODE> distribution (<CODE>bs</CODE> and <CODE>knight</CODE>) contain 68862449Spetercode that illustrates how this can be done. <P> 68962449Speter 69062449SpeterSee the manual page <CODE>curs_mouse(3X)</CODE> for full details of the 69162449Spetermouse-interface functions. 69262449Speter 69362449Speter<H3><A NAME="finishing">Finishing Up</A></H3> 69462449Speter 69562449SpeterIn order to clean up after the <CODE>ncurses</CODE> routines, the routine 69662449Speter<CODE>endwin()</CODE> is provided. It restores tty modes to what they were when 69762449Speter<CODE>initscr()</CODE> was first called, and moves the cursor down to the 69862449Speterlower-left corner. Thus, anytime after the call to initscr, <CODE>endwin()</CODE> 69962449Spetershould be called before exiting. 70062449Speter 70162449Speter<H2><A NAME="functions">Function Descriptions</A></H2> 70262449Speter 70362449SpeterWe describe the detailed behavior of some important curses functions here, as a 70462449Spetersupplement to the manual page descriptions. 70562449Speter 70662449Speter<H3><A NAME="init">Initialization and Wrapup</A></H3> 70762449Speter 70862449Speter<DL> 70962449Speter<DT> <CODE>initscr()</CODE> 71062449Speter<DD> The first function called should almost always be <CODE>initscr()</CODE>. 71162449SpeterThis will determine the terminal type and 71262449Speterinitialize curses data structures. <CODE>initscr()</CODE> also arranges that 71362449Speterthe first call to <CODE>refresh()</CODE> will clear the screen. If an error 71462449Speteroccurs a message is written to standard error and the program 71562449Speterexits. Otherwise it returns a pointer to stdscr. A few functions may be 71662449Spetercalled before initscr (<CODE>slk_init()</CODE>, <CODE>filter()</CODE>, 717166124Srafan<CODE>ripoffline()</CODE>, <CODE>use_env()</CODE>, and, if you are using multiple 71862449Speterterminals, <CODE>newterm()</CODE>.) 71962449Speter<DT> <CODE>endwin()</CODE> 72062449Speter<DD> Your program should always call <CODE>endwin()</CODE> before exiting or 72162449Spetershelling out of the program. This function will restore tty modes, 72262449Spetermove the cursor to the lower left corner of the screen, reset the 72362449Speterterminal into the proper non-visual mode. Calling <CODE>refresh()</CODE> 72462449Speteror <CODE>doupdate()</CODE> after a temporary escape from the program will 72562449Speterrestore the ncurses screen from before the escape. 72662449Speter<DT> <CODE>newterm(type, ofp, ifp)</CODE> 72762449Speter<DD> A program which outputs to more than one terminal should use 72862449Speter<CODE>newterm()</CODE> instead of <CODE>initscr()</CODE>. <CODE>newterm()</CODE> should 72962449Speterbe called once for each terminal. It returns a variable of type 73062449Speter<CODE>SCREEN *</CODE> which should be saved as a reference to that 73197049Speterterminal. 73297049Speter(NOTE: a SCREEN variable is not a <em>screen</em> in the sense we 73397049Speterare describing in this introduction, but a collection of 73497049Speterparameters used to assist in optimizing the display.) 73597049SpeterThe arguments are the type of the terminal (a string) and 73662449Speter<CODE>FILE</CODE> pointers for the output and input of the terminal. If 73762449Spetertype is NULL then the environment variable <CODE>$TERM</CODE> is used. 73862449Speter<CODE>endwin()</CODE> should called once at wrapup time for each terminal 73962449Speteropened using this function. 74062449Speter<DT> <CODE>set_term(new)</CODE> 74162449Speter<DD> This function is used to switch to a different terminal previously 74262449Speteropened by <CODE>newterm()</CODE>. The screen reference for the new terminal 74362449Speteris passed as the parameter. The previous terminal is returned by the 74462449Speterfunction. All other calls affect only the current terminal. 74562449Speter<DT> <CODE>delscreen(sp)</CODE> 74662449Speter<DD> The inverse of <CODE>newterm()</CODE>; deallocates the data structures 74762449Speterassociated with a given <CODE>SCREEN</CODE> reference. 74862449Speter</DL> 74962449Speter 75062449Speter<H3><A NAME="flush">Causing Output to the Terminal</A></H3> 75162449Speter 75262449Speter<DL> 75362449Speter<DT> <CODE>refresh()</CODE> and <CODE>wrefresh(win)</CODE> 75462449Speter<DD> These functions must be called to actually get any output on 75562449Speterthe terminal, as other routines merely manipulate data 75662449Speterstructures. <CODE>wrefresh()</CODE> copies the named window to the physical 75762449Speterterminal screen, taking into account what is already 75862449Speterthere in order to do optimizations. <CODE>refresh()</CODE> does a 759166124Srafanrefresh of <CODE>stdscr</CODE>. Unless <CODE>leaveok()</CODE> has been 76062449Speterenabled, the physical cursor of the terminal is left at the 76162449Speterlocation of the window's cursor. 76262449Speter<DT> <CODE>doupdate()</CODE> and <CODE>wnoutrefresh(win)</CODE> 76362449Speter<DD> These two functions allow multiple updates with more efficiency 76462449Speterthan wrefresh. To use them, it is important to understand how curses 76562449Speterworks. In addition to all the window structures, curses keeps two 76662449Speterdata structures representing the terminal screen: a physical screen, 76762449Speterdescribing what is actually on the screen, and a virtual screen, 76862449Speterdescribing what the programmer wants to have on the screen. wrefresh 76962449Speterworks by first copying the named window to the virtual screen 77062449Speter(<CODE>wnoutrefresh()</CODE>), and then calling the routine to update the 77162449Speterscreen (<CODE>doupdate()</CODE>). If the programmer wishes to output 77262449Speterseveral windows at once, a series of calls to <CODE>wrefresh</CODE> will result 77362449Speterin alternating calls to <CODE>wnoutrefresh()</CODE> and <CODE>doupdate()</CODE>, 77462449Spetercausing several bursts of output to the screen. By calling 77562449Speter<CODE>wnoutrefresh()</CODE> for each window, it is then possible to call 77662449Speter<CODE>doupdate()</CODE> once, resulting in only one burst of output, with 77762449Speterfewer total characters transmitted (this also avoids a visually annoying 77862449Speterflicker at each update). 77962449Speter</DL> 78062449Speter 78162449Speter<H3><A NAME="lowlevel">Low-Level Capability Access</A></H3> 78262449Speter 78362449Speter<DL> 78462449Speter<DT> <CODE>setupterm(term, filenum, errret)</CODE> 78562449Speter<DD> This routine is called to initialize a terminal's description, without setting 78662449Speterup the curses screen structures or changing the tty-driver mode bits. 78762449Speter<CODE>term</CODE> is the character string representing the name of the terminal 78862449Speterbeing used. <CODE>filenum</CODE> is the UNIX file descriptor of the terminal to 78962449Speterbe used for output. <CODE>errret</CODE> is a pointer to an integer, in which a 79062449Spetersuccess or failure indication is returned. The values returned can be 1 (all 79162449Speteris well), 0 (no such terminal), or -1 (some problem locating the terminfo 79262449Speterdatabase). <P> 79362449Speter 79462449SpeterThe value of <CODE>term</CODE> can be given as NULL, which will cause the value of 79562449Speter<CODE>TERM</CODE> in the environment to be used. The <CODE>errret</CODE> pointer can 79662449Speteralso be given as NULL, meaning no error code is wanted. If <CODE>errret</CODE> is 79762449Speterdefaulted, and something goes wrong, <CODE>setupterm()</CODE> will print an 79862449Speterappropriate error message and exit, rather than returning. Thus, a simple 79962449Speterprogram can call setupterm(0, 1, 0) and not worry about initialization 80062449Spetererrors. <P> 80162449Speter 80262449SpeterAfter the call to <CODE>setupterm()</CODE>, the global variable <CODE>cur_term</CODE> is 80362449Speterset to point to the current structure of terminal capabilities. By calling 80462449Speter<CODE>setupterm()</CODE> for each terminal, and saving and restoring 80562449Speter<CODE>cur_term</CODE>, it is possible for a program to use two or more terminals at 80662449Speteronce. <CODE>Setupterm()</CODE> also stores the names section of the terminal 80762449Speterdescription in the global character array <CODE>ttytype[]</CODE>. Subsequent calls 80862449Speterto <CODE>setupterm()</CODE> will overwrite this array, so you'll have to save it 80962449Speteryourself if need be. 81062449Speter</DL> 81162449Speter 81262449Speter<H3><A NAME="debugging">Debugging</A></H3> 81362449Speter 81462449Speter<!-- The 'note' tag is not portable enough --> 81562449Speter<blockquote> 81662449Speter<strong>NOTE:</strong> These functions are not part of the standard curses API! 81762449Speter</blockquote> 81862449Speter 81962449Speter<DL> 82062449Speter<DT> <CODE>trace()</CODE> 82162449Speter<DD> 82262449SpeterThis function can be used to explicitly set a trace level. If the 82362449Spetertrace level is nonzero, execution of your program will generate a file 82462449Spetercalled `trace' in the current working directory containing a report on 82562449Speterthe library's actions. Higher trace levels enable more detailed (and 82662449Speterverbose) reporting -- see comments attached to <CODE>TRACE_</CODE> defines 82762449Speterin the <CODE>curses.h</CODE> file for details. (It is also possible to set 82862449Spetera trace level by assigning a trace level value to the environment variable 82962449Speter<CODE>NCURSES_TRACE</CODE>). 83062449Speter<DT> <CODE>_tracef()</CODE> 83162449Speter<DD> 83262449SpeterThis function can be used to output your own debugging information. It is only 83362449Speteravailable only if you link with -lncurses_g. It can be used the same way as 83462449Speter<CODE>printf()</CODE>, only it outputs a newline after the end of arguments. 83562449SpeterThe output goes to a file called <CODE>trace</CODE> in the current directory. 83662449Speter</DL> 83762449Speter 83862449SpeterTrace logs can be difficult to interpret due to the sheer volume of 83962449Speterdata dumped in them. There is a script called <STRONG>tracemunch</STRONG> 84062449Speterincluded with the <CODE>ncurses</CODE> distribution that can alleviate 84162449Speterthis problem somewhat; it compacts long sequences of similar operations into 84262449Spetermore succinct single-line pseudo-operations. These pseudo-ops can be 84362449Speterdistinguished by the fact that they are named in capital letters. 84462449Speter 84562449Speter<H2><A NAME="hints">Hints, Tips, and Tricks</A></H2> 84662449Speter 84762449SpeterThe <CODE>ncurses</CODE> manual pages are a complete reference for this library. 84862449SpeterIn the remainder of this document, we discuss various useful methods that 84962449Spetermay not be obvious from the manual page descriptions. 85062449Speter 85162449Speter<H3><A NAME="caution">Some Notes of Caution</A></H3> 85262449Speter 85362449SpeterIf you find yourself thinking you need to use <CODE>noraw()</CODE> or 85462449Speter<CODE>nocbreak()</CODE>, think again and move carefully. It's probably 85562449Speterbetter design to use <CODE>getstr()</CODE> or one of its relatives to 85662449Spetersimulate cooked mode. The <CODE>noraw()</CODE> and <CODE>nocbreak()</CODE> 85762449Speterfunctions try to restore cooked mode, but they may end up clobbering 85862449Spetersome control bits set before you started your application. Also, they 85962449Speterhave always been poorly documented, and are likely to hurt your 86062449Speterapplication's usability with other curses libraries. <P> 86162449Speter 86262449SpeterBear in mind that <CODE>refresh()</CODE> is a synonym for <CODE>wrefresh(stdscr)</CODE>. 86362449SpeterDon't try to mix use of <CODE>stdscr</CODE> with use of windows declared 86462449Speterby <CODE>newwin()</CODE>; a <CODE>refresh()</CODE> call will blow them off the 86562449Speterscreen. The right way to handle this is to use <CODE>subwin()</CODE>, or 86662449Speternot touch <CODE>stdscr</CODE> at all and tile your screen with declared 86762449Speterwindows which you then <CODE>wnoutrefresh()</CODE> somewhere in your program 86862449Speterevent loop, with a single <CODE>doupdate()</CODE> call to trigger actual 86962449Speterrepainting. <P> 87062449Speter 87162449SpeterYou are much less likely to run into problems if you design your screen 87262449Speterlayouts to use tiled rather than overlapping windows. Historically, 87362449Spetercurses support for overlapping windows has been weak, fragile, and poorly 87462449Speterdocumented. The <CODE>ncurses</CODE> library is not yet an exception to this 87562449Speterrule. <P> 87662449Speter 87762449SpeterThere is a panels library included in the <CODE>ncurses</CODE> 87862449Speterdistribution that does a pretty good job of strengthening the 87962449Speteroverlapping-windows facilities. <P> 88062449Speter 88162449SpeterTry to avoid using the global variables LINES and COLS. Use 88262449Speter<CODE>getmaxyx()</CODE> on the <CODE>stdscr</CODE> context instead. Reason: 88362449Speteryour code may be ported to run in an environment with window resizes, 88462449Speterin which case several screens could be open with different sizes. 88562449Speter 88662449Speter<H3><A NAME="leaving">Temporarily Leaving NCURSES Mode</A></H3> 88762449Speter 88862449SpeterSometimes you will want to write a program that spends most of its time in 88962449Speterscreen mode, but occasionally returns to ordinary `cooked' mode. A common 89062449Speterreason for this is to support shell-out. This behavior is simple to arrange 89162449Speterin <CODE>ncurses</CODE>. <P> 89262449Speter 89362449SpeterTo leave <CODE>ncurses</CODE> mode, call <CODE>endwin()</CODE> as you would if you 89462449Speterwere intending to terminate the program. This will take the screen back to 89562449Spetercooked mode; you can do your shell-out. When you want to return to 89662449Speter<CODE>ncurses</CODE> mode, simply call <CODE>refresh()</CODE> or <CODE>doupdate()</CODE>. 89762449SpeterThis will repaint the screen. <P> 89862449Speter 89962449SpeterThere is a boolean function, <CODE>isendwin()</CODE>, which code can use to 90062449Spetertest whether <CODE>ncurses</CODE> screen mode is active. It returns <CODE>TRUE</CODE> 90162449Speterin the interval between an <CODE>endwin()</CODE> call and the following 90262449Speter<CODE>refresh()</CODE>, <CODE>FALSE</CODE> otherwise. <P> 90362449Speter 90462449SpeterHere is some sample code for shellout: 90562449Speter 90662449Speter<PRE> 90762449Speter addstr("Shelling out..."); 90862449Speter def_prog_mode(); /* save current tty modes */ 90962449Speter endwin(); /* restore original tty modes */ 91062449Speter system("sh"); /* run shell */ 91162449Speter addstr("returned.\n"); /* prepare return message */ 91262449Speter refresh(); /* restore save modes, repaint screen */ 91362449Speter</PRE> 91462449Speter 91562449Speter<H3><A NAME="xterm">Using NCURSES under XTERM</A></H3> 91662449Speter 91762449SpeterA resize operation in X sends SIGWINCH to the application running under xterm. 91862449SpeterThe <CODE>ncurses</CODE> library provides an experimental signal 91962449Speterhandler, but in general does not catch this signal, because it cannot 92062449Speterknow how you want the screen re-painted. You will usually have to write the 92162449SpeterSIGWINCH handler yourself. Ncurses can give you some help. <P> 92262449Speter 92362449SpeterThe easiest way to code your SIGWINCH handler is to have it do an 92462449Speter<CODE>endwin</CODE>, followed by an <CODE>refresh</CODE> and a screen repaint you code 92562449Speteryourself. The <CODE>refresh</CODE> will pick up the new screen size from the 92662449Speterxterm's environment. <P> 92762449Speter 92862449SpeterThat is the standard way, of course (it even works with some vendor's curses 92962449Speterimplementations). 93062449SpeterIts drawback is that it clears the screen to reinitialize the display, and does 93162449Speternot resize subwindows which must be shrunk. 93262449Speter<CODE>Ncurses</CODE> provides an extension which works better, the 93362449Speter<CODE>resizeterm</CODE> function. That function ensures that all windows 93462449Speterare limited to the new screen dimensions, and pads <CODE>stdscr</CODE> 93562449Speterwith blanks if the screen is larger. <P> 93662449Speter 93762449SpeterFinally, ncurses can be configured to provide its own SIGWINCH handler, 93862449Speterbased on <CODE>resizeterm</CODE>. 93962449Speter 94062449Speter<H3><A NAME="screens">Handling Multiple Terminal Screens</A></H3> 94162449Speter 94262449SpeterThe <CODE>initscr()</CODE> function actually calls a function named 94362449Speter<CODE>newterm()</CODE> to do most of its work. If you are writing a program that 94462449Speteropens multiple terminals, use <CODE>newterm()</CODE> directly. <P> 94562449Speter 94662449SpeterFor each call, you will have to specify a terminal type and a pair of file 94762449Speterpointers; each call will return a screen reference, and <CODE>stdscr</CODE> will be 94862449Speterset to the last one allocated. You will switch between screens with the 94962449Speter<CODE>set_term</CODE> call. Note that you will also have to call 95062449Speter<CODE>def_shell_mode</CODE> and <CODE>def_prog_mode</CODE> on each tty yourself. 95162449Speter 95262449Speter<H3><A NAME="testing">Testing for Terminal Capabilities</A></H3> 95362449Speter 95462449SpeterSometimes you may want to write programs that test for the presence of various 95562449Spetercapabilities before deciding whether to go into <CODE>ncurses</CODE> mode. An easy 95662449Speterway to do this is to call <CODE>setupterm()</CODE>, then use the functions 95762449Speter<CODE>tigetflag()</CODE>, <CODE>tigetnum()</CODE>, and <CODE>tigetstr()</CODE> to do your 95862449Spetertesting. <P> 95962449Speter 96062449SpeterA particularly useful case of this often comes up when you want to 96162449Spetertest whether a given terminal type should be treated as `smart' 96262449Speter(cursor-addressable) or `stupid'. The right way to test this is to see 96362449Speterif the return value of <CODE>tigetstr("cup")</CODE> is non-NULL. Alternatively, 96462449Speteryou can include the <CODE>term.h</CODE> file and test the value of the 96562449Spetermacro <CODE>cursor_address</CODE>. 96662449Speter 96762449Speter<H3><A NAME="tuning">Tuning for Speed</A></H3> 96862449Speter 96962449SpeterUse the <CODE>addchstr()</CODE> family of functions for fast 97062449Speterscreen-painting of text when you know the text doesn't contain any 97162449Spetercontrol characters. Try to make attribute changes infrequent on your 97262449Speterscreens. Don't use the <CODE>immedok()</CODE> option! 97362449Speter 97462449Speter<H3><A NAME="special">Special Features of NCURSES</A></H3> 97562449Speter 97662449SpeterThe <CODE>wresize()</CODE> function allows you to resize a window in place. 97762449SpeterThe associated <CODE>resizeterm()</CODE> function simplifies the construction 97862449Speterof <a HREF="#xterm">SIGWINCH</a> handlers, for resizing all windows. <P> 97962449Speter 98062449SpeterThe <CODE>define_key()</CODE> function allows you 98162449Speterto define at runtime function-key control sequences which are not in the 98262449Speterterminal description. 98362449SpeterThe <CODE>keyok()</CODE> function allows you to temporarily 98462449Speterenable or disable interpretation of any function-key control sequence. <P> 98562449Speter 98662449SpeterThe <CODE>use_default_colors()</CODE> function allows you to construct 98762449Speterapplications which can use the terminal's default foreground and 98862449Speterbackground colors as an additional "default" color. 98962449SpeterSeveral terminal emulators support this feature, which is based on ISO 6429. <P> 99062449Speter 99162449SpeterNcurses supports up 16 colors, unlike SVr4 curses which defines only 8. 99262449SpeterWhile most terminals which provide color allow only 8 colors, about 99362449Spetera quarter (including XFree86 xterm) support 16 colors. 99462449Speter 99562449Speter<H2><A NAME="compat">Compatibility with Older Versions</A></H2> 99662449Speter 99762449SpeterDespite our best efforts, there are some differences between <CODE>ncurses</CODE> 99862449Speterand the (undocumented!) behavior of older curses implementations. These arise 99962449Speterfrom ambiguities or omissions in the documentation of the API. 100062449Speter 100162449Speter<H3><A NAME="refbug">Refresh of Overlapping Windows</A></H3> 100262449Speter 100362449SpeterIf you define two windows A and B that overlap, and then alternately scribble 100462449Speteron and refresh them, the changes made to the overlapping region under historic 100562449Speter<CODE>curses</CODE> versions were often not documented precisely. <P> 100662449Speter 100762449SpeterTo understand why this is a problem, remember that screen updates are 100862449Spetercalculated between two representations of the <EM>entire</EM> display. The 1009166124Srafandocumentation says that when you refresh a window, it is first copied to the 101062449Spetervirtual screen, and then changes are calculated to update the physical screen 101162449Speter(and applied to the terminal). But "copied to" is not very specific, and 101262449Spetersubtle differences in how copying works can produce different behaviors in the 101362449Spetercase where two overlapping windows are each being refreshed at unpredictable 101462449Speterintervals. <P> 101562449Speter 101662449SpeterWhat happens to the overlapping region depends on what <CODE>wnoutrefresh()</CODE> 101762449Speterdoes with its argument -- what portions of the argument window it copies to the 101862449Spetervirtual screen. Some implementations do "change copy", copying down only 101962449Speterlocations in the window that have changed (or been marked changed with 102062449Speter<CODE>wtouchln()</CODE> and friends). Some implementations do "entire copy", 102162449Spetercopying <EM>all</EM> window locations to the virtual screen whether or not 102262449Speterthey have changed. <P> 102362449Speter 102462449SpeterThe <CODE>ncurses</CODE> library itself has not always been consistent on this 102562449Speterscore. Due to a bug, versions 1.8.7 to 1.9.8a did entire copy. Versions 102662449Speter1.8.6 and older, and versions 1.9.9 and newer, do change copy. <P> 102762449Speter 102862449SpeterFor most commercial curses implementations, it is not documented and not known 102962449Speterfor sure (at least not to the <CODE>ncurses</CODE> maintainers) whether they do 103062449Speterchange copy or entire copy. We know that System V release 3 curses has logic 103162449Speterin it that looks like an attempt to do change copy, but the surrounding logic 103262449Speterand data representations are sufficiently complex, and our knowledge 103362449Spetersufficiently indirect, that it's hard to know whether this is reliable. 103462449Speter 103562449SpeterIt is not clear what the SVr4 documentation and XSI standard intend. The XSI 103662449SpeterCurses standard barely mentions wnoutrefresh(); the SVr4 documents seem to be 103762449Speterdescribing entire-copy, but it is possible with some effort and straining to 103862449Speterread them the other way. <P> 103962449Speter 104062449SpeterIt might therefore be unwise to rely on either behavior in programs that might 104162449Speterhave to be linked with other curses implementations. Instead, you can do an 104262449Speterexplicit <CODE>touchwin()</CODE> before the <CODE>wnoutrefresh()</CODE> call to 104362449Speterguarantee an entire-contents copy anywhere. <P> 104462449Speter 104562449SpeterThe really clean way to handle this is to use the panels library. If, 104662449Speterwhen you want a screen update, you do <CODE>update_panels()</CODE>, it will 1047166124Srafando all the necessary <CODE>wnoutrefresh()</CODE> calls for whatever panel 104862449Speterstacking order you have defined. Then you can do one <CODE>doupdate()</CODE> 104962449Speterand there will be a <EM>single</EM> burst of physical I/O that will do 105062449Speterall your updates. 105162449Speter 105262449Speter<H3><A NAME="backbug">Background Erase</A></H3> 105362449Speter 105462449SpeterIf you have been using a very old versions of <CODE>ncurses</CODE> (1.8.7 or 105562449Speterolder) you may be surprised by the behavior of the erase functions. In older 105662449Speterversions, erased areas of a window were filled with a blank modified by the 105762449Speterwindow's current attribute (as set by <STRONG>wattrset()</STRONG>, <STRONG>wattron()</STRONG>, 105862449Speter<STRONG>wattroff()</STRONG> and friends). <P> 105962449Speter 106062449SpeterIn newer versions, this is not so. Instead, the attribute of erased blanks 106162449Speteris normal unless and until it is modified by the functions <CODE>bkgdset()</CODE> 106262449Speteror <CODE>wbkgdset()</CODE>. <P> 106362449Speter 106462449SpeterThis change in behavior conforms <CODE>ncurses</CODE> to System V Release 4 and 106562449Speterthe XSI Curses standard. 106662449Speter 106762449Speter<H2><A NAME="xsifuncs">XSI Curses Conformance</A></H2> 106862449Speter 106962449SpeterThe <CODE>ncurses</CODE> library is intended to be base-level conformant with the 107062449SpeterXSI Curses standard from X/Open. Many extended-level features (in fact, almost 107162449Speterall features not directly concerned with wide characters and 107262449Speterinternationalization) are also supported. <P> 107362449Speter 107462449SpeterOne effect of XSI conformance is the change in behavior described under 107562449Speter<A HREF="#backbug">"Background Erase -- Compatibility with Old Versions"</A>. <P> 107662449Speter 107762449SpeterAlso, <CODE>ncurses</CODE> meets the XSI requirement that every macro 107862449Speterentry point have a corresponding function which may be linked (and 107962449Speterwill be prototype-checked) if the macro definition is disabled with 108062449Speter<CODE>#undef</CODE>. 108162449Speter 108262449Speter<H1><A NAME="panels">The Panels Library</A></H1> 108362449Speter 108462449SpeterThe <CODE>ncurses</CODE> library by itself provides good support for screen 108562449Speterdisplays in which the windows are tiled (non-overlapping). In the more 108662449Spetergeneral case that windows may overlap, you have to use a series of 108762449Speter<CODE>wnoutrefresh()</CODE> calls followed by a <CODE>doupdate()</CODE>, and be 108862449Spetercareful about the order you do the window refreshes in. It has to be 108962449Speterbottom-upwards, otherwise parts of windows that should be obscured will 109062449Spetershow through. <P> 109162449Speter 109262449SpeterWhen your interface design is such that windows may dive deeper into the 109362449Spetervisibility stack or pop to the top at runtime, the resulting book-keeping 109462449Spetercan be tedious and difficult to get right. Hence the panels library. <P> 109562449Speter 109662449SpeterThe <CODE>panel</CODE> library first appeared in AT&T System V. The 109762449Speterversion documented here is the <CODE>panel</CODE> code distributed 109862449Speterwith <CODE>ncurses</CODE>. 109962449Speter 110062449Speter<H2><A NAME="pcompile">Compiling With the Panels Library</A></H2> 110162449Speter 110262449SpeterYour panels-using modules must import the panels library declarations with 110362449Speter 110462449Speter<PRE> 110562449Speter #include <panel.h> 110662449Speter</PRE> 110762449Speter 110862449Speterand must be linked explicitly with the panels library using an 110962449Speter<CODE>-lpanel</CODE> argument. Note that they must also link the 111062449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 111162449Speterare two-pass and will accept either order, but it is still good practice 111262449Speterto put <CODE>-lpanel</CODE> first and <CODE>-lncurses</CODE> second. 111362449Speter 111462449Speter<H2><A NAME="poverview">Overview of Panels</A></H2> 111562449Speter 111662449SpeterA panel object is a window that is implicitly treated as part of a 111762449Speter<DFN>deck</DFN> including all other panel objects. The deck has an implicit 111862449Speterbottom-to-top visibility order. The panels library includes an update 111962449Speterfunction (analogous to <CODE>refresh()</CODE>) that displays all panels in the 112062449Speterdeck in the proper order to resolve overlaps. The standard window, 112162449Speter<CODE>stdscr</CODE>, is considered below all panels. <P> 112262449Speter 112362449SpeterDetails on the panels functions are available in the man pages. We'll just 112462449Speterhit the highlights here. <P> 112562449Speter 112662449SpeterYou create a panel from a window by calling <CODE>new_panel()</CODE> on a 112762449Speterwindow pointer. It then becomes the top of the deck. The panel's window 112862449Speteris available as the value of <CODE>panel_window()</CODE> called with the 112962449Speterpanel pointer as argument.<P> 113062449Speter 113162449SpeterYou can delete a panel (removing it from the deck) with <CODE>del_panel</CODE>. 113262449SpeterThis will not deallocate the associated window; you have to do that yourself. 113362449Speter 113462449SpeterYou can replace a panel's window with a different window by calling 113562449Speter<CODE>replace_window</CODE>. The new window may be of different size; 113662449Speterthe panel code will re-compute all overlaps. This operation doesn't 113762449Speterchange the panel's position in the deck. <P> 113862449Speter 113962449SpeterTo move a panel's window, use <CODE>move_panel()</CODE>. The 114062449Speter<CODE>mvwin()</CODE> function on the panel's window isn't sufficient because it 114162449Speterdoesn't update the panels library's representation of where the windows are. 114262449SpeterThis operation leaves the panel's depth, contents, and size unchanged. <P> 114362449Speter 114462449SpeterTwo functions (<CODE>top_panel()</CODE>, <CODE>bottom_panel()</CODE>) are 114562449Speterprovided for rearranging the deck. The first pops its argument window to the 114662449Spetertop of the deck; the second sends it to the bottom. Either operation leaves 114762449Speterthe panel's screen location, contents, and size unchanged. <P> 114862449Speter 114962449SpeterThe function <CODE>update_panels()</CODE> does all the 115062449Speter<CODE>wnoutrefresh()</CODE> calls needed to prepare for 115162449Speter<CODE>doupdate()</CODE> (which you must call yourself, afterwards). <P> 115262449Speter 115362449SpeterTypically, you will want to call <CODE>update_panels()</CODE> and 115462449Speter<CODE>doupdate()</CODE> just before accepting command input, once in each cycle 115562449Speterof interaction with the user. If you call <CODE>update_panels()</CODE> after 115662449Spetereach and every panel write, you'll generate a lot of unnecessary refresh 115762449Speteractivity and screen flicker. 115862449Speter 115962449Speter<H2><A NAME="pstdscr">Panels, Input, and the Standard Screen</A></H2> 116062449Speter 116162449SpeterYou shouldn't mix <CODE>wnoutrefresh()</CODE> or <CODE>wrefresh()</CODE> 116262449Speteroperations with panels code; this will work only if the argument window 116362449Speteris either in the top panel or unobscured by any other panels. <P> 116462449Speter 116562449SpeterThe <CODE>stsdcr</CODE> window is a special case. It is considered below all 116662449Speterpanels. Because changes to panels may obscure parts of <CODE>stdscr</CODE>, 116762449Speterthough, you should call <CODE>update_panels()</CODE> before 116862449Speter<CODE>doupdate()</CODE> even when you only change <CODE>stdscr</CODE>. <P> 116962449Speter 117062449SpeterNote that <CODE>wgetch</CODE> automatically calls <CODE>wrefresh</CODE>. 117162449SpeterTherefore, before requesting input from a panel window, you need to be sure 117262449Speterthat the panel is totally unobscured. <P> 117362449Speter 117462449SpeterThere is presently no way to display changes to one obscured panel without 117562449Speterrepainting all panels. 117662449Speter 117762449Speter<H2><A NAME="hiding">Hiding Panels</A></H2> 117862449Speter 117962449SpeterIt's possible to remove a panel from the deck temporarily; use 118062449Speter<CODE>hide_panel</CODE> for this. Use <CODE>show_panel()</CODE> to render it 118162449Spetervisible again. The predicate function <CODE>panel_hidden</CODE> 118262449Spetertests whether or not a panel is hidden. <P> 118362449Speter 118462449SpeterThe <CODE>panel_update</CODE> code ignores hidden panels. You cannot do 118562449Speter<CODE>top_panel()</CODE> or <CODE>bottom_panel</CODE> on a hidden panel(). 118662449SpeterOther panels operations are applicable. 118762449Speter 118862449Speter<H2><A NAME="pmisc">Miscellaneous Other Facilities</A></H2> 118962449Speter 119062449SpeterIt's possible to navigate the deck using the functions 119162449Speter<CODE>panel_above()</CODE> and <CODE>panel_below</CODE>. Handed a panel 119262449Speterpointer, they return the panel above or below that panel. Handed 119362449Speter<CODE>NULL</CODE>, they return the bottom-most or top-most panel. <P> 119462449Speter 119562449SpeterEvery panel has an associated user pointer, not used by the panel code, to 119662449Speterwhich you can attach application data. See the man page documentation 119762449Speterof <CODE>set_panel_userptr()</CODE> and <CODE>panel_userptr</CODE> for 119862449Speterdetails. 119962449Speter 120062449Speter<H1><A NAME="menu">The Menu Library</A></H1> 120162449Speter 120262449SpeterA menu is a screen display that assists the user to choose some subset 120362449Speterof a given set of items. The <CODE>menu</CODE> library is a curses 120462449Speterextension that supports easy programming of menu hierarchies with a 120562449Speteruniform but flexible interface. <P> 120662449Speter 120762449SpeterThe <CODE>menu</CODE> library first appeared in AT&T System V. The 120862449Speterversion documented here is the <CODE>menu</CODE> code distributed 120962449Speterwith <CODE>ncurses</CODE>. 121062449Speter 121162449Speter<H2><A NAME="mcompile">Compiling With the menu Library</A></H2> 121262449Speter 121362449SpeterYour menu-using modules must import the menu library declarations with 121462449Speter 121562449Speter<PRE> 121662449Speter #include <menu.h> 121762449Speter</PRE> 121862449Speter 121962449Speterand must be linked explicitly with the menus library using an 122062449Speter<CODE>-lmenu</CODE> argument. Note that they must also link the 122162449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 122262449Speterare two-pass and will accept either order, but it is still good practice 122362449Speterto put <CODE>-lmenu</CODE> first and <CODE>-lncurses</CODE> second. 122462449Speter 122562449Speter<H2><A NAME="moverview">Overview of Menus</A></H2> 122662449Speter 122762449SpeterThe menus created by this library consist of collections of 122862449Speter<DFN>items</DFN> including a name string part and a description string 122962449Speterpart. To make menus, you create groups of these items and connect 123062449Speterthem with menu frame objects. <P> 123162449Speter 123262449SpeterThe menu can then by <DFN>posted</DFN>, that is written to an 123362449Speterassociated window. Actually, each menu has two associated windows; a 123462449Spetercontaining window in which the programmer can scribble titles or 123562449Speterborders, and a subwindow in which the menu items proper are displayed. 123662449SpeterIf this subwindow is too small to display all the items, it will be a 123762449Speterscrollable viewport on the collection of items. <P> 123862449Speter 123962449SpeterA menu may also be <DFN>unposted</DFN> (that is, undisplayed), and finally 124062449Speterfreed to make the storage associated with it and its items available for 124162449Speterre-use. <P> 124262449Speter 124362449SpeterThe general flow of control of a menu program looks like this: 124462449Speter 124562449Speter<OL> 124662449Speter<LI>Initialize <CODE>curses</CODE>. 124762449Speter<LI>Create the menu items, using <CODE>new_item()</CODE>. 124862449Speter<LI>Create the menu using <CODE>new_menu()</CODE>. 1249166124Srafan<LI>Post the menu using <CODE>post_menu()</CODE>. 125062449Speter<LI>Refresh the screen. 125162449Speter<LI>Process user requests via an input loop. 1252166124Srafan<LI>Unpost the menu using <CODE>unpost_menu()</CODE>. 125362449Speter<LI>Free the menu, using <CODE>free_menu()</CODE>. 125462449Speter<LI>Free the items using <CODE>free_item()</CODE>. 125562449Speter<LI>Terminate <CODE>curses</CODE>. 125662449Speter</OL> 125762449Speter 125862449Speter<H2><A NAME="mselect">Selecting items</A></H2> 125962449Speter 126062449SpeterMenus may be multi-valued or (the default) single-valued (see the manual 126162449Speterpage <CODE>menu_opts(3x)</CODE> to see how to change the default). 126262449SpeterBoth types always have a <DFN>current item</DFN>. <P> 126362449Speter 126462449SpeterFrom a single-valued menu you can read the selected value simply by looking 126562449Speterat the current item. From a multi-valued menu, you get the selected set 126662449Speterby looping through the items applying the <CODE>item_value()</CODE> 126762449Speterpredicate function. Your menu-processing code can use the function 126862449Speter<CODE>set_item_value()</CODE> to flag the items in the select set. <P> 126962449Speter 127062449SpeterMenu items can be made unselectable using <CODE>set_item_opts()</CODE> 127162449Speteror <CODE>item_opts_off()</CODE> with the <CODE>O_SELECTABLE</CODE> 127262449Speterargument. This is the only option so far defined for menus, but it 127362449Speteris good practice to code as though other option bits might be on. 127462449Speter 127562449Speter<H2><A NAME="mdisplay">Menu Display</A></H2> 127662449Speter 127762449SpeterThe menu library calculates a minimum display size for your window, based 127862449Speteron the following variables: 127962449Speter 128062449Speter<UL> 128162449Speter<LI>The number and maximum length of the menu items 128262449Speter<LI>Whether the O_ROWMAJOR option is enabled 128362449Speter<LI>Whether display of descriptions is enabled 128462449Speter<LI>Whatever menu format may have been set by the programmer 128562449Speter<LI>The length of the menu mark string used for highlighting selected items 128662449Speter</UL> 128762449Speter 128862449SpeterThe function <CODE>set_menu_format()</CODE> allows you to set the 128962449Spetermaximum size of the viewport or <DFN>menu page</DFN> that will be used 129062449Speterto display menu items. You can retrieve any format associated with a 129162449Spetermenu with <CODE>menu_format()</CODE>. The default format is rows=16, 129262449Spetercolumns=1. <P> 129362449Speter 129462449SpeterThe actual menu page may be smaller than the format size. This depends 129562449Speteron the item number and size and whether O_ROWMAJOR is on. This option 129662449Speter(on by default) causes menu items to be displayed in a `raster-scan' 129762449Speterpattern, so that if more than one item will fit horizontally the first 129862449Spetercouple of items are side-by-side in the top row. The alternative is 129962449Spetercolumn-major display, which tries to put the first several items in 130062449Speterthe first column. <P> 130162449Speter 130262449SpeterAs mentioned above, a menu format not large enough to allow all items to fit 130362449Speteron-screen will result in a menu display that is vertically scrollable. <P> 130462449SpeterYou can scroll it with requests to the menu driver, which will be described 130562449Speterin the section on <A HREF="#minput">menu input handling</A>. <P> 130662449Speter 130762449SpeterEach menu has a <DFN>mark string</DFN> used to visually tag selected items; 130862449Spetersee the <CODE>menu_mark(3x)</CODE> manual page for details. The mark 130962449Speterstring length also influences the menu page size. <P> 131062449Speter 131162449SpeterThe function <CODE>scale_menu()</CODE> returns the minimum display size 131262449Speterthat the menu code computes from all these factors. 131362449Speter 131462449SpeterThere are other menu display attributes including a select attribute, 131562449Speteran attribute for selectable items, an attribute for unselectable items, 131662449Speterand a pad character used to separate item name text from description 131762449Spetertext. These have reasonable defaults which the library allows you to 131862449Speterchange (see the <CODE>menu_attribs(3x)</CODE> manual page. 131962449Speter 132062449Speter<H2><A NAME="mwindows">Menu Windows</A></H2> 132162449Speter 132262449SpeterEach menu has, as mentioned previously, a pair of associated windows. 132362449SpeterBoth these windows are painted when the menu is posted and erased when 132462449Speterthe menu is unposted. <P> 132562449Speter 132662449SpeterThe outer or frame window is not otherwise touched by the menu 132762449Speterroutines. It exists so the programmer can associate a title, a 132862449Speterborder, or perhaps help text with the menu and have it properly 132962449Speterrefreshed or erased at post/unpost time. The inner window or 133062449Speter<DFN>subwindow</DFN> is where the current menu page is displayed. <P> 133162449Speter 133262449SpeterBy default, both windows are <CODE>stdscr</CODE>. You can set them with the 133362449Speterfunctions in <CODE>menu_win(3x)</CODE>. <P> 133462449Speter 1335166124SrafanWhen you call <CODE>post_menu()</CODE>, you write the menu to its 1336166124Srafansubwindow. When you call <CODE>unpost_menu()</CODE>, you erase the 133762449Spetersubwindow, However, neither of these actually modifies the screen. To 133862449Speterdo that, call <CODE>wrefresh()</CODE> or some equivalent. 133962449Speter 134062449Speter<H2><A NAME="minput">Processing Menu Input</A></H2> 134162449Speter 134262449SpeterThe main loop of your menu-processing code should call 134362449Speter<CODE>menu_driver()</CODE> repeatedly. The first argument of this routine 134462449Speteris a menu pointer; the second is a menu command code. You should write an 134562449Speterinput-fetching routine that maps input characters to menu command codes, and 134662449Speterpass its output to <CODE>menu_driver()</CODE>. The menu command codes are 134762449Speterfully documented in <CODE>menu_driver(3x)</CODE>. <P> 134862449Speter 134962449SpeterThe simplest group of command codes is <CODE>REQ_NEXT_ITEM</CODE>, 135062449Speter<CODE>REQ_PREV_ITEM</CODE>, <CODE>REQ_FIRST_ITEM</CODE>, 135162449Speter<CODE>REQ_LAST_ITEM</CODE>, <CODE>REQ_UP_ITEM</CODE>, 135262449Speter<CODE>REQ_DOWN_ITEM</CODE>, <CODE>REQ_LEFT_ITEM</CODE>, 135362449Speter<CODE>REQ_RIGHT_ITEM</CODE>. These change the currently selected 135462449Speteritem. These requests may cause scrolling of the menu page if it only 135562449Speterpartially displayed. <P> 135662449Speter 135762449SpeterThere are explicit requests for scrolling which also change the 135862449Spetercurrent item (because the select location does not change, but the 135962449Speteritem there does). These are <CODE>REQ_SCR_DLINE</CODE>, 136062449Speter<CODE>REQ_SCR_ULINE</CODE>, <CODE>REQ_SCR_DPAGE</CODE>, and 136162449Speter<CODE>REQ_SCR_UPAGE</CODE>. <P> 136262449Speter 136362449SpeterThe <CODE>REQ_TOGGLE_ITEM</CODE> selects or deselects the current item. 136462449SpeterIt is for use in multi-valued menus; if you use it with <CODE>O_ONEVALUE</CODE> 136562449Speteron, you'll get an error return (<CODE>E_REQUEST_DENIED</CODE>). <P> 136662449Speter 136762449SpeterEach menu has an associated pattern buffer. The 136862449Speter<CODE>menu_driver()</CODE> logic tries to accumulate printable ASCII 136962449Spetercharacters passed in in that buffer; when it matches a prefix of an 137062449Speteritem name, that item (or the next matching item) is selected. If 137162449Speterappending a character yields no new match, that character is deleted 137262449Speterfrom the pattern buffer, and <CODE>menu_driver()</CODE> returns 137362449Speter<CODE>E_NO_MATCH</CODE>. <P> 137462449Speter 137562449SpeterSome requests change the pattern buffer directly: 137662449Speter<CODE>REQ_CLEAR_PATTERN</CODE>, <CODE>REQ_BACK_PATTERN</CODE>, 137762449Speter<CODE>REQ_NEXT_MATCH</CODE>, <CODE>REQ_PREV_MATCH</CODE>. The latter 137862449Spetertwo are useful when pattern buffer input matches more than one item 137962449Speterin a multi-valued menu. <P> 138062449Speter 138162449SpeterEach successful scroll or item navigation request clears the pattern 138262449Speterbuffer. It is also possible to set the pattern buffer explicitly 138362449Speterwith <CODE>set_menu_pattern()</CODE>. <P> 138462449Speter 138562449SpeterFinally, menu driver requests above the constant <CODE>MAX_COMMAND</CODE> 138662449Speterare considered application-specific commands. The <CODE>menu_driver()</CODE> 138762449Spetercode ignores them and returns <CODE>E_UNKNOWN_COMMAND</CODE>. 138862449Speter 138962449Speter<H2><A NAME="mmisc">Miscellaneous Other Features</A></H2> 139062449Speter 139162449SpeterVarious menu options can affect the processing and visual appearance 139262449Speterand input processing of menus. See <CODE>menu_opts(3x) for 139362449Speterdetails.</CODE> <P> 139462449Speter 139562449SpeterIt is possible to change the current item from application code; this 139662449Speteris useful if you want to write your own navigation requests. It is 139762449Speteralso possible to explicitly set the top row of the menu display. See 139862449Speter<CODE>mitem_current(3x)</CODE>. 139962449Speter 140062449SpeterIf your application needs to change the menu subwindow cursor for 140162449Speterany reason, <CODE>pos_menu_cursor()</CODE> will restore it to the 140262449Spetercorrect location for continuing menu driver processing. <P> 140362449Speter 140462449SpeterIt is possible to set hooks to be called at menu initialization and 140562449Speterwrapup time, and whenever the selected item changes. See 140662449Speter<CODE>menu_hook(3x)</CODE>. <P> 140762449Speter 140862449SpeterEach item, and each menu, has an associated user pointer on which you 140962449Spetercan hang application data. See <CODE>mitem_userptr(3x)</CODE> and 141062449Speter<CODE>menu_userptr(3x)</CODE>. 141162449Speter 141262449Speter<H1><A NAME="form">The Forms Library</A></H1> 141362449Speter 141462449SpeterThe <CODE>form</CODE> library is a curses extension that supports easy 141562449Speterprogramming of on-screen forms for data entry and program control. <P> 141662449Speter 141762449SpeterThe <CODE>form</CODE> library first appeared in AT&T System V. The 141862449Speterversion documented here is the <CODE>form</CODE> code distributed 141962449Speterwith <CODE>ncurses</CODE>. 142062449Speter 142162449Speter<H2><A NAME="fcompile">Compiling With the form Library</A></H2> 142262449Speter 142362449SpeterYour form-using modules must import the form library declarations with 142462449Speter 142562449Speter<PRE> 142662449Speter #include <form.h> 142762449Speter</PRE> 142862449Speter 142962449Speterand must be linked explicitly with the forms library using an 143062449Speter<CODE>-lform</CODE> argument. Note that they must also link the 143162449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 143262449Speterare two-pass and will accept either order, but it is still good practice 143362449Speterto put <CODE>-lform</CODE> first and <CODE>-lncurses</CODE> second. 143462449Speter 143562449Speter<H2><A NAME="foverview">Overview of Forms</A></H2> 143662449Speter 143762449SpeterA form is a collection of fields; each field may be either a label 143862449Speter(explanatory text) or a data-entry location. Long forms may be 143962449Spetersegmented into pages; each entry to a new page clears the screen. <P> 144062449SpeterTo make forms, you create groups of fields and connect them with form 144162449Speterframe objects; the form library makes this relatively simple. <P> 144262449Speter 144362449SpeterOnce defined, a form can be <DFN>posted</DFN>, that is written to an 144462449Speterassociated window. Actually, each form has two associated windows; a 144562449Spetercontaining window in which the programmer can scribble titles or 144662449Speterborders, and a subwindow in which the form fields proper are displayed. <P> 144762449Speter 144862449SpeterAs the form user fills out the posted form, navigation and editing 144962449Speterkeys support movement between fields, editing keys support modifying 145062449Speterfield, and plain text adds to or changes data in a current field. The 145162449Speterform library allows you (the forms designer) to bind each navigation 145262449Speterand editing key to any keystroke accepted by <CODE>curses</CODE> 145362449Speter 145462449SpeterFields may have validation conditions on them, so that they check input 145562449Speterdata for type and value. The form library supplies a rich set of 145662449Speterpre-defined field types, and makes it relatively easy to define new ones. <P> 145762449Speter 145862449SpeterOnce its transaction is completed (or aborted), a form may be 145962449Speter<DFN>unposted</DFN> (that is, undisplayed), and finally freed to make 146062449Speterthe storage associated with it and its items available for re-use. <P> 146162449Speter 146262449SpeterThe general flow of control of a form program looks like this: 146362449Speter 146462449Speter<OL> 146562449Speter<LI>Initialize <CODE>curses</CODE>. 146662449Speter<LI>Create the form fields, using <CODE>new_field()</CODE>. 146762449Speter<LI>Create the form using <CODE>new_form()</CODE>. 1468166124Srafan<LI>Post the form using <CODE>post_form()</CODE>. 146962449Speter<LI>Refresh the screen. 147062449Speter<LI>Process user requests via an input loop. 1471166124Srafan<LI>Unpost the form using <CODE>unpost_form()</CODE>. 147262449Speter<LI>Free the form, using <CODE>free_form()</CODE>. 147362449Speter<LI>Free the fields using <CODE>free_field()</CODE>. 147462449Speter<LI>Terminate <CODE>curses</CODE>. 147562449Speter</OL> 147662449Speter 147762449SpeterNote that this looks much like a menu program; the form library handles 147862449Spetertasks which are in many ways similar, and its interface was obviously 147962449Speterdesigned to resemble that of the <A HREF="#menu">menu library</A> 148062449Speterwherever possible. <P> 148162449Speter 148262449SpeterIn forms programs, however, the `process user requests' is somewhat more 148362449Spetercomplicated than for menus. Besides menu-like navigation operations, 148462449Speterthe menu driver loop has to support field editing and data validation. 148562449Speter 148662449Speter<H2><A NAME="fcreate">Creating and Freeing Fields and Forms</A></H2> 148762449Speter 148862449SpeterThe basic function for creating fields is <CODE>new_field()</CODE>: 148962449Speter 149062449Speter<PRE> 149162449SpeterFIELD *new_field(int height, int width, /* new field size */ 149262449Speter int top, int left, /* upper left corner */ 149362449Speter int offscreen, /* number of offscreen rows */ 149462449Speter int nbuf); /* number of working buffers */ 149562449Speter</PRE> 149662449Speter 149762449SpeterMenu items always occupy a single row, but forms fields may have 149862449Spetermultiple rows. So <CODE>new_field()</CODE> requires you to specify a 149962449Speterwidth and height (the first two arguments, which mist both be greater 150062449Speterthan zero). <P> 150162449Speter 150262449SpeterYou must also specify the location of the field's upper left corner on 150362449Speterthe screen (the third and fourth arguments, which must be zero or 150462449Spetergreater). Note that these coordinates are relative to the form 150562449Spetersubwindow, which will coincide with <CODE>stdscr</CODE> by default but 150662449Speterneed not be <CODE>stdscr</CODE> if you've done an explicit 1507166124Srafan<CODE>set_form_win()</CODE> call. <P> 150862449Speter 150962449SpeterThe fifth argument allows you to specify a number of off-screen rows. If 151062449Speterthis is zero, the entire field will always be displayed. If it is 151162449Speternonzero, the form will be scrollable, with only one screen-full (initially 151262449Speterthe top part) displayed at any given time. If you make a field dynamic 151362449Speterand grow it so it will no longer fit on the screen, the form will become 151462449Speterscrollable even if the <CODE>offscreen</CODE> argument was initially zero. <P> 151562449Speter 151662449SpeterThe forms library allocates one working buffer per field; the size of 151762449Spetereach buffer is <CODE>((height + offscreen)*width + 1</CODE>, one character 151862449Speterfor each position in the field plus a NUL terminator. The sixth 151962449Speterargument is the number of additional data buffers to allocate for the 152062449Speterfield; your application can use them for its own purposes. 152162449Speter 152262449Speter<PRE> 152362449SpeterFIELD *dup_field(FIELD *field, /* field to copy */ 152462449Speter int top, int left); /* location of new copy */ 152562449Speter</PRE> 152662449Speter 152762449SpeterThe function <CODE>dup_field()</CODE> duplicates an existing field at a 152862449Speternew location. Size and buffering information are copied; some 152962449Speterattribute flags and status bits are not (see the 153062449Speter<CODE>form_field_new(3X)</CODE> for details). 153162449Speter 153262449Speter<PRE> 153362449SpeterFIELD *link_field(FIELD *field, /* field to copy */ 153462449Speter int top, int left); /* location of new copy */ 153562449Speter</PRE> 153662449Speter 153762449SpeterThe function <CODE>link_field()</CODE> also duplicates an existing field 153862449Speterat a new location. The difference from <CODE>dup_field()</CODE> is that 153962449Speterit arranges for the new field's buffer to be shared with the old one. <P> 154062449Speter 154162449SpeterBesides the obvious use in making a field editable from two different 154262449Speterform pages, linked fields give you a way to hack in dynamic labels. If 154362449Speteryou declare several fields linked to an original, and then make them 154462449Speterinactive, changes from the original will still be propagated to the 154562449Speterlinked fields. <P> 154662449Speter 154762449SpeterAs with duplicated fields, linked fields have attribute bits separate 154862449Speterfrom the original. <P> 154962449Speter 155062449SpeterAs you might guess, all these field-allocations return <CODE>NULL</CODE> if 155162449Speterthe field allocation is not possible due to an out-of-memory error or 155262449Speterout-of-bounds arguments. <P> 155362449Speter 155462449SpeterTo connect fields to a form, use 155562449Speter 155662449Speter<PRE> 155762449SpeterFORM *new_form(FIELD **fields); 155862449Speter</PRE> 155962449Speter 156062449SpeterThis function expects to see a NULL-terminated array of field pointers. 156162449SpeterSaid fields are connected to a newly-allocated form object; its address 156262449Speteris returned (or else NULL if the allocation fails). <P> 156362449Speter 156462449SpeterNote that <CODE>new_field()</CODE> does <EM>not</EM> copy the pointer array 156562449Speterinto private storage; if you modify the contents of the pointer array 156662449Speterduring forms processing, all manner of bizarre things might happen. Also 156762449Speternote that any given field may only be connected to one form. <P> 156862449Speter 156962449SpeterThe functions <CODE>free_field()</CODE> and <CODE>free_form</CODE> are available 157062449Speterto free field and form objects. It is an error to attempt to free a field 157162449Speterconnected to a form, but not vice-versa; thus, you will generally free 157262449Speteryour form objects first. 157362449Speter 157462449Speter<H2><A NAME="fattributes">Fetching and Changing Field Attributes</A></H2> 157562449Speter 157662449SpeterEach form field has a number of location and size attributes 157762449Speterassociated with it. There are other field attributes used to control 157862449Speterdisplay and editing of the field. Some (for example, the <CODE>O_STATIC</CODE> bit) 157962449Speterinvolve sufficient complications to be covered in sections of their own 158062449Speterlater on. We cover the functions used to get and set several basic 158162449Speterattributes here. <P> 158262449Speter 158362449SpeterWhen a field is created, the attributes not specified by the 158462449Speter<CODE>new_field</CODE> function are copied from an invisible system 158562449Speterdefault field. In attribute-setting and -fetching functions, the 158662449Speterargument NULL is taken to mean this field. Changes to it persist 158762449Speteras defaults until your forms application terminates. 158862449Speter 158962449Speter<H3><A NAME="fsizes">Fetching Size and Location Data</A></H3> 159062449Speter 159162449SpeterYou can retrieve field sizes and locations through: 159262449Speter 159362449Speter<PRE> 159462449Speterint field_info(FIELD *field, /* field from which to fetch */ 159562449Speter int *height, *int width, /* field size */ 159662449Speter int *top, int *left, /* upper left corner */ 159762449Speter int *offscreen, /* number of offscreen rows */ 159862449Speter int *nbuf); /* number of working buffers */ 159962449Speter</PRE> 160062449Speter 160162449SpeterThis function is a sort of inverse of <CODE>new_field()</CODE>; instead of 160262449Spetersetting size and location attributes of a new field, it fetches them 160362449Speterfrom an existing one. 160462449Speter 160562449Speter<H3><A NAME="flocation">Changing the Field Location</A></H3> 160662449Speter 160762449SpeterIt is possible to move a field's location on the screen: 160862449Speter 160962449Speter<PRE> 161062449Speterint move_field(FIELD *field, /* field to alter */ 161162449Speter int top, int left); /* new upper-left corner */ 161262449Speter</PRE> 161362449Speter 161462449SpeterYou can, of course. query the current location through <CODE>field_info()</CODE>. 161562449Speter 161662449Speter<H3><A NAME="fjust">The Justification Attribute</A></H3> 161762449Speter 161862449SpeterOne-line fields may be unjustified, justified right, justified left, 161962449Speteror centered. Here is how you manipulate this attribute: 162062449Speter 162162449Speter<PRE> 162262449Speterint set_field_just(FIELD *field, /* field to alter */ 162362449Speter int justmode); /* mode to set */ 162462449Speter 162562449Speterint field_just(FIELD *field); /* fetch mode of field */ 162662449Speter</PRE> 162762449Speter 162862449SpeterThe mode values accepted and returned by this functions are 162962449Speterpreprocessor macros <CODE>NO_JUSTIFICATION</CODE>, <CODE>JUSTIFY_RIGHT</CODE>, 163062449Speter<CODE>JUSTIFY_LEFT</CODE>, or <CODE>JUSTIFY_CENTER</CODE>. 163162449Speter 163262449Speter<H3><A NAME="fdispatts">Field Display Attributes</A></H3> 163362449Speter 163462449SpeterFor each field, you can set a foreground attribute for entered 163562449Spetercharacters, a background attribute for the entire field, and a pad 163662449Spetercharacter for the unfilled portion of the field. You can also 163762449Spetercontrol pagination of the form. <P> 163862449Speter 163962449SpeterThis group of four field attributes controls the visual appearance 164062449Speterof the field on the screen, without affecting in any way the data 164162449Speterin the field buffer. 164262449Speter 164362449Speter<PRE> 164462449Speterint set_field_fore(FIELD *field, /* field to alter */ 164562449Speter chtype attr); /* attribute to set */ 164662449Speter 164762449Speterchtype field_fore(FIELD *field); /* field to query */ 164862449Speter 164962449Speterint set_field_back(FIELD *field, /* field to alter */ 165062449Speter chtype attr); /* attribute to set */ 165162449Speter 165262449Speterchtype field_back(FIELD *field); /* field to query */ 165362449Speter 165462449Speterint set_field_pad(FIELD *field, /* field to alter */ 165562449Speter int pad); /* pad character to set */ 165662449Speter 165762449Speterchtype field_pad(FIELD *field); 165862449Speter 165962449Speterint set_new_page(FIELD *field, /* field to alter */ 166062449Speter int flag); /* TRUE to force new page */ 166162449Speter 166262449Speterchtype new_page(FIELD *field); /* field to query */ 166362449Speter</PRE> 166462449Speter 166562449SpeterThe attributes set and returned by the first four functions are normal 166662449Speter<CODE>curses(3x)</CODE> display attribute values (<CODE>A_STANDOUT</CODE>, 166762449Speter<CODE>A_BOLD</CODE>, <CODE>A_REVERSE</CODE> etc). 166862449Speter 166962449SpeterThe page bit of a field controls whether it is displayed at the start of 167062449Spetera new form screen. 167162449Speter 167262449Speter<H3><A NAME="foptions">Field Option Bits</A></H3> 167362449Speter 167462449SpeterThere is also a large collection of field option bits you can set to control 167562449Spetervarious aspects of forms processing. You can manipulate them with these 167662449Speterfunctions: 167762449Speter 167862449Speter<PRE> 167962449Speterint set_field_opts(FIELD *field, /* field to alter */ 168062449Speter int attr); /* attribute to set */ 168162449Speter 168262449Speterint field_opts_on(FIELD *field, /* field to alter */ 168362449Speter int attr); /* attributes to turn on */ 168462449Speter 168562449Speterint field_opts_off(FIELD *field, /* field to alter */ 168662449Speter int attr); /* attributes to turn off */ 168762449Speter 168862449Speterint field_opts(FIELD *field); /* field to query */ 168962449Speter</PRE> 169062449Speter 169162449SpeterBy default, all options are on. Here are the available option bits: 169262449Speter<DL> 169362449Speter<DT> O_VISIBLE 169462449Speter<DD> Controls whether the field is visible on the screen. Can be used 169562449Speterduring form processing to hide or pop up fields depending on the value 169662449Speterof parent fields. 169762449Speter<DT> O_ACTIVE 169862449Speter<DD> Controls whether the field is active during forms processing (i.e. 169962449Spetervisited by form navigation keys). Can be used to make labels or derived 170062449Speterfields with buffer values alterable by the forms application, not the user. 170162449Speter<DT> O_PUBLIC 170262449Speter<DD> Controls whether data is displayed during field entry. If this option is 170362449Speterturned off on a field, the library will accept and edit data in that field, 170462449Speterbut it will not be displayed and the visible field cursor will not move. 170562449SpeterYou can turn off the O_PUBLIC bit to define password fields. 170662449Speter<DT> O_EDIT 170762449Speter<DD> Controls whether the field's data can be modified. When this option is 170862449Speteroff, all editing requests except <CODE>REQ_PREV_CHOICE</CODE> and 170962449Speter<CODE>REQ_NEXT_CHOICE</CODE> will fail. Such read-only fields may be useful for 171062449Speterhelp messages. 171162449Speter<DT> O_WRAP 171262449Speter<DD> Controls word-wrapping in multi-line fields. Normally, when any 171362449Spetercharacter of a (blank-separated) word reaches the end of the current line, the 171462449Speterentire word is wrapped to the next line (assuming there is one). When this 171562449Speteroption is off, the word will be split across the line break. 171662449Speter<DT> O_BLANK 171762449Speter<DD> Controls field blanking. When this option is on, entering a character at 171862449Speterthe first field position erases the entire field (except for the just-entered 171962449Spetercharacter). 172062449Speter<DT> O_AUTOSKIP 172162449Speter<DD> Controls automatic skip to next field when this one fills. Normally, 172262449Speterwhen the forms user tries to type more data into a field than will fit, 172362449Speterthe editing location jumps to next field. When this option is off, the 172462449Speteruser's cursor will hang at the end of the field. This option is ignored 172562449Speterin dynamic fields that have not reached their size limit. 172662449Speter<DT> O_NULLOK 172762449Speter<DD> Controls whether <A HREF="#fvalidation">validation</A> is applied to 172862449Speterblank fields. Normally, it is not; the user can leave a field blank 172962449Speterwithout invoking the usual validation check on exit. If this option is 173062449Speteroff on a field, exit from it will invoke a validation check. 173162449Speter<DT> O_PASSOK 173262449Speter<DD> Controls whether validation occurs on every exit, or only after 173362449Speterthe field is modified. Normally the latter is true. Setting O_PASSOK 173462449Spetermay be useful if your field's validation function may change during 173562449Speterforms processing. 173662449Speter<DT> O_STATIC 173762449Speter<DD> Controls whether the field is fixed to its initial dimensions. If you 173862449Speterturn this off, the field becomes <A HREF="#fdynamic">dynamic</A> and will 173962449Speterstretch to fit entered data. 174062449Speter</DL> 174162449Speter 174262449SpeterA field's options cannot be changed while the field is currently selected. 174362449SpeterHowever, options may be changed on posted fields that are not current. <P> 174462449Speter 174562449SpeterThe option values are bit-masks and can be composed with logical-or in 174662449Speterthe obvious way. 174762449Speter 174862449Speter<H2><A NAME="fstatus">Field Status</A></H2> 174962449Speter 175062449SpeterEvery field has a status flag, which is set to FALSE when the field is 175162449Spetercreated and TRUE when the value in field buffer 0 changes. This flag can 175262449Speterbe queried and set directly: 175362449Speter 175462449Speter<PRE> 175562449Speterint set_field_status(FIELD *field, /* field to alter */ 175662449Speter int status); /* mode to set */ 175762449Speter 175862449Speterint field_status(FIELD *field); /* fetch mode of field */ 175962449Speter</PRE> 176062449Speter 176162449SpeterSetting this flag under program control can be useful if you use the same 176262449Speterform repeatedly, looking for modified fields each time. <P> 176362449Speter 176462449SpeterCalling <CODE>field_status()</CODE> on a field not currently selected 176562449Speterfor input will return a correct value. Calling <CODE>field_status()</CODE> on a 176662449Speterfield that is currently selected for input may not necessarily give a 176762449Spetercorrect field status value, because entered data isn't necessarily copied to 176862449Speterbuffer zero before the exit validation check. 176962449Speter 177062449SpeterTo guarantee that the returned status value reflects reality, call 177162449Speter<CODE>field_status()</CODE> either (1) in the field's exit validation check 177262449Speterroutine, (2) from the field's or form's initialization or termination 177362449Speterhooks, or (3) just after a <CODE>REQ_VALIDATION</CODE> request has been 177462449Speterprocessed by the forms driver. 177562449Speter 177662449Speter<H2><A NAME="fuser">Field User Pointer</A></H2> 177762449Speter 177862449SpeterEach field structure contains one character pointer slot that is not used 177962449Speterby the forms library. It is intended to be used by applications to store 178062449Speterprivate per-field data. You can manipulate it with: 178162449Speter 178262449Speter<PRE> 178362449Speterint set_field_userptr(FIELD *field, /* field to alter */ 178462449Speter char *userptr); /* mode to set */ 178562449Speter 178662449Speterchar *field_userptr(FIELD *field); /* fetch mode of field */ 178762449Speter</PRE> 178862449Speter 178962449Speter(Properly, this user pointer field ought to have <CODE>(void *)</CODE> type. 179062449SpeterThe <CODE>(char *)</CODE> type is retained for System V compatibility.) <P> 179162449Speter 179262449SpeterIt is valid to set the user pointer of the default field (with a 179362449Speter<CODE>set_field_userptr()</CODE> call passed a NULL field pointer.) 179462449SpeterWhen a new field is created, the default-field user pointer is copied 179562449Speterto initialize the new field's user pointer. 179662449Speter 179762449Speter<H2><A NAME="fdynamic">Variable-Sized Fields</A></H2> 179862449Speter 179962449SpeterNormally, a field is fixed at the size specified for it at creation 180062449Spetertime. If, however, you turn off its O_STATIC bit, it becomes 180162449Speter<DFN>dynamic</DFN> and will automatically resize itself to accommodate 180262449Speterdata as it is entered. If the field has extra buffers associated with it, 180362449Speterthey will grow right along with the main input buffer. <P> 180462449Speter 180562449SpeterA one-line dynamic field will have a fixed height (1) but variable 180662449Speterwidth, scrolling horizontally to display data within the field area as 180762449Speteroriginally dimensioned and located. A multi-line dynamic field will 180862449Speterhave a fixed width, but variable height (number of rows), scrolling 180962449Spetervertically to display data within the field area as originally 181062449Speterdimensioned and located. <P> 181162449Speter 181262449SpeterNormally, a dynamic field is allowed to grow without limit. But it is 181362449Speterpossible to set an upper limit on the size of a dynamic field. You do 181462449Speterit with this function: 181562449Speter 181662449Speter<PRE> 181762449Speterint set_max_field(FIELD *field, /* field to alter (may not be NULL) */ 181862449Speter int max_size); /* upper limit on field size */ 181962449Speter</PRE> 182062449Speter 182162449SpeterIf the field is one-line, <CODE>max_size</CODE> is taken to be a column size 182262449Speterlimit; if it is multi-line, it is taken to be a line size limit. To disable 182362449Speterany limit, use an argument of zero. The growth limit can be changed whether 182462449Speteror not the O_STATIC bit is on, but has no effect until it is. <P> 182562449Speter 182662449SpeterThe following properties of a field change when it becomes dynamic: 182762449Speter 182862449Speter<UL> 182962449Speter<LI>If there is no growth limit, there is no final position of the field; 183062449Spetertherefore <CODE>O_AUTOSKIP</CODE> and <CODE>O_NL_OVERLOAD</CODE> are ignored. 183162449Speter<LI>Field justification will be ignored (though whatever justification is 183262449Speterset up will be retained internally and can be queried). 183362449Speter<LI>The <CODE>dup_field()</CODE> and <CODE>link_field()</CODE> calls copy 183462449Speterdynamic-buffer sizes. If the <CODE>O_STATIC</CODE> option is set on one of a 183562449Spetercollection of links, buffer resizing will occur only when the field is 183662449Speteredited through that link. 183762449Speter<LI>The call <CODE>field_info()</CODE> will retrieve the original static size of 183862449Speterthe field; use <CODE>dynamic_field_info()</CODE> to get the actual dynamic size. 183962449Speter</UL> 184062449Speter 184162449Speter<H2><A NAME="fvalidation">Field Validation</A></H2> 184262449Speter 184362449SpeterBy default, a field will accept any data that will fit in its input buffer. 184462449SpeterHowever, it is possible to attach a validation type to a field. If you do 184562449Speterthis, any attempt to leave the field while it contains data that doesn't 184662449Spetermatch the validation type will fail. Some validation types also have a 184762449Spetercharacter-validity check for each time a character is entered in the field. <P> 184862449Speter 184962449SpeterA field's validation check (if any) is not called when 185062449Speter<CODE>set_field_buffer()</CODE> modifies the input buffer, nor when that buffer 185162449Speteris changed through a linked field. <P> 185262449Speter 185362449SpeterThe <CODE>form</CODE> library provides a rich set of pre-defined validation 185462449Spetertypes, and gives you the capability to define custom ones of your own. You 185562449Spetercan examine and change field validation attributes with the following 185662449Speterfunctions: 185762449Speter 185862449Speter<PRE> 185962449Speterint set_field_type(FIELD *field, /* field to alter */ 186062449Speter FIELDTYPE *ftype, /* type to associate */ 186162449Speter ...); /* additional arguments*/ 186262449Speter 186362449SpeterFIELDTYPE *field_type(FIELD *field); /* field to query */ 186462449Speter</PRE> 186562449Speter 186662449SpeterThe validation type of a field is considered an attribute of the field. As 186762449Speterwith other field attributes, Also, doing <CODE>set_field_type()</CODE> with a 186862449Speter<CODE>NULL</CODE> field default will change the system default for validation of 186962449Speternewly-created fields. <P> 187062449Speter 187162449SpeterHere are the pre-defined validation types: 187262449Speter 187362449Speter<H3><A NAME="ftype_alpha">TYPE_ALPHA</A></H3> 187462449Speter 187562449SpeterThis field type accepts alphabetic data; no blanks, no digits, no special 187662449Spetercharacters (this is checked at character-entry time). It is set up with: 187762449Speter 187862449Speter<PRE> 187962449Speterint set_field_type(FIELD *field, /* field to alter */ 188062449Speter TYPE_ALPHA, /* type to associate */ 188162449Speter int width); /* maximum width of field */ 188262449Speter</PRE> 188362449Speter 188462449SpeterThe <CODE>width</CODE> argument sets a minimum width of data. Typically 188562449Speteryou'll want to set this to the field width; if it's greater than the 188662449Speterfield width, the validation check will always fail. A minimum width 188762449Speterof zero makes field completion optional. 188862449Speter 188962449Speter<H3><A NAME="ftype_alnum">TYPE_ALNUM</A></H3> 189062449Speter 189162449SpeterThis field type accepts alphabetic data and digits; no blanks, no special 189262449Spetercharacters (this is checked at character-entry time). It is set up with: 189362449Speter 189462449Speter<PRE> 189562449Speterint set_field_type(FIELD *field, /* field to alter */ 189662449Speter TYPE_ALNUM, /* type to associate */ 189762449Speter int width); /* maximum width of field */ 189862449Speter</PRE> 189962449Speter 190062449SpeterThe <CODE>width</CODE> argument sets a minimum width of data. As with 190162449SpeterTYPE_ALPHA, typically you'll want to set this to the field width; if it's 190262449Spetergreater than the field width, the validation check will always fail. A 190362449Speterminimum width of zero makes field completion optional. 190462449Speter 190562449Speter<H3><A NAME="ftype_enum">TYPE_ENUM</A></H3> 190662449Speter 190762449SpeterThis type allows you to restrict a field's values to be among a specified 190862449Speterset of string values (for example, the two-letter postal codes for U.S. 190962449Speterstates). It is set up with: 191062449Speter 191162449Speter<PRE> 191262449Speterint set_field_type(FIELD *field, /* field to alter */ 191362449Speter TYPE_ENUM, /* type to associate */ 191462449Speter char **valuelist; /* list of possible values */ 191562449Speter int checkcase; /* case-sensitive? */ 191662449Speter int checkunique); /* must specify uniquely? */ 191762449Speter</PRE> 191862449Speter 191962449SpeterThe <CODE>valuelist</CODE> parameter must point at a NULL-terminated list of 192062449Spetervalid strings. The <CODE>checkcase</CODE> argument, if true, makes comparison 192162449Speterwith the string case-sensitive. <P> 192262449Speter 192362449SpeterWhen the user exits a TYPE_ENUM field, the validation procedure tries to 192462449Spetercomplete the data in the buffer to a valid entry. If a complete choice string 192562449Speterhas been entered, it is of course valid. But it is also possible to enter a 192662449Speterprefix of a valid string and have it completed for you. <P> 192762449Speter 192862449SpeterBy default, if you enter such a prefix and it matches more than one value 192962449Speterin the string list, the prefix will be completed to the first matching 193062449Spetervalue. But the <CODE>checkunique</CODE> argument, if true, requires prefix 193162449Spetermatches to be unique in order to be valid. <P> 193262449Speter 193362449SpeterThe <CODE>REQ_NEXT_CHOICE</CODE> and <CODE>REQ_PREV_CHOICE</CODE> input requests 193462449Spetercan be particularly useful with these fields. 193562449Speter 193662449Speter<H3><A NAME="ftype_integer">TYPE_INTEGER</A></H3> 193762449Speter 193862449SpeterThis field type accepts an integer. It is set up as follows: 193962449Speter 194062449Speter<PRE> 194162449Speterint set_field_type(FIELD *field, /* field to alter */ 194262449Speter TYPE_INTEGER, /* type to associate */ 194362449Speter int padding, /* # places to zero-pad to */ 194462449Speter int vmin, int vmax); /* valid range */ 194562449Speter</PRE> 194662449Speter 194762449SpeterValid characters consist of an optional leading minus and digits. 194862449SpeterThe range check is performed on exit. If the range maximum is less 194962449Speterthan or equal to the minimum, the range is ignored. <P> 195062449Speter 195162449SpeterIf the value passes its range check, it is padded with as many leading 195262449Speterzero digits as necessary to meet the padding argument. <P> 195362449Speter 195462449SpeterA <CODE>TYPE_INTEGER</CODE> value buffer can conveniently be interpreted 195562449Speterwith the C library function <CODE>atoi(3)</CODE>. 195662449Speter 195762449Speter<H3><A NAME="ftype_numeric">TYPE_NUMERIC</A></H3> 195862449Speter 195962449SpeterThis field type accepts a decimal number. It is set up as follows: 196062449Speter 196162449Speter<PRE> 196262449Speterint set_field_type(FIELD *field, /* field to alter */ 196362449Speter TYPE_NUMERIC, /* type to associate */ 196462449Speter int padding, /* # places of precision */ 196562449Speter double vmin, double vmax); /* valid range */ 196662449Speter</PRE> 196762449Speter 196862449SpeterValid characters consist of an optional leading minus and digits. possibly 196962449Speterincluding a decimal point. If your system supports locale's, the decimal point 197062449Spetercharacter used must be the one defined by your locale. The range check is 197162449Speterperformed on exit. If the range maximum is less than or equal to the minimum, 197262449Speterthe range is ignored. <P> 197362449Speter 197462449SpeterIf the value passes its range check, it is padded with as many trailing 197562449Speterzero digits as necessary to meet the padding argument. <P> 197662449Speter 197762449SpeterA <CODE>TYPE_NUMERIC</CODE> value buffer can conveniently be interpreted 197862449Speterwith the C library function <CODE>atof(3)</CODE>. 197962449Speter 198062449Speter<H3><A NAME="ftype_regexp">TYPE_REGEXP</A></H3> 198162449Speter 198262449SpeterThis field type accepts data matching a regular expression. It is set up 198362449Speteras follows: 198462449Speter 198562449Speter<PRE> 198662449Speterint set_field_type(FIELD *field, /* field to alter */ 198762449Speter TYPE_REGEXP, /* type to associate */ 198862449Speter char *regexp); /* expression to match */ 198962449Speter</PRE> 199062449Speter 199162449SpeterThe syntax for regular expressions is that of <CODE>regcomp(3)</CODE>. 199262449SpeterThe check for regular-expression match is performed on exit. 199362449Speter 199462449Speter<H2><A NAME="fbuffer">Direct Field Buffer Manipulation</A></H2> 199562449Speter 199662449SpeterThe chief attribute of a field is its buffer contents. When a form has 199762449Speterbeen completed, your application usually needs to know the state of each 199862449Speterfield buffer. You can find this out with: 199962449Speter 200062449Speter<PRE> 200162449Speterchar *field_buffer(FIELD *field, /* field to query */ 200262449Speter int bufindex); /* number of buffer to query */ 200362449Speter</PRE> 200462449Speter 200562449SpeterNormally, the state of the zero-numbered buffer for each field is set by 200662449Speterthe user's editing actions on that field. It's sometimes useful to be able 200762449Speterto set the value of the zero-numbered (or some other) buffer from your 200862449Speterapplication: 200962449Speter 201062449Speter<PRE> 201162449Speterint set_field_buffer(FIELD *field, /* field to alter */ 201262449Speter int bufindex, /* number of buffer to alter */ 201362449Speter char *value); /* string value to set */ 201462449Speter</PRE> 201562449Speter 201662449SpeterIf the field is not large enough and cannot be resized to a sufficiently 201762449Speterlarge size to contain the specified value, the value will be truncated 201862449Speterto fit. <P> 201962449Speter 202062449SpeterCalling <CODE>field_buffer()</CODE> with a null field pointer will raise an 202162449Spetererror. Calling <CODE>field_buffer()</CODE> on a field not currently selected 202262449Speterfor input will return a correct value. Calling <CODE>field_buffer()</CODE> on a 202362449Speterfield that is currently selected for input may not necessarily give a 202462449Spetercorrect field buffer value, because entered data isn't necessarily copied to 202562449Speterbuffer zero before the exit validation check. 202662449Speter 202762449SpeterTo guarantee that the returned buffer value reflects on-screen reality, 202862449Spetercall <CODE>field_buffer()</CODE> either (1) in the field's exit validation 202962449Spetercheck routine, (2) from the field's or form's initialization or termination 203062449Speterhooks, or (3) just after a <CODE>REQ_VALIDATION</CODE> request has been processed 203162449Speterby the forms driver. 203262449Speter 203362449Speter<H2><A NAME="formattrs">Attributes of Forms</A></H2> 203462449Speter 203562449SpeterAs with field attributes, form attributes inherit a default from a 203662449Spetersystem default form structure. These defaults can be queried or set by 203762449Speterof these functions using a form-pointer argument of <CODE>NULL</CODE>. <P> 203862449Speter 203962449SpeterThe principal attribute of a form is its field list. You can query 204062449Speterand change this list with: 204162449Speter 204262449Speter<PRE> 204362449Speterint set_form_fields(FORM *form, /* form to alter */ 204462449Speter FIELD **fields); /* fields to connect */ 204562449Speter 204662449Speterchar *form_fields(FORM *form); /* fetch fields of form */ 204762449Speter 204862449Speterint field_count(FORM *form); /* count connect fields */ 204962449Speter</PRE> 205062449Speter 205162449SpeterThe second argument of <CODE>set_form_fields()</CODE> may be a 205262449SpeterNULL-terminated field pointer array like the one required by 205362449Speter<CODE>new_form()</CODE>. In that case, the old fields of the form are 205462449Speterdisconnected but not freed (and eligible to be connected to other 205562449Speterforms), then the new fields are connected. <P> 205662449Speter 205762449SpeterIt may also be null, in which case the old fields are disconnected 205862449Speter(and not freed) but no new ones are connected. <P> 205962449Speter 206062449SpeterThe <CODE>field_count()</CODE> function simply counts the number of fields 206162449Speterconnected to a given from. It returns -1 if the form-pointer argument 206262449Speteris NULL. 206362449Speter 206462449Speter<H2><A NAME="fdisplay">Control of Form Display</A></H2> 206562449Speter 206662449SpeterIn the overview section, you saw that to display a form you normally 206762449Speterstart by defining its size (and fields), posting it, and refreshing 206862449Speterthe screen. There is an hidden step before posting, which is the 206962449Speterassociation of the form with a frame window (actually, a pair of 207062449Speterwindows) within which it will be displayed. By default, the forms 207162449Speterlibrary associates every form with the full-screen window 207262449Speter<CODE>stdscr</CODE>. <P> 207362449Speter 207462449SpeterBy making this step explicit, you can associate a form with a declared 207562449Speterframe window on your screen display. This can be useful if you want to 207662449Speteradapt the form display to different screen sizes, dynamically tile 207762449Speterforms on the screen, or use a form as part of an interface layout 207862449Spetermanaged by <A HREF="#panels">panels</A>. <P> 207962449Speter 208062449SpeterThe two windows associated with each form have the same functions as 208162449Spetertheir analogues in the <A HREF="#menu">menu library</A>. Both these 208262449Speterwindows are painted when the form is posted and erased when the form 208362449Speteris unposted. <P> 208462449Speter 208562449SpeterThe outer or frame window is not otherwise touched by the form 208662449Speterroutines. It exists so the programmer can associate a title, a 208762449Speterborder, or perhaps help text with the form and have it properly 208862449Speterrefreshed or erased at post/unpost time. The inner window or subwindow 208962449Speteris where the current form page is actually displayed. <P> 209062449Speter 209162449SpeterIn order to declare your own frame window for a form, you'll need to 209262449Speterknow the size of the form's bounding rectangle. You can get this 209362449Speterinformation with: 209462449Speter 209562449Speter<PRE> 209662449Speterint scale_form(FORM *form, /* form to query */ 209762449Speter int *rows, /* form rows */ 209862449Speter int *cols); /* form cols */ 209962449Speter</PRE> 210062449Speter 210162449SpeterThe form dimensions are passed back in the locations pointed to by 210262449Speterthe arguments. Once you have this information, you can use it to 210362449Speterdeclare of windows, then use one of these functions: 210462449Speter 210562449Speter<PRE> 210662449Speterint set_form_win(FORM *form, /* form to alter */ 210762449Speter WINDOW *win); /* frame window to connect */ 210862449Speter 210962449SpeterWINDOW *form_win(FORM *form); /* fetch frame window of form */ 211062449Speter 211162449Speterint set_form_sub(FORM *form, /* form to alter */ 211262449Speter WINDOW *win); /* form subwindow to connect */ 211362449Speter 211462449SpeterWINDOW *form_sub(FORM *form); /* fetch form subwindow of form */ 211562449Speter</PRE> 211662449Speter 211762449SpeterNote that curses operations, including <CODE>refresh()</CODE>, on the form, 211862449Spetershould be done on the frame window, not the form subwindow. <P> 211962449Speter 212062449SpeterIt is possible to check from your application whether all of a 212162449Speterscrollable field is actually displayed within the menu subwindow. Use 212262449Speterthese functions: 212362449Speter 212462449Speter<PRE> 212562449Speterint data_ahead(FORM *form); /* form to be queried */ 212662449Speter 212762449Speterint data_behind(FORM *form); /* form to be queried */ 212862449Speter</PRE> 212962449Speter 213062449SpeterThe function <CODE>data_ahead()</CODE> returns TRUE if (a) the current 213162449Speterfield is one-line and has undisplayed data off to the right, (b) the current 213262449Speterfield is multi-line and there is data off-screen below it. <P> 213362449Speter 213462449SpeterThe function <CODE>data_behind()</CODE> returns TRUE if the first (upper 213562449Speterleft hand) character position is off-screen (not being displayed). <P> 213662449Speter 213762449SpeterFinally, there is a function to restore the form window's cursor to the 213862449Spetervalue expected by the forms driver: 213962449Speter 214062449Speter<PRE> 214162449Speterint pos_form_cursor(FORM *) /* form to be queried */ 214262449Speter</PRE> 214362449Speter 214462449SpeterIf your application changes the form window cursor, call this function before 214562449Speterhanding control back to the forms driver in order to re-synchronize it. 214662449Speter 214762449Speter<H2><A NAME="fdriver">Input Processing in the Forms Driver</A></H2> 214862449Speter 214962449SpeterThe function <CODE>form_driver()</CODE> handles virtualized input requests 215062449Speterfor form navigation, editing, and validation requests, just as 215162449Speter<CODE>menu_driver</CODE> does for menus (see the section on <A 215262449SpeterHREF="#minput">menu input handling</A>). 215362449Speter 215462449Speter<PRE> 215562449Speterint form_driver(FORM *form, /* form to pass input to */ 215662449Speter int request); /* form request code */ 215762449Speter</PRE> 215862449Speter 215962449SpeterYour input virtualization function needs to take input and then convert it 216062449Speterto either an alphanumeric character (which is treated as data to be 216162449Speterentered in the currently-selected field), or a forms processing request. <P> 216262449Speter 216362449SpeterThe forms driver provides hooks (through input-validation and 216462449Speterfield-termination functions) with which your application code can check 216562449Speterthat the input taken by the driver matched what was expected. 216662449Speter 216762449Speter<H3><A NAME="fpage">Page Navigation Requests</A></H3> 216862449Speter 216962449SpeterThese requests cause page-level moves through the form, 217062449Spetertriggering display of a new form screen. 217162449Speter 217262449Speter<DL> 217362449Speter<DT> <CODE>REQ_NEXT_PAGE</CODE> 217462449Speter<DD> Move to the next form page. 217562449Speter<DT> <CODE>REQ_PREV_PAGE</CODE> 217662449Speter<DD> Move to the previous form page. 217762449Speter<DT> <CODE>REQ_FIRST_PAGE</CODE> 217862449Speter<DD> Move to the first form page. 217962449Speter<DT> <CODE>REQ_LAST_PAGE</CODE> 218062449Speter<DD> Move to the last form page. 218162449Speter</DL> 218262449Speter 218362449SpeterThese requests treat the list as cyclic; that is, <CODE>REQ_NEXT_PAGE</CODE> 218462449Speterfrom the last page goes to the first, and <CODE>REQ_PREV_PAGE</CODE> from 218562449Speterthe first page goes to the last. 218662449Speter 218762449Speter<H3><A NAME="#ffield">Inter-Field Navigation Requests</A></H3> 218862449Speter 218962449SpeterThese requests handle navigation between fields on the same page. 219062449Speter 219162449Speter<DL> 219262449Speter<DT> <CODE>REQ_NEXT_FIELD</CODE> 219362449Speter<DD> Move to next field. 219462449Speter<DT> <CODE>REQ_PREV_FIELD</CODE> 219562449Speter<DD> Move to previous field. 219662449Speter<DT> <CODE>REQ_FIRST_FIELD</CODE> 219762449Speter<DD> Move to the first field. 219862449Speter<DT> <CODE>REQ_LAST_FIELD</CODE> 219962449Speter<DD> Move to the last field. 220062449Speter<DT> <CODE>REQ_SNEXT_FIELD</CODE> 220162449Speter<DD> Move to sorted next field. 220262449Speter<DT> <CODE>REQ_SPREV_FIELD</CODE> 220362449Speter<DD> Move to sorted previous field. 220462449Speter<DT> <CODE>REQ_SFIRST_FIELD</CODE> 220562449Speter<DD> Move to the sorted first field. 220662449Speter<DT> <CODE>REQ_SLAST_FIELD</CODE> 220762449Speter<DD> Move to the sorted last field. 220862449Speter<DT> <CODE>REQ_LEFT_FIELD</CODE> 220962449Speter<DD> Move left to field. 221062449Speter<DT> <CODE>REQ_RIGHT_FIELD</CODE> 221162449Speter<DD> Move right to field. 221262449Speter<DT> <CODE>REQ_UP_FIELD</CODE> 221362449Speter<DD> Move up to field. 221462449Speter<DT> <CODE>REQ_DOWN_FIELD</CODE> 221562449Speter<DD> Move down to field. 221662449Speter</DL> 221762449Speter 221862449SpeterThese requests treat the list of fields on a page as cyclic; that is, 221962449Speter<CODE>REQ_NEXT_FIELD</CODE> from the last field goes to the first, and 222062449Speter<CODE>REQ_PREV_FIELD</CODE> from the first field goes to the last. The 222162449Speterorder of the fields for these (and the <CODE>REQ_FIRST_FIELD</CODE> and 222262449Speter<CODE>REQ_LAST_FIELD</CODE> requests) is simply the order of the field 222362449Speterpointers in the form array (as set up by <CODE>new_form()</CODE> or 222462449Speter<CODE>set_form_fields()</CODE> <P> 222562449Speter 222662449SpeterIt is also possible to traverse the fields as if they had been sorted in 222762449Speterscreen-position order, so the sequence goes left-to-right and top-to-bottom. 222862449SpeterTo do this, use the second group of four sorted-movement requests. <P> 222962449Speter 223062449SpeterFinally, it is possible to move between fields using visual directions up, 223162449Speterdown, right, and left. To accomplish this, use the third group of four 223262449Speterrequests. Note, however, that the position of a form for purposes of these 223362449Speterrequests is its upper-left corner. <P> 223462449Speter 223562449SpeterFor example, suppose you have a multi-line field B, and two 223662449Spetersingle-line fields A and C on the same line with B, with A to the left 223762449Speterof B and C to the right of B. A <CODE>REQ_MOVE_RIGHT</CODE> from A will 223862449Spetergo to B only if A, B, and C <EM>all</EM> share the same first line; 223962449Speterotherwise it will skip over B to C. 224062449Speter 224162449Speter<H3><A NAME="#fifield">Intra-Field Navigation Requests</A></H3> 224262449Speter 224362449SpeterThese requests drive movement of the edit cursor within the currently 224462449Speterselected field. 224562449Speter 224662449Speter<DL> 224762449Speter<DT> <CODE>REQ_NEXT_CHAR</CODE> 224862449Speter<DD> Move to next character. 224962449Speter<DT> <CODE>REQ_PREV_CHAR</CODE> 225062449Speter<DD> Move to previous character. 225162449Speter<DT> <CODE>REQ_NEXT_LINE</CODE> 225262449Speter<DD> Move to next line. 225362449Speter<DT> <CODE>REQ_PREV_LINE</CODE> 225462449Speter<DD> Move to previous line. 225562449Speter<DT> <CODE>REQ_NEXT_WORD</CODE> 225662449Speter<DD> Move to next word. 225762449Speter<DT> <CODE>REQ_PREV_WORD</CODE> 225862449Speter<DD> Move to previous word. 225962449Speter<DT> <CODE>REQ_BEG_FIELD</CODE> 226062449Speter<DD> Move to beginning of field. 226162449Speter<DT> <CODE>REQ_END_FIELD</CODE> 226262449Speter<DD> Move to end of field. 226362449Speter<DT> <CODE>REQ_BEG_LINE</CODE> 226462449Speter<DD> Move to beginning of line. 226562449Speter<DT> <CODE>REQ_END_LINE</CODE> 226662449Speter<DD> Move to end of line. 226762449Speter<DT> <CODE>REQ_LEFT_CHAR</CODE> 226862449Speter<DD> Move left in field. 226962449Speter<DT> <CODE>REQ_RIGHT_CHAR</CODE> 227062449Speter<DD> Move right in field. 227162449Speter<DT> <CODE>REQ_UP_CHAR</CODE> 227262449Speter<DD> Move up in field. 227362449Speter<DT> <CODE>REQ_DOWN_CHAR</CODE> 227462449Speter<DD> Move down in field. 227562449Speter</DL> 227662449Speter 227762449SpeterEach <EM>word</EM> is separated from the previous and next characters 227862449Speterby whitespace. The commands to move to beginning and end of line or field 227962449Speterlook for the first or last non-pad character in their ranges. 228062449Speter 228162449Speter<H3><A NAME="fscroll">Scrolling Requests</A></H3> 228262449Speter 228362449SpeterFields that are dynamic and have grown and fields explicitly created 228462449Speterwith offscreen rows are scrollable. One-line fields scroll horizontally; 228562449Spetermulti-line fields scroll vertically. Most scrolling is triggered by 228662449Speterediting and intra-field movement (the library scrolls the field to keep the 228762449Spetercursor visible). It is possible to explicitly request scrolling with the 228862449Speterfollowing requests: 228962449Speter 229062449Speter<DL> 229162449Speter<DT> <CODE>REQ_SCR_FLINE</CODE> 229262449Speter<DD> Scroll vertically forward a line. 229362449Speter<DT> <CODE>REQ_SCR_BLINE</CODE> 229462449Speter<DD> Scroll vertically backward a line. 229562449Speter<DT> <CODE>REQ_SCR_FPAGE</CODE> 229662449Speter<DD> Scroll vertically forward a page. 229762449Speter<DT> <CODE>REQ_SCR_BPAGE</CODE> 229862449Speter<DD> Scroll vertically backward a page. 229962449Speter<DT> <CODE>REQ_SCR_FHPAGE</CODE> 230062449Speter<DD> Scroll vertically forward half a page. 230162449Speter<DT> <CODE>REQ_SCR_BHPAGE</CODE> 230262449Speter<DD> Scroll vertically backward half a page. 230362449Speter<DT> <CODE>REQ_SCR_FCHAR</CODE> 230462449Speter<DD> Scroll horizontally forward a character. 230562449Speter<DT> <CODE>REQ_SCR_BCHAR</CODE> 230662449Speter<DD> Scroll horizontally backward a character. 230762449Speter<DT> <CODE>REQ_SCR_HFLINE</CODE> 230862449Speter<DD> Scroll horizontally one field width forward. 230962449Speter<DT> <CODE>REQ_SCR_HBLINE</CODE> 231062449Speter<DD> Scroll horizontally one field width backward. 231162449Speter<DT> <CODE>REQ_SCR_HFHALF</CODE> 231262449Speter<DD> Scroll horizontally one half field width forward. 231362449Speter<DT> <CODE>REQ_SCR_HBHALF</CODE> 231462449Speter<DD> Scroll horizontally one half field width backward. 231562449Speter</DL> 231662449Speter 231762449SpeterFor scrolling purposes, a <EM>page</EM> of a field is the height 231862449Speterof its visible part. 231962449Speter 232062449Speter<H3><A NAME="fedit">Editing Requests</A></H3> 232162449Speter 232262449SpeterWhen you pass the forms driver an ASCII character, it is treated as a 232362449Speterrequest to add the character to the field's data buffer. Whether this 232462449Speteris an insertion or a replacement depends on the field's edit mode 232562449Speter(insertion is the default. <P> 232662449Speter 232762449SpeterThe following requests support editing the field and changing the edit 232862449Spetermode: 232962449Speter 233062449Speter<DL> 233162449Speter<DT> <CODE>REQ_INS_MODE</CODE> 233262449Speter<DD> Set insertion mode. 233362449Speter<DT> <CODE>REQ_OVL_MODE</CODE> 233462449Speter<DD> Set overlay mode. 233562449Speter<DT> <CODE>REQ_NEW_LINE</CODE> 233662449Speter<DD> New line request (see below for explanation). 233762449Speter<DT> <CODE>REQ_INS_CHAR</CODE> 233862449Speter<DD> Insert space at character location. 233962449Speter<DT> <CODE>REQ_INS_LINE</CODE> 234062449Speter<DD> Insert blank line at character location. 234162449Speter<DT> <CODE>REQ_DEL_CHAR</CODE> 234262449Speter<DD> Delete character at cursor. 234362449Speter<DT> <CODE>REQ_DEL_PREV</CODE> 234462449Speter<DD> Delete previous word at cursor. 234562449Speter<DT> <CODE>REQ_DEL_LINE</CODE> 234662449Speter<DD> Delete line at cursor. 234762449Speter<DT> <CODE>REQ_DEL_WORD</CODE> 234862449Speter<DD> Delete word at cursor. 234962449Speter<DT> <CODE>REQ_CLR_EOL</CODE> 235062449Speter<DD> Clear to end of line. 235162449Speter<DT> <CODE>REQ_CLR_EOF</CODE> 235262449Speter<DD> Clear to end of field. 235362449Speter<DT> <CODE>REQ_CLEAR_FIELD</CODE> 235462449Speter<DD> Clear entire field. 235562449Speter</DL> 235662449Speter 235762449SpeterThe behavior of the <CODE>REQ_NEW_LINE</CODE> and <CODE>REQ_DEL_PREV</CODE> requests 235862449Speteris complicated and partly controlled by a pair of forms options. 235962449SpeterThe special cases are triggered when the cursor is at the beginning of 236062449Spetera field, or on the last line of the field. <P> 236162449Speter 236262449SpeterFirst, we consider <CODE>REQ_NEW_LINE</CODE>: <P> 236362449Speter 236462449SpeterThe normal behavior of <CODE>REQ_NEW_LINE</CODE> in insert mode is to break the 236562449Spetercurrent line at the position of the edit cursor, inserting the portion of 236662449Speterthe current line after the cursor as a new line following the current 236762449Speterand moving the cursor to the beginning of that new line (you may think 236862449Speterof this as inserting a newline in the field buffer). <P> 236962449Speter 237062449SpeterThe normal behavior of <CODE>REQ_NEW_LINE</CODE> in overlay mode is to clear the 237162449Spetercurrent line from the position of the edit cursor to end of line. 237262449SpeterThe cursor is then moved to the beginning of the next line. <P> 237362449Speter 237462449SpeterHowever, <CODE>REQ_NEW_LINE</CODE> at the beginning of a field, or on the 237562449Speterlast line of a field, instead does a <CODE>REQ_NEXT_FIELD</CODE>. 237662449Speter<CODE>O_NL_OVERLOAD</CODE> option is off, this special action is 237762449Speterdisabled. <P> 237862449Speter 237962449SpeterNow, let us consider <CODE>REQ_DEL_PREV</CODE>: <P> 238062449Speter 238162449SpeterThe normal behavior of <CODE>REQ_DEL_PREV</CODE> is to delete the previous 238262449Spetercharacter. If insert mode is on, and the cursor is at the start of a 238362449Speterline, and the text on that line will fit on the previous one, it 238462449Speterinstead appends the contents of the current line to the previous one 238562449Speterand deletes the current line (you may think of this as deleting a 238662449Speternewline from the field buffer). <P> 238762449Speter 238862449SpeterHowever, <CODE>REQ_DEL_PREV</CODE> at the beginning of a field is instead 238962449Spetertreated as a <CODE>REQ_PREV_FIELD</CODE>. <P> If the 239062449Speter<CODE>O_BS_OVERLOAD</CODE> option is off, this special action is 239162449Speterdisabled and the forms driver just returns <CODE>E_REQUEST_DENIED</CODE>. <P> 239262449Speter 239362449SpeterSee <A HREF="#frmoptions">Form Options</A> for discussion of how to set 239462449Speterand clear the overload options. 239562449Speter 239662449Speter<H3><A NAME="forder">Order Requests</A></H3> 239762449Speter 239862449SpeterIf the type of your field is ordered, and has associated functions 239962449Speterfor getting the next and previous values of the type from a given value, 240062449Speterthere are requests that can fetch that value into the field buffer: 240162449Speter 240262449Speter<DL> 240362449Speter<DT> <CODE>REQ_NEXT_CHOICE</CODE> 240462449Speter<DD> Place the successor value of the current value in the buffer. 240562449Speter<DT> <CODE>REQ_PREV_CHOICE</CODE> 240662449Speter<DD> Place the predecessor value of the current value in the buffer. 240762449Speter</DL> 240862449Speter 240962449SpeterOf the built-in field types, only <CODE>TYPE_ENUM</CODE> has built-in successor 241062449Speterand predecessor functions. When you define a field type of your own 241162449Speter(see <A HREF="#fcustom">Custom Validation Types</A>), you can associate 241262449Speterour own ordering functions. 241362449Speter 241462449Speter<H3><A NAME="fappcmds">Application Commands</A></H3> 241562449Speter 241662449SpeterForm requests are represented as integers above the <CODE>curses</CODE> value 241762449Spetergreater than <CODE>KEY_MAX</CODE> and less than or equal to the constant 241862449Speter<CODE>MAX_COMMAND</CODE>. If your input-virtualization routine returns a 241962449Spetervalue above <CODE>MAX_COMMAND</CODE>, the forms driver will ignore it. 242062449Speter 242162449Speter<H2><A NAME="fhooks">Field Change Hooks</A></H2> 242262449Speter 242362449SpeterIt is possible to set function hooks to be executed whenever the 242462449Spetercurrent field or form changes. Here are the functions that support this: 242562449Speter 242662449Speter<PRE> 242762449Spetertypedef void (*HOOK)(); /* pointer to function returning void */ 242862449Speter 242962449Speterint set_form_init(FORM *form, /* form to alter */ 243062449Speter HOOK hook); /* initialization hook */ 243162449Speter 243262449SpeterHOOK form_init(FORM *form); /* form to query */ 243362449Speter 243462449Speterint set_form_term(FORM *form, /* form to alter */ 243562449Speter HOOK hook); /* termination hook */ 243662449Speter 243762449SpeterHOOK form_term(FORM *form); /* form to query */ 243862449Speter 243962449Speterint set_field_init(FORM *form, /* form to alter */ 244062449Speter HOOK hook); /* initialization hook */ 244162449Speter 244262449SpeterHOOK field_init(FORM *form); /* form to query */ 244362449Speter 244462449Speterint set_field_term(FORM *form, /* form to alter */ 244562449Speter HOOK hook); /* termination hook */ 244662449Speter 244762449SpeterHOOK field_term(FORM *form); /* form to query */ 244862449Speter</PRE> 244962449Speter 245062449SpeterThese functions allow you to either set or query four different hooks. 245162449SpeterIn each of the set functions, the second argument should be the 245262449Speteraddress of a hook function. These functions differ only in the timing 245362449Speterof the hook call. 245462449Speter 245562449Speter<DL> 245662449Speter<DT> form_init 245762449Speter<DD> This hook is called when the form is posted; also, just after 245862449Spetereach page change operation. 245962449Speter<DT> field_init 246062449Speter<DD> This hook is called when the form is posted; also, just after 246162449Spetereach field change 246262449Speter<DT> field_term 246362449Speter<DD> This hook is called just after field validation; that is, just before 246462449Speterthe field is altered. It is also called when the form is unposted. 246562449Speter<DT> form_term 246662449Speter<DD> This hook is called when the form is unposted; also, just before 246762449Spetereach page change operation. 246862449Speter</DL> 246962449Speter 247062449SpeterCalls to these hooks may be triggered 247162449Speter<OL> 247262449Speter<LI>When user editing requests are processed by the forms driver 247362449Speter<LI>When the current page is changed by <CODE>set_current_field()</CODE> call 247462449Speter<LI>When the current field is changed by a <CODE>set_form_page()</CODE> call 247562449Speter</OL> 247662449Speter 247762449SpeterSee <A NAME="ffocus">Field Change Commands</A> for discussion of the latter 247862449Spetertwo cases. <P> 247962449Speter 248062449SpeterYou can set a default hook for all fields by passing one of the set functions 248162449Spetera NULL first argument. <P> 248262449Speter 248362449SpeterYou can disable any of these hooks by (re)setting them to NULL, the default 248462449Spetervalue. 248562449Speter 248662449Speter<H2><A HREF="#ffocus">Field Change Commands</A></H2> 248762449Speter 248862449SpeterNormally, navigation through the form will be driven by the user's 248962449Speterinput requests. But sometimes it is useful to be able to move the 249062449Speterfocus for editing and viewing under control of your application, or 249162449Speterask which field it currently is in. The following functions help you 249262449Speteraccomplish this: 249362449Speter 249462449Speter<PRE> 249562449Speterint set_current_field(FORM *form, /* form to alter */ 249662449Speter FIELD *field); /* field to shift to */ 249762449Speter 249862449SpeterFIELD *current_field(FORM *form); /* form to query */ 249962449Speter 250062449Speterint field_index(FORM *form, /* form to query */ 250162449Speter FIELD *field); /* field to get index of */ 250262449Speter</PRE> 250362449Speter 250462449SpeterThe function <CODE>field_index()</CODE> returns the index of the given field 250562449Speterin the given form's field array (the array passed to <CODE>new_form()</CODE> or 250662449Speter<CODE>set_form_fields()</CODE>). <P> 250762449Speter 250862449SpeterThe initial current field of a form is the first active field on the 250962449Speterfirst page. The function <CODE>set_form_fields()</CODE> resets this.<P> 251062449Speter 251162449SpeterIt is also possible to move around by pages. 251262449Speter 251362449Speter<PRE> 251462449Speterint set_form_page(FORM *form, /* form to alter */ 251562449Speter int page); /* page to go to (0-origin) */ 251662449Speter 251762449Speterint form_page(FORM *form); /* return form's current page */ 251862449Speter</PRE> 251962449Speter 252062449SpeterThe initial page of a newly-created form is 0. The function 252162449Speter<CODE>set_form_fields()</CODE> resets this. 252262449Speter 252362449Speter<H2><A NAME="frmoptions">Form Options</A></H2> 252462449Speter 252562449SpeterLike fields, forms may have control option bits. They can be changed 252662449Speteror queried with these functions: 252762449Speter 252862449Speter<PRE> 252962449Speterint set_form_opts(FORM *form, /* form to alter */ 253062449Speter int attr); /* attribute to set */ 253162449Speter 253262449Speterint form_opts_on(FORM *form, /* form to alter */ 253362449Speter int attr); /* attributes to turn on */ 253462449Speter 253562449Speterint form_opts_off(FORM *form, /* form to alter */ 253662449Speter int attr); /* attributes to turn off */ 253762449Speter 253862449Speterint form_opts(FORM *form); /* form to query */ 253962449Speter</PRE> 254062449Speter 254162449SpeterBy default, all options are on. Here are the available option bits: 254262449Speter 254362449Speter<DL> 254462449Speter<DT> O_NL_OVERLOAD 254562449Speter<DD> Enable overloading of <CODE>REQ_NEW_LINE</CODE> as described in <A 2546166124Srafanhref="#fedit">Editing Requests</A>. The value of this option is 254762449Speterignored on dynamic fields that have not reached their size limit; 254862449Speterthese have no last line, so the circumstances for triggering a 254962449Speter<CODE>REQ_NEXT_FIELD</CODE> never arise. 255062449Speter<DT> O_BS_OVERLOAD 255162449Speter<DD> Enable overloading of <CODE>REQ_DEL_PREV</CODE> as described in 2552166124Srafan<A href="#fedit">Editing Requests</A>. 255362449Speter</DL> 255462449Speter 255562449SpeterThe option values are bit-masks and can be composed with logical-or in 255662449Speterthe obvious way. 255762449Speter 255862449Speter<H2><A NAME="fcustom">Custom Validation Types</A></H2> 255962449Speter 256062449SpeterThe <CODE>form</CODE> library gives you the capability to define custom 256162449Spetervalidation types of your own. Further, the optional additional arguments 256262449Speterof <CODE>set_field_type</CODE> effectively allow you to parameterize validation 256362449Spetertypes. Most of the complications in the validation-type interface have to 256462449Speterdo with the handling of the additional arguments within custom validation 256562449Speterfunctions. 256662449Speter 256762449Speter<H3><A NAME="flinktypes">Union Types</A></H3> 256862449Speter 256962449SpeterThe simplest way to create a custom data type is to compose it from two 257062449Speterpreexisting ones: 257162449Speter 257262449Speter<PRE> 257362449SpeterFIELD *link_fieldtype(FIELDTYPE *type1, 257462449Speter FIELDTYPE *type2); 257562449Speter</PRE> 257662449Speter 257762449SpeterThis function creates a field type that will accept any of the values 257862449Speterlegal for either of its argument field types (which may be either 257962449Speterpredefined or programmer-defined). 258062449Speter 258162449SpeterIf a <CODE>set_field_type()</CODE> call later requires arguments, the new 258262449Spetercomposite type expects all arguments for the first type, than all arguments 258362449Speterfor the second. Order functions (see <A HREF="#forder">Order Requests</A>) 258462449Speterassociated with the component types will work on the composite; what it does 258562449Speteris check the validation function for the first type, then for the second, to 258662449Speterfigure what type the buffer contents should be treated as. 258762449Speter 258862449Speter<H3><A NAME="fnewtypes">New Field Types</A></H3> 258962449Speter 259062449SpeterTo create a field type from scratch, you need to specify one or both of the 259162449Speterfollowing things: 259262449Speter 259362449Speter<UL> 259462449Speter<LI>A character-validation function, to check each character as it is entered. 259562449Speter<LI>A field-validation function to be applied on exit from the field. 259662449Speter</UL> 259762449Speter 259862449SpeterHere's how you do that: 259962449Speter<PRE> 260062449Spetertypedef int (*HOOK)(); /* pointer to function returning int */ 260162449Speter 260262449SpeterFIELDTYPE *new_fieldtype(HOOK f_validate, /* field validator */ 260362449Speter HOOK c_validate) /* character validator */ 260462449Speter 260562449Speter 260662449Speterint free_fieldtype(FIELDTYPE *ftype); /* type to free */ 260762449Speter</PRE> 260862449Speter 260962449SpeterAt least one of the arguments of <CODE>new_fieldtype()</CODE> must be 261062449Speternon-NULL. The forms driver will automatically call the new type's 261162449Spetervalidation functions at appropriate points in processing a field of 261262449Speterthe new type. <P> 261362449Speter 261462449SpeterThe function <CODE>free_fieldtype()</CODE> deallocates the argument 261562449Speterfieldtype, freeing all storage associated with it. <P> 261662449Speter 261762449SpeterNormally, a field validator is called when the user attempts to 261862449Speterleave the field. Its first argument is a field pointer, from which it 261962449Spetercan get to field buffer 0 and test it. If the function returns TRUE, 262062449Speterthe operation succeeds; if it returns FALSE, the edit cursor stays in 262162449Speterthe field. <P> 262262449Speter 262362449SpeterA character validator gets the character passed in as a first argument. 262462449SpeterIt too should return TRUE if the character is valid, FALSE otherwise. 262562449Speter 262662449Speter<H3><A NAME="fcheckargs">Validation Function Arguments</A></H3> 262762449Speter 262862449SpeterYour field- and character- validation functions will be passed a 262962449Spetersecond argument as well. This second argument is the address of a 263062449Speterstructure (which we'll call a <EM>pile</EM>) built from any of the 263162449Speterfield-type-specific arguments passed to <CODE>set_field_type()</CODE>. If 263262449Speterno such arguments are defined for the field type, this pile pointer 263362449Speterargument will be NULL. <P> 263462449Speter 263562449SpeterIn order to arrange for such arguments to be passed to your validation 263662449Speterfunctions, you must associate a small set of storage-management functions 263762449Speterwith the type. The forms driver will use these to synthesize a pile 263862449Speterfrom the trailing arguments of each <CODE>set_field_type()</CODE> argument, and 263962449Spetera pointer to the pile will be passed to the validation functions. <P> 264062449Speter 264162449SpeterHere is how you make the association: 264262449Speter 264362449Speter<PRE> 264462449Spetertypedef char *(*PTRHOOK)(); /* pointer to function returning (char *) */ 264562449Spetertypedef void (*VOIDHOOK)(); /* pointer to function returning void */ 264662449Speter 264762449Speterint set_fieldtype_arg(FIELDTYPE *type, /* type to alter */ 264862449Speter PTRHOOK make_str, /* make structure from args */ 264962449Speter PTRHOOK copy_str, /* make copy of structure */ 265062449Speter VOIDHOOK free_str); /* free structure storage */ 265162449Speter</PRE> 265262449Speter 265362449SpeterHere is how the storage-management hooks are used: 265462449Speter 265562449Speter<DL> 265662449Speter<DT> <CODE>make_str</CODE> 265762449Speter<DD> This function is called by <CODE>set_field_type()</CODE>. It gets one 265862449Speterargument, a <CODE>va_list</CODE> of the type-specific arguments passed to 265962449Speter<CODE>set_field_type()</CODE>. It is expected to return a pile pointer to a data 266062449Speterstructure that encapsulates those arguments. 266162449Speter<DT> <CODE>copy_str</CODE> 266262449Speter<DD> This function is called by form library functions that allocate new 266362449Speterfield instances. It is expected to take a pile pointer, copy the pile 266462449Speterto allocated storage, and return the address of the pile copy. 266562449Speter<DT> <CODE>free_str</CODE> 266662449Speter<DD> This function is called by field- and type-deallocation routines in the 266762449Speterlibrary. It takes a pile pointer argument, and is expected to free the 266862449Speterstorage of that pile. 266962449Speter</DL> 267062449Speter 267162449SpeterThe <CODE>make_str</CODE> and <CODE>copy_str</CODE> functions may return NULL to 267262449Spetersignal allocation failure. The library routines will that call them will 267362449Speterreturn error indication when this happens. Thus, your validation functions 267462449Spetershould never see a NULL file pointer and need not check specially for it. 267562449Speter 267662449Speter<H3><A NAME="fcustorder">Order Functions For Custom Types</A></H3> 267762449Speter 267862449SpeterSome custom field types are simply ordered in the same well-defined way 267962449Speterthat <CODE>TYPE_ENUM</CODE> is. For such types, it is possible to define 268062449Spetersuccessor and predecessor functions to support the <CODE>REQ_NEXT_CHOICE</CODE> 268162449Speterand <CODE>REQ_PREV_CHOICE</CODE> requests. Here's how: 268262449Speter 268362449Speter<PRE> 268462449Spetertypedef int (*INTHOOK)(); /* pointer to function returning int */ 268562449Speter 268662449Speterint set_fieldtype_arg(FIELDTYPE *type, /* type to alter */ 268762449Speter INTHOOK succ, /* get successor value */ 268862449Speter INTHOOK pred); /* get predecessor value */ 268962449Speter</PRE> 269062449Speter 269162449SpeterThe successor and predecessor arguments will each be passed two arguments; 269262449Spetera field pointer, and a pile pointer (as for the validation functions). They 269362449Speterare expected to use the function <CODE>field_buffer()</CODE> to read the 269462449Spetercurrent value, and <CODE>set_field_buffer()</CODE> on buffer 0 to set the next 269562449Speteror previous value. Either hook may return TRUE to indicate success (a 269662449Speterlegal next or previous value was set) or FALSE to indicate failure. 269762449Speter 269862449Speter<H3><A NAME="fcustprobs">Avoiding Problems</A></H3> 269962449Speter 270062449SpeterThe interface for defining custom types is complicated and tricky. 270162449SpeterRather than attempting to create a custom type entirely from scratch, 270262449Speteryou should start by studying the library source code for whichever of 270362449Speterthe pre-defined types seems to be closest to what you want. <P> 270462449Speter 270562449SpeterUse that code as a model, and evolve it towards what you really want. 270662449SpeterYou will avoid many problems and annoyances that way. The code 270762449Speterin the <CODE>ncurses</CODE> library has been specifically exempted from 270862449Speterthe package copyright to support this. <P> 270962449Speter 271062449SpeterIf your custom type defines order functions, have do something intuitive 271162449Speterwith a blank field. A useful convention is to make the successor of a 271262449Speterblank field the types minimum value, and its predecessor the maximum. 271362449Speter</BODY> 271462449Speter</HTML> 2715