Newt
FunctionsWhile most newt
functions are concerned with widgets or groups
of widgets (called grids and forms), some parts of the newt
API
deal with more global issues, such as initializing newt
or writing
to the root window.
newt
Services
There are three functions which nearly every newt
application use. The
first two are used to initialize the system.
int newtInit(void); void newtCls(void);
newtInit()
should be the first function called by every newt
program. It initializes internal data structures and places the terminal
in raw mode. Most applications invoke newtCls()
immediately after
newtInit()
, which causes the screen to be cleared. It's not
necessary to call newtCls()
to use any of newt
's features, but
doing so will normally give a much neater appearance.
When a newt
program is ready to exit, it should call newtFinished()
.
int newtFinished(void);
newtFinished()
restores the terminal to its appearance when
newtInit()
was called (if possible -- on some terminals the cursor will
be moved to the bottom, but it won't be possible to remember the original
terminal contents) and places the terminal in its original input state.
If this function isn't called, the terminal will probably need to be
reset with the reset
command before it can be used easily.
Normally, newt
programs don't read input directly from the
user. Instead, they let newt
read the input and hand it to the
program in a semi-digested form. Newt
does provide a couple of simple
functions which give programs (a bit of) control over the terminal.
void newtWaitForKey(void); void newtClearKeyBuffer(void);
The first of these, newtWaitForKey()
, doesn't return until a key
has been pressed. The keystroke is then ignored. If a key is already in
the terminal's buffer, newtWaitForKey()
discards a keystroke and
returns immediately.
newtClearKeyBuffer()
discards the contents of the terminal's input
buffer without waiting for additional input.
The background of the terminal's display (the part without any windows
covering it) is known as the root window (it's the parent of all
windows, just like the system's root directory is the parent of all
subdirectories). Normally, applications don't use the root window, instead
drawing all of their text inside of windows (newt
doesn't require
this though -- widgets may be placed directly on the root window without
difficulty). It is often desirable to display some text, such as a
program's name or copyright information, on the root window, however.
Newt
provides two ways of displaying text on the root window. These
functions may be called at any time. They are the only newt
functions
which are meant to write outside of the current window.
void newtDrawRootText(int left, int top, const char * text);
This function is straightforward. It displays the string text
at
the position indicated. If either the left
or top
is
negative, the position is measured from the opposite side of the
screen. The final measurement will seem to be off by one though. For
example, a top
of -1 indicates the last line on the screen, and
one of -2 is the line above that.
As it's common to use the last line on the screen to display help information,
newt
includes special support for doing exactly that. The last
line on the display is known as the help line, and is treated as a
stack. As the value of the help line normally relates to the window
currently displayed, using the same structure for window order and the
help line is very natural. Two functions are provided to manipulate the
help line.
void newtPushHelpLine(const char * text); void newtPopHelpLine(void);
The first function, newtPushHelpLine()
, saves the current help line
on a stack (which is independent of the window stack) and displays the
new line. If text
is NULL
, newt
's default help line is
displayed (which provides basic instructions on using newt
). If
text
is a string of length 0, the help line is cleared. For all
other values of text
, the passed string is displayed at the bottom,
left-hand corner of the display. The space between the end of the displayed
string the the right-hand edge of the terminal is cleared.
newtPopHelpLine()
replaces the current help line with the one it
replaced. It's important not to call tt/newtPopHelpLine()/ more then
newtPushHelpLine()
!
Suspending Newt Applications
By default, newt
programs cannot be suspended by the user (compare
this to most Unix programs which can be suspended by pressing the suspend
key (normally ^Z
). Instead, programs can specify a callback
function which gets invoked when the user presses the suspend key.
typedef void (*newtSuspendCallback)(void); void newtSetSuspendCallback(newtSuspendCallback cb);
The suspend function neither expects nor returns any value, and can do whatever it likes to when it is invoked. If no suspend callback is registered, the suspend keystroke is ignored.
If the application should suspend and continue like most user applications,
the suspend callback needs two other newt
functions.
void newtSuspend(void); void newtResume(void);
newtSuspend()
tells newt
to return the terminal to its initial
state. Once this is done, the application can suspend itself (by
sending itself a SIGTSTP
, fork a child program, or do whatever
else it likes. When it wants to resume using the newt
interface,
it must call newtResume
before doing so.
Note that suspend callbacks are not signal handlers. When newtInit()
takes over the terminal, it disables the part of the terminal interface
which sends the suspend signal. Instead, if newt
sees the suspend
keystroke during normal input processing, it immediately calls the suspend
callback if one has been set. This means that suspending newt applications
is not asynchronous.
To increase performance, S-Lang only updates the display when it needs
to, not when the program tells S-Lang to write to the terminal. ``When it
needs to'' is implemented as ``right before the we wait for the user to
press a key''. While this allows for optimized screen displays most of
the time, this optimization makes things difficult for programs which
want to display progress messages without forcing the user to input
characters. Applications can force S-Lang to immediately update modified
portions of the screen by calling newtRefresh
.
The program wants to display a progress message, without forcing for the user to enter any characters.
A misfeature of the program causes part of the screen to be corrupted. Ideally, the program would be fixed, but that may not always be practical.
As always, some function defy characterization. Two of newt
's general
function fit this oddball category.
void newtBell(void); void newtGetScreenSize(int * cols, int * rows);
The first sends a beep to the terminal. Depending on the terminal's
settings, this been may or may not be audible. The second function,
newtGetScreenSize()
, fills in the passed pointers with the
current size of the terminal.
newt
Example
To help illustrate the functions presented in this section here is a short
sample newt
program which uses many of them. While it doesn't do
anything interesting, it does show the basic structure of newt
programs.
#include <newt.h> #include <stdlib.h> int main(void) { newtInit(); newtCls(); newtDrawRootText(0, 0, "Some root text"); newtDrawRootText(-25, -2, "Root text in the other corner"); newtPushHelpLine(NULL); newtRefresh(); sleep(1); newtPushHelpLine("A help line"); newtRefresh(); sleep(1); newtPopHelpLine(); newtRefresh(); sleep(1); newtFinished(); }