Blame tutorial.sgml

Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<article>
Packit Service 8876fe
Packit Service 8876fe
<artheader>
Packit Service 8876fe
<title>Writing Programs Using <literal remap="tt">newt</literal></title>
Packit Service 8876fe
<author> 
Packit Service 8876fe
<firstname>Erik Troan, <ewt@redhat.com></firstname>
Packit Service 8876fe
</author>
Packit Service 8876fe
Packit Service 8876fe
<pubdate>v0.31, 2003-Jan-06</pubdate>
Packit Service 8876fe
Packit Service 8876fe
<abstract>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The <literal remap="tt">newt</literal> windowing system is a terminal-based window and widget
Packit Service 8876fe
library designed for writing applications with a simple, but user-friendly,
Packit Service 8876fe
interface. While <literal remap="tt">newt</literal> is not intended to provide the rich feature
Packit Service 8876fe
set advanced applications may require, it has proven to be flexible enough
Packit Service 8876fe
for a wide range of applications (most notably, Red Hat's installation
Packit Service 8876fe
process). This tutorial explains the design philosophy behind <literal remap="tt">newt</literal> and
Packit Service 8876fe
how to use <literal remap="tt">newt</literal> from your programs.
Packit Service 8876fe
</para>
Packit Service 8876fe
Packit Service 8876fe
</abstract>
Packit Service 8876fe
</artheader>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect1><title>Introduction</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">Newt</literal> has a definite design philosophy behind it, and knowing that design
Packit Service 8876fe
makes it significantly easier to craft robust <literal remap="tt">newt</literal> applications. This
Packit Service 8876fe
tutorial documents <literal remap="tt">newt</literal> 0.30 --- older versions of <literal remap="tt">newt</literal> had
Packit Service 8876fe
annoying inconsistencies in it (which writing this tutorial pointed out),
Packit Service 8876fe
which were removed while this tutorial was written. The latest version of
Packit Service 8876fe
<literal remap="tt">newt</literal> is always available from Red Hat.</para>
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Background</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">Newt</literal> was originally designed for use in the install code for
Packit Service 8876fe
Red Hat Linux. As this install code runs in an environment with limited
Packit Service 8876fe
resources (most importantly limited filesystem space), <literal remap="tt">newt</literal>'s size
Packit Service 8876fe
was immediately an issue. To help minimize its size, the following design
Packit Service 8876fe
decisions were made early in its implementation:
Packit Service 8876fe
</para>
Packit Service 8876fe
Packit Service 8876fe
<itemizedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 <literal remap="tt">newt</literal> does not use an event-driven architecture.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>
Packit Service 8876fe
 <literal remap="tt">newt</literal> is written in C, not C++. While there has been interest
Packit Service 8876fe
in constructing C++ wrapper classes around the <literal remap="tt">newt</literal> API, nothing has
Packit Service 8876fe
yet come of those ideas.</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 Windows must be created and destroyed as a stack (in other words, all
Packit Service 8876fe
<literal remap="tt">newt</literal> windows behave as modal dialogs). This is probably
Packit Service 8876fe
the greatest functionality restriction of <literal remap="tt">newt</literal>.</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>
Packit Service 8876fe
 The tty keyboard is the only supported input device.</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 Many behaviours, such as widget traversal order, are difficult
Packit Service 8876fe
or impossible to change.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
</itemizedlist>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
While <literal remap="tt">newt</literal> provides a complete API, it does not handle the low-level
Packit Service 8876fe
screen drawing itself. Instead, <literal remap="tt">newt</literal> is layered on top of the screen
Packit Service 8876fe
management capabilities of John E. Davis's 
Packit Service 8876fe
<ulink url="ftp://space.mit.edu/pub/davis/slang/">S-Lang</ulink> library.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Designing <literal remap="tt">newt</literal> applications</title>
Packit Service 8876fe
<para>
Packit Service 8876fe
As <literal remap="tt">newt</literal> is not event driven and forces modal windows (forcing window
Packit Service 8876fe
order to behave like a stack), newt applications tend to look quite like
Packit Service 8876fe
other text-mode programs. It is quite straightforward to convert a command
Packit Service 8876fe
line program which uses simple user prompts into a <literal remap="tt">newt</literal> application.
Packit Service 8876fe
Some of the programs run as part of the Red Hat installation process
Packit Service 8876fe
(such as <literal remap="tt">Xconfigurator</literal> and <literal remap="tt">mouseconfig</literal>) were originally written
Packit Service 8876fe
as simple terminal mode programs which used line-oriented menus to get
Packit Service 8876fe
input from the user and were later converted into <literal remap="tt">newt</literal> applications
Packit Service 8876fe
(through a process affectionately known as newtering). Such a conversion
Packit Service 8876fe
does not require changes to the control flow of most applications.
Packit Service 8876fe
Packit Service 8876fe
Programming <literal remap="tt">newt</literal> is dramatically different from writing programs for
Packit Service 8876fe
most other windowing systems as <literal remap="tt">newt</literal>'s API is not event driven. This
Packit Service 8876fe
means that <literal remap="tt">newt</literal> applications look dramatically different from programs
Packit Service 8876fe
written for event-driven architectures such as Motif, <literal remap="tt">gtk</literal>, or even
Packit Service 8876fe
Borland's old TurboVision libraries.
Packit Service 8876fe
Packit Service 8876fe
When you're designing your <literal remap="tt">newt</literal> program, keep this differentiation
Packit Service 8876fe
in mind. As long as you plan your application to call a function to
Packit Service 8876fe
get input and then continue (rather then having your program called
Packit Service 8876fe
when input is ready), programming with the newt libraries should be
Packit Service 8876fe
simple.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Components</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Displayable items in <literal remap="tt">newt</literal> are known as <emphasis remap="bf">components</emphasis>, which are
Packit Service 8876fe
analogous to the widgets provided by most Unix widget sets. There are
Packit Service 8876fe
two main types of components in <literal remap="tt">newt</literal>, forms and everything else.
Packit Service 8876fe
Forms logically group components into functional sets. When an application
Packit Service 8876fe
is ready to get input from a user, it ``runs a form'', which makes the
Packit Service 8876fe
form active and lets the user enter information into the components the
Packit Service 8876fe
form contains. A form may contain any other component, including other
Packit Service 8876fe
forms. Using subforms in this manner lets the application change the details
Packit Service 8876fe
of how the user tabs between components on the form, scroll regions of the
Packit Service 8876fe
screen, and control background colors for portions of windows.
Packit Service 8876fe
Packit Service 8876fe
Every component is of type <literal remap="tt">newtComponent</literal>, which is an opaque type. It's
Packit Service 8876fe
guaranteed to be a pointer though, which lets applications move it through
Packit Service 8876fe
void pointers if the need arises. Variables of type <literal remap="tt">newtComponent</literal> should
Packit Service 8876fe
never be directly manipulated -- they should only be passed to <literal remap="tt">newt</literal>
Packit Service 8876fe
functions. As <literal remap="tt">newtComponent</literal> variables are pointers, remember that
Packit Service 8876fe
they are always passed by value -- if you pass a <literal remap="tt">newtComponent</literal> to
Packit Service 8876fe
a function which manipulates it, that component is manipulated everywhere,
Packit Service 8876fe
not just inside of that function (which is nearly always the behaviour
Packit Service 8876fe
you want).</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Conventions</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">Newt</literal> uses a number of conventions to make it easier for programmers
Packit Service 8876fe
to use. 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<itemizedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 All functions which manipulate data structures take the data
Packit Service 8876fe
structure being modified as their first parameter. For example, all
Packit Service 8876fe
of the functions which manipulate forms expect the <literal remap="tt">newtComponent</literal>
Packit Service 8876fe
for that form to be the first parameter.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 As <literal remap="tt">newt</literal> is loosely typed (forcing all of the components into
Packit Service 8876fe
a single variable makes coding easier, but nullifies the value of type
Packit Service 8876fe
checking), <literal remap="tt">newt</literal> functions include the name of the type they are
Packit Service 8876fe
manipulating. An example of this is <literal remap="tt">newtFormAddComponent()</literal>, which
Packit Service 8876fe
adds a component to a form. Note that the first parameter to this function
Packit Service 8876fe
is a form, as the name would suggest.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 When screen coordinates are passed into a function, the 
Packit Service 8876fe
x location precedes the y location. To help keep this clear,
Packit Service 8876fe
we'll use the words ``left'' and ``top'' to describe those indicators (with
Packit Service 8876fe
left corresponding to the x position).</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 When box sizes are passed, the horizontal width precedes the vertical
Packit Service 8876fe
width.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 When both a screen location and a box size are being passed, the
Packit Service 8876fe
screen location precedes the box size.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 When any component other then a form is created, the first two
Packit Service 8876fe
parameters are always the (left, right) location.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 Many functions take a set of flags as the final parameter. These
Packit Service 8876fe
flags may be logically ORed together to pass more then one flag at a time.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
 <literal remap="tt">Newt</literal> uses <emphasis remap="bf">callback</emphasis> functions to convey certain events to
