162449Speter<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> 262449Speter<!-- 3174993Srafan $Id: ncurses-intro.html,v 1.43 2007/03/03 19:31:50 tom Exp $ 4166124Srafan **************************************************************************** 5174993Srafan * Copyright (c) 1998-2006,2007 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 917174993SrafanA resize operation in X sends <CODE>SIGWINCH</CODE> to the application running 918174993Srafanunder xterm. 91962449Speter 920174993SrafanThe easiest way to handle <CODE>SIGWINCH</CODE> 921174993Srafanis to do an <CODE>endwin</CODE>, 922174993Srafanfollowed by an <CODE>refresh</CODE> and a screen repaint you code 923174993Srafanyourself. 924174993SrafanThe <CODE>refresh</CODE> will pick up the new screen size from the 92562449Speterxterm's environment. <P> 92662449Speter 92762449SpeterThat is the standard way, of course (it even works with some vendor's curses 92862449Speterimplementations). 92962449SpeterIts drawback is that it clears the screen to reinitialize the display, and does 93062449Speternot resize subwindows which must be shrunk. 93162449Speter<CODE>Ncurses</CODE> provides an extension which works better, the 93262449Speter<CODE>resizeterm</CODE> function. That function ensures that all windows 93362449Speterare limited to the new screen dimensions, and pads <CODE>stdscr</CODE> 93462449Speterwith blanks if the screen is larger. <P> 93562449Speter 936174993SrafanThe <CODE>ncurses</CODE> library provides a SIGWINCH signal handler, 937174993Srafanwhich pushes a <CODE>KEY_RESIZE</CODE> via the wgetch() calls. 938174993SrafanWhen <CODE>ncurses</CODE> returns that code, 939174993Srafanit calls <code>resizeterm</CODE> 940174993Srafanto update the size of the standard screen's window, repainting that 941174993Srafan(filling with blanks or truncating as needed). 942174993SrafanIt also resizes other windows, 943174993Srafanbut its effect may be less satisfactory because it cannot 944174993Srafanknow how you want the screen re-painted. 945174993SrafanYou will usually have to write special-purpose code to handle 946174993Srafan<CODE>KEY_RESIZE</CODE> yourself. 94762449Speter 94862449Speter<H3><A NAME="screens">Handling Multiple Terminal Screens</A></H3> 94962449Speter 95062449SpeterThe <CODE>initscr()</CODE> function actually calls a function named 95162449Speter<CODE>newterm()</CODE> to do most of its work. If you are writing a program that 95262449Speteropens multiple terminals, use <CODE>newterm()</CODE> directly. <P> 95362449Speter 95462449SpeterFor each call, you will have to specify a terminal type and a pair of file 95562449Speterpointers; each call will return a screen reference, and <CODE>stdscr</CODE> will be 95662449Speterset to the last one allocated. You will switch between screens with the 95762449Speter<CODE>set_term</CODE> call. Note that you will also have to call 95862449Speter<CODE>def_shell_mode</CODE> and <CODE>def_prog_mode</CODE> on each tty yourself. 95962449Speter 96062449Speter<H3><A NAME="testing">Testing for Terminal Capabilities</A></H3> 96162449Speter 96262449SpeterSometimes you may want to write programs that test for the presence of various 96362449Spetercapabilities before deciding whether to go into <CODE>ncurses</CODE> mode. An easy 96462449Speterway to do this is to call <CODE>setupterm()</CODE>, then use the functions 96562449Speter<CODE>tigetflag()</CODE>, <CODE>tigetnum()</CODE>, and <CODE>tigetstr()</CODE> to do your 96662449Spetertesting. <P> 96762449Speter 96862449SpeterA particularly useful case of this often comes up when you want to 96962449Spetertest whether a given terminal type should be treated as `smart' 97062449Speter(cursor-addressable) or `stupid'. The right way to test this is to see 97162449Speterif the return value of <CODE>tigetstr("cup")</CODE> is non-NULL. Alternatively, 97262449Speteryou can include the <CODE>term.h</CODE> file and test the value of the 97362449Spetermacro <CODE>cursor_address</CODE>. 97462449Speter 97562449Speter<H3><A NAME="tuning">Tuning for Speed</A></H3> 97662449Speter 97762449SpeterUse the <CODE>addchstr()</CODE> family of functions for fast 97862449Speterscreen-painting of text when you know the text doesn't contain any 97962449Spetercontrol characters. Try to make attribute changes infrequent on your 98062449Speterscreens. Don't use the <CODE>immedok()</CODE> option! 98162449Speter 98262449Speter<H3><A NAME="special">Special Features of NCURSES</A></H3> 98362449Speter 98462449SpeterThe <CODE>wresize()</CODE> function allows you to resize a window in place. 98562449SpeterThe associated <CODE>resizeterm()</CODE> function simplifies the construction 98662449Speterof <a HREF="#xterm">SIGWINCH</a> handlers, for resizing all windows. <P> 98762449Speter 98862449SpeterThe <CODE>define_key()</CODE> function allows you 98962449Speterto define at runtime function-key control sequences which are not in the 99062449Speterterminal description. 99162449SpeterThe <CODE>keyok()</CODE> function allows you to temporarily 99262449Speterenable or disable interpretation of any function-key control sequence. <P> 99362449Speter 99462449SpeterThe <CODE>use_default_colors()</CODE> function allows you to construct 99562449Speterapplications which can use the terminal's default foreground and 99662449Speterbackground colors as an additional "default" color. 99762449SpeterSeveral terminal emulators support this feature, which is based on ISO 6429. <P> 99862449Speter 99962449SpeterNcurses supports up 16 colors, unlike SVr4 curses which defines only 8. 100062449SpeterWhile most terminals which provide color allow only 8 colors, about 100162449Spetera quarter (including XFree86 xterm) support 16 colors. 100262449Speter 100362449Speter<H2><A NAME="compat">Compatibility with Older Versions</A></H2> 100462449Speter 100562449SpeterDespite our best efforts, there are some differences between <CODE>ncurses</CODE> 100662449Speterand the (undocumented!) behavior of older curses implementations. These arise 100762449Speterfrom ambiguities or omissions in the documentation of the API. 100862449Speter 100962449Speter<H3><A NAME="refbug">Refresh of Overlapping Windows</A></H3> 101062449Speter 101162449SpeterIf you define two windows A and B that overlap, and then alternately scribble 101262449Speteron and refresh them, the changes made to the overlapping region under historic 101362449Speter<CODE>curses</CODE> versions were often not documented precisely. <P> 101462449Speter 101562449SpeterTo understand why this is a problem, remember that screen updates are 101662449Spetercalculated between two representations of the <EM>entire</EM> display. The 1017166124Srafandocumentation says that when you refresh a window, it is first copied to the 101862449Spetervirtual screen, and then changes are calculated to update the physical screen 101962449Speter(and applied to the terminal). But "copied to" is not very specific, and 102062449Spetersubtle differences in how copying works can produce different behaviors in the 102162449Spetercase where two overlapping windows are each being refreshed at unpredictable 102262449Speterintervals. <P> 102362449Speter 102462449SpeterWhat happens to the overlapping region depends on what <CODE>wnoutrefresh()</CODE> 102562449Speterdoes with its argument -- what portions of the argument window it copies to the 102662449Spetervirtual screen. Some implementations do "change copy", copying down only 102762449Speterlocations in the window that have changed (or been marked changed with 102862449Speter<CODE>wtouchln()</CODE> and friends). Some implementations do "entire copy", 102962449Spetercopying <EM>all</EM> window locations to the virtual screen whether or not 103062449Speterthey have changed. <P> 103162449Speter 103262449SpeterThe <CODE>ncurses</CODE> library itself has not always been consistent on this 103362449Speterscore. Due to a bug, versions 1.8.7 to 1.9.8a did entire copy. Versions 103462449Speter1.8.6 and older, and versions 1.9.9 and newer, do change copy. <P> 103562449Speter 103662449SpeterFor most commercial curses implementations, it is not documented and not known 103762449Speterfor sure (at least not to the <CODE>ncurses</CODE> maintainers) whether they do 103862449Speterchange copy or entire copy. We know that System V release 3 curses has logic 103962449Speterin it that looks like an attempt to do change copy, but the surrounding logic 104062449Speterand data representations are sufficiently complex, and our knowledge 104162449Spetersufficiently indirect, that it's hard to know whether this is reliable. 104262449Speter 104362449SpeterIt is not clear what the SVr4 documentation and XSI standard intend. The XSI 104462449SpeterCurses standard barely mentions wnoutrefresh(); the SVr4 documents seem to be 104562449Speterdescribing entire-copy, but it is possible with some effort and straining to 104662449Speterread them the other way. <P> 104762449Speter 104862449SpeterIt might therefore be unwise to rely on either behavior in programs that might 104962449Speterhave to be linked with other curses implementations. Instead, you can do an 105062449Speterexplicit <CODE>touchwin()</CODE> before the <CODE>wnoutrefresh()</CODE> call to 105162449Speterguarantee an entire-contents copy anywhere. <P> 105262449Speter 105362449SpeterThe really clean way to handle this is to use the panels library. If, 105462449Speterwhen you want a screen update, you do <CODE>update_panels()</CODE>, it will 1055166124Srafando all the necessary <CODE>wnoutrefresh()</CODE> calls for whatever panel 105662449Speterstacking order you have defined. Then you can do one <CODE>doupdate()</CODE> 105762449Speterand there will be a <EM>single</EM> burst of physical I/O that will do 105862449Speterall your updates. 105962449Speter 106062449Speter<H3><A NAME="backbug">Background Erase</A></H3> 106162449Speter 106262449SpeterIf you have been using a very old versions of <CODE>ncurses</CODE> (1.8.7 or 106362449Speterolder) you may be surprised by the behavior of the erase functions. In older 106462449Speterversions, erased areas of a window were filled with a blank modified by the 106562449Speterwindow's current attribute (as set by <STRONG>wattrset()</STRONG>, <STRONG>wattron()</STRONG>, 106662449Speter<STRONG>wattroff()</STRONG> and friends). <P> 106762449Speter 106862449SpeterIn newer versions, this is not so. Instead, the attribute of erased blanks 106962449Speteris normal unless and until it is modified by the functions <CODE>bkgdset()</CODE> 107062449Speteror <CODE>wbkgdset()</CODE>. <P> 107162449Speter 107262449SpeterThis change in behavior conforms <CODE>ncurses</CODE> to System V Release 4 and 107362449Speterthe XSI Curses standard. 107462449Speter 107562449Speter<H2><A NAME="xsifuncs">XSI Curses Conformance</A></H2> 107662449Speter 107762449SpeterThe <CODE>ncurses</CODE> library is intended to be base-level conformant with the 107862449SpeterXSI Curses standard from X/Open. Many extended-level features (in fact, almost 107962449Speterall features not directly concerned with wide characters and 108062449Speterinternationalization) are also supported. <P> 108162449Speter 108262449SpeterOne effect of XSI conformance is the change in behavior described under 108362449Speter<A HREF="#backbug">"Background Erase -- Compatibility with Old Versions"</A>. <P> 108462449Speter 108562449SpeterAlso, <CODE>ncurses</CODE> meets the XSI requirement that every macro 108662449Speterentry point have a corresponding function which may be linked (and 108762449Speterwill be prototype-checked) if the macro definition is disabled with 108862449Speter<CODE>#undef</CODE>. 108962449Speter 109062449Speter<H1><A NAME="panels">The Panels Library</A></H1> 109162449Speter 109262449SpeterThe <CODE>ncurses</CODE> library by itself provides good support for screen 109362449Speterdisplays in which the windows are tiled (non-overlapping). In the more 109462449Spetergeneral case that windows may overlap, you have to use a series of 109562449Speter<CODE>wnoutrefresh()</CODE> calls followed by a <CODE>doupdate()</CODE>, and be 109662449Spetercareful about the order you do the window refreshes in. It has to be 109762449Speterbottom-upwards, otherwise parts of windows that should be obscured will 109862449Spetershow through. <P> 109962449Speter 110062449SpeterWhen your interface design is such that windows may dive deeper into the 110162449Spetervisibility stack or pop to the top at runtime, the resulting book-keeping 110262449Spetercan be tedious and difficult to get right. Hence the panels library. <P> 110362449Speter 110462449SpeterThe <CODE>panel</CODE> library first appeared in AT&T System V. The 110562449Speterversion documented here is the <CODE>panel</CODE> code distributed 110662449Speterwith <CODE>ncurses</CODE>. 110762449Speter 110862449Speter<H2><A NAME="pcompile">Compiling With the Panels Library</A></H2> 110962449Speter 111062449SpeterYour panels-using modules must import the panels library declarations with 111162449Speter 111262449Speter<PRE> 111362449Speter #include <panel.h> 111462449Speter</PRE> 111562449Speter 111662449Speterand must be linked explicitly with the panels library using an 111762449Speter<CODE>-lpanel</CODE> argument. Note that they must also link the 111862449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 111962449Speterare two-pass and will accept either order, but it is still good practice 112062449Speterto put <CODE>-lpanel</CODE> first and <CODE>-lncurses</CODE> second. 112162449Speter 112262449Speter<H2><A NAME="poverview">Overview of Panels</A></H2> 112362449Speter 112462449SpeterA panel object is a window that is implicitly treated as part of a 112562449Speter<DFN>deck</DFN> including all other panel objects. The deck has an implicit 112662449Speterbottom-to-top visibility order. The panels library includes an update 112762449Speterfunction (analogous to <CODE>refresh()</CODE>) that displays all panels in the 112862449Speterdeck in the proper order to resolve overlaps. The standard window, 112962449Speter<CODE>stdscr</CODE>, is considered below all panels. <P> 113062449Speter 113162449SpeterDetails on the panels functions are available in the man pages. We'll just 113262449Speterhit the highlights here. <P> 113362449Speter 113462449SpeterYou create a panel from a window by calling <CODE>new_panel()</CODE> on a 113562449Speterwindow pointer. It then becomes the top of the deck. The panel's window 113662449Speteris available as the value of <CODE>panel_window()</CODE> called with the 113762449Speterpanel pointer as argument.<P> 113862449Speter 113962449SpeterYou can delete a panel (removing it from the deck) with <CODE>del_panel</CODE>. 114062449SpeterThis will not deallocate the associated window; you have to do that yourself. 114162449Speter 114262449SpeterYou can replace a panel's window with a different window by calling 114362449Speter<CODE>replace_window</CODE>. The new window may be of different size; 114462449Speterthe panel code will re-compute all overlaps. This operation doesn't 114562449Speterchange the panel's position in the deck. <P> 114662449Speter 114762449SpeterTo move a panel's window, use <CODE>move_panel()</CODE>. The 114862449Speter<CODE>mvwin()</CODE> function on the panel's window isn't sufficient because it 114962449Speterdoesn't update the panels library's representation of where the windows are. 115062449SpeterThis operation leaves the panel's depth, contents, and size unchanged. <P> 115162449Speter 115262449SpeterTwo functions (<CODE>top_panel()</CODE>, <CODE>bottom_panel()</CODE>) are 115362449Speterprovided for rearranging the deck. The first pops its argument window to the 115462449Spetertop of the deck; the second sends it to the bottom. Either operation leaves 115562449Speterthe panel's screen location, contents, and size unchanged. <P> 115662449Speter 115762449SpeterThe function <CODE>update_panels()</CODE> does all the 115862449Speter<CODE>wnoutrefresh()</CODE> calls needed to prepare for 115962449Speter<CODE>doupdate()</CODE> (which you must call yourself, afterwards). <P> 116062449Speter 116162449SpeterTypically, you will want to call <CODE>update_panels()</CODE> and 116262449Speter<CODE>doupdate()</CODE> just before accepting command input, once in each cycle 116362449Speterof interaction with the user. If you call <CODE>update_panels()</CODE> after 116462449Spetereach and every panel write, you'll generate a lot of unnecessary refresh 116562449Speteractivity and screen flicker. 116662449Speter 116762449Speter<H2><A NAME="pstdscr">Panels, Input, and the Standard Screen</A></H2> 116862449Speter 116962449SpeterYou shouldn't mix <CODE>wnoutrefresh()</CODE> or <CODE>wrefresh()</CODE> 117062449Speteroperations with panels code; this will work only if the argument window 117162449Speteris either in the top panel or unobscured by any other panels. <P> 117262449Speter 117362449SpeterThe <CODE>stsdcr</CODE> window is a special case. It is considered below all 117462449Speterpanels. Because changes to panels may obscure parts of <CODE>stdscr</CODE>, 117562449Speterthough, you should call <CODE>update_panels()</CODE> before 117662449Speter<CODE>doupdate()</CODE> even when you only change <CODE>stdscr</CODE>. <P> 117762449Speter 117862449SpeterNote that <CODE>wgetch</CODE> automatically calls <CODE>wrefresh</CODE>. 117962449SpeterTherefore, before requesting input from a panel window, you need to be sure 118062449Speterthat the panel is totally unobscured. <P> 118162449Speter 118262449SpeterThere is presently no way to display changes to one obscured panel without 118362449Speterrepainting all panels. 118462449Speter 118562449Speter<H2><A NAME="hiding">Hiding Panels</A></H2> 118662449Speter 118762449SpeterIt's possible to remove a panel from the deck temporarily; use 118862449Speter<CODE>hide_panel</CODE> for this. Use <CODE>show_panel()</CODE> to render it 118962449Spetervisible again. The predicate function <CODE>panel_hidden</CODE> 119062449Spetertests whether or not a panel is hidden. <P> 119162449Speter 119262449SpeterThe <CODE>panel_update</CODE> code ignores hidden panels. You cannot do 119362449Speter<CODE>top_panel()</CODE> or <CODE>bottom_panel</CODE> on a hidden panel(). 119462449SpeterOther panels operations are applicable. 119562449Speter 119662449Speter<H2><A NAME="pmisc">Miscellaneous Other Facilities</A></H2> 119762449Speter 119862449SpeterIt's possible to navigate the deck using the functions 119962449Speter<CODE>panel_above()</CODE> and <CODE>panel_below</CODE>. Handed a panel 120062449Speterpointer, they return the panel above or below that panel. Handed 120162449Speter<CODE>NULL</CODE>, they return the bottom-most or top-most panel. <P> 120262449Speter 120362449SpeterEvery panel has an associated user pointer, not used by the panel code, to 120462449Speterwhich you can attach application data. See the man page documentation 120562449Speterof <CODE>set_panel_userptr()</CODE> and <CODE>panel_userptr</CODE> for 120662449Speterdetails. 120762449Speter 120862449Speter<H1><A NAME="menu">The Menu Library</A></H1> 120962449Speter 121062449SpeterA menu is a screen display that assists the user to choose some subset 121162449Speterof a given set of items. The <CODE>menu</CODE> library is a curses 121262449Speterextension that supports easy programming of menu hierarchies with a 121362449Speteruniform but flexible interface. <P> 121462449Speter 121562449SpeterThe <CODE>menu</CODE> library first appeared in AT&T System V. The 121662449Speterversion documented here is the <CODE>menu</CODE> code distributed 121762449Speterwith <CODE>ncurses</CODE>. 121862449Speter 121962449Speter<H2><A NAME="mcompile">Compiling With the menu Library</A></H2> 122062449Speter 122162449SpeterYour menu-using modules must import the menu library declarations with 122262449Speter 122362449Speter<PRE> 122462449Speter #include <menu.h> 122562449Speter</PRE> 122662449Speter 122762449Speterand must be linked explicitly with the menus library using an 122862449Speter<CODE>-lmenu</CODE> argument. Note that they must also link the 122962449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 123062449Speterare two-pass and will accept either order, but it is still good practice 123162449Speterto put <CODE>-lmenu</CODE> first and <CODE>-lncurses</CODE> second. 123262449Speter 123362449Speter<H2><A NAME="moverview">Overview of Menus</A></H2> 123462449Speter 123562449SpeterThe menus created by this library consist of collections of 123662449Speter<DFN>items</DFN> including a name string part and a description string 123762449Speterpart. To make menus, you create groups of these items and connect 123862449Speterthem with menu frame objects. <P> 123962449Speter 124062449SpeterThe menu can then by <DFN>posted</DFN>, that is written to an 124162449Speterassociated window. Actually, each menu has two associated windows; a 124262449Spetercontaining window in which the programmer can scribble titles or 124362449Speterborders, and a subwindow in which the menu items proper are displayed. 124462449SpeterIf this subwindow is too small to display all the items, it will be a 124562449Speterscrollable viewport on the collection of items. <P> 124662449Speter 124762449SpeterA menu may also be <DFN>unposted</DFN> (that is, undisplayed), and finally 124862449Speterfreed to make the storage associated with it and its items available for 124962449Speterre-use. <P> 125062449Speter 125162449SpeterThe general flow of control of a menu program looks like this: 125262449Speter 125362449Speter<OL> 125462449Speter<LI>Initialize <CODE>curses</CODE>. 125562449Speter<LI>Create the menu items, using <CODE>new_item()</CODE>. 125662449Speter<LI>Create the menu using <CODE>new_menu()</CODE>. 1257166124Srafan<LI>Post the menu using <CODE>post_menu()</CODE>. 125862449Speter<LI>Refresh the screen. 125962449Speter<LI>Process user requests via an input loop. 1260166124Srafan<LI>Unpost the menu using <CODE>unpost_menu()</CODE>. 126162449Speter<LI>Free the menu, using <CODE>free_menu()</CODE>. 126262449Speter<LI>Free the items using <CODE>free_item()</CODE>. 126362449Speter<LI>Terminate <CODE>curses</CODE>. 126462449Speter</OL> 126562449Speter 126662449Speter<H2><A NAME="mselect">Selecting items</A></H2> 126762449Speter 126862449SpeterMenus may be multi-valued or (the default) single-valued (see the manual 126962449Speterpage <CODE>menu_opts(3x)</CODE> to see how to change the default). 127062449SpeterBoth types always have a <DFN>current item</DFN>. <P> 127162449Speter 127262449SpeterFrom a single-valued menu you can read the selected value simply by looking 127362449Speterat the current item. From a multi-valued menu, you get the selected set 127462449Speterby looping through the items applying the <CODE>item_value()</CODE> 127562449Speterpredicate function. Your menu-processing code can use the function 127662449Speter<CODE>set_item_value()</CODE> to flag the items in the select set. <P> 127762449Speter 127862449SpeterMenu items can be made unselectable using <CODE>set_item_opts()</CODE> 127962449Speteror <CODE>item_opts_off()</CODE> with the <CODE>O_SELECTABLE</CODE> 128062449Speterargument. This is the only option so far defined for menus, but it 128162449Speteris good practice to code as though other option bits might be on. 128262449Speter 128362449Speter<H2><A NAME="mdisplay">Menu Display</A></H2> 128462449Speter 128562449SpeterThe menu library calculates a minimum display size for your window, based 128662449Speteron the following variables: 128762449Speter 128862449Speter<UL> 128962449Speter<LI>The number and maximum length of the menu items 129062449Speter<LI>Whether the O_ROWMAJOR option is enabled 129162449Speter<LI>Whether display of descriptions is enabled 129262449Speter<LI>Whatever menu format may have been set by the programmer 129362449Speter<LI>The length of the menu mark string used for highlighting selected items 129462449Speter</UL> 129562449Speter 129662449SpeterThe function <CODE>set_menu_format()</CODE> allows you to set the 129762449Spetermaximum size of the viewport or <DFN>menu page</DFN> that will be used 129862449Speterto display menu items. You can retrieve any format associated with a 129962449Spetermenu with <CODE>menu_format()</CODE>. The default format is rows=16, 130062449Spetercolumns=1. <P> 130162449Speter 130262449SpeterThe actual menu page may be smaller than the format size. This depends 130362449Speteron the item number and size and whether O_ROWMAJOR is on. This option 130462449Speter(on by default) causes menu items to be displayed in a `raster-scan' 130562449Speterpattern, so that if more than one item will fit horizontally the first 130662449Spetercouple of items are side-by-side in the top row. The alternative is 130762449Spetercolumn-major display, which tries to put the first several items in 130862449Speterthe first column. <P> 130962449Speter 131062449SpeterAs mentioned above, a menu format not large enough to allow all items to fit 131162449Speteron-screen will result in a menu display that is vertically scrollable. <P> 131262449SpeterYou can scroll it with requests to the menu driver, which will be described 131362449Speterin the section on <A HREF="#minput">menu input handling</A>. <P> 131462449Speter 131562449SpeterEach menu has a <DFN>mark string</DFN> used to visually tag selected items; 131662449Spetersee the <CODE>menu_mark(3x)</CODE> manual page for details. The mark 131762449Speterstring length also influences the menu page size. <P> 131862449Speter 131962449SpeterThe function <CODE>scale_menu()</CODE> returns the minimum display size 132062449Speterthat the menu code computes from all these factors. 132162449Speter 132262449SpeterThere are other menu display attributes including a select attribute, 132362449Speteran attribute for selectable items, an attribute for unselectable items, 132462449Speterand a pad character used to separate item name text from description 132562449Spetertext. These have reasonable defaults which the library allows you to 132662449Speterchange (see the <CODE>menu_attribs(3x)</CODE> manual page. 132762449Speter 132862449Speter<H2><A NAME="mwindows">Menu Windows</A></H2> 132962449Speter 133062449SpeterEach menu has, as mentioned previously, a pair of associated windows. 133162449SpeterBoth these windows are painted when the menu is posted and erased when 133262449Speterthe menu is unposted. <P> 133362449Speter 133462449SpeterThe outer or frame window is not otherwise touched by the menu 133562449Speterroutines. It exists so the programmer can associate a title, a 133662449Speterborder, or perhaps help text with the menu and have it properly 133762449Speterrefreshed or erased at post/unpost time. The inner window or 133862449Speter<DFN>subwindow</DFN> is where the current menu page is displayed. <P> 133962449Speter 134062449SpeterBy default, both windows are <CODE>stdscr</CODE>. You can set them with the 134162449Speterfunctions in <CODE>menu_win(3x)</CODE>. <P> 134262449Speter 1343166124SrafanWhen you call <CODE>post_menu()</CODE>, you write the menu to its 1344166124Srafansubwindow. When you call <CODE>unpost_menu()</CODE>, you erase the 134562449Spetersubwindow, However, neither of these actually modifies the screen. To 134662449Speterdo that, call <CODE>wrefresh()</CODE> or some equivalent. 134762449Speter 134862449Speter<H2><A NAME="minput">Processing Menu Input</A></H2> 134962449Speter 135062449SpeterThe main loop of your menu-processing code should call 135162449Speter<CODE>menu_driver()</CODE> repeatedly. The first argument of this routine 135262449Speteris a menu pointer; the second is a menu command code. You should write an 135362449Speterinput-fetching routine that maps input characters to menu command codes, and 135462449Speterpass its output to <CODE>menu_driver()</CODE>. The menu command codes are 135562449Speterfully documented in <CODE>menu_driver(3x)</CODE>. <P> 135662449Speter 135762449SpeterThe simplest group of command codes is <CODE>REQ_NEXT_ITEM</CODE>, 135862449Speter<CODE>REQ_PREV_ITEM</CODE>, <CODE>REQ_FIRST_ITEM</CODE>, 135962449Speter<CODE>REQ_LAST_ITEM</CODE>, <CODE>REQ_UP_ITEM</CODE>, 136062449Speter<CODE>REQ_DOWN_ITEM</CODE>, <CODE>REQ_LEFT_ITEM</CODE>, 136162449Speter<CODE>REQ_RIGHT_ITEM</CODE>. These change the currently selected 136262449Speteritem. These requests may cause scrolling of the menu page if it only 136362449Speterpartially displayed. <P> 136462449Speter 136562449SpeterThere are explicit requests for scrolling which also change the 136662449Spetercurrent item (because the select location does not change, but the 136762449Speteritem there does). These are <CODE>REQ_SCR_DLINE</CODE>, 136862449Speter<CODE>REQ_SCR_ULINE</CODE>, <CODE>REQ_SCR_DPAGE</CODE>, and 136962449Speter<CODE>REQ_SCR_UPAGE</CODE>. <P> 137062449Speter 137162449SpeterThe <CODE>REQ_TOGGLE_ITEM</CODE> selects or deselects the current item. 137262449SpeterIt is for use in multi-valued menus; if you use it with <CODE>O_ONEVALUE</CODE> 137362449Speteron, you'll get an error return (<CODE>E_REQUEST_DENIED</CODE>). <P> 137462449Speter 137562449SpeterEach menu has an associated pattern buffer. The 137662449Speter<CODE>menu_driver()</CODE> logic tries to accumulate printable ASCII 137762449Spetercharacters passed in in that buffer; when it matches a prefix of an 137862449Speteritem name, that item (or the next matching item) is selected. If 137962449Speterappending a character yields no new match, that character is deleted 138062449Speterfrom the pattern buffer, and <CODE>menu_driver()</CODE> returns 138162449Speter<CODE>E_NO_MATCH</CODE>. <P> 138262449Speter 138362449SpeterSome requests change the pattern buffer directly: 138462449Speter<CODE>REQ_CLEAR_PATTERN</CODE>, <CODE>REQ_BACK_PATTERN</CODE>, 138562449Speter<CODE>REQ_NEXT_MATCH</CODE>, <CODE>REQ_PREV_MATCH</CODE>. The latter 138662449Spetertwo are useful when pattern buffer input matches more than one item 138762449Speterin a multi-valued menu. <P> 138862449Speter 138962449SpeterEach successful scroll or item navigation request clears the pattern 139062449Speterbuffer. It is also possible to set the pattern buffer explicitly 139162449Speterwith <CODE>set_menu_pattern()</CODE>. <P> 139262449Speter 139362449SpeterFinally, menu driver requests above the constant <CODE>MAX_COMMAND</CODE> 139462449Speterare considered application-specific commands. The <CODE>menu_driver()</CODE> 139562449Spetercode ignores them and returns <CODE>E_UNKNOWN_COMMAND</CODE>. 139662449Speter 139762449Speter<H2><A NAME="mmisc">Miscellaneous Other Features</A></H2> 139862449Speter 139962449SpeterVarious menu options can affect the processing and visual appearance 140062449Speterand input processing of menus. See <CODE>menu_opts(3x) for 140162449Speterdetails.</CODE> <P> 140262449Speter 140362449SpeterIt is possible to change the current item from application code; this 140462449Speteris useful if you want to write your own navigation requests. It is 140562449Speteralso possible to explicitly set the top row of the menu display. See 140662449Speter<CODE>mitem_current(3x)</CODE>. 140762449Speter 140862449SpeterIf your application needs to change the menu subwindow cursor for 140962449Speterany reason, <CODE>pos_menu_cursor()</CODE> will restore it to the 141062449Spetercorrect location for continuing menu driver processing. <P> 141162449Speter 141262449SpeterIt is possible to set hooks to be called at menu initialization and 141362449Speterwrapup time, and whenever the selected item changes. See 141462449Speter<CODE>menu_hook(3x)</CODE>. <P> 141562449Speter 141662449SpeterEach item, and each menu, has an associated user pointer on which you 141762449Spetercan hang application data. See <CODE>mitem_userptr(3x)</CODE> and 141862449Speter<CODE>menu_userptr(3x)</CODE>. 141962449Speter 142062449Speter<H1><A NAME="form">The Forms Library</A></H1> 142162449Speter 142262449SpeterThe <CODE>form</CODE> library is a curses extension that supports easy 142362449Speterprogramming of on-screen forms for data entry and program control. <P> 142462449Speter 142562449SpeterThe <CODE>form</CODE> library first appeared in AT&T System V. The 142662449Speterversion documented here is the <CODE>form</CODE> code distributed 142762449Speterwith <CODE>ncurses</CODE>. 142862449Speter 142962449Speter<H2><A NAME="fcompile">Compiling With the form Library</A></H2> 143062449Speter 143162449SpeterYour form-using modules must import the form library declarations with 143262449Speter 143362449Speter<PRE> 143462449Speter #include <form.h> 143562449Speter</PRE> 143662449Speter 143762449Speterand must be linked explicitly with the forms library using an 143862449Speter<CODE>-lform</CODE> argument. Note that they must also link the 143962449Speter<CODE>ncurses</CODE> library with <CODE>-lncurses</CODE>. Many linkers 144062449Speterare two-pass and will accept either order, but it is still good practice 144162449Speterto put <CODE>-lform</CODE> first and <CODE>-lncurses</CODE> second. 144262449Speter 144362449Speter<H2><A NAME="foverview">Overview of Forms</A></H2> 144462449Speter 144562449SpeterA form is a collection of fields; each field may be either a label 144662449Speter(explanatory text) or a data-entry location. Long forms may be 144762449Spetersegmented into pages; each entry to a new page clears the screen. <P> 144862449SpeterTo make forms, you create groups of fields and connect them with form 144962449Speterframe objects; the form library makes this relatively simple. <P> 145062449Speter 145162449SpeterOnce defined, a form can be <DFN>posted</DFN>, that is written to an 145262449Speterassociated window. Actually, each form has two associated windows; a 145362449Spetercontaining window in which the programmer can scribble titles or 145462449Speterborders, and a subwindow in which the form fields proper are displayed. <P> 145562449Speter 145662449SpeterAs the form user fills out the posted form, navigation and editing 145762449Speterkeys support movement between fields, editing keys support modifying 145862449Speterfield, and plain text adds to or changes data in a current field. The 145962449Speterform library allows you (the forms designer) to bind each navigation 146062449Speterand editing key to any keystroke accepted by <CODE>curses</CODE> 146162449Speter 146262449SpeterFields may have validation conditions on them, so that they check input 146362449Speterdata for type and value. The form library supplies a rich set of 146462449Speterpre-defined field types, and makes it relatively easy to define new ones. <P> 146562449Speter 146662449SpeterOnce its transaction is completed (or aborted), a form may be 146762449Speter<DFN>unposted</DFN> (that is, undisplayed), and finally freed to make 146862449Speterthe storage associated with it and its items available for re-use. <P> 146962449Speter 147062449SpeterThe general flow of control of a form program looks like this: 147162449Speter 147262449Speter<OL> 147362449Speter<LI>Initialize <CODE>curses</CODE>. 147462449Speter<LI>Create the form fields, using <CODE>new_field()</CODE>. 147562449Speter<LI>Create the form using <CODE>new_form()</CODE>. 1476166124Srafan<LI>Post the form using <CODE>post_form()</CODE>. 147762449Speter<LI>Refresh the screen. 147862449Speter<LI>Process user requests via an input loop. 1479166124Srafan<LI>Unpost the form using <CODE>unpost_form()</CODE>. 148062449Speter<LI>Free the form, using <CODE>free_form()</CODE>. 148162449Speter<LI>Free the fields using <CODE>free_field()</CODE>. 148262449Speter<LI>Terminate <CODE>curses</CODE>. 148362449Speter</OL> 148462449Speter 148562449SpeterNote that this looks much like a menu program; the form library handles 148662449Spetertasks which are in many ways similar, and its interface was obviously 148762449Speterdesigned to resemble that of the <A HREF="#menu">menu library</A> 148862449Speterwherever possible. <P> 148962449Speter 149062449SpeterIn forms programs, however, the `process user requests' is somewhat more 149162449Spetercomplicated than for menus. Besides menu-like navigation operations, 149262449Speterthe menu driver loop has to support field editing and data validation. 149362449Speter 149462449Speter<H2><A NAME="fcreate">Creating and Freeing Fields and Forms</A></H2> 149562449Speter 149662449SpeterThe basic function for creating fields is <CODE>new_field()</CODE>: 149762449Speter 149862449Speter<PRE> 149962449SpeterFIELD *new_field(int height, int width, /* new field size */ 150062449Speter int top, int left, /* upper left corner */ 150162449Speter int offscreen, /* number of offscreen rows */ 150262449Speter int nbuf); /* number of working buffers */ 150362449Speter</PRE> 150462449Speter 150562449SpeterMenu items always occupy a single row, but forms fields may have 150662449Spetermultiple rows. So <CODE>new_field()</CODE> requires you to specify a 150762449Speterwidth and height (the first two arguments, which mist both be greater 150862449Speterthan zero). <P> 150962449Speter 151062449SpeterYou must also specify the location of the field's upper left corner on 151162449Speterthe screen (the third and fourth arguments, which must be zero or 151262449Spetergreater). Note that these coordinates are relative to the form 151362449Spetersubwindow, which will coincide with <CODE>stdscr</CODE> by default but 151462449Speterneed not be <CODE>stdscr</CODE> if you've done an explicit 1515166124Srafan<CODE>set_form_win()</CODE> call. <P> 151662449Speter 151762449SpeterThe fifth argument allows you to specify a number of off-screen rows. If 151862449Speterthis is zero, the entire field will always be displayed. If it is 151962449Speternonzero, the form will be scrollable, with only one screen-full (initially 152062449Speterthe top part) displayed at any given time. If you make a field dynamic 152162449Speterand grow it so it will no longer fit on the screen, the form will become 152262449Speterscrollable even if the <CODE>offscreen</CODE> argument was initially zero. <P> 152362449Speter 152462449SpeterThe forms library allocates one working buffer per field; the size of 152562449Spetereach buffer is <CODE>((height + offscreen)*width + 1</CODE>, one character 152662449Speterfor each position in the field plus a NUL terminator. The sixth 152762449Speterargument is the number of additional data buffers to allocate for the 152862449Speterfield; your application can use them for its own purposes. 152962449Speter 153062449Speter<PRE> 153162449SpeterFIELD *dup_field(FIELD *field, /* field to copy */ 153262449Speter int top, int left); /* location of new copy */ 153362449Speter</PRE> 153462449Speter 153562449SpeterThe function <CODE>dup_field()</CODE> duplicates an existing field at a 153662449Speternew location. Size and buffering information are copied; some 153762449Speterattribute flags and status bits are not (see the 153862449Speter<CODE>form_field_new(3X)</CODE> for details). 153962449Speter 154062449Speter<PRE> 154162449SpeterFIELD *link_field(FIELD *field, /* field to copy */ 154262449Speter int top, int left); /* location of new copy */ 154362449Speter</PRE> 154462449Speter 154562449SpeterThe function <CODE>link_field()</CODE> also duplicates an existing field 154662449Speterat a new location. The difference from <CODE>dup_field()</CODE> is that 154762449Speterit arranges for the new field's buffer to be shared with the old one. <P> 154862449Speter 154962449SpeterBesides the obvious use in making a field editable from two different 155062449Speterform pages, linked fields give you a way to hack in dynamic labels. If 155162449Speteryou declare several fields linked to an original, and then make them 155262449Speterinactive, changes from the original will still be propagated to the 155362449Speterlinked fields. <P> 155462449Speter 155562449SpeterAs with duplicated fields, linked fields have attribute bits separate 155662449Speterfrom the original. <P> 155762449Speter 155862449SpeterAs you might guess, all these field-allocations return <CODE>NULL</CODE> if 155962449Speterthe field allocation is not possible due to an out-of-memory error or 156062449Speterout-of-bounds arguments. <P> 156162449Speter 156262449SpeterTo connect fields to a form, use 156362449Speter 156462449Speter<PRE> 156562449SpeterFORM *new_form(FIELD **fields); 156662449Speter</PRE> 156762449Speter 156862449SpeterThis function expects to see a NULL-terminated array of field pointers. 156962449SpeterSaid fields are connected to a newly-allocated form object; its address 157062449Speteris returned (or else NULL if the allocation fails). <P> 157162449Speter 157262449SpeterNote that <CODE>new_field()</CODE> does <EM>not</EM> copy the pointer array 157362449Speterinto private storage; if you modify the contents of the pointer array 157462449Speterduring forms processing, all manner of bizarre things might happen. Also 157562449Speternote that any given field may only be connected to one form. <P> 157662449Speter 157762449SpeterThe functions <CODE>free_field()</CODE> and <CODE>free_form</CODE> are available 157862449Speterto free field and form objects. It is an error to attempt to free a field 157962449Speterconnected to a form, but not vice-versa; thus, you will generally free 158062449Speteryour form objects first. 158162449Speter 158262449Speter<H2><A NAME="fattributes">Fetching and Changing Field Attributes</A></H2> 158362449Speter 158462449SpeterEach form field has a number of location and size attributes 158562449Speterassociated with it. There are other field attributes used to control 158662449Speterdisplay and editing of the field. Some (for example, the <CODE>O_STATIC</CODE> bit) 158762449Speterinvolve sufficient complications to be covered in sections of their own 158862449Speterlater on. We cover the functions used to get and set several basic 158962449Speterattributes here. <P> 159062449Speter 159162449SpeterWhen a field is created, the attributes not specified by the 159262449Speter<CODE>new_field</CODE> function are copied from an invisible system 159362449Speterdefault field. In attribute-setting and -fetching functions, the 159462449Speterargument NULL is taken to mean this field. Changes to it persist 159562449Speteras defaults until your forms application terminates. 159662449Speter 159762449Speter<H3><A NAME="fsizes">Fetching Size and Location Data</A></H3> 159862449Speter 159962449SpeterYou can retrieve field sizes and locations through: 160062449Speter 160162449Speter<PRE> 160262449Speterint field_info(FIELD *field, /* field from which to fetch */ 160362449Speter int *height, *int width, /* field size */ 160462449Speter int *top, int *left, /* upper left corner */ 160562449Speter int *offscreen, /* number of offscreen rows */ 160662449Speter int *nbuf); /* number of working buffers */ 160762449Speter</PRE> 160862449Speter 160962449SpeterThis function is a sort of inverse of <CODE>new_field()</CODE>; instead of 161062449Spetersetting size and location attributes of a new field, it fetches them 161162449Speterfrom an existing one. 161262449Speter 161362449Speter<H3><A NAME="flocation">Changing the Field Location</A></H3> 161462449Speter 161562449SpeterIt is possible to move a field's location on the screen: 161662449Speter 161762449Speter<PRE> 161862449Speterint move_field(FIELD *field, /* field to alter */ 161962449Speter int top, int left); /* new upper-left corner */ 162062449Speter</PRE> 162162449Speter 162262449SpeterYou can, of course. query the current location through <CODE>field_info()</CODE>. 162362449Speter 162462449Speter<H3><A NAME="fjust">The Justification Attribute</A></H3> 162562449Speter 162662449SpeterOne-line fields may be unjustified, justified right, justified left, 162762449Speteror centered. Here is how you manipulate this attribute: 162862449Speter 162962449Speter<PRE> 163062449Speterint set_field_just(FIELD *field, /* field to alter */ 163162449Speter int justmode); /* mode to set */ 163262449Speter 163362449Speterint field_just(FIELD *field); /* fetch mode of field */ 163462449Speter</PRE> 163562449Speter 163662449SpeterThe mode values accepted and returned by this functions are 163762449Speterpreprocessor macros <CODE>NO_JUSTIFICATION</CODE>, <CODE>JUSTIFY_RIGHT</CODE>, 163862449Speter<CODE>JUSTIFY_LEFT</CODE>, or <CODE>JUSTIFY_CENTER</CODE>. 163962449Speter 164062449Speter<H3><A NAME="fdispatts">Field Display Attributes</A></H3> 164162449Speter 164262449SpeterFor each field, you can set a foreground attribute for entered 164362449Spetercharacters, a background attribute for the entire field, and a pad 164462449Spetercharacter for the unfilled portion of the field. You can also 164562449Spetercontrol pagination of the form. <P> 164662449Speter 164762449SpeterThis group of four field attributes controls the visual appearance 164862449Speterof the field on the screen, without affecting in any way the data 164962449Speterin the field buffer. 165062449Speter 165162449Speter<PRE> 165262449Speterint set_field_fore(FIELD *field, /* field to alter */ 165362449Speter chtype attr); /* attribute to set */ 165462449Speter 165562449Speterchtype field_fore(FIELD *field); /* field to query */ 165662449Speter 165762449Speterint set_field_back(FIELD *field, /* field to alter */ 165862449Speter chtype attr); /* attribute to set */ 165962449Speter 166062449Speterchtype field_back(FIELD *field); /* field to query */ 166162449Speter 166262449Speterint set_field_pad(FIELD *field, /* field to alter */ 166362449Speter int pad); /* pad character to set */ 166462449Speter 166562449Speterchtype field_pad(FIELD *field); 166662449Speter 166762449Speterint set_new_page(FIELD *field, /* field to alter */ 166862449Speter int flag); /* TRUE to force new page */ 166962449Speter 167062449Speterchtype new_page(FIELD *field); /* field to query */ 167162449Speter</PRE> 167262449Speter 167362449SpeterThe attributes set and returned by the first four functions are normal 167462449Speter<CODE>curses(3x)</CODE> display attribute values (<CODE>A_STANDOUT</CODE>, 167562449Speter<CODE>A_BOLD</CODE>, <CODE>A_REVERSE</CODE> etc). 167662449Speter 167762449SpeterThe page bit of a field controls whether it is displayed at the start of 167862449Spetera new form screen. 167962449Speter 168062449Speter<H3><A NAME="foptions">Field Option Bits</A></H3> 168162449Speter 168262449SpeterThere is also a large collection of field option bits you can set to control 168362449Spetervarious aspects of forms processing. You can manipulate them with these 168462449Speterfunctions: 168562449Speter 168662449Speter<PRE> 168762449Speterint set_field_opts(FIELD *field, /* field to alter */ 168862449Speter int attr); /* attribute to set */ 168962449Speter 169062449Speterint field_opts_on(FIELD *field, /* field to alter */ 169162449Speter int attr); /* attributes to turn on */ 169262449Speter 169362449Speterint field_opts_off(FIELD *field, /* field to alter */ 169462449Speter int attr); /* attributes to turn off */ 169562449Speter 169662449Speterint field_opts(FIELD *field); /* field to query */ 169762449Speter</PRE> 169862449Speter 169962449SpeterBy default, all options are on. Here are the available option bits: 170062449Speter<DL> 170162449Speter<DT> O_VISIBLE 170262449Speter<DD> Controls whether the field is visible on the screen. Can be used 170362449Speterduring form processing to hide or pop up fields depending on the value 170462449Speterof parent fields. 170562449Speter<DT> O_ACTIVE 170662449Speter<DD> Controls whether the field is active during forms processing (i.e. 170762449Spetervisited by form navigation keys). Can be used to make labels or derived 170862449Speterfields with buffer values alterable by the forms application, not the user. 170962449Speter<DT> O_PUBLIC 171062449Speter<DD> Controls whether data is displayed during field entry. If this option is 171162449Speterturned off on a field, the library will accept and edit data in that field, 171262449Speterbut it will not be displayed and the visible field cursor will not move. 171362449SpeterYou can turn off the O_PUBLIC bit to define password fields. 171462449Speter<DT> O_EDIT 171562449Speter<DD> Controls whether the field's data can be modified. When this option is 171662449Speteroff, all editing requests except <CODE>REQ_PREV_CHOICE</CODE> and 171762449Speter<CODE>REQ_NEXT_CHOICE</CODE> will fail. Such read-only fields may be useful for 171862449Speterhelp messages. 171962449Speter<DT> O_WRAP 172062449Speter<DD> Controls word-wrapping in multi-line fields. Normally, when any 172162449Spetercharacter of a (blank-separated) word reaches the end of the current line, the 172262449Speterentire word is wrapped to the next line (assuming there is one). When this 172362449Speteroption is off, the word will be split across the line break. 172462449Speter<DT> O_BLANK 172562449Speter<DD> Controls field blanking. When this option is on, entering a character at 172662449Speterthe first field position erases the entire field (except for the just-entered 172762449Spetercharacter). 172862449Speter<DT> O_AUTOSKIP 172962449Speter<DD> Controls automatic skip to next field when this one fills. Normally, 173062449Speterwhen the forms user tries to type more data into a field than will fit, 173162449Speterthe editing location jumps to next field. When this option is off, the 173262449Speteruser's cursor will hang at the end of the field. This option is ignored 173362449Speterin dynamic fields that have not reached their size limit. 173462449Speter<DT> O_NULLOK 173562449Speter<DD> Controls whether <A HREF="#fvalidation">validation</A> is applied to 173662449Speterblank fields. Normally, it is not; the user can leave a field blank 173762449Speterwithout invoking the usual validation check on exit. If this option is 173862449Speteroff on a field, exit from it will invoke a validation check. 173962449Speter<DT> O_PASSOK 174062449Speter<DD> Controls whether validation occurs on every exit, or only after 174162449Speterthe field is modified. Normally the latter is true. Setting O_PASSOK 174262449Spetermay be useful if your field's validation function may change during 174362449Speterforms processing. 174462449Speter<DT> O_STATIC 174562449Speter<DD> Controls whether the field is fixed to its initial dimensions. If you 174662449Speterturn this off, the field becomes <A HREF="#fdynamic">dynamic</A> and will 174762449Speterstretch to fit entered data. 174862449Speter</DL> 174962449Speter 175062449SpeterA field's options cannot be changed while the field is currently selected. 175162449SpeterHowever, options may be changed on posted fields that are not current. <P> 175262449Speter 175362449SpeterThe option values are bit-masks and can be composed with logical-or in 175462449Speterthe obvious way. 175562449Speter 175662449Speter<H2><A NAME="fstatus">Field Status</A></H2> 175762449Speter 175862449SpeterEvery field has a status flag, which is set to FALSE when the field is 175962449Spetercreated and TRUE when the value in field buffer 0 changes. This flag can 176062449Speterbe queried and set directly: 176162449Speter 176262449Speter<PRE> 176362449Speterint set_field_status(FIELD *field, /* field to alter */ 176462449Speter int status); /* mode to set */ 176562449Speter 176662449Speterint field_status(FIELD *field); /* fetch mode of field */ 176762449Speter</PRE> 176862449Speter 176962449SpeterSetting this flag under program control can be useful if you use the same 177062449Speterform repeatedly, looking for modified fields each time. <P> 177162449Speter 177262449SpeterCalling <CODE>field_status()</CODE> on a field not currently selected 177362449Speterfor input will return a correct value. Calling <CODE>field_status()</CODE> on a 177462449Speterfield that is currently selected for input may not necessarily give a 177562449Spetercorrect field status value, because entered data isn't necessarily copied to 177662449Speterbuffer zero before the exit validation check. 177762449Speter 177862449SpeterTo guarantee that the returned status value reflects reality, call 177962449Speter<CODE>field_status()</CODE> either (1) in the field's exit validation check 178062449Speterroutine, (2) from the field's or form's initialization or termination 178162449Speterhooks, or (3) just after a <CODE>REQ_VALIDATION</CODE> request has been 178262449Speterprocessed by the forms driver. 178362449Speter 178462449Speter<H2><A NAME="fuser">Field User Pointer</A></H2> 178562449Speter 178662449SpeterEach field structure contains one character pointer slot that is not used 178762449Speterby the forms library. It is intended to be used by applications to store 178862449Speterprivate per-field data. You can manipulate it with: 178962449Speter 179062449Speter<PRE> 179162449Speterint set_field_userptr(FIELD *field, /* field to alter */ 179262449Speter char *userptr); /* mode to set */ 179362449Speter 179462449Speterchar *field_userptr(FIELD *field); /* fetch mode of field */ 179562449Speter</PRE> 179662449Speter 179762449Speter(Properly, this user pointer field ought to have <CODE>(void *)</CODE> type. 179862449SpeterThe <CODE>(char *)</CODE> type is retained for System V compatibility.) <P> 179962449Speter 180062449SpeterIt is valid to set the user pointer of the default field (with a 180162449Speter<CODE>set_field_userptr()</CODE> call passed a NULL field pointer.) 180262449SpeterWhen a new field is created, the default-field user pointer is copied 180362449Speterto initialize the new field's user pointer. 180462449Speter 180562449Speter<H2><A NAME="fdynamic">Variable-Sized Fields</A></H2> 180662449Speter 180762449SpeterNormally, a field is fixed at the size specified for it at creation 180862449Spetertime. If, however, you turn off its O_STATIC bit, it becomes 180962449Speter<DFN>dynamic</DFN> and will automatically resize itself to accommodate 181062449Speterdata as it is entered. If the field has extra buffers associated with it, 181162449Speterthey will grow right along with the main input buffer. <P> 181262449Speter 181362449SpeterA one-line dynamic field will have a fixed height (1) but variable 181462449Speterwidth, scrolling horizontally to display data within the field area as 181562449Speteroriginally dimensioned and located. A multi-line dynamic field will 181662449Speterhave a fixed width, but variable height (number of rows), scrolling 181762449Spetervertically to display data within the field area as originally 181862449Speterdimensioned and located. <P> 181962449Speter 182062449SpeterNormally, a dynamic field is allowed to grow without limit. But it is 182162449Speterpossible to set an upper limit on the size of a dynamic field. You do 182262449Speterit with this function: 182362449Speter 182462449Speter<PRE> 182562449Speterint set_max_field(FIELD *field, /* field to alter (may not be NULL) */ 182662449Speter int max_size); /* upper limit on field size */ 182762449Speter</PRE> 182862449Speter 182962449SpeterIf the field is one-line, <CODE>max_size</CODE> is taken to be a column size 183062449Speterlimit; if it is multi-line, it is taken to be a line size limit. To disable 183162449Speterany limit, use an argument of zero. The growth limit can be changed whether 183262449Speteror not the O_STATIC bit is on, but has no effect until it is. <P> 183362449Speter 183462449SpeterThe following properties of a field change when it becomes dynamic: 183562449Speter 183662449Speter<UL> 183762449Speter<LI>If there is no growth limit, there is no final position of the field; 183862449Spetertherefore <CODE>O_AUTOSKIP</CODE> and <CODE>O_NL_OVERLOAD</CODE> are ignored. 183962449Speter<LI>Field justification will be ignored (though whatever justification is 184062449Speterset up will be retained internally and can be queried). 184162449Speter<LI>The <CODE>dup_field()</CODE> and <CODE>link_field()</CODE> calls copy 184262449Speterdynamic-buffer sizes. If the <CODE>O_STATIC</CODE> option is set on one of a 184362449Spetercollection of links, buffer resizing will occur only when the field is 184462449Speteredited through that link. 184562449Speter<LI>The call <CODE>field_info()</CODE> will retrieve the original static size of 184662449Speterthe field; use <CODE>dynamic_field_info()</CODE> to get the actual dynamic size. 184762449Speter</UL> 184862449Speter 184962449Speter<H2><A NAME="fvalidation">Field Validation</A></H2> 185062449Speter 185162449SpeterBy default, a field will accept any data that will fit in its input buffer. 185262449SpeterHowever, it is possible to attach a validation type to a field. If you do 185362449Speterthis, any attempt to leave the field while it contains data that doesn't 185462449Spetermatch the validation type will fail. Some validation types also have a 185562449Spetercharacter-validity check for each time a character is entered in the field. <P> 185662449Speter 185762449SpeterA field's validation check (if any) is not called when 185862449Speter<CODE>set_field_buffer()</CODE> modifies the input buffer, nor when that buffer 185962449Speteris changed through a linked field. <P> 186062449Speter 186162449SpeterThe <CODE>form</CODE> library provides a rich set of pre-defined validation 186262449Spetertypes, and gives you the capability to define custom ones of your own. You 186362449Spetercan examine and change field validation attributes with the following 186462449Speterfunctions: 186562449Speter 186662449Speter<PRE> 186762449Speterint set_field_type(FIELD *field, /* field to alter */ 186862449Speter FIELDTYPE *ftype, /* type to associate */ 186962449Speter ...); /* additional arguments*/ 187062449Speter 187162449SpeterFIELDTYPE *field_type(FIELD *field); /* field to query */ 187262449Speter</PRE> 187362449Speter 187462449SpeterThe validation type of a field is considered an attribute of the field. As 187562449Speterwith other field attributes, Also, doing <CODE>set_field_type()</CODE> with a 187662449Speter<CODE>NULL</CODE> field default will change the system default for validation of 187762449Speternewly-created fields. <P> 187862449Speter 187962449SpeterHere are the pre-defined validation types: 188062449Speter 188162449Speter<H3><A NAME="ftype_alpha">TYPE_ALPHA</A></H3> 188262449Speter 188362449SpeterThis field type accepts alphabetic data; no blanks, no digits, no special 188462449Spetercharacters (this is checked at character-entry time). It is set up with: 188562449Speter 188662449Speter<PRE> 188762449Speterint set_field_type(FIELD *field, /* field to alter */ 188862449Speter TYPE_ALPHA, /* type to associate */ 188962449Speter int width); /* maximum width of field */ 189062449Speter</PRE> 189162449Speter 189262449SpeterThe <CODE>width</CODE> argument sets a minimum width of data. Typically 189362449Speteryou'll want to set this to the field width; if it's greater than the 189462449Speterfield width, the validation check will always fail. A minimum width 189562449Speterof zero makes field completion optional. 189662449Speter 189762449Speter<H3><A NAME="ftype_alnum">TYPE_ALNUM</A></H3> 189862449Speter 189962449SpeterThis field type accepts alphabetic data and digits; no blanks, no special 190062449Spetercharacters (this is checked at character-entry time). It is set up with: 190162449Speter 190262449Speter<PRE> 190362449Speterint set_field_type(FIELD *field, /* field to alter */ 190462449Speter TYPE_ALNUM, /* type to associate */ 190562449Speter int width); /* maximum width of field */ 190662449Speter</PRE> 190762449Speter 190862449SpeterThe <CODE>width</CODE> argument sets a minimum width of data. As with 190962449SpeterTYPE_ALPHA, typically you'll want to set this to the field width; if it's 191062449Spetergreater than the field width, the validation check will always fail. A 191162449Speterminimum width of zero makes field completion optional. 191262449Speter 191362449Speter<H3><A NAME="ftype_enum">TYPE_ENUM</A></H3> 191462449Speter 191562449SpeterThis type allows you to restrict a field's values to be among a specified 191662449Speterset of string values (for example, the two-letter postal codes for U.S. 191762449Speterstates). It is set up with: 191862449Speter 191962449Speter<PRE> 192062449Speterint set_field_type(FIELD *field, /* field to alter */ 192162449Speter TYPE_ENUM, /* type to associate */ 192262449Speter char **valuelist; /* list of possible values */ 192362449Speter int checkcase; /* case-sensitive? */ 192462449Speter int checkunique); /* must specify uniquely? */ 192562449Speter</PRE> 192662449Speter 192762449SpeterThe <CODE>valuelist</CODE> parameter must point at a NULL-terminated list of 192862449Spetervalid strings. The <CODE>checkcase</CODE> argument, if true, makes comparison 192962449Speterwith the string case-sensitive. <P> 193062449Speter 193162449SpeterWhen the user exits a TYPE_ENUM field, the validation procedure tries to 193262449Spetercomplete the data in the buffer to a valid entry. If a complete choice string 193362449Speterhas been entered, it is of course valid. But it is also possible to enter a 193462449Speterprefix of a valid string and have it completed for you. <P> 193562449Speter 193662449SpeterBy default, if you enter such a prefix and it matches more than one value 193762449Speterin the string list, the prefix will be completed to the first matching 193862449Spetervalue. But the <CODE>checkunique</CODE> argument, if true, requires prefix 193962449Spetermatches to be unique in order to be valid. <P> 194062449Speter 194162449SpeterThe <CODE>REQ_NEXT_CHOICE</CODE> and <CODE>REQ_PREV_CHOICE</CODE> input requests 194262449Spetercan be particularly useful with these fields. 194362449Speter 194462449Speter<H3><A NAME="ftype_integer">TYPE_INTEGER</A></H3> 194562449Speter 194662449SpeterThis field type accepts an integer. It is set up as follows: 194762449Speter 194862449Speter<PRE> 194962449Speterint set_field_type(FIELD *field, /* field to alter */ 195062449Speter TYPE_INTEGER, /* type to associate */ 195162449Speter int padding, /* # places to zero-pad to */ 195262449Speter int vmin, int vmax); /* valid range */ 195362449Speter</PRE> 195462449Speter 195562449SpeterValid characters consist of an optional leading minus and digits. 195662449SpeterThe range check is performed on exit. If the range maximum is less 195762449Speterthan or equal to the minimum, the range is ignored. <P> 195862449Speter 195962449SpeterIf the value passes its range check, it is padded with as many leading 196062449Speterzero digits as necessary to meet the padding argument. <P> 196162449Speter 196262449SpeterA <CODE>TYPE_INTEGER</CODE> value buffer can conveniently be interpreted 196362449Speterwith the C library function <CODE>atoi(3)</CODE>. 196462449Speter 196562449Speter<H3><A NAME="ftype_numeric">TYPE_NUMERIC</A></H3> 196662449Speter 196762449SpeterThis field type accepts a decimal number. It is set up as follows: 196862449Speter 196962449Speter<PRE> 197062449Speterint set_field_type(FIELD *field, /* field to alter */ 197162449Speter TYPE_NUMERIC, /* type to associate */ 197262449Speter int padding, /* # places of precision */ 197362449Speter double vmin, double vmax); /* valid range */ 197462449Speter</PRE> 197562449Speter 197662449SpeterValid characters consist of an optional leading minus and digits. possibly 197762449Speterincluding a decimal point. If your system supports locale's, the decimal point 197862449Spetercharacter used must be the one defined by your locale. The range check is 197962449Speterperformed on exit. If the range maximum is less than or equal to the minimum, 198062449Speterthe range is ignored. <P> 198162449Speter 198262449SpeterIf the value passes its range check, it is padded with as many trailing 198362449Speterzero digits as necessary to meet the padding argument. <P> 198462449Speter 198562449SpeterA <CODE>TYPE_NUMERIC</CODE> value buffer can conveniently be interpreted 198662449Speterwith the C library function <CODE>atof(3)</CODE>. 198762449Speter 198862449Speter<H3><A NAME="ftype_regexp">TYPE_REGEXP</A></H3> 198962449Speter 199062449SpeterThis field type accepts data matching a regular expression. It is set up 199162449Speteras follows: 199262449Speter 199362449Speter<PRE> 199462449Speterint set_field_type(FIELD *field, /* field to alter */ 199562449Speter TYPE_REGEXP, /* type to associate */ 199662449Speter char *regexp); /* expression to match */ 199762449Speter</PRE> 199862449Speter 199962449SpeterThe syntax for regular expressions is that of <CODE>regcomp(3)</CODE>. 200062449SpeterThe check for regular-expression match is performed on exit. 200162449Speter 200262449Speter<H2><A NAME="fbuffer">Direct Field Buffer Manipulation</A></H2> 200362449Speter 200462449SpeterThe chief attribute of a field is its buffer contents. When a form has 200562449Speterbeen completed, your application usually needs to know the state of each 200662449Speterfield buffer. You can find this out with: 200762449Speter 200862449Speter<PRE> 200962449Speterchar *field_buffer(FIELD *field, /* field to query */ 201062449Speter int bufindex); /* number of buffer to query */ 201162449Speter</PRE> 201262449Speter 201362449SpeterNormally, the state of the zero-numbered buffer for each field is set by 201462449Speterthe user's editing actions on that field. It's sometimes useful to be able 201562449Speterto set the value of the zero-numbered (or some other) buffer from your 201662449Speterapplication: 201762449Speter 201862449Speter<PRE> 201962449Speterint set_field_buffer(FIELD *field, /* field to alter */ 202062449Speter int bufindex, /* number of buffer to alter */ 202162449Speter char *value); /* string value to set */ 202262449Speter</PRE> 202362449Speter 202462449SpeterIf the field is not large enough and cannot be resized to a sufficiently 202562449Speterlarge size to contain the specified value, the value will be truncated 202662449Speterto fit. <P> 202762449Speter 202862449SpeterCalling <CODE>field_buffer()</CODE> with a null field pointer will raise an 202962449Spetererror. Calling <CODE>field_buffer()</CODE> on a field not currently selected 203062449Speterfor input will return a correct value. Calling <CODE>field_buffer()</CODE> on a 203162449Speterfield that is currently selected for input may not necessarily give a 203262449Spetercorrect field buffer value, because entered data isn't necessarily copied to 203362449Speterbuffer zero before the exit validation check. 203462449Speter 203562449SpeterTo guarantee that the returned buffer value reflects on-screen reality, 203662449Spetercall <CODE>field_buffer()</CODE> either (1) in the field's exit validation 203762449Spetercheck routine, (2) from the field's or form's initialization or termination 203862449Speterhooks, or (3) just after a <CODE>REQ_VALIDATION</CODE> request has been processed 203962449Speterby the forms driver. 204062449Speter 204162449Speter<H2><A NAME="formattrs">Attributes of Forms</A></H2> 204262449Speter 204362449SpeterAs with field attributes, form attributes inherit a default from a 204462449Spetersystem default form structure. These defaults can be queried or set by 204562449Speterof these functions using a form-pointer argument of <CODE>NULL</CODE>. <P> 204662449Speter 204762449SpeterThe principal attribute of a form is its field list. You can query 204862449Speterand change this list with: 204962449Speter 205062449Speter<PRE> 205162449Speterint set_form_fields(FORM *form, /* form to alter */ 205262449Speter FIELD **fields); /* fields to connect */ 205362449Speter 205462449Speterchar *form_fields(FORM *form); /* fetch fields of form */ 205562449Speter 205662449Speterint field_count(FORM *form); /* count connect fields */ 205762449Speter</PRE> 205862449Speter 205962449SpeterThe second argument of <CODE>set_form_fields()</CODE> may be a 206062449SpeterNULL-terminated field pointer array like the one required by 206162449Speter<CODE>new_form()</CODE>. In that case, the old fields of the form are 206262449Speterdisconnected but not freed (and eligible to be connected to other 206362449Speterforms), then the new fields are connected. <P> 206462449Speter 206562449SpeterIt may also be null, in which case the old fields are disconnected 206662449Speter(and not freed) but no new ones are connected. <P> 206762449Speter 206862449SpeterThe <CODE>field_count()</CODE> function simply counts the number of fields 206962449Speterconnected to a given from. It returns -1 if the form-pointer argument 207062449Speteris NULL. 207162449Speter 207262449Speter<H2><A NAME="fdisplay">Control of Form Display</A></H2> 207362449Speter 207462449SpeterIn the overview section, you saw that to display a form you normally 207562449Speterstart by defining its size (and fields), posting it, and refreshing 207662449Speterthe screen. There is an hidden step before posting, which is the 207762449Speterassociation of the form with a frame window (actually, a pair of 207862449Speterwindows) within which it will be displayed. By default, the forms 207962449Speterlibrary associates every form with the full-screen window 208062449Speter<CODE>stdscr</CODE>. <P> 208162449Speter 208262449SpeterBy making this step explicit, you can associate a form with a declared 208362449Speterframe window on your screen display. This can be useful if you want to 208462449Speteradapt the form display to different screen sizes, dynamically tile 208562449Speterforms on the screen, or use a form as part of an interface layout 208662449Spetermanaged by <A HREF="#panels">panels</A>. <P> 208762449Speter 208862449SpeterThe two windows associated with each form have the same functions as 208962449Spetertheir analogues in the <A HREF="#menu">menu library</A>. Both these 209062449Speterwindows are painted when the form is posted and erased when the form 209162449Speteris unposted. <P> 209262449Speter 209362449SpeterThe outer or frame window is not otherwise touched by the form 209462449Speterroutines. It exists so the programmer can associate a title, a 209562449Speterborder, or perhaps help text with the form and have it properly 209662449Speterrefreshed or erased at post/unpost time. The inner window or subwindow 209762449Speteris where the current form page is actually displayed. <P> 209862449Speter 209962449SpeterIn order to declare your own frame window for a form, you'll need to 210062449Speterknow the size of the form's bounding rectangle. You can get this 210162449Speterinformation with: 210262449Speter 210362449Speter<PRE> 210462449Speterint scale_form(FORM *form, /* form to query */ 210562449Speter int *rows, /* form rows */ 210662449Speter int *cols); /* form cols */ 210762449Speter</PRE> 210862449Speter 210962449SpeterThe form dimensions are passed back in the locations pointed to by 211062449Speterthe arguments. Once you have this information, you can use it to 211162449Speterdeclare of windows, then use one of these functions: 211262449Speter 211362449Speter<PRE> 211462449Speterint set_form_win(FORM *form, /* form to alter */ 211562449Speter WINDOW *win); /* frame window to connect */ 211662449Speter 211762449SpeterWINDOW *form_win(FORM *form); /* fetch frame window of form */ 211862449Speter 211962449Speterint set_form_sub(FORM *form, /* form to alter */ 212062449Speter WINDOW *win); /* form subwindow to connect */ 212162449Speter 212262449SpeterWINDOW *form_sub(FORM *form); /* fetch form subwindow of form */ 212362449Speter</PRE> 212462449Speter 212562449SpeterNote that curses operations, including <CODE>refresh()</CODE>, on the form, 212662449Spetershould be done on the frame window, not the form subwindow. <P> 212762449Speter 212862449SpeterIt is possible to check from your application whether all of a 212962449Speterscrollable field is actually displayed within the menu subwindow. Use 213062449Speterthese functions: 213162449Speter 213262449Speter<PRE> 213362449Speterint data_ahead(FORM *form); /* form to be queried */ 213462449Speter 213562449Speterint data_behind(FORM *form); /* form to be queried */ 213662449Speter</PRE> 213762449Speter 213862449SpeterThe function <CODE>data_ahead()</CODE> returns TRUE if (a) the current 213962449Speterfield is one-line and has undisplayed data off to the right, (b) the current 214062449Speterfield is multi-line and there is data off-screen below it. <P> 214162449Speter 214262449SpeterThe function <CODE>data_behind()</CODE> returns TRUE if the first (upper 214362449Speterleft hand) character position is off-screen (not being displayed). <P> 214462449Speter 214562449SpeterFinally, there is a function to restore the form window's cursor to the 214662449Spetervalue expected by the forms driver: 214762449Speter 214862449Speter<PRE> 214962449Speterint pos_form_cursor(FORM *) /* form to be queried */ 215062449Speter</PRE> 215162449Speter 215262449SpeterIf your application changes the form window cursor, call this function before 215362449Speterhanding control back to the forms driver in order to re-synchronize it. 215462449Speter 215562449Speter<H2><A NAME="fdriver">Input Processing in the Forms Driver</A></H2> 215662449Speter 215762449SpeterThe function <CODE>form_driver()</CODE> handles virtualized input requests 215862449Speterfor form navigation, editing, and validation requests, just as 215962449Speter<CODE>menu_driver</CODE> does for menus (see the section on <A 216062449SpeterHREF="#minput">menu input handling</A>). 216162449Speter 216262449Speter<PRE> 216362449Speterint form_driver(FORM *form, /* form to pass input to */ 216462449Speter int request); /* form request code */ 216562449Speter</PRE> 216662449Speter 216762449SpeterYour input virtualization function needs to take input and then convert it 216862449Speterto either an alphanumeric character (which is treated as data to be 216962449Speterentered in the currently-selected field), or a forms processing request. <P> 217062449Speter 217162449SpeterThe forms driver provides hooks (through input-validation and 217262449Speterfield-termination functions) with which your application code can check 217362449Speterthat the input taken by the driver matched what was expected. 217462449Speter 217562449Speter<H3><A NAME="fpage">Page Navigation Requests</A></H3> 217662449Speter 217762449SpeterThese requests cause page-level moves through the form, 217862449Spetertriggering display of a new form screen. 217962449Speter 218062449Speter<DL> 218162449Speter<DT> <CODE>REQ_NEXT_PAGE</CODE> 218262449Speter<DD> Move to the next form page. 218362449Speter<DT> <CODE>REQ_PREV_PAGE</CODE> 218462449Speter<DD> Move to the previous form page. 218562449Speter<DT> <CODE>REQ_FIRST_PAGE</CODE> 218662449Speter<DD> Move to the first form page. 218762449Speter<DT> <CODE>REQ_LAST_PAGE</CODE> 218862449Speter<DD> Move to the last form page. 218962449Speter</DL> 219062449Speter 219162449SpeterThese requests treat the list as cyclic; that is, <CODE>REQ_NEXT_PAGE</CODE> 219262449Speterfrom the last page goes to the first, and <CODE>REQ_PREV_PAGE</CODE> from 219362449Speterthe first page goes to the last. 219462449Speter 2195174993Srafan<H3><A NAME="ffield">Inter-Field Navigation Requests</A></H3> 219662449Speter 219762449SpeterThese requests handle navigation between fields on the same page. 219862449Speter 219962449Speter<DL> 220062449Speter<DT> <CODE>REQ_NEXT_FIELD</CODE> 220162449Speter<DD> Move to next field. 220262449Speter<DT> <CODE>REQ_PREV_FIELD</CODE> 220362449Speter<DD> Move to previous field. 220462449Speter<DT> <CODE>REQ_FIRST_FIELD</CODE> 220562449Speter<DD> Move to the first field. 220662449Speter<DT> <CODE>REQ_LAST_FIELD</CODE> 220762449Speter<DD> Move to the last field. 220862449Speter<DT> <CODE>REQ_SNEXT_FIELD</CODE> 220962449Speter<DD> Move to sorted next field. 221062449Speter<DT> <CODE>REQ_SPREV_FIELD</CODE> 221162449Speter<DD> Move to sorted previous field. 221262449Speter<DT> <CODE>REQ_SFIRST_FIELD</CODE> 221362449Speter<DD> Move to the sorted first field. 221462449Speter<DT> <CODE>REQ_SLAST_FIELD</CODE> 221562449Speter<DD> Move to the sorted last field. 221662449Speter<DT> <CODE>REQ_LEFT_FIELD</CODE> 221762449Speter<DD> Move left to field. 221862449Speter<DT> <CODE>REQ_RIGHT_FIELD</CODE> 221962449Speter<DD> Move right to field. 222062449Speter<DT> <CODE>REQ_UP_FIELD</CODE> 222162449Speter<DD> Move up to field. 222262449Speter<DT> <CODE>REQ_DOWN_FIELD</CODE> 222362449Speter<DD> Move down to field. 222462449Speter</DL> 222562449Speter 222662449SpeterThese requests treat the list of fields on a page as cyclic; that is, 222762449Speter<CODE>REQ_NEXT_FIELD</CODE> from the last field goes to the first, and 222862449Speter<CODE>REQ_PREV_FIELD</CODE> from the first field goes to the last. The 222962449Speterorder of the fields for these (and the <CODE>REQ_FIRST_FIELD</CODE> and 223062449Speter<CODE>REQ_LAST_FIELD</CODE> requests) is simply the order of the field 223162449Speterpointers in the form array (as set up by <CODE>new_form()</CODE> or 223262449Speter<CODE>set_form_fields()</CODE> <P> 223362449Speter 223462449SpeterIt is also possible to traverse the fields as if they had been sorted in 223562449Speterscreen-position order, so the sequence goes left-to-right and top-to-bottom. 223662449SpeterTo do this, use the second group of four sorted-movement requests. <P> 223762449Speter 223862449SpeterFinally, it is possible to move between fields using visual directions up, 223962449Speterdown, right, and left. To accomplish this, use the third group of four 224062449Speterrequests. Note, however, that the position of a form for purposes of these 224162449Speterrequests is its upper-left corner. <P> 224262449Speter 224362449SpeterFor example, suppose you have a multi-line field B, and two 224462449Spetersingle-line fields A and C on the same line with B, with A to the left 224562449Speterof B and C to the right of B. A <CODE>REQ_MOVE_RIGHT</CODE> from A will 224662449Spetergo to B only if A, B, and C <EM>all</EM> share the same first line; 224762449Speterotherwise it will skip over B to C. 224862449Speter 2249174993Srafan<H3><A NAME="fifield">Intra-Field Navigation Requests</A></H3> 225062449Speter 225162449SpeterThese requests drive movement of the edit cursor within the currently 225262449Speterselected field. 225362449Speter 225462449Speter<DL> 225562449Speter<DT> <CODE>REQ_NEXT_CHAR</CODE> 225662449Speter<DD> Move to next character. 225762449Speter<DT> <CODE>REQ_PREV_CHAR</CODE> 225862449Speter<DD> Move to previous character. 225962449Speter<DT> <CODE>REQ_NEXT_LINE</CODE> 226062449Speter<DD> Move to next line. 226162449Speter<DT> <CODE>REQ_PREV_LINE</CODE> 226262449Speter<DD> Move to previous line. 226362449Speter<DT> <CODE>REQ_NEXT_WORD</CODE> 226462449Speter<DD> Move to next word. 226562449Speter<DT> <CODE>REQ_PREV_WORD</CODE> 226662449Speter<DD> Move to previous word. 226762449Speter<DT> <CODE>REQ_BEG_FIELD</CODE> 226862449Speter<DD> Move to beginning of field. 226962449Speter<DT> <CODE>REQ_END_FIELD</CODE> 227062449Speter<DD> Move to end of field. 227162449Speter<DT> <CODE>REQ_BEG_LINE</CODE> 227262449Speter<DD> Move to beginning of line. 227362449Speter<DT> <CODE>REQ_END_LINE</CODE> 227462449Speter<DD> Move to end of line. 227562449Speter<DT> <CODE>REQ_LEFT_CHAR</CODE> 227662449Speter<DD> Move left in field. 227762449Speter<DT> <CODE>REQ_RIGHT_CHAR</CODE> 227862449Speter<DD> Move right in field. 227962449Speter<DT> <CODE>REQ_UP_CHAR</CODE> 228062449Speter<DD> Move up in field. 228162449Speter<DT> <CODE>REQ_DOWN_CHAR</CODE> 228262449Speter<DD> Move down in field. 228362449Speter</DL> 228462449Speter 228562449SpeterEach <EM>word</EM> is separated from the previous and next characters 228662449Speterby whitespace. The commands to move to beginning and end of line or field 228762449Speterlook for the first or last non-pad character in their ranges. 228862449Speter 228962449Speter<H3><A NAME="fscroll">Scrolling Requests</A></H3> 229062449Speter 229162449SpeterFields that are dynamic and have grown and fields explicitly created 229262449Speterwith offscreen rows are scrollable. One-line fields scroll horizontally; 229362449Spetermulti-line fields scroll vertically. Most scrolling is triggered by 229462449Speterediting and intra-field movement (the library scrolls the field to keep the 229562449Spetercursor visible). It is possible to explicitly request scrolling with the 229662449Speterfollowing requests: 229762449Speter 229862449Speter<DL> 229962449Speter<DT> <CODE>REQ_SCR_FLINE</CODE> 230062449Speter<DD> Scroll vertically forward a line. 230162449Speter<DT> <CODE>REQ_SCR_BLINE</CODE> 230262449Speter<DD> Scroll vertically backward a line. 230362449Speter<DT> <CODE>REQ_SCR_FPAGE</CODE> 230462449Speter<DD> Scroll vertically forward a page. 230562449Speter<DT> <CODE>REQ_SCR_BPAGE</CODE> 230662449Speter<DD> Scroll vertically backward a page. 230762449Speter<DT> <CODE>REQ_SCR_FHPAGE</CODE> 230862449Speter<DD> Scroll vertically forward half a page. 230962449Speter<DT> <CODE>REQ_SCR_BHPAGE</CODE> 231062449Speter<DD> Scroll vertically backward half a page. 231162449Speter<DT> <CODE>REQ_SCR_FCHAR</CODE> 231262449Speter<DD> Scroll horizontally forward a character. 231362449Speter<DT> <CODE>REQ_SCR_BCHAR</CODE> 231462449Speter<DD> Scroll horizontally backward a character. 231562449Speter<DT> <CODE>REQ_SCR_HFLINE</CODE> 231662449Speter<DD> Scroll horizontally one field width forward. 231762449Speter<DT> <CODE>REQ_SCR_HBLINE</CODE> 231862449Speter<DD> Scroll horizontally one field width backward. 231962449Speter<DT> <CODE>REQ_SCR_HFHALF</CODE> 232062449Speter<DD> Scroll horizontally one half field width forward. 232162449Speter<DT> <CODE>REQ_SCR_HBHALF</CODE> 232262449Speter<DD> Scroll horizontally one half field width backward. 232362449Speter</DL> 232462449Speter 232562449SpeterFor scrolling purposes, a <EM>page</EM> of a field is the height 232662449Speterof its visible part. 232762449Speter 232862449Speter<H3><A NAME="fedit">Editing Requests</A></H3> 232962449Speter 233062449SpeterWhen you pass the forms driver an ASCII character, it is treated as a 233162449Speterrequest to add the character to the field's data buffer. Whether this 233262449Speteris an insertion or a replacement depends on the field's edit mode 233362449Speter(insertion is the default. <P> 233462449Speter 233562449SpeterThe following requests support editing the field and changing the edit 233662449Spetermode: 233762449Speter 233862449Speter<DL> 233962449Speter<DT> <CODE>REQ_INS_MODE</CODE> 234062449Speter<DD> Set insertion mode. 234162449Speter<DT> <CODE>REQ_OVL_MODE</CODE> 234262449Speter<DD> Set overlay mode. 234362449Speter<DT> <CODE>REQ_NEW_LINE</CODE> 234462449Speter<DD> New line request (see below for explanation). 234562449Speter<DT> <CODE>REQ_INS_CHAR</CODE> 234662449Speter<DD> Insert space at character location. 234762449Speter<DT> <CODE>REQ_INS_LINE</CODE> 234862449Speter<DD> Insert blank line at character location. 234962449Speter<DT> <CODE>REQ_DEL_CHAR</CODE> 235062449Speter<DD> Delete character at cursor. 235162449Speter<DT> <CODE>REQ_DEL_PREV</CODE> 235262449Speter<DD> Delete previous word at cursor. 235362449Speter<DT> <CODE>REQ_DEL_LINE</CODE> 235462449Speter<DD> Delete line at cursor. 235562449Speter<DT> <CODE>REQ_DEL_WORD</CODE> 235662449Speter<DD> Delete word at cursor. 235762449Speter<DT> <CODE>REQ_CLR_EOL</CODE> 235862449Speter<DD> Clear to end of line. 235962449Speter<DT> <CODE>REQ_CLR_EOF</CODE> 236062449Speter<DD> Clear to end of field. 236162449Speter<DT> <CODE>REQ_CLEAR_FIELD</CODE> 236262449Speter<DD> Clear entire field. 236362449Speter</DL> 236462449Speter 236562449SpeterThe behavior of the <CODE>REQ_NEW_LINE</CODE> and <CODE>REQ_DEL_PREV</CODE> requests 236662449Speteris complicated and partly controlled by a pair of forms options. 236762449SpeterThe special cases are triggered when the cursor is at the beginning of 236862449Spetera field, or on the last line of the field. <P> 236962449Speter 237062449SpeterFirst, we consider <CODE>REQ_NEW_LINE</CODE>: <P> 237162449Speter 237262449SpeterThe normal behavior of <CODE>REQ_NEW_LINE</CODE> in insert mode is to break the 237362449Spetercurrent line at the position of the edit cursor, inserting the portion of 237462449Speterthe current line after the cursor as a new line following the current 237562449Speterand moving the cursor to the beginning of that new line (you may think 237662449Speterof this as inserting a newline in the field buffer). <P> 237762449Speter 237862449SpeterThe normal behavior of <CODE>REQ_NEW_LINE</CODE> in overlay mode is to clear the 237962449Spetercurrent line from the position of the edit cursor to end of line. 238062449SpeterThe cursor is then moved to the beginning of the next line. <P> 238162449Speter 238262449SpeterHowever, <CODE>REQ_NEW_LINE</CODE> at the beginning of a field, or on the 238362449Speterlast line of a field, instead does a <CODE>REQ_NEXT_FIELD</CODE>. 238462449Speter<CODE>O_NL_OVERLOAD</CODE> option is off, this special action is 238562449Speterdisabled. <P> 238662449Speter 238762449SpeterNow, let us consider <CODE>REQ_DEL_PREV</CODE>: <P> 238862449Speter 238962449SpeterThe normal behavior of <CODE>REQ_DEL_PREV</CODE> is to delete the previous 239062449Spetercharacter. If insert mode is on, and the cursor is at the start of a 239162449Speterline, and the text on that line will fit on the previous one, it 239262449Speterinstead appends the contents of the current line to the previous one 239362449Speterand deletes the current line (you may think of this as deleting a 239462449Speternewline from the field buffer). <P> 239562449Speter 239662449SpeterHowever, <CODE>REQ_DEL_PREV</CODE> at the beginning of a field is instead 239762449Spetertreated as a <CODE>REQ_PREV_FIELD</CODE>. <P> If the 239862449Speter<CODE>O_BS_OVERLOAD</CODE> option is off, this special action is 239962449Speterdisabled and the forms driver just returns <CODE>E_REQUEST_DENIED</CODE>. <P> 240062449Speter 240162449SpeterSee <A HREF="#frmoptions">Form Options</A> for discussion of how to set 240262449Speterand clear the overload options. 240362449Speter 240462449Speter<H3><A NAME="forder">Order Requests</A></H3> 240562449Speter 240662449SpeterIf the type of your field is ordered, and has associated functions 240762449Speterfor getting the next and previous values of the type from a given value, 240862449Speterthere are requests that can fetch that value into the field buffer: 240962449Speter 241062449Speter<DL> 241162449Speter<DT> <CODE>REQ_NEXT_CHOICE</CODE> 241262449Speter<DD> Place the successor value of the current value in the buffer. 241362449Speter<DT> <CODE>REQ_PREV_CHOICE</CODE> 241462449Speter<DD> Place the predecessor value of the current value in the buffer. 241562449Speter</DL> 241662449Speter 241762449SpeterOf the built-in field types, only <CODE>TYPE_ENUM</CODE> has built-in successor 241862449Speterand predecessor functions. When you define a field type of your own 241962449Speter(see <A HREF="#fcustom">Custom Validation Types</A>), you can associate 242062449Speterour own ordering functions. 242162449Speter 242262449Speter<H3><A NAME="fappcmds">Application Commands</A></H3> 242362449Speter 242462449SpeterForm requests are represented as integers above the <CODE>curses</CODE> value 242562449Spetergreater than <CODE>KEY_MAX</CODE> and less than or equal to the constant 242662449Speter<CODE>MAX_COMMAND</CODE>. If your input-virtualization routine returns a 242762449Spetervalue above <CODE>MAX_COMMAND</CODE>, the forms driver will ignore it. 242862449Speter 242962449Speter<H2><A NAME="fhooks">Field Change Hooks</A></H2> 243062449Speter 243162449SpeterIt is possible to set function hooks to be executed whenever the 243262449Spetercurrent field or form changes. Here are the functions that support this: 243362449Speter 243462449Speter<PRE> 243562449Spetertypedef void (*HOOK)(); /* pointer to function returning void */ 243662449Speter 243762449Speterint set_form_init(FORM *form, /* form to alter */ 243862449Speter HOOK hook); /* initialization hook */ 243962449Speter 244062449SpeterHOOK form_init(FORM *form); /* form to query */ 244162449Speter 244262449Speterint set_form_term(FORM *form, /* form to alter */ 244362449Speter HOOK hook); /* termination hook */ 244462449Speter 244562449SpeterHOOK form_term(FORM *form); /* form to query */ 244662449Speter 244762449Speterint set_field_init(FORM *form, /* form to alter */ 244862449Speter HOOK hook); /* initialization hook */ 244962449Speter 245062449SpeterHOOK field_init(FORM *form); /* form to query */ 245162449Speter 245262449Speterint set_field_term(FORM *form, /* form to alter */ 245362449Speter HOOK hook); /* termination hook */ 245462449Speter 245562449SpeterHOOK field_term(FORM *form); /* form to query */ 245662449Speter</PRE> 245762449Speter 245862449SpeterThese functions allow you to either set or query four different hooks. 245962449SpeterIn each of the set functions, the second argument should be the 246062449Speteraddress of a hook function. These functions differ only in the timing 246162449Speterof the hook call. 246262449Speter 246362449Speter<DL> 246462449Speter<DT> form_init 246562449Speter<DD> This hook is called when the form is posted; also, just after 246662449Spetereach page change operation. 246762449Speter<DT> field_init 246862449Speter<DD> This hook is called when the form is posted; also, just after 246962449Spetereach field change 247062449Speter<DT> field_term 247162449Speter<DD> This hook is called just after field validation; that is, just before 247262449Speterthe field is altered. It is also called when the form is unposted. 247362449Speter<DT> form_term 247462449Speter<DD> This hook is called when the form is unposted; also, just before 247562449Spetereach page change operation. 247662449Speter</DL> 247762449Speter 247862449SpeterCalls to these hooks may be triggered 247962449Speter<OL> 248062449Speter<LI>When user editing requests are processed by the forms driver 248162449Speter<LI>When the current page is changed by <CODE>set_current_field()</CODE> call 248262449Speter<LI>When the current field is changed by a <CODE>set_form_page()</CODE> call 248362449Speter</OL> 248462449Speter 248562449SpeterSee <A NAME="ffocus">Field Change Commands</A> for discussion of the latter 248662449Spetertwo cases. <P> 248762449Speter 248862449SpeterYou can set a default hook for all fields by passing one of the set functions 248962449Spetera NULL first argument. <P> 249062449Speter 249162449SpeterYou can disable any of these hooks by (re)setting them to NULL, the default 249262449Spetervalue. 249362449Speter 249462449Speter<H2><A HREF="#ffocus">Field Change Commands</A></H2> 249562449Speter 249662449SpeterNormally, navigation through the form will be driven by the user's 249762449Speterinput requests. But sometimes it is useful to be able to move the 249862449Speterfocus for editing and viewing under control of your application, or 249962449Speterask which field it currently is in. The following functions help you 250062449Speteraccomplish this: 250162449Speter 250262449Speter<PRE> 250362449Speterint set_current_field(FORM *form, /* form to alter */ 250462449Speter FIELD *field); /* field to shift to */ 250562449Speter 250662449SpeterFIELD *current_field(FORM *form); /* form to query */ 250762449Speter 250862449Speterint field_index(FORM *form, /* form to query */ 250962449Speter FIELD *field); /* field to get index of */ 251062449Speter</PRE> 251162449Speter 251262449SpeterThe function <CODE>field_index()</CODE> returns the index of the given field 251362449Speterin the given form's field array (the array passed to <CODE>new_form()</CODE> or 251462449Speter<CODE>set_form_fields()</CODE>). <P> 251562449Speter 251662449SpeterThe initial current field of a form is the first active field on the 251762449Speterfirst page. The function <CODE>set_form_fields()</CODE> resets this.<P> 251862449Speter 251962449SpeterIt is also possible to move around by pages. 252062449Speter 252162449Speter<PRE> 252262449Speterint set_form_page(FORM *form, /* form to alter */ 252362449Speter int page); /* page to go to (0-origin) */ 252462449Speter 252562449Speterint form_page(FORM *form); /* return form's current page */ 252662449Speter</PRE> 252762449Speter 252862449SpeterThe initial page of a newly-created form is 0. The function 252962449Speter<CODE>set_form_fields()</CODE> resets this. 253062449Speter 253162449Speter<H2><A NAME="frmoptions">Form Options</A></H2> 253262449Speter 253362449SpeterLike fields, forms may have control option bits. They can be changed 253462449Speteror queried with these functions: 253562449Speter 253662449Speter<PRE> 253762449Speterint set_form_opts(FORM *form, /* form to alter */ 253862449Speter int attr); /* attribute to set */ 253962449Speter 254062449Speterint form_opts_on(FORM *form, /* form to alter */ 254162449Speter int attr); /* attributes to turn on */ 254262449Speter 254362449Speterint form_opts_off(FORM *form, /* form to alter */ 254462449Speter int attr); /* attributes to turn off */ 254562449Speter 254662449Speterint form_opts(FORM *form); /* form to query */ 254762449Speter</PRE> 254862449Speter 254962449SpeterBy default, all options are on. Here are the available option bits: 255062449Speter 255162449Speter<DL> 255262449Speter<DT> O_NL_OVERLOAD 255362449Speter<DD> Enable overloading of <CODE>REQ_NEW_LINE</CODE> as described in <A 2554166124Srafanhref="#fedit">Editing Requests</A>. The value of this option is 255562449Speterignored on dynamic fields that have not reached their size limit; 255662449Speterthese have no last line, so the circumstances for triggering a 255762449Speter<CODE>REQ_NEXT_FIELD</CODE> never arise. 255862449Speter<DT> O_BS_OVERLOAD 255962449Speter<DD> Enable overloading of <CODE>REQ_DEL_PREV</CODE> as described in 2560166124Srafan<A href="#fedit">Editing Requests</A>. 256162449Speter</DL> 256262449Speter 256362449SpeterThe option values are bit-masks and can be composed with logical-or in 256462449Speterthe obvious way. 256562449Speter 256662449Speter<H2><A NAME="fcustom">Custom Validation Types</A></H2> 256762449Speter 256862449SpeterThe <CODE>form</CODE> library gives you the capability to define custom 256962449Spetervalidation types of your own. Further, the optional additional arguments 257062449Speterof <CODE>set_field_type</CODE> effectively allow you to parameterize validation 257162449Spetertypes. Most of the complications in the validation-type interface have to 257262449Speterdo with the handling of the additional arguments within custom validation 257362449Speterfunctions. 257462449Speter 257562449Speter<H3><A NAME="flinktypes">Union Types</A></H3> 257662449Speter 257762449SpeterThe simplest way to create a custom data type is to compose it from two 257862449Speterpreexisting ones: 257962449Speter 258062449Speter<PRE> 258162449SpeterFIELD *link_fieldtype(FIELDTYPE *type1, 258262449Speter FIELDTYPE *type2); 258362449Speter</PRE> 258462449Speter 258562449SpeterThis function creates a field type that will accept any of the values 258662449Speterlegal for either of its argument field types (which may be either 258762449Speterpredefined or programmer-defined). 258862449Speter 258962449SpeterIf a <CODE>set_field_type()</CODE> call later requires arguments, the new 259062449Spetercomposite type expects all arguments for the first type, than all arguments 259162449Speterfor the second. Order functions (see <A HREF="#forder">Order Requests</A>) 259262449Speterassociated with the component types will work on the composite; what it does 259362449Speteris check the validation function for the first type, then for the second, to 259462449Speterfigure what type the buffer contents should be treated as. 259562449Speter 259662449Speter<H3><A NAME="fnewtypes">New Field Types</A></H3> 259762449Speter 259862449SpeterTo create a field type from scratch, you need to specify one or both of the 259962449Speterfollowing things: 260062449Speter 260162449Speter<UL> 260262449Speter<LI>A character-validation function, to check each character as it is entered. 260362449Speter<LI>A field-validation function to be applied on exit from the field. 260462449Speter</UL> 260562449Speter 260662449SpeterHere's how you do that: 260762449Speter<PRE> 260862449Spetertypedef int (*HOOK)(); /* pointer to function returning int */ 260962449Speter 261062449SpeterFIELDTYPE *new_fieldtype(HOOK f_validate, /* field validator */ 261162449Speter HOOK c_validate) /* character validator */ 261262449Speter 261362449Speter 261462449Speterint free_fieldtype(FIELDTYPE *ftype); /* type to free */ 261562449Speter</PRE> 261662449Speter 261762449SpeterAt least one of the arguments of <CODE>new_fieldtype()</CODE> must be 261862449Speternon-NULL. The forms driver will automatically call the new type's 261962449Spetervalidation functions at appropriate points in processing a field of 262062449Speterthe new type. <P> 262162449Speter 262262449SpeterThe function <CODE>free_fieldtype()</CODE> deallocates the argument 262362449Speterfieldtype, freeing all storage associated with it. <P> 262462449Speter 262562449SpeterNormally, a field validator is called when the user attempts to 262662449Speterleave the field. Its first argument is a field pointer, from which it 262762449Spetercan get to field buffer 0 and test it. If the function returns TRUE, 262862449Speterthe operation succeeds; if it returns FALSE, the edit cursor stays in 262962449Speterthe field. <P> 263062449Speter 263162449SpeterA character validator gets the character passed in as a first argument. 263262449SpeterIt too should return TRUE if the character is valid, FALSE otherwise. 263362449Speter 263462449Speter<H3><A NAME="fcheckargs">Validation Function Arguments</A></H3> 263562449Speter 263662449SpeterYour field- and character- validation functions will be passed a 263762449Spetersecond argument as well. This second argument is the address of a 263862449Speterstructure (which we'll call a <EM>pile</EM>) built from any of the 263962449Speterfield-type-specific arguments passed to <CODE>set_field_type()</CODE>. If 264062449Speterno such arguments are defined for the field type, this pile pointer 264162449Speterargument will be NULL. <P> 264262449Speter 264362449SpeterIn order to arrange for such arguments to be passed to your validation 264462449Speterfunctions, you must associate a small set of storage-management functions 264562449Speterwith the type. The forms driver will use these to synthesize a pile 264662449Speterfrom the trailing arguments of each <CODE>set_field_type()</CODE> argument, and 264762449Spetera pointer to the pile will be passed to the validation functions. <P> 264862449Speter 264962449SpeterHere is how you make the association: 265062449Speter 265162449Speter<PRE> 265262449Spetertypedef char *(*PTRHOOK)(); /* pointer to function returning (char *) */ 265362449Spetertypedef void (*VOIDHOOK)(); /* pointer to function returning void */ 265462449Speter 265562449Speterint set_fieldtype_arg(FIELDTYPE *type, /* type to alter */ 265662449Speter PTRHOOK make_str, /* make structure from args */ 265762449Speter PTRHOOK copy_str, /* make copy of structure */ 265862449Speter VOIDHOOK free_str); /* free structure storage */ 265962449Speter</PRE> 266062449Speter 266162449SpeterHere is how the storage-management hooks are used: 266262449Speter 266362449Speter<DL> 266462449Speter<DT> <CODE>make_str</CODE> 266562449Speter<DD> This function is called by <CODE>set_field_type()</CODE>. It gets one 266662449Speterargument, a <CODE>va_list</CODE> of the type-specific arguments passed to 266762449Speter<CODE>set_field_type()</CODE>. It is expected to return a pile pointer to a data 266862449Speterstructure that encapsulates those arguments. 266962449Speter<DT> <CODE>copy_str</CODE> 267062449Speter<DD> This function is called by form library functions that allocate new 267162449Speterfield instances. It is expected to take a pile pointer, copy the pile 267262449Speterto allocated storage, and return the address of the pile copy. 267362449Speter<DT> <CODE>free_str</CODE> 267462449Speter<DD> This function is called by field- and type-deallocation routines in the 267562449Speterlibrary. It takes a pile pointer argument, and is expected to free the 267662449Speterstorage of that pile. 267762449Speter</DL> 267862449Speter 267962449SpeterThe <CODE>make_str</CODE> and <CODE>copy_str</CODE> functions may return NULL to 268062449Spetersignal allocation failure. The library routines will that call them will 268162449Speterreturn error indication when this happens. Thus, your validation functions 268262449Spetershould never see a NULL file pointer and need not check specially for it. 268362449Speter 268462449Speter<H3><A NAME="fcustorder">Order Functions For Custom Types</A></H3> 268562449Speter 268662449SpeterSome custom field types are simply ordered in the same well-defined way 268762449Speterthat <CODE>TYPE_ENUM</CODE> is. For such types, it is possible to define 268862449Spetersuccessor and predecessor functions to support the <CODE>REQ_NEXT_CHOICE</CODE> 268962449Speterand <CODE>REQ_PREV_CHOICE</CODE> requests. Here's how: 269062449Speter 269162449Speter<PRE> 269262449Spetertypedef int (*INTHOOK)(); /* pointer to function returning int */ 269362449Speter 269462449Speterint set_fieldtype_arg(FIELDTYPE *type, /* type to alter */ 269562449Speter INTHOOK succ, /* get successor value */ 269662449Speter INTHOOK pred); /* get predecessor value */ 269762449Speter</PRE> 269862449Speter 269962449SpeterThe successor and predecessor arguments will each be passed two arguments; 270062449Spetera field pointer, and a pile pointer (as for the validation functions). They 270162449Speterare expected to use the function <CODE>field_buffer()</CODE> to read the 270262449Spetercurrent value, and <CODE>set_field_buffer()</CODE> on buffer 0 to set the next 270362449Speteror previous value. Either hook may return TRUE to indicate success (a 270462449Speterlegal next or previous value was set) or FALSE to indicate failure. 270562449Speter 270662449Speter<H3><A NAME="fcustprobs">Avoiding Problems</A></H3> 270762449Speter 270862449SpeterThe interface for defining custom types is complicated and tricky. 270962449SpeterRather than attempting to create a custom type entirely from scratch, 271062449Speteryou should start by studying the library source code for whichever of 271162449Speterthe pre-defined types seems to be closest to what you want. <P> 271262449Speter 271362449SpeterUse that code as a model, and evolve it towards what you really want. 271462449SpeterYou will avoid many problems and annoyances that way. The code 271562449Speterin the <CODE>ncurses</CODE> library has been specifically exempted from 271662449Speterthe package copyright to support this. <P> 271762449Speter 271862449SpeterIf your custom type defines order functions, have do something intuitive 271962449Speterwith a blank field. A useful convention is to make the successor of a 272062449Speterblank field the types minimum value, and its predecessor the maximum. 272162449Speter</BODY> 272262449Speter</HTML> 2723