Interface to the ncurses Library

In this chapter we describe the &GAP; interface to the `GNU` curses/ncurses C-library. This library contains routines to manipulate the contents of terminal windows. It allows one to write programs which should work on a wide variety of terminal emulations with different sets of capabilities.

This technical chapter is intended for readers who want to program new applications using the ncurses functionality. If you are only interested in the function from this package or some of its applications you can skip this chapter.

Detailed documentation of the ncurses library is probably available in your operating system (try man ncurses) and from the web (see for example ). Here, we only give short reminders about the functions provided in the &GAP; interface and explain how to use the &GAP; functions.

The ncurses Library

In this section we list the functions from the GNU ncurses library and its panel extension which are made available in &GAP; via the `Browse` package. See the following section for explanations how to use these functions from within &GAP;.

The basic objects to manipulate are called windows, they correspond to rectangular regions of the terminal screen. Windows can overlap but ncurses cannot handle this for the display. Therefore windows can be wrapped in panels, they provide a display depth for windows and it is possible to move panels to the top and bottom of the display or to hide a panel.

We will not import all the functions of the ncurses library to &GAP;. For example, there are many pairs of functions with the same name except for a leading w (like move and wmove for moving the cursor in a window). Here, we only import the versions with w, which get a window as first argument. The functions without w are for the ncurses standard screen window stdscr which is available as window 0 in &GAP;. Similarly, there are functions with the same name except for an extra n (like waddstr and waddnstr for placing a string into a window). Here, we only import the safer functions with n which get the number of characters to write as argument. (More convenient functions are then implemented on the &GAP; level.)

Setting the terminal

We first list flags for setting the basic behavior of a terminal. With savetty/resetty a setting can be stored and recovered.

savetty
savetty()
This stores the current setting of the terminal in a buffer.
resetty
resetty()
This resets the terminal to what was stored in the last call to savetty.
cbreak
nocbreak
cbreak()/nocbreak()
In cbreak mode each input character from a terminal is directly forwarded to the application (but see keypad). With nocbreak this only happens after a newline or return is typed.
keypad
keypad(win, bool)
If set to true some special input like arrow or function keys can be read as single characters from the input (such keys actually generate certain sequences of characters), see also . (The win argument is irrelevant.)
echo
noecho
echo()
/noecho()
This determines if input characters are automatically echoed by the terminal at the current cursor position.
curs_set
curs_set(vis)
This determines the visibility of the cursor. The argument vis=0 makes the cursor invisible. With vis=1 it becomes visible; some terminals allow also higher levels of visibility.
wtimeout
wtimeout(win, delay)
Here delay determines a timeout in milliseconds for reading characters from the input of a window. Negative values mean infinity, that is a blocking read.
nonl
nl
nl()
/nonl()
With nl a return on input is translated to a newline character and a newline on output is interpreted as return and linefeed.
intrflush
intrflush(win, bool)
This flag determines if after an interrupt pending output to the terminal is flushed. (The win argument is irrelevant.)
idlok
idlok(win, bool)
With true the library tries to use a hardware line insertion functionality (in particular for scrolling).
scrollok
scrollok(win, bool)
If set to true moving the cursor down from the last line of a window causes scrolling of the whole window, otherwise nothing happens.
leaveok
leaveok(win, bool)
If set to true a refresh of the window leaves the cursor at its current location, otherwise this is not guaranteed.
clearok
clearok(win, bool)
If set to true the next refresh of the window will clear the screen completely and redraw everything.
immedok
immedok(win, bool)
If set to true all changes of the window will automatically also call a wrefresh.
noraw
raw
raw()
/noraw()
Similar to cbreak, usually not needed (see the ncurses documentation for details).
Manipulating windows

In ncurses an arbitrary number of windows which correspond to rectangular regions (maybe overlapping) of the screen can be handled. You should always delete windows which are no longer needed. To get a proper display of overlapping windows (which may occur by recursively called functions using this library) we suggest that you always wrap windows in panels, see .