Packit Service 8876fe
the application. While callbacks differ slightly in their parameters, most
Packit Service 8876fe
of them allow the application to specify an arbitrary argument to be passed
Packit Service 8876fe
to the callback when the callback is invoked. This argument is always a 
Packit Service 8876fe
<literal remap="tt">void *</literal>, which allows the application great flexibility.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
</itemizedlist>
Packit Service 8876fe
</para></sect2></sect1>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect1><title>Basic <literal remap="tt">Newt</literal> Functions</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
While most <literal remap="tt">newt</literal> functions are concerned with widgets or groups
Packit Service 8876fe
of widgets (called grids and forms), some parts of the <literal remap="tt">newt</literal> API
Packit Service 8876fe
deal with more global issues, such as initializing <literal remap="tt">newt</literal> or writing
Packit Service 8876fe
to the root window.</para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Starting and Ending <literal remap="tt">newt</literal> Services</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
There are three functions which nearly every <literal remap="tt">newt</literal> application use. The
Packit Service 8876fe
first two are used to initialize the system.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
int newtInit(void);
Packit Service 8876fe
void newtCls(void);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtInit()</literal> should be the first function called by every <literal remap="tt">newt</literal>
Packit Service 8876fe
program. It initializes internal data structures and places the terminal
Packit Service 8876fe
in raw mode. Most applications invoke <literal remap="tt">newtCls()</literal> immediately after
Packit Service 8876fe
<literal remap="tt">newtInit()</literal>, which causes the screen to be cleared. It's not
Packit Service 8876fe
necessary to call <literal remap="tt">newtCls()</literal> to use any of <literal remap="tt">newt</literal>'s features, but
Packit Service 8876fe
doing so will normally give a much neater appearance.
Packit Service 8876fe
Packit Service 8876fe
When a <literal remap="tt">newt</literal> program is ready to exit, it should call <literal remap="tt">newtFinished()</literal>.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
int newtFinished(void);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtFinished()</literal> restores the terminal to its appearance when
Packit Service 8876fe
<literal remap="tt">newtInit()</literal> was called (if possible -- on some terminals the cursor will
Packit Service 8876fe
be moved to the bottom, but it won't be possible to remember the original
Packit Service 8876fe
terminal contents) and places the terminal in its original input state.
Packit Service 8876fe
If this function isn't called, the terminal will probably need to be
Packit Service 8876fe
reset with the <literal remap="tt">reset</literal> command before it can be used easily.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Handling Keyboard Input</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Normally, <literal remap="tt">newt</literal> programs don't read input directly from the
Packit Service 8876fe
user. Instead, they let <literal remap="tt">newt</literal> read the input and hand it to the
Packit Service 8876fe
program in a semi-digested form. <literal remap="tt">Newt</literal> does provide a couple of simple
Packit Service 8876fe
functions which give programs (a bit of) control over the terminal.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtWaitForKey(void);
Packit Service 8876fe
void newtClearKeyBuffer(void);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The first of these, <literal remap="tt">newtWaitForKey()</literal>, doesn't return until a key
Packit Service 8876fe
has been pressed. The keystroke is then ignored. If a key is already in
Packit Service 8876fe
the terminal's buffer, <literal remap="tt">newtWaitForKey()</literal> discards a keystroke and
Packit Service 8876fe
returns immediately.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtClearKeyBuffer()</literal> discards the contents of the terminal's input
Packit Service 8876fe
buffer without waiting for additional input.</para></sect2> 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Drawing on the Root Window</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The background of the terminal's display (the part without any windows 
Packit Service 8876fe
covering it) is known as the <emphasis remap="bf">root window</emphasis> (it's the parent of all
Packit Service 8876fe
windows, just like the system's root directory is the parent of all 
Packit Service 8876fe
subdirectories). Normally, applications don't use the root window, instead
Packit Service 8876fe
drawing all of their text inside of windows (<literal remap="tt">newt</literal> doesn't require
Packit Service 8876fe
this though -- widgets may be placed directly on the root window without
Packit Service 8876fe
difficulty). It is often desirable to display some text, such as a
Packit Service 8876fe
program's name or copyright information, on the root window, however.
Packit Service 8876fe
<literal remap="tt">Newt</literal> provides two ways of displaying text on the root window. These
Packit Service 8876fe
functions may be called at any time. They are the only <literal remap="tt">newt</literal> functions
Packit Service 8876fe
which are meant to write outside of the current window.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtDrawRootText(int left, int top, const char * text);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
This function is straightforward. It displays the string <literal remap="tt">text</literal> at
Packit Service 8876fe
the position indicated. If either the <literal remap="tt">left</literal> or <literal remap="tt">top</literal> is
Packit Service 8876fe
negative, the position is measured from the opposite side of the
Packit Service 8876fe
screen. The final measurement will seem to be off by one though. For
Packit Service 8876fe
example, a <literal remap="tt">top</literal> of -1 indicates the last line on the screen, and
Packit Service 8876fe
one of -2 is the line above that.
Packit Service 8876fe
Packit Service 8876fe
As it's common to use the last line on the screen to display help information,
Packit Service 8876fe
<literal remap="tt">newt</literal> includes special support for doing exactly that. The last
Packit Service 8876fe
line on the display is known as the <emphasis remap="bf">help line</emphasis>, and is treated as a
Packit Service 8876fe
stack. As the value of the help line normally relates to the window
Packit Service 8876fe
currently displayed, using the same structure for window order and the
Packit Service 8876fe
help line is very natural. Two functions are provided to manipulate the
Packit Service 8876fe
help line.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtPushHelpLine(const char * text);
Packit Service 8876fe
void newtPopHelpLine(void);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The first function, <literal remap="tt">newtPushHelpLine()</literal>, saves the current help line
Packit Service 8876fe
on a stack (which is independent of the window stack) and displays the
Packit Service 8876fe
new line. If <literal remap="tt">text</literal> is <literal remap="tt">NULL</literal>, <literal remap="tt">newt</literal>'s default help line is
Packit Service 8876fe
displayed (which provides basic instructions on using <literal remap="tt">newt</literal>). If
Packit Service 8876fe
<literal remap="tt">text</literal> is a string of length 0, the help line is cleared. For all
Packit Service 8876fe
other values of <literal remap="tt">text</literal>, the passed string is displayed at the bottom,
Packit Service 8876fe
left-hand corner of the display. The space between the end of the displayed
Packit Service 8876fe
string the the right-hand edge of the terminal is cleared.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtPopHelpLine()</literal> replaces the current help line with the one it
Packit Service 8876fe
replaced. It's important not to call tt/newtPopHelpLine()/ more then
Packit Service 8876fe
<literal remap="tt">newtPushHelpLine()</literal>!
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">Suspending Newt Applications</literal>
Packit Service 8876fe
Packit Service 8876fe
By default, <literal remap="tt">newt</literal> programs cannot be suspended by the user (compare
Packit Service 8876fe
this to most Unix programs which can be suspended by pressing the suspend
Packit Service 8876fe
key (normally <literal remap="tt">^Z</literal>).  Instead, programs can specify a <emphasis remap="bf">callback</emphasis>
Packit Service 8876fe
function which gets invoked when the user presses the suspend key. 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
typedef void (*newtSuspendCallback)(void);
Packit Service 8876fe
Packit Service 8876fe
void newtSetSuspendCallback(newtSuspendCallback cb);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The suspend function neither expects nor returns any value, and can
Packit Service 8876fe
do whatever it likes to when it is invoked. If no suspend callback
Packit Service 8876fe
is registered, the suspend keystroke is ignored.
Packit Service 8876fe
Packit Service 8876fe
If the application should suspend and continue like most user applications,
Packit Service 8876fe
the suspend callback needs two other <literal remap="tt">newt</literal> functions.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtSuspend(void);
Packit Service 8876fe
void newtResume(void);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtSuspend()</literal> tells <literal remap="tt">newt</literal> to return the terminal to its initial
Packit Service 8876fe
state. Once this is done, the application can suspend itself (by
Packit Service 8876fe
sending itself a <literal remap="tt">SIGTSTP</literal>, fork a child program, or do whatever
Packit Service 8876fe
else it likes. When it wants to resume using the <literal remap="tt">newt</literal> interface,
Packit Service 8876fe
it must call <literal remap="tt">newtResume</literal> before doing so. 
Packit Service 8876fe
Packit Service 8876fe
Note that suspend callbacks are not signal handlers. When <literal remap="tt">newtInit()</literal>
Packit Service 8876fe
takes over the terminal, it disables the part of the terminal interface
Packit Service 8876fe
which sends the suspend signal. Instead, if <literal remap="tt">newt</literal> sees the suspend
Packit Service 8876fe
keystroke during normal input processing, it immediately calls the suspend
Packit Service 8876fe
callback if one has been set. This means that suspending newt applications
Packit Service 8876fe
is not asynchronous.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Refreshing the Screen</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
To increase performance, S-Lang only updates the display when it needs
Packit Service 8876fe
to, not when the program tells S-Lang to write to the terminal. ``When it
Packit Service 8876fe
needs to'' is implemented as ``right before the we wait for the user to
Packit Service 8876fe
press a key''. While this allows for optimized screen displays most of
Packit Service 8876fe
the time, this optimization makes things difficult for programs which
Packit Service 8876fe
want to display progress messages without forcing the user to input 
Packit Service 8876fe
characters. Applications can force S-Lang to immediately update modified
Packit Service 8876fe
portions of the screen by calling <literal remap="tt">newtRefresh</literal>.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<orderedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The program wants to display a progress message, without forcing
Packit Service 8876fe
for the user to enter any characters.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
A misfeature of the program causes part of the screen to be
Packit Service 8876fe
corrupted. Ideally, the program would be fixed, but that may not 
Packit Service 8876fe
always be practical.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem></orderedlist>
Packit Service 8876fe
</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Other Miscellaneous Functions</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
As always, some function defy characterization. Two of <literal remap="tt">newt</literal>'s general
Packit Service 8876fe
function fit this oddball category.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtBell(void);
Packit Service 8876fe
void newtGetScreenSize(int * cols, int * rows);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The first sends a beep to the terminal. Depending on the terminal's
Packit Service 8876fe
settings, this been may or may not be audible. The second function,
Packit Service 8876fe
<literal remap="tt">newtGetScreenSize()</literal>, fills in the passed pointers with the
Packit Service 8876fe
current size of the terminal.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Basic <literal remap="tt">newt</literal> Example</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
To help illustrate the functions presented in this section here is a short
Packit Service 8876fe
sample <literal remap="tt">newt</literal> program which uses many of them. While it doesn't do
Packit Service 8876fe
anything interesting, it does show the basic structure of <literal remap="tt">newt</literal> programs.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
#include <newt.h>
Packit Service 8876fe
#include <stdlib.h>
Packit Service 8876fe
Packit Service 8876fe
int main(void) {
Packit Service 8876fe
    newtInit();
Packit Service 8876fe
    newtCls();
Packit Service 8876fe
Packit Service 8876fe
    newtDrawRootText(0, 0, "Some root text");
Packit Service 8876fe
    newtDrawRootText(-25, -2, "Root text in the other corner");
Packit Service 8876fe
Packit Service 8876fe
    newtPushHelpLine(NULL);
Packit Service 8876fe
    newtRefresh();
Packit Service 8876fe
    sleep(1);
Packit Service 8876fe
Packit Service 8876fe
    newtPushHelpLine("A help line");
Packit Service 8876fe
    newtRefresh();
Packit Service 8876fe
    sleep(1);
Packit Service 8876fe
Packit Service 8876fe
    newtPopHelpLine();
Packit Service 8876fe
    newtRefresh();
Packit Service 8876fe
    sleep(1);
Packit Service 8876fe
Packit Service 8876fe
    newtFinished();
Packit Service 8876fe
}
Packit Service 8876fe
</screen></para></sect2></sect1>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect1><title>Windows</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
While most <literal remap="tt">newt</literal> applications do use windows, <literal remap="tt">newt</literal>'s window
Packit Service 8876fe
support is actually extremely limited. Windows must be destroyed in the
Packit Service 8876fe
opposite of the order they were created, and only the topmost window may be
Packit Service 8876fe
active. Corollaries to this are:
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<itemizedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The user may not switch between windows.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Only the top window may be destroyed.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem></itemizedlist>
Packit Service 8876fe
Packit Service 8876fe
While this is quite a severe limitation, adopting it greatly simplifies
Packit Service 8876fe
both writing <literal remap="tt">newt</literal> applications and developing <literal remap="tt">newt</literal> itself, as it
Packit Service 8876fe
separates <literal remap="tt">newt</literal> from the world of event-driven programming. However,
Packit Service 8876fe
this tradeoff between function and simplicity may make <literal remap="tt">newt</literal>
Packit Service 8876fe
unsuitable for some tasks.
Packit Service 8876fe
</para>
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Creating Windows</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
There are two main ways of opening <literal remap="tt">newt</literal> windows: with or without
Packit Service 8876fe
explicit sizings. When grids (which will be introduced later in this
Packit Service 8876fe
tutorial) are used, a window may be made to just fit the grid. When
Packit Service 8876fe
grids are not used, explicit sizing must be given.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
int newtCenteredWindow(int width, int height, const char * title);
Packit Service 8876fe
int newtOpenWindow(int left, int top, int width, int height, 
Packit Service 8876fe
		   const char * title);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The first of these functions open a centered window of the specified
Packit Service 8876fe
size. The <literal remap="tt">title</literal> is optional -- if it is <literal remap="tt">NULL</literal>, then no title
Packit Service 8876fe
is used. <literal remap="tt">newtOpenWindow*(</literal> is similar, but it requires a specific
Packit Service 8876fe
location for the upper left-hand corner of the window.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Destroying Windows</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
All windows are destroyed in the same manner, no matter how the windows
Packit Service 8876fe
were originally created.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtPopWindow(void);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
This function removes the top window from the display, and redraws the
Packit Service 8876fe
display areas which the window overwrote.</para></sect2></sect1> 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect1><title>Components</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Components are the basic user interface element <literal remap="tt">newt</literal> provides. A
Packit Service 8876fe
single component may be (for example) a listbox, push button checkbox,
Packit Service 8876fe
a collection of other components. Most components are used to display
Packit Service 8876fe
information in a window, provide a place for the user to enter data, or a
Packit Service 8876fe
combination of these two functions. 
Packit Service 8876fe
Packit Service 8876fe
Forms, however, are a component whose primary purpose is not noticed by
Packit Service 8876fe
the user at all. Forms are collections of components (a form may contain
Packit Service 8876fe
another form) which logically relate the components to one another. Once
Packit Service 8876fe
a form is created and had all of its constituent components added to it,
Packit Service 8876fe
applications normally then run the form.  This gives control of the
Packit Service 8876fe
application to the form, which then lets the user enter data onto the
Packit Service 8876fe
form. When the user is done (a number of different events qualify as
Packit Service 8876fe
``done''), the form returns control to the part of the application which
Packit Service 8876fe
invoked it. The application may then read the information the user provided
Packit Service 8876fe
and continue appropriately.
Packit Service 8876fe
Packit Service 8876fe
All <literal remap="tt">newt</literal> components are stored in a common data type, a
Packit Service 8876fe
<literal remap="tt">newtComponent</literal> (some of the particulars of <literal remap="tt">newtComponent</literal>s have
Packit Service 8876fe
already been mentioned. While this makes it easy for programmers to pass
Packit Service 8876fe
components around, it does force them to make sure they don't pass
Packit Service 8876fe
entry boxes to routines expecting push buttons, as the compiler can't
Packit Service 8876fe
ensure that for them.
Packit Service 8876fe
Packit Service 8876fe
We start off with a brief introduction to forms. While not terribly
Packit Service 8876fe
complete, this introduction is enough to let us illustrate the rest of
Packit Service 8876fe
the components with some sample code. We'll then discuss the remainder of
Packit Service 8876fe
the components, and end this section with a more exhaustive description of
Packit Service 8876fe
forms.</para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Introduction to Forms</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
As we've mentioned, forms are simply collections of components. As only one
Packit Service 8876fe
form can be active (or running) at a time, every component which the user
Packit Service 8876fe
should be able to access must be on the running form (or on a subform of
Packit Service 8876fe
the running form). A form is itself a component, which means forms are
Packit Service 8876fe
stored in <literal remap="tt">newtComponent</literal> data structures.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
To create a form, call <literal remap="tt">newtForm()</literal>. The first parameter is a vertical
Packit Service 8876fe
scrollbar which should be associated with the form. For now, that should
Packit Service 8876fe
always be <literal remap="tt">NULL</literal> (we'll discuss how to create scrolling forms later in
Packit Service 8876fe
this section). The second parameter, <literal remap="tt">help</literal>, is currently unused and
Packit Service 8876fe
should always be <literal remap="tt">NULL</literal>. The <literal remap="tt">flags</literal> is normally 0, and other values
Packit Service 8876fe
it can take will be discussed later. Now that we've waved away the
Packit Service 8876fe
complexity of this function, creating a form boils down to simply:
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent myForm;
Packit Service 8876fe
Packit Service 8876fe
myForm = newtForm(NULL, NULL, 0);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
After a form is created, components need to be added to it --- after all,
Packit Service 8876fe
an empty form isn't terribly useful. There are two functions which add
Packit Service 8876fe
components to a form.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtFormAddComponent(newtComponent form, newtComponent co);
Packit Service 8876fe
void newtFormAddComponents(newtComponent form, ...);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The first function, <literal remap="tt">newtFormAddComponent()</literal>, adds a single component
Packit Service 8876fe
to the form which is passed as the first parameter. The second function
Packit Service 8876fe
is simply a convenience function. After passing the form to
Packit Service 8876fe
<literal remap="tt">newtFormAddComponents()</literal>, an arbitrary number of components is then
Packit Service 8876fe
passed, followed by <literal remap="tt">NULL</literal>. Every component passed is added to the form.
Packit Service 8876fe
Packit Service 8876fe
Once a form has been created and components have been added to it, it's
Packit Service 8876fe
time to run the form.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtRunForm(newtComponent form);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
This function runs the form passed to it, and returns the component which
Packit Service 8876fe
caused the form to stop running. For now, we'll ignore the return value
Packit Service 8876fe
completely.
Packit Service 8876fe
Packit Service 8876fe
Notice that this function doesn't fit in with <literal remap="tt">newt</literal>'s normal
Packit Service 8876fe
naming convention. It is an older interface which will not work for all
Packit Service 8876fe
forms. It was left in <literal remap="tt">newt</literal> only for legacy applications. It is a
Packit Service 8876fe
simpler interface than the new <literal remap="tt">newtFormRun()</literal> though, and is still used
Packit Service 8876fe
quite often as a result.
Packit Service 8876fe
Packit Service 8876fe
When an application is done with a form, it destroys the form and
Packit Service 8876fe
all of the components the form contains.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtFormDestroy(newtComponent form);	
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
This function frees the memory resources used by the form and all of the
Packit Service 8876fe
components which have been added to the form (including those components
Packit Service 8876fe
which are on subforms). Once a form has been destroyed, none of the form's
Packit Service 8876fe
components can be used.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Components</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Non-form components are the most important user-interface component for
Packit Service 8876fe
users. They determine how users interact with <literal remap="tt">newt</literal> and how information
Packit Service 8876fe
is presented to them.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>General Component Manipulation</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
There are a couple of functions which work on more then one type of
Packit Service 8876fe
components. The description of each component indicates which (if any)
Packit Service 8876fe
of these functions are valid for that particular component.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
typedef void (*newtCallback)(newtComponent, void *);
Packit Service 8876fe
Packit Service 8876fe
void newtComponentAddCallback(newtComponent co, newtCallback f, void * data);
Packit Service 8876fe
void newtComponentTakesFocus(newtComponent co, int val);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The first registers a callback function for that component. A callback
Packit Service 8876fe
function is a function the application provides which <literal remap="tt">newt</literal> calls for a
Packit Service 8876fe
particular component. Exactly when (if ever) the callback is invoked
Packit Service 8876fe
depends on the type of component the callback is attached to, and will be
Packit Service 8876fe
discussed for the components which support callbacks.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtComponentTakesFocus()</literal> works on all components. It allows the
Packit Service 8876fe
application to change which components the user is allowed to select as the
Packit Service 8876fe
current component, and hence provide input to. Components which do not
Packit Service 8876fe
take focus are skipped over during form traversal, but they are displayed
Packit Service 8876fe
on the terminal. Some components should never be set to take focus, such
Packit Service 8876fe
as those which display static text.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Buttons</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Nearly all forms contain at least one button. <literal remap="tt">Newt</literal> buttons come in two
Packit Service 8876fe
flavors, full buttons and compact buttons. Full buttons take up quit a bit
Packit Service 8876fe
of screen space, but look much better then the single-row compact buttons.
Packit Service 8876fe
Other then their size, both button styles behave identically. Different
Packit Service 8876fe
functions are used to create the two types of buttons.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtButton(int left, int top, const char * text);
Packit Service 8876fe
newtComponent newtCompactButton(int left, int top, const char * text);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Both functions take identical parameters. The first two parameters are the
Packit Service 8876fe
location of the upper left corner of the button, and the final parameter is
Packit Service 8876fe
the text which should be displayed in the button (such as ``Ok'' or
Packit Service 8876fe
``Cancel'').</para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Button Example</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Here is a simple example of both full and compact buttons. It also
Packit Service 8876fe
illustrates opening and closing windows, as well a simple form.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
#include <newt.h>
Packit Service 8876fe
#include <stdlib.h>
Packit Service 8876fe
Packit Service 8876fe
void main(void) {
Packit Service 8876fe
    newtComponent form, b1, b2;
Packit Service 8876fe
    newtInit();
Packit Service 8876fe
    newtCls();
Packit Service 8876fe
Packit Service 8876fe
    newtOpenWindow(10, 5, 40, 6, "Button Sample");
Packit Service 8876fe
Packit Service 8876fe
    b1 = newtButton(10, 1, "Ok");
Packit Service 8876fe
    b2 = newtCompactButton(22, 2, "Cancel");
Packit Service 8876fe
    form = newtForm(NULL, NULL, 0);
Packit Service 8876fe
    newtFormAddComponents(form, b1, b2, NULL);
Packit Service 8876fe
Packit Service 8876fe
    newtRunForm(form);
Packit Service 8876fe
Packit Service 8876fe
    newtFormDestroy(form);
Packit Service 8876fe
    newtFinished();
Packit Service 8876fe
}
Packit Service 8876fe
</screen></para></sect3></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Labels</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Labels are <literal remap="tt">newt</literal>'s simplest component. They display some given text and
Packit Service 8876fe
don't allow any user input.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtLabel(int left, int top, const char * text);
Packit Service 8876fe
void newtLabelSetText(newtComponent co, const char * text);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Creating a label is just like creating a button; just pass the location of
Packit Service 8876fe
the label and the text it should display. Unlike buttons, labels do let the
Packit Service 8876fe
application change the text in the label with <literal remap="tt">newtLabelSetText</literal>. When
Packit Service 8876fe
the label's text is changed, the label automatically redraws itself. It
Packit Service 8876fe
does not clear out any old text which may be leftover from the previous
Packit Service 8876fe
time is was displayed, however, so be sure that the new text is at least
Packit Service 8876fe
as long as the old text.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Entry Boxes</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Entry boxes allow the user to enter a text string into the form which the
Packit Service 8876fe
application can later retrieve.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
typedef int (*newtEntryFilter)(newtComponent entry, void * data, int ch,
Packit Service 8876fe
			       int cursor);
Packit Service 8876fe
Packit Service 8876fe
newtComponent newtEntry(int left, int top, const char * initialValue, int width,
Packit Service 8876fe
			char ** resultPtr, int flags);
Packit Service 8876fe
void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd);
Packit Service 8876fe
char * newtEntryGetValue(newtComponent co);
Packit Service 8876fe
void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">newtEntry()</literal> creates a new entry box. After the location of the entry
Packit Service 8876fe
box, the initial value for the entry box is passed, which may be <literal remap="tt">NULL</literal>
Packit Service 8876fe
if the box should start off empty. Next, the width of the physical box is
Packit Service 8876fe
given. This width may or may not limit the length of the string the user is
Packit Service 8876fe
allowed to enter; that depends on the <literal remap="tt">flags</literal>. The <literal remap="tt">resultPtr</literal> must
Packit Service 8876fe
be the address of a <literal remap="tt">char *</literal>. Until the entry box is destroyed by
Packit Service 8876fe
<literal remap="tt">newtFormDestroy()</literal>, that <literal remap="tt">char *</literal> will point to the current value
Packit Service 8876fe
of the entry box. It's important that applications make a copy of that
Packit Service 8876fe
value before destroying the form if they need to use it later. The
Packit Service 8876fe
<literal remap="tt">resultPtr</literal> may be <literal remap="tt">NULL</literal>, in which case the user must use the
Packit Service 8876fe
<literal remap="tt">newtEntryGetValue()</literal> function to get the value of the entry box.
Packit Service 8876fe
Packit Service 8876fe
Entry boxes support a number of flags:
Packit Service 8876fe
Packit Service 8876fe
<variablelist>
Packit Service 8876fe
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_ENTRY_SCROLL</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>If this flag is not specified, the user cannot
Packit Service 8876fe
enter text into the entry box which is wider then the entry box itself.
Packit Service 8876fe
This flag removes this limitation, and lets the user enter data of an
Packit Service 8876fe
arbitrary length.</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_HIDDEN</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>If this flag is specified, the value of the entry box
Packit Service 8876fe
is not displayed. This is useful when the application needs to read a
Packit Service 8876fe
password, for example.</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_RETURNEXIT</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>When this flag is given, the entry box will cause
Packit Service 8876fe
the form to stop running if the user pressed return inside of the entry
Packit Service 8876fe
box. This can provide a nice shortcut for users.</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
</variablelist>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
After an entry box has been created, its contents can be set by
Packit Service 8876fe
<literal remap="tt">newtEntrySet()</literal>. After the entry box itself, the new string to place
Packit Service 8876fe
in the entry box is passed. The final parameter, <literal remap="tt">cursorAtEnd</literal>, controls
Packit Service 8876fe
where the cursor will appear in the entry box. If it is zero, the cursor
Packit Service 8876fe
remains at its present location; a nonzero value moves the cursor to the
Packit Service 8876fe
end of the entry box's new value.
Packit Service 8876fe
Packit Service 8876fe
While the simplest way to find the value of an entry box is by using a
Packit Service 8876fe
<literal remap="tt">resultPtr</literal>, doing so complicates some applications.
Packit Service 8876fe
<literal remap="tt">newtEntryGetValue()</literal> returns a pointer to the string which the entry
Packit Service 8876fe
box currently contains. The returned pointer may not be valid once the
Packit Service 8876fe
user further modifies the entry box, and will not be valid after the 
Packit Service 8876fe
entry box has been destroyed, so be sure to save its value in a more
Packit Service 8876fe
permanent location if necessary.
Packit Service 8876fe
Packit Service 8876fe
Entry boxes allow applications to filter characters as they are entered.
Packit Service 8876fe
This allows programs to ignore characters which are invalid (such as
Packit Service 8876fe
entering a ^ in the middle of a phone number) and provide intelligent aids
Packit Service 8876fe
to the user (such as automatically adding a '.' after the user has typed in
Packit Service 8876fe
the first three numbers in an IP address). 
Packit Service 8876fe
Packit Service 8876fe
When a filter is registered through <literal remap="tt">newtEntrySetFilter()</literal>, both the
Packit Service 8876fe
filter itself and an arbitrary <literal remap="tt">void *</literal>, which passed to the filter
Packit Service 8876fe
whenever it is invoked, are recorded. This data pointer isn't used for any
Packit Service 8876fe
other purpose, and may be <literal remap="tt">NULL</literal>. Entry filters take four arguments.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<orderedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The entry box which had data entered into it</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The data pointer which was registered along with the filter</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The new character which <literal remap="tt">newt</literal> is considering inserting into the
Packit Service 8876fe
entry box</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The current cursor position (0 is the leftmost position)
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem>
Packit Service 8876fe
</orderedlist>
Packit Service 8876fe
Packit Service 8876fe
The filter returns 0 if the character should be ignored, or the value of
Packit Service 8876fe
the character which should be inserted into the entry box. Filter functions
Packit Service 8876fe
which want to do complex manipulations of the string should use
Packit Service 8876fe
<literal remap="tt">newtEntrySet()</literal> to update the entry box and then return 0 to prevent
Packit Service 8876fe
the new character from being inserted.
Packit Service 8876fe
Packit Service 8876fe
When a callback is attached to a entry box, the callback is invoked
Packit Service 8876fe
whenever the user moves off of the callback and on to another component.
Packit Service 8876fe
Packit Service 8876fe
Here is a sample program which illustrates the use of both labels and
Packit Service 8876fe
entry boxes.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
#include <newt.h>
Packit Service 8876fe
#include <stdlib.h>
Packit Service 8876fe
#include <stdio.h>
Packit Service 8876fe
Packit Service 8876fe
void main(void) {
Packit Service 8876fe
    newtComponent form, label, entry, button;
Packit Service 8876fe
    char * entryValue;
Packit Service 8876fe
Packit Service 8876fe
    newtInit();
Packit Service 8876fe
    newtCls();
Packit Service 8876fe
Packit Service 8876fe
    newtOpenWindow(10, 5, 40, 8, "Entry and Label Sample");
Packit Service 8876fe
Packit Service 8876fe
    label = newtLabel(1, 1, "Enter a string");
Packit Service 8876fe
    entry = newtEntry(16, 1, "sample", 20, &entryValue, 
Packit Service 8876fe
		      NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
Packit Service 8876fe
    button = newtButton(17, 3, "Ok");
Packit Service 8876fe
    form = newtForm(NULL, NULL, 0);
Packit Service 8876fe
    newtFormAddComponents(form, label, entry, button, NULL);
Packit Service 8876fe
Packit Service 8876fe
    newtRunForm(form);
Packit Service 8876fe
Packit Service 8876fe
    newtFinished();
Packit Service 8876fe
Packit Service 8876fe
    printf("Final string was: %s\n", entryValue);
Packit Service 8876fe
Packit Service 8876fe
    /* We cannot destroy the form until after we've used the value
Packit Service 8876fe
       from the entry widget. */
Packit Service 8876fe
    newtFormDestroy(form);
Packit Service 8876fe
}
Packit Service 8876fe
</screen></para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Checkboxes</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Most widget sets include checkboxes which toggle between two value (checked
Packit Service 8876fe
or not checked). <literal remap="tt">Newt</literal> checkboxes are more flexible. When the user
Packit Service 8876fe
presses the space bar on a checkbox, the checkbox's value changes to the
Packit Service 8876fe
next value in an arbitrary sequence (which wraps). Most checkboxes have
Packit Service 8876fe
two items in that sequence, checked or not, but <literal remap="tt">newt</literal> allows an
Packit Service 8876fe
arbitrary number of value. This is useful when the user must pick from a
Packit Service 8876fe
limited number of choices.
Packit Service 8876fe
Packit Service 8876fe
Each item in the sequence is a single character, and the sequence itself is
Packit Service 8876fe
represented as a string. The checkbox components displays the character
Packit Service 8876fe
which currently represents its value the left of a text label, and returns
Packit Service 8876fe
the same character as its current value. The default sequence for
Packit Service 8876fe
checkboxes is <literal remap="tt">" *"</literal>, with <literal remap="tt">' '</literal> indicating false and <literal remap="tt">'*'</literal> true.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
Packit Service 8876fe
			   const char * seq, char * result);
Packit Service 8876fe
char newtCheckboxGetValue(newtComponent co);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Like most components, the position of the checkbox is the first thing
Packit Service 8876fe
passed to the function that creates one. The next parameter, <literal remap="tt">text</literal>, is
Packit Service 8876fe
the text which is displayed to the right of the area which is checked.  The
Packit Service 8876fe
<literal remap="tt">defValue</literal> is the initial value for the checkbox, and <literal remap="tt">seq</literal> is the
Packit Service 8876fe
sequence which the checkbox should go through (<literal remap="tt">defValue</literal> must be
Packit Service 8876fe
in <literal remap="tt">seq</literal>. <literal remap="tt">seq</literal> may be <literal remap="tt">NULL</literal>, in which case <literal remap="tt">" *"</literal> is used.
Packit Service 8876fe
The final parameter, <literal remap="tt">result</literal>, should point to a character which the
Packit Service 8876fe
checkbox should always record its current value in. If <literal remap="tt">result</literal> is
Packit Service 8876fe
<literal remap="tt">NULL</literal>, <literal remap="tt">newtCheckboxGetValue()</literal> must be used to get the current
Packit Service 8876fe
value of the checkbox.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtCheckboxGetValue()</literal> is straightforward, returning the character
Packit Service 8876fe
in the sequence which indicates the current value of the checkbox
Packit Service 8876fe
Packit Service 8876fe
If a callback is attached to a checkbox, the callback is invoked whenever
Packit Service 8876fe
the checkbox responds to a user's keystroke. The entry box may respond by
Packit Service 8876fe
taking focus or giving up focus, as well as by changing its current value.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Radio Buttons</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Radio buttons look very similar to checkboxes. The key difference between
Packit Service 8876fe
the two is that radio buttons are grouped into sets, and exactly one radio
Packit Service 8876fe
button in that set may be turned on. If another radio button is selected,
Packit Service 8876fe
the button which was selected is automatically deselected.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtRadiobutton(int left, int top, const char * text, 
Packit Service 8876fe
			      int isDefault, newtComponent prevButton);
Packit Service 8876fe
newtComponent newtRadioGetCurrent(newtComponent setMember);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Each radio button is created by calling <literal remap="tt">newtRadiobutton()</literal>. After
Packit Service 8876fe
the position of the radio button, the text displayed with the button
Packit Service 8876fe
is passed. <literal remap="tt">isDefault</literal> should be nonzero if the radio button is to
Packit Service 8876fe
be turned on by default. The final parameter, <literal remap="tt">prevMember</literal> is used
Packit Service 8876fe
to group radio buttons into sets. If <literal remap="tt">prevMember</literal> is <literal remap="tt">NULL</literal>, the 
Packit Service 8876fe
radio button is assigned to a new set. If the radio button should belong
Packit Service 8876fe
to a preexisting set, <literal remap="tt">prevMember</literal> must be the previous radio button
Packit Service 8876fe
added to that set.
Packit Service 8876fe
Packit Service 8876fe
Discovering which radio button in a set is currently selected necessitates
Packit Service 8876fe
<literal remap="tt">newtRadioGetCurrent()</literal>. It may be passed any radio button in the set
Packit Service 8876fe
you're interested in, and it returns the radio button component currently
Packit Service 8876fe
selected.
Packit Service 8876fe
Packit Service 8876fe
Here is an example of both checkboxes and radio buttons.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
#include <newt.h>
Packit Service 8876fe
#include <stdlib.h>
Packit Service 8876fe
#include <stdio.h>
Packit Service 8876fe
Packit Service 8876fe
void main(void) {
Packit Service 8876fe
    newtComponent form, checkbox, rb[3], button;
Packit Service 8876fe
    char cbValue;
Packit Service 8876fe
    int i;
Packit Service 8876fe
Packit Service 8876fe
    newtInit();
Packit Service 8876fe
    newtCls();
Packit Service 8876fe
Packit Service 8876fe
    newtOpenWindow(10, 5, 40, 11, "Checkboxes and Radio buttons");
Packit Service 8876fe
Packit Service 8876fe
    checkbox = newtCheckbox(1, 1, "A checkbox", ' ', " *X", &cbValue);
Packit Service 8876fe
Packit Service 8876fe
    rb[0] = newtRadiobutton(1, 3, "Choice 1", 1, NULL);
Packit Service 8876fe
    rb[1] = newtRadiobutton(1, 4, "Choice 2", 0, rb[0]);
Packit Service 8876fe
    rb[2] = newtRadiobutton(1, 5, "Choice 3", 0, rb[1]);
Packit Service 8876fe
Packit Service 8876fe
    button = newtButton(1, 7, "Ok");
Packit Service 8876fe
Packit Service 8876fe
    form = newtForm(NULL, NULL, 0);
Packit Service 8876fe
    newtFormAddComponent(form, checkbox);
Packit Service 8876fe
    for (i = 0; i < 3; i++)
Packit Service 8876fe
	newtFormAddComponent(form, rb[i]);
Packit Service 8876fe
    newtFormAddComponent(form, button);
Packit Service 8876fe
Packit Service 8876fe
    newtRunForm(form);
Packit Service 8876fe
    newtFinished();
Packit Service 8876fe
Packit Service 8876fe
    /* We cannot destroy the form until after we've found the current
Packit Service 8876fe
       radio button */
Packit Service 8876fe
Packit Service 8876fe
    for (i = 0; i < 3; i++)
Packit Service 8876fe
	if (newtRadioGetCurrent(rb[0]) == rb[i])
Packit Service 8876fe
	    printf("radio button picked: %d\n", i);
Packit Service 8876fe
    newtFormDestroy(form);
Packit Service 8876fe
Packit Service 8876fe
    /* But the checkbox's value is stored locally */
Packit Service 8876fe
    printf("checkbox value: '%c'\n", cbValue);
Packit Service 8876fe
}
Packit Service 8876fe
</screen></para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Scales</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
It's common for programs to need to display a progress meter on the
Packit Service 8876fe
terminal while it performs some length operation (it behaves like an
Packit Service 8876fe
anesthetic). The scale component is a simple way of doing this. It
Packit Service 8876fe
displays a horizontal bar graph which the application can update as the
Packit Service 8876fe
operation continues.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtScale(int left, int top, int width, long long fullValue);
Packit Service 8876fe
void newtScaleSet(newtComponent co, unsigned long long amount);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
When the scale is created with <literal remap="tt">newtScale</literal>, it is given the width of the
Packit Service 8876fe
scale itself as well as the value which means that the scale should be
Packit Service 8876fe
drawn as full. When the position of the scale is set with
Packit Service 8876fe
<literal remap="tt">newtScaleSet()</literal>, the scale is told the amount of the scale which should
Packit Service 8876fe
be filled in relative to the <literal remap="tt">fullAmount</literal>. For example, if the
Packit Service 8876fe
application is copying a file, <literal remap="tt">fullValue</literal> could be the number of bytes
Packit Service 8876fe
in the file, and when the scale is updated <literal remap="tt">newtScaleSet()</literal> would be
Packit Service 8876fe
passed the number of bytes which have been copied so far.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Textboxes</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Textboxes display a block of text on the terminal, and is appropriate for
Packit Service 8876fe
display large amounts of text. 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtTextbox(int left, int top, int width, int height, int flags);
Packit Service 8876fe
void newtTextboxSetText(newtComponent co, const char * text);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtTextbox()</literal> creates a new textbox, but does not fill it with data.
Packit Service 8876fe
The function is passed the location for the textbox on the screen, the
Packit Service 8876fe
width and height of the textbox (in characters), and zero or more of the
Packit Service 8876fe
following flags:
Packit Service 8876fe
Packit Service 8876fe
<variablelist>
Packit Service 8876fe
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_WRAP</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>All text in the textbox should be wrapped to fit
Packit Service 8876fe
the width of the textbox. If this flag is not specified, each newline
Packit Service 8876fe
delimited line in the text is truncated if it is too long to fit.
Packit Service 8876fe
Packit Service 8876fe
When <literal remap="tt">newt</literal> wraps text, it tries not to break lines on spaces or tabs.
Packit Service 8876fe
Literal newline characters are respected, and may be used to force line
Packit Service 8876fe
breaks.</para>
Packit Service 8876fe
<variablelist>
Packit Service 8876fe
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_SCROLL</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>The text box should be scrollable. When this option
Packit Service 8876fe
is used, the scrollbar which is added increases the width of the area used
Packit Service 8876fe
by the textbox by 2 characters; that is the textbox is 2 characters wider
Packit Service 8876fe
then the width passed to <literal remap="tt">newtTextbox()</literal>.
Packit Service 8876fe
</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
</variablelist>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
After a textbox has been created, text may be added to it through
Packit Service 8876fe
<literal remap="tt">newtTextboxSetText()</literal>, which takes only the textbox and the new text as
Packit Service 8876fe
parameters. If the textbox already contained text, that text is replaced by
Packit Service 8876fe
the new text. The textbox makes its own copy of the passed text, so these
Packit Service 8876fe
is no need to keep the original around unless it's convenient.</para></listitem></varlistentry></variablelist></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Reflowing Text</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
When applications need to display large amounts of text, it's common not to
Packit Service 8876fe
know exactly where the linebreaks should go. While textboxes are quite
Packit Service 8876fe
willing to scroll the text, the programmer still must know what width the
Packit Service 8876fe
text will look ``best'' at (where ``best'' means most exactly rectangular;
Packit Service 8876fe
no lines much shorter or much longer then the rest). This common is
Packit Service 8876fe
especially prevalent in internationalized programs, which need to make a
Packit Service 8876fe
wide variety of message string look god on a screen.
Packit Service 8876fe
Packit Service 8876fe
To help with this, <literal remap="tt">newt</literal> provides routines to reformat text to look
Packit Service 8876fe
good. It tries different widths to figure out which one will look ``best''
Packit Service 8876fe
to the user. As these commons are almost always used to format text for
Packit Service 8876fe
textbox components, <literal remap="tt">newt</literal> makes it easy to construct a textbox with
Packit Service 8876fe
reflowed text.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
char * newtReflowText(char * text, int width, int flexDown, int flexUp,
Packit Service 8876fe
		      int * actualWidth, int * actualHeight);
Packit Service 8876fe
newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
Packit Service 8876fe
				  int flexDown, int flexUp, int flags);
Packit Service 8876fe
int newtTextboxGetNumLines(newtComponent co);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">newtReflowText()</literal> reflows the <literal remap="tt">text</literal> to a target width of
Packit Service 8876fe
<literal remap="tt">width</literal>. The actual width of the longest line in the returned string is
Packit Service 8876fe
between <literal remap="tt">width - flexDown</literal> and <literal remap="tt">width + flexUp</literal>; the actual maximum
Packit Service 8876fe
line length is chosen to make the displayed check look rectangular. 
Packit Service 8876fe
The <literal remap="tt">int</literal>s pointed to by <literal remap="tt">actualWidth</literal> and <literal remap="tt">actualHeight</literal> are set
Packit Service 8876fe
to the width of the longest line and the number of lines in in the
Packit Service 8876fe
returned text, respectively. Either one may be <literal remap="tt">NULL</literal>. The return
Packit Service 8876fe
value points to the reflowed text, and is allocated through <literal remap="tt">malloc()</literal>.
Packit Service 8876fe
Packit Service 8876fe
When the reflowed text is being placed in a textbox it may be easier to use
Packit Service 8876fe
<literal remap="tt">newtTextboxReflowed()</literal>, which creates a textbox, reflows the text, and
Packit Service 8876fe
places the reflowed text in the listbox. It's parameters consist of the
Packit Service 8876fe
position of the final textbox, the width and flex values for the text
Packit Service 8876fe
(which are identical to the parameters passed to <literal remap="tt">newtReflowText()</literal>,
Packit Service 8876fe
and the flags for the textbox (which are the same as the flags for
Packit Service 8876fe
<literal remap="tt">newtTextbox()</literal>. This function does not let you limit the height of the
Packit Service 8876fe
textbox, however, making limiting it's use to constructing textboxes which
Packit Service 8876fe
don't need to scroll.
Packit Service 8876fe
Packit Service 8876fe
To find out how tall the textbox created by <literal remap="tt">newtTextboxReflowed()</literal> is, 
Packit Service 8876fe
use <literal remap="tt">newtTextboxGetNumLines()</literal>, which returns the number of lines in the
Packit Service 8876fe
textbox. For textboxes created by <literal remap="tt">newtTextboxReflowed()</literal>, this is
Packit Service 8876fe
always the same as the height of the textbox.
Packit Service 8876fe
Packit Service 8876fe
Here's a simple program which uses a textbox to display a message.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
#include <newt.h>
Packit Service 8876fe
#include <stdlib.h>
Packit Service 8876fe
Packit Service 8876fe
char message[] = "This is a pretty long message. It will be displayed "
Packit Service 8876fe
		 "in a newt textbox, and illustrates how to construct "
Packit Service 8876fe
		 "a textbox from arbitrary text which may not have "
Packit Service 8876fe
		 "very good line breaks.\n\n"
Packit Service 8876fe
		 "Notice how literal \\n characters are respected, and "
Packit Service 8876fe
		 "may be used to force line breaks and blank lines.";
Packit Service 8876fe
Packit Service 8876fe
void main(void) {
Packit Service 8876fe
    newtComponent form, text, button;
Packit Service 8876fe
Packit Service 8876fe
    newtInit();
Packit Service 8876fe
    newtCls();
Packit Service 8876fe
Packit Service 8876fe
    text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0);
Packit Service 8876fe
    button = newtButton(12, newtTextboxGetNumLines(text) + 2, "Ok");
Packit Service 8876fe
Packit Service 8876fe
    newtOpenWindow(10, 5, 37,
Packit Service 8876fe
		   newtTextboxGetNumLines(text) + 7, "Textboxes");
Packit Service 8876fe
Packit Service 8876fe
    form = newtForm(NULL, NULL, 0);
Packit Service 8876fe
    newtFormAddComponents(form, text, button, NULL);
Packit Service 8876fe
Packit Service 8876fe
    newtRunForm(form);
Packit Service 8876fe
    newtFormDestroy(form);
Packit Service 8876fe
    newtFinished();
Packit Service 8876fe
}
Packit Service 8876fe
</screen></para></sect3></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Scrollbars</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Scrollbars (which, currently, are always vertical in <literal remap="tt">newt</literal>), may be
Packit Service 8876fe
attached to forms to let them contain more data then they have space for.
Packit Service 8876fe
While the actual process of making scrolling forms is discussed at the end 
Packit Service 8876fe
of this section, we'll go ahead and introduce scrollbars now so you'll be
Packit Service 8876fe
ready.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtVerticalScrollbar(int left, int top, int height,
Packit Service 8876fe
				    int normalColorset, int thumbColorset);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
When a scrollbar is created, it is given a position on the screen, a
Packit Service 8876fe
height, and two colors. The first color is the color used for drawing the
Packit Service 8876fe
scrollbar, and the second color is used for drawing the thumb. This is the
Packit Service 8876fe
only place in newt where an application specifically sets colors for a
Packit Service 8876fe
component. It's done here to let the colors a scrollbar use match the
Packit Service 8876fe
colors of the component the scrollbar is mated too. When a scrollbar is
Packit Service 8876fe
being used with a form, <literal remap="tt">normalColorset</literal> is often
Packit Service 8876fe
<literal remap="tt">NEWT_COLORSET_WINDOW</literal> and <literal remap="tt">thumbColorset</literal>
Packit Service 8876fe
<literal remap="tt">NEWT_COLORSET_ACTCHECKBOX</literal>. Of course, feel free to peruse
Packit Service 8876fe
<literal remap="tt"><newt.h></literal> and pick your own colors.
Packit Service 8876fe
Packit Service 8876fe
As the scrollbar is normally updated by the component it is mated with,
Packit Service 8876fe
there is no public interface for moving the thumb.</para></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Listboxes</title>
Packit Service 8876fe
<para>
Packit Service 8876fe
Listboxes are the most complicated components 
Packit Service 8876fe
<literal remap="tt">newt</literal> provides. They can
Packit Service 8876fe
allow a single selection or multiple selection, and are easy to update.
Packit Service 8876fe
Unfortunately, their API is also the least consistent of <literal remap="tt">newt</literal>'s
Packit Service 8876fe
components. Each entry in a listbox is a ordered pair of the text which should be
Packit Service 8876fe
displayed for that item and a <emphasis remap="bf">key</emphasis>, which is a <literal remap="tt">void *</literal> that
Packit Service 8876fe
uniquely identifies that listbox item. Many applications pass integers in
Packit Service 8876fe
as keys, but using arbitrary pointers makes many applications significantly
Packit Service 8876fe
easier to code.</para>
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Basic Listboxes</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Let's start off by looking at the most important listbox functions.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtListbox(int left, int top, int height, int flags);
Packit Service 8876fe
int newtListboxAppendEntry(newtComponent co, const char * text, 
Packit Service 8876fe
			   const void * data);
Packit Service 8876fe
void * newtListboxGetCurrent(newtComponent co);
Packit Service 8876fe
void newtListboxSetWidth(newtComponent co, int width);
Packit Service 8876fe
void newtListboxSetCurrent(newtComponent co, int num);
Packit Service 8876fe
void newtListboxSetCurrentByKey(newtComponent co, void * key);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
A listbox is created at a certain position and a given height. The
Packit Service 8876fe
<literal remap="tt">height</literal> is used for two things. First of all, it is the minimum
Packit Service 8876fe
height the listbox will use. If there are less items in the listbox then
Packit Service 8876fe
the height, suggests the listbox will still take up that minimum amount
Packit Service 8876fe
of space. Secondly, if the listbox is set to be scrollable (by setting
Packit Service 8876fe
the <literal remap="tt">NEWT_FLAG_SCROLL flag</literal>, the <literal remap="tt">height</literal> is also the maximum height
Packit Service 8876fe
of the listbox. If the listbox may not scroll, it increases its height to
Packit Service 8876fe
display all of its items.
Packit Service 8876fe
Packit Service 8876fe
The following flags may be used when creating a listbox:
Packit Service 8876fe
Packit Service 8876fe
<variablelist>
Packit Service 8876fe
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_SCROLL</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>The listbox should scroll to display all of the
Packit Service 8876fe
items it contains.</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_RETURNEXIT</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>When the user presses return on an item in the
Packit Service 8876fe
list, the form should return.</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_BORDER</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>A frame is drawn around the listbox, which can make
Packit Service 8876fe
it easier to see which listbox has the focus when a form contains multiple
Packit Service 8876fe
listboxes.</para></listitem>
Packit Service 8876fe
</varlistentry>
Packit Service 8876fe
<varlistentry>
Packit Service 8876fe
<term>NEWT_FLAG_MULTIPLE</term>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
<para>By default, a listbox only lets the user select
Packit Service 8876fe
one item in the list at a time. When this flag is specified, they may
Packit Service 8876fe
select multiple items from the list.</para></listitem></varlistentry>
Packit Service 8876fe
</variablelist></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Once a listbox has been created, items are added to it by invoking
Packit Service 8876fe
<literal remap="tt">newtListboxAppendEntry()</literal>, which adds new items to the end of the list.
Packit Service 8876fe
In addition to the listbox component, <literal remap="tt">newtListboxAppendEntry()</literal> needs
Packit Service 8876fe
both elements of the (text, key) ordered pair. 
Packit Service 8876fe
Packit Service 8876fe
For lists which only allow a single selection, <literal remap="tt">newtListboxGetCurrent()</literal>
Packit Service 8876fe
should be used to find out which listbox item is currently selected. It
Packit Service 8876fe
returns the key of the currently selected item.
Packit Service 8876fe
Packit Service 8876fe
Normally, a listbox is as wide as its widest element, plus space for a
Packit Service 8876fe
scrollbar if the listbox is supposed to have one. To make the listbox
Packit Service 8876fe
any larger then that, use <literal remap="tt">newtListboxSetWidth()</literal>, which overrides the
Packit Service 8876fe
natural list of the listbox. Once the width has been set, it's fixed. The
Packit Service 8876fe
listbox will no longer grow to accommodate new entries, so bad things may
Packit Service 8876fe
happen! 
Packit Service 8876fe
Packit Service 8876fe
An application can change the current position of the listbox (where the
Packit Service 8876fe
selection bar is displayed) by calling <literal remap="tt">newtListboxSetCurrent()</literal> or
Packit Service 8876fe
<literal remap="tt">newtListboxSetCurrentByKey()</literal>. The first sets the current position to the
Packit Service 8876fe
entry number which is passed as the second argument, with 0 indicating
Packit Service 8876fe
the first entry. <literal remap="tt">newtListboxSetCurrentByKey()</literal> sets the current position
Packit Service 8876fe
to the entry whose <literal remap="tt">key</literal> is passed into the function.</para></sect3>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Manipulating Listbox Contents</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
While the contents of many listboxes never need to change, some applications
Packit Service 8876fe
need to change the contents of listboxes regularly. <literal remap="tt">Newt</literal> includes
Packit Service 8876fe
complete support for updating listboxes. These new functions are in
Packit Service 8876fe
addition to <literal remap="tt">newtListboxAppendEntry()</literal>, which was already discussed.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtListboxSetEntry(newtComponent co, void * key, const char * text);
Packit Service 8876fe
int newtListboxInsertEntry(newtComponent co, const char * text, 
Packit Service 8876fe
                           const void * data, void * key);
Packit Service 8876fe
int newtListboxDeleteEntry(newtComponent co, void * key);
Packit Service 8876fe
void newtListboxClear(newtComponent co);
Packit Service 8876fe
</screen></para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
The first of these, <literal remap="tt">newtListboxSetEntry()</literal>, updates the text for a
Packit Service 8876fe
key which is already in the listbox. The <literal remap="tt">key</literal> specifies which listbox
Packit Service 8876fe
entry should be modified, and <literal remap="tt">text</literal> becomes the new text for that entry
Packit Service 8876fe
in the listbox.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtListboxInsertEntry()</literal> inserts a new listbox entry <emphasis remap="bf">after</emphasis> an
Packit Service 8876fe
already existing entry, which is specified by the <literal remap="tt">key</literal> parameter.
Packit Service 8876fe
The <literal remap="tt">text</literal> and <literal remap="tt">data</literal> parameters specify the new entry which should
Packit Service 8876fe
be added.
Packit Service 8876fe
Packit Service 8876fe
Already-existing entries are removed from a listbox with
Packit Service 8876fe
<literal remap="tt">newtListboxDeleteEntry()</literal>. It removes the listbox entry with the
Packit Service 8876fe
specified <literal remap="tt">key</literal>. If you want to remove all of the entries from a
Packit Service 8876fe
listbox, use <literal remap="tt">newtListboxClear()</literal>.</para></sect3> 
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Multiple Selections</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
When a listbox is created with <literal remap="tt">NEWT_FLAG_MULTIPLE</literal>, the user can select
Packit Service 8876fe
multiple items from the list. When this option is used, a different set of
Packit Service 8876fe
functions must be used to manipulate the listbox selection.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtListboxClearSelection(newtComponent co);
Packit Service 8876fe
void **newtListboxGetSelection(newtComponent co, int *numitems);
Packit Service 8876fe
void newtListboxSelectItem(newtComponent co, const void * key,
Packit Service 8876fe
	                   enum newtFlagsSense sense);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
The simplest of these is <literal remap="tt">newtListboxClearSelection()</literal>, which deselects
Packit Service 8876fe
all of the items in the list (listboxes which allow multiple selections
Packit Service 8876fe
also allow zero selections). <literal remap="tt">newtListboxGetSelection()</literal> returns a
Packit Service 8876fe
pointer to an array which contains the keys for all of the items in the
Packit Service 8876fe
listbox currently selected. The <literal remap="tt">int</literal> pointed to by <literal remap="tt">numitems</literal> is
Packit Service 8876fe
set to the number of items currently selected (and hence the number of
Packit Service 8876fe
items in the returned array). The returned array is dynamically allocated,
Packit Service 8876fe
and must be released through <literal remap="tt">free()</literal>.
Packit Service 8876fe
Packit Service 8876fe
<literal remap="tt">newtListboxSelectItem()</literal> lets the program select and deselect specific
Packit Service 8876fe
listbox entries. The <literal remap="tt">key</literal> of the listbox entry is being affected is
Packit Service 8876fe
passed, and <literal remap="tt">sense</literal> is one of <literal remap="tt">NEWT_FLAGS_RESET</literal>, which deselects
Packit Service 8876fe
the entry, <literal remap="tt">NEWT_FLAGS_SET</literal>, which selects the entry, or
Packit Service 8876fe
<literal remap="tt">NEWT_FLAGS_TOGGLE</literal>, which reverses the current selection status.</para></sect3></sect2>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect2><title>Advanced Forms</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Forms, which tie components together, are quite important in the world of
Packit Service 8876fe
<literal remap="tt">newt</literal>. While we've already discussed the basics of forms, we've omitted
Packit Service 8876fe
many of the details.</para>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<sect3><title>Exiting From Forms</title>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Forms return control to the application for a number of reasons:
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<itemizedlist>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
A component can force the form to exit. Buttons do this whenever they
Packit Service 8876fe
are pushed, and other components exit when <literal remap="tt">NEWT_FLAG_RETURNEXIT</literal> has
Packit Service 8876fe
been specified.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
Applications can setup hot keys which cause the form to exit when
Packit Service 8876fe
they are pressed.</para></listitem>
Packit Service 8876fe
<listitem>
Packit Service 8876fe
Packit Service 8876fe
<para>
Packit Service 8876fe
<literal remap="tt">Newt</literal> can exit when file descriptors are ready to be read or
Packit Service 8876fe
ready to be written to.
Packit Service 8876fe
</para>
Packit Service 8876fe
</listitem></itemizedlist>
Packit Service 8876fe
Packit Service 8876fe
By default, <literal remap="tt">newt</literal> forms exit when the F12 key is pressed (F12 is setup
Packit Service 8876fe
as a hot key by default). <literal remap="tt">Newt</literal> applications should treat F12 as an
Packit Service 8876fe
``Ok'' button. If applications don't want F12 to exit the form, they can
Packit Service 8876fe
specify <literal remap="tt">NEWT_FLAG_NOF12</literal> as flag when creating the form with 
Packit Service 8876fe
<literal remap="tt">newtForm</literal>.
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtFormAddHotKey(newtComponent co, int key);
Packit Service 8876fe
void newtFormWatchFd(newtComponent form, int fd, int fdFlags);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
void newtDrawForm(newtComponent form);
Packit Service 8876fe
newtComponent newtFormGetCurrent(newtComponent co);
Packit Service 8876fe
void newtFormSetCurrent(newtComponent co, newtComponent subco);
Packit Service 8876fe
void newtFormRun(newtComponent co, struct newtExitStruct * es);
Packit Service 8876fe
</screen>
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
Packit Service 8876fe
<screen>
Packit Service 8876fe
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
Packit Service 8876fe
void newtFormSetBackground(newtComponent co, int color);
Packit Service 8876fe
void newtFormSetHeight(newtComponent co, int height);
Packit Service 8876fe
void newtFormSetWidth(newtComponent co, int width);
Packit Service 8876fe
</screen>
Packit Service 8876fe
</para>
Packit Service 8876fe
</sect3>
Packit Service 8876fe
</sect2>
Packit Service 8876fe
</sect1>
Packit Service 8876fe
</article>
Packit Service 8876fe