For functions which involve coordinates recall that the upper left corner of the screen or internally of any window has the coordinates (0,0). newwin newwin(nlines, ncols, y, x) This creates a new window whose upper left corner has the coordinates (y,x) on the screen and has nlines lines and ncols columns, if this is possible. The arguments nlines and ncols can be zero, then their maximal possible values are assumed. delwin delwin(win) Deletes a window. mvwin mvwin(win, y, x) Moves the upper left corner of the window to the given coordinates, if the window still fits on the screen. With panels don't use this function, but use move_panel mentioned below. wrefresh wrefresh(win) Writing to a window only changes some internal buffers, this function copies the window content to the actual display screen. You don't need this function if you wrap your windows in panels, use update_panels and doupdate instead. doupdate doupdate() Use this function to update the content of your display screen to the current content of all windows. If your terminal is not yet in visual mode this function changes to visual mode. endwin endwin() Use this function to leave the visual mode of your terminal. (Remark: If you use this function while not in visual mode the cursor will be moved to the line where the visual mode was started last time. To avoid this use isendwin first.) isendwin isendwin() Returns true if called while not in visual mode and false otherwise getbegyx getbegyx(win) Get the coordinates of the upper left corner of a window on the screen. getmaxyx getmaxyx(win) Get the number of lines and columns of a window.
Manipulating panels

Wrap windows in panels to get a proper handling of overlapping windows on the display. Don't forget to delete a panel before deleting the corresponding window.

new_panel
new_panel(win)
Create a panel for a window.
del_panel
del_panel(pan)
Delete a panel.
update_panels
update_panels()
Use this function to copy changes of windows and panels to a screen buffer. Then call doupdate() to update the display screen.
move_panel
move_panel(pan, y, x)
Move top left corner of a panel wrapped window to coordinates (y,x) if possible.
show_panel
hide_panel
hide_panel(pan)
/show_panel(pan)
Hide or show, respectively, the content of a panel on the display screen.
bottom_panel
top_panel
top_panel(pan)
/bottom_panel(pan)
Move a panel to the top or bottom of all panels, respectively.
panel_above
panel_below
panel_below(pan)
/panel_above(pan)
Return the panel directly below or above the given one, respectively. With argument 0 the top or bottom panel are returned, respectively. If argument is the bottom or top panel, respectively, then false is returned.
Getting keyboard input

If you want to read input from the user first adjust the terminal settings of cbreak, keypad, echo, wtimeout and curs_set to your needs, see . The basic functions are as follows.

wgetch
wgetch(win)
Reads one character from user input (returned as integer). If wtimeout was set with a positive delay then the function returns false if there was no input for delay milliseconds. Note that in nocbreak mode typed characters reach the application only after typing a return. If the keypad flag is set to true some special keys can be read like single characters; the keys are explained below. (Note that there is only one input queue for all windows.)
ungetch
ungetch(char)
Puts back the character char on the input queue.
NCurses.keys
Some terminals allow one to read special keys like one character, we import some of the symbolic names of such keys into &GAP;. You can check for such characters by comparing with the components of the record NCurses.keys, these are

UP
/DOWN/LEFT/RIGHT
the arrow keys
PPAGE
/NPAGE
the page up and page down keys
HOME
/END
the home and end keys
BACKSPACE
/DC
the backspace and delete keys
IC
the insert key
ENTER
the enter key
F1
/F2/../F24
the function keys
MOUSE
a pseudo key to detect mouse events
A1
/A3/B2/C1/C3
the keys around the arrow keys on a num pad
It can happen that on a specific keyboard there is no key for some of these. Also, not all terminals can interpret all of these keys. You can check this with the function

has_key
has_key(key)
Checks if the special key key is recognized by the terminal.
Writing to windows

The display of text in ncurses windows has two aspects. The first is to get actual characters on the screen. The second is to specify attributes which influence the display, for example normal or bold fonts or colors. This subsection is for the first aspect. Possible attributes are explained below in .

wmove
wmove(win, y, x)
Moves the cursor to position (y,x), recall that the coordinates are zero based, (0,0) being the top left corner.
waddnstr
waddnstr(win, str, len)
Writes the string str to the window starting from the current cursor position. Writes at most len characters. At end of line the cursor moves to the beginning of next line. The behavior at the end of the window depends on the setting of scrollok, see .
waddch
waddch(win, char)
Writes a character to the window at the current cursor position and moves the cursor on. The character char is given as integer and can include attribute information.
wborder
wborder(win, charlist)
Draws a border around the window. If charlist is a plain list of eight &GAP; characters these are taken for left/right/top/bottom sides and top-left/top-right/bottom-left/bottom-right corners. Otherwise default characters are used. (See for a more user friendly interface.)
wvline
wvline(win, char, len)
Writes a vertical line of length len (or as long as fitting into the window) starting from the current cursor position to the bottom, using the character char. If char=0 the default character is used.
whline
whline(win, char, len)
Same as wvline but for horizontal lines starting from the cursor position to the right.
werase
werase(win)
Deletes all characters in the window.
wclear
wclear(win)
Like werase, but also calls clearok.
wclrtobot
wclrtobot(win)
Deletes all characters from cursor position to the right and bottom.
wclrtoeol
wclrtoeol(win)
Deletes all characters from cursor position to end of line.
winch
winch(win)
Returns the character at current cursor position, as integer and including color and attribute information.
getyx
getyx(win)
Returns the current cursor position.
waddstr
waddstr(win, str)
Delegates to waddnstr(win, str, Length(str)).
Line drawing characters
NCurses.lineDraw
For drawing lines and grids in a terminal window you should use some "virtual" characters which are available as components of the record NCurses.lineDraw. On some terminals these are nicely displayed as proper lines (on others they are simulated by ASCII characters). These are:

BLOCK
solid block
BOARD
board of squares
BTEE/LTEE/RTEE/TTEE
bottom/left/right/top tee
BULLET
bullet
CKBOARD
checker board
DARROW/LARROW/RARROW/UARROW
down/left/right/up arrow
DEGREE
degree symbol
DIAMOND
diamond
GEQUAL
greater than or equal
HLINE/VLINE
horizontal/vertical line
LANTERN
lantern symbol
LEQUAL
less than or equal
LLCORNER/LRCORNER/ULCORNER/URCORNER
lower left/lower right/upper left/upper right corner
NEQUAL
not equal
PI
letter pi
PLMINUS
plus-minus
PLUS
crossing lines like a plus
S1/S3/S7/S9
scan line 1/3/7/9
STERLING
pound sterling
Text attributes and colors

In addition to the actual characters to be written to the screen the way they are displayed can be changed by additional attributes. attributes of text (There should be no danger to mix up this notion of attributes with the one introduced in .)

NCurses.attrs
The available attributes are stored in the record NCurses.attrs, they are NORMAL normal display with no extra attributes. STANDOUT displays text in the best highlighting mode of the terminal. UNDERLINE underlines the text. REVERSE display in reverse video by exchanging the foreground and background color. BLINK displays the text blinking. DIM displays the text half bright. BOLD displays the text in a bold font.

Note that not all of these work with all types of terminals, or some may cause the same display.

Furthermore, if NCurses.attrs.has_colors is true there is a list NCurses.attrs.ColorPairs of attributes to set the foreground and background color. These should be accessed indirectly with . Attributes can be combined by adding their values (internally, they are represented by integers). They can also be added to the integer representing a character for use with waddch.

The library functions for setting attributes are:

wattrset
wattrset(win, attr)
This sets the default (combined) attributes for a window which is added to all characters written to it; using NCurses.attrs.NORMAL as attribute is a reset.
wattroff
wattron
wattron(win, attr)
/wattroff(win, attr)
This sets or unsets one or some default attributes of the window without changing the others.
wattr_get
wattr_get(win)
This returns the current default attribute and default color pair of a window.
wbkgdset
wbkgdset(win, attr)
This is similar to wattrset but you can also add a character to attr which is used as default instead of blanks.
wbkgd
wbkgd(win, attr)
This function changes the attributes for all characters in the window to attr, also used for further characters written to that window.
Low level ncurses mouse support
Many xterm based terminals support mouse events. The recognition of mouse events by the ncurses input queue can be switched on and off. If switched on and a mouse event occurs, then NCurses.wgetch gets NCurses.keys.MOUSE if the keypad flag is true (see ). If this is read one must call NCurses.getmouse which reads further characters from the input queue and interprets them as details on the mouse event. In most cases the function can be used in applications (it calls NCurses.getmouse). The following low level functions are available as components of the record NCurses.

The names of mouse events which may be possible are stored in the list NCurses.mouseEvents, which starts [ "BUTTON1_PRESSED", "BUTTON1_RELEASED", "BUTTON1_CLICKED", "BUTTON1_DOUBLE_CLICKED", "BUTTON1_TRIPLE_CLICKED", ... and contains the same for buttons number 2 to 5 and a few other events.

mousemask
mousemask(intlist)
The argument intlist is a list of integers specifying mouse events. An entry i refers to the event described in NCurses.mouseEvents[i+1]. It returns a record with components .new (for the current setting) and .old (for the previous setting) which are again lists of integers with the same meaning. Note that .new may be different from intlist, it is always the empty list if the terminal does not support mouse events. In applications use instead of this low level function.
getmouse
getmouse()
This function must be called after a key NCurses.keys.MOUSE was read. It returns a list with three entries [y, x, intlist] where y and x are the coordinates of the character cell where the mouse event occured and intlist describes the event, it should have length one and refers to a position in NCurses.mouseEvents.
wenclose
wenclose(win, y, x)
This functions returns true if the screen position y, x is within window win and false otherwise.
mouseinterval
mouseinterval(t)
Sets the time to recognize a press and release of a mouse button as a click to t milliseconds. (Note that this may have no effect because a window manager may catch this.)
Miscellaneous function
mnap
IsStdinATty
IsStdoutATty
We also provide the ncurses function mnap(msec) which is a sleep for msec milliseconds.

Furthermore, there a two utilities which can be useful for scripts and testing, namely a check if standard input or standard output are connected to terminals. These can be called as NCurses.IsStdinATty() or NCurses.IsStdoutATty(), respectively.
The ncurses &GAP; functions

The functions of the ncurses library are used within &GAP; very similarly to their C equivalents. The functions are available as components of a record NCurses with the name of the C function (e.g., NCurses.newwin).

In &GAP; the ncurses windows are accessed via integers (as returned by NCurses.newwin). The standard screen stdscr from the ncurses library is available as window number 0. But this should not be used; to allow recursive applications of ncurses always create a new window, wrap it in a panel and delete both when they are no longer needed.

Each window can be wrapped in one panel which is accessed by the same integer. (Window 0 cannot be used with a panel.)

Coordinates in windows are the same zero based integers as in the corresponding C functions. The interface of functions which return coordinates is slightly different from the C version; they just return lists of integers and you just give the window as argument, e.g., NCurses.getmaxyx(win) returns a list [nrows, ncols] of two integers.

Characters to be written to a window can be given either as &GAP; characters like 'a' or as integers like INT_CHAR('a') = 97. If you use the integer version you can also add attributes including color settings to it for use with NCurses.waddch.

When writing an application decide about an appropriate terminal setting for your visual mode windows, see and the utility function below. Use NCurses.savetty() and NCurses.resetty() to save and restore the previous setting.

We also provide some higher level functionality for displaying marked up text, see and .

We now describe some utility functions for putting text on a terminal window.

<#Include Label="NCurses.ColorAttr">

<#Include Label="NCurses.SetTerm">

<#Include Label="IsAttributeLine_man">

<#Include Label="ConcatenationAttributeLines_man">

<#Include Label="RepeatedAttributeLine_man">

<#Include Label="NCurses.PutLine">

<#Include Label="NCurses.WidthAttributeLine">

<#Include Label="NCurses.Grid">

<#Include Label="NCurses.WBorder">

<#Include Label="NCurses.Mouse">

<#Include Label="NCurses.SaveRestoreWin">