Goto Chapter: Top 1 2 3 4 5 6 Bib Ind
Top of Book Previous Chapter Next Chapter

2. Interface to the `ncurses` Library
2.1 The `ncurses` Library
2.1-1 Setting the terminal
2.1-2 Manipulating windows
2.1-3 Manipulating panels
2.1-4 Getting keyboard input
2.1-5 Writing to windows
2.1-6 Line drawing characters
2.1-7 Text attributes and colors
2.1-8 Miscellaneous function
2.2 The `ncurses` GAP functions
2.2-1 NCurses.ColorAttr
2.2-2 NCurses.SetTerm
2.2-3 NCurses.IsAttributeLine
2.2-4 NCurses.ConcatenationAttributeLines
2.2-5 NCurses.RepeatedAttributeLine
2.2-6 NCurses.PutLine
2.2-7 NCurses.WidthAttributeLine
2.2-8 NCurses.Grid
2.2-9 NCurses.WBorder
2.2-10 NCurses.SaveWin

### 2. 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 `NCurses.BrowseGeneric` (4.3-1) 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 [NOAUTHOROREDITOR_SPECIFYKEYb]). Here, we only give short reminders about the functions provided in the GAP interface and explain how to use the GAP functions.

#### 2.1 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 2.2 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.)

##### 2.1-1 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()`

  This stores the current setting of the terminal in a buffer.

`resetty()`

  This resets the terminal to what was stored in the last call to `savetty`.

`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(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 2.1-4. (The win argument is irrelevant.)

`echo()`/`noecho()`

  This determines if input characters are automatically echoed by the terminal at the current cursor position.

`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(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.

`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(win, bool)`

  This flag determines if after an interrupt pending output to the terminal is flushed. (The win argument is irrelevant.)

`idlok(win, bool)`

  With `true` the library tries to use a hardware line insertion functionality (in particular for scrolling).

`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(win, bool)`

  If set to `true` a refresh of the window leaves the cursor at its current location, otherwise this is not guaranteed.

`clearok(win, bool)`

  If set to `true` the next refresh of the window will clear the screen completely and redraw everything.

`immedok(win, bool)`

  If set to `true` all changes of the window will automatically also call a `wrefresh`.

`raw()`/`noraw()`

  Similar to `cbreak`, usually not needed (see the `ncurses` documentation for details).

##### 2.1-2 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 2.1-3.

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(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(win)`

  Deletes a window.

`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(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()`

  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()`

  Use this function to leave the visual mode of your terminal.

`getbegyx(win)`

  Get the coordinates of the upper left corner of a window on the screen.

`getmaxyx(win)`

  Get the number of lines and columns of a window.

##### 2.1-3 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(win)`

  Create a panel for a window.

`del_panel(pan)`

  Delete a panel.

`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(pan, y, x)`

  Move top left corner of a panel wrapped window to coordinates (y,x) if possible.

`hide_panel(pan)`/`show_panel(pan)`

  Hide or show, respectively, the content of a panel on the display screen.

`top_panel(pan)`/`bottom_panel(pan)`

  Move a panel to the top or bottom of all panels, respectively.

`panel_below(pan)`/`panel_above(pan)`

  Return the panel directly below or above the given one, respectively.

##### 2.1-4 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 2.1-1. The basic functions are as follows.

`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(char)`

  Puts back the character char on the input queue.

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(key)`

  Checks if the special key key is recognized by the terminal.

##### 2.1-5 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 2.1-7.

`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(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 2.1-1.

`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(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 `NCurses.WBorder` (2.2-9) for a more user friendly interface.)

`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(win, char, len)`

  Same as `wvline` but for horizontal lines starting from the cursor position to the right.

`werase(win)`

  Deletes all characters in the window.

`wclear(win)`

  Like `werase`, but also calls `clearok`.

`wclrtobot(win)`

  Deletes all characters from cursor position to the right and bottom.

`wclrtoeol(win)`

  Deletes all characters from cursor position to end of line.

`winch(win)`

  Returns the character at current cursor position, as integer and including color and attribute information.

`getyx(win)`

  Returns the current cursor position.

`waddstr(win, str)`

  Delegates to `waddnstr(win, str, Length(str))`.

##### 2.1-6 Line drawing characters

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

##### 2.1-7 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. (There should be no danger to mix up this notion of attributes with the one introduced in Reference: Attributes.) 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 `NCurses.ColorAttr` (2.2-1). 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(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.

`wattron(win, attr)`/`wattroff(win, attr)`

  This sets or unsets one or some default attributes of the window without changing the others.

`wattr_get(win)`

  This returns the current default attribute and default color pair of a window.

`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(win, attr)`

  This function changes the attributes for all characters in the window to attr, also used for further characters written to that window.

##### 2.1-8 Miscellaneous function

We also provide the `ncurses` function `mnap(msec)` which is a sleep for msec milliseconds.

#### 2.2 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 2.1-1 and the utility function `NCurses.SetTerm` (2.2-2) 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 `NCurses.PutLine` (2.2-6) and `NCurses.IsAttributeLine` (2.2-3).

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

##### 2.2-1 NCurses.ColorAttr

`> NCurses.ColorAttr`( fgcolor, bgcolor ) | ( function )

Returns: an attribute for setting the foreground and background color to be used on a terminal window (it is a GAP integer).

`> NCurses.attrs.has_colors` | ( global variable )

The return value can be used like any other attribute as described in 2.1-7. The arguments fgcolor and bgcolor can be given as strings, allowed are those in `[ "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" ]`. These are the default foreground colors 0 to 7 on ANSI terminals. Alternatively, the numbers 0 to 7 can be used directly as arguments.

Note that terminals can be configured in a way such that these named colors are not the colors which are actually displayed.

The variable `NCurses.attrs.has_colors` is set to `true` or `false` if the terminal supports colors or not, respectively. If a terminal does not support colors then `NCurses.ColorAttr` always returns `NCurses.attrs.NORMAL`.

For an attribute setting the foreground color with the default background color of the terminal use `-1` as bgcolor or the same as fgcolor.

    gap> win := NCurses.newwin(0,0,0,0);; pan := NCurses.new_panel(win);;
    gap> defc := NCurses.defaultColors;;
    gap> NCurses.wmove(win, 0, 0);;
    gap> for a in defc do for b in defc do
    >      NCurses.wattrset(win, NCurses.ColorAttr(a, b));
    >      NCurses.waddstr(win, Concatenation(a,"/",b,"\t"));
    >    od; od;
    gap> NCurses.update_panels();; NCurses.doupdate();;
    gap> NCurses.napms(5000); # show for 5 seconds
    gap> NCurses.endwin();; NCurses.del_panel(pan);; NCurses.delwin(win);;

##### 2.2-2 NCurses.SetTerm

`> NCurses.SetTerm`( [record] ) | ( function )

This function provides a unified interface to the various terminal setting functions of `ncurses` listed in 2.1-1. The optional argument is a record with components which are assigned to `true` or `false`. Recognised components are: `cbreak`, `echo`, `nl`, `intrflush`, `leaveok`, `scrollok`, `keypad`, `raw` (with the obvious meaning if set to `true` or `false`, respectively).

The default, if no argument is given, is `rec(cbreak := true, echo := false, nl := false, intrflush := false, leaveok := true, scrollok := false, keypad := true)`. (This is a useful setting for many applications.) If there is an argument record, then the given components overwrite the corresponding defaults.

##### 2.2-3 NCurses.IsAttributeLine

`> NCurses.IsAttributeLine`( obj ) | ( function )

Returns: `true` if the argument describes a string with attributes.

An attribute line describes a string with attributes. It is represented by either a string or a dense list of strings, integers, and Booleans immediately following integers, where at least one list entry must not be a string. (The reason is that we want to be able to distinguish between an attribute line and a list of such lines, and that the case of plain strings is perhaps the most usual one, so we do not want to force wrapping each string in a list.) The integers denote attribute values such as color or font information, the Booleans denote that the attribute given by the preceding integer is set or reset.

If an integer is not followed by a Boolean then it is used as the attribute for the following characters, that is it overwrites all previously set attributes. Note that in some applications the variant with explicit Boolean values is preferable, because such a line can nicely be highlighted just by prepending a `NCurses.attrs.STANDOUT` attribute.

For an overview of attributes, see 2.1-7.

    gap> NCurses.IsAttributeLine( "abc" );
    true
    gap> NCurses.IsAttributeLine( [ "abc", "def" ] );
    false
    gap> NCurses.IsAttributeLine( [ NCurses.attrs.UNDERLINE, true, "abc" ] );
    true
    gap> NCurses.IsAttributeLine( "" );  NCurses.IsAttributeLine( [] );
    true
    false

The empty string is an attribute line whereas the empty list (which is not in `IsStringRep`, see `IsStringRep` (Reference: IsStringRep)) is not an attribute line.

##### 2.2-4 NCurses.ConcatenationAttributeLines

`> NCurses.ConcatenationAttributeLines`( lines[, keep] ) | ( function )

Returns: an attribute line.

For a list lines of attribute lines (see `NCurses.IsAttributeLine` (2.2-3)), `NCurses.ConcatenationAttributeLines` returns the attribute line obtained by concatenating the attribute lines in lines.

If the optional argument keep is `true` then attributes set in an entry of lines are valid also for the following entries of lines. Otherwise (in particular if there is no second argument) the attributes are reset to `NCurses.attrs.NORMAL` between the entries of lines.

    gap> plain_str:= "hello";;
    gap> with_attr:= [ NCurses.attrs.BOLD, "bold" ];;
    gap> NCurses.ConcatenationAttributeLines( [ plain_str, plain_str ] );
    "hellohello"
    gap> NCurses.ConcatenationAttributeLines( [ plain_str, with_attr ] );
    [ "hello", 2097152, "bold" ]
    gap> NCurses.ConcatenationAttributeLines( [ with_attr, plain_str ] );
    [ 2097152, "bold", 0, "hello" ]
    gap> NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ] );
    [ 2097152, "bold", 0, 2097152, "bold" ]
    gap> NCurses.ConcatenationAttributeLines( [ with_attr, with_attr ], true );
    [ 2097152, "bold", 2097152, "bold" ]

##### 2.2-5 NCurses.RepeatedAttributeLine

`> NCurses.RepeatedAttributeLine`( line, width ) | ( function )

Returns: an attribute line.

For an attribute line line (see `NCurses.IsAttributeLine` (2.2-3)) and a positive integer width, `NCurses.RepeatedAttributeLine` returns an attribute line with width displayed characters (see `NCurses.WidthAttributeLine` (2.2-7)) that is obtained by concatenating sufficiently many copies of line and cutting off a tail if applicable.

    gap> NCurses.RepeatedAttributeLine( "12345", 23 );
    "12345123451234512345123"
    gap> NCurses.RepeatedAttributeLine( [ NCurses.attrs.BOLD, "12345" ], 13 );
    [ 2097152, "12345", 0, 2097152, "12345", 0, 2097152, "123" ]

##### 2.2-6 NCurses.PutLine

`> NCurses.PutLine`( win, y, x, lines[, skip] ) | ( function )

Returns: `true` if lines were written, otherwise `false`.

The argument lines can be a list of attribute lines (see `NCurses.IsAttributeLine` (2.2-3)) or a single attribute line. This function writes the attribute lines to window win at and below of position y, x.

If the argument skip is given, it must be a nonnegative integer. In that case the first skip characters of each given line are not written to the window (but the attributes are).

##### 2.2-7 NCurses.WidthAttributeLine

`> NCurses.WidthAttributeLine`( line ) | ( function )

Returns: number of displayed characters in an attribute line.

For an attribute line line (see `NCurses.IsAttributeLine` (2.2-3)), the function returns the number of displayed characters of line.

    gap> NCurses.WidthAttributeLine( "abcde" );
    5
    gap> NCurses.WidthAttributeLine( [ NCurses.attrs.BOLD, "abc",
    >        NCurses.attrs.NORMAL, "de" ] );
    5

##### 2.2-8 NCurses.Grid

`> NCurses.Grid`( win, trow, brow, lcol, rcol, rowinds, colinds ) | ( function )

This function draws a grid of horizontal and vertical lines on the window win, using the line drawing characters explained in 2.1-6. The given arguments specify the top and bottom row of the grid, its left and right column, and lists of row and column numbers where lines should be drawn.

    gap> fun := function() local win, pan;
    >      win := NCurses.newwin(0,0,0,0);
    >      pan := NCurses.new_panel(win);
    >      NCurses.Grid(win, 2, 11, 5, 22, [5, 6], [13, 14]);
    >      NCurses.PutLine(win, 12, 0, "Press <Enter> to quit");
    >      NCurses.update_panels(); NCurses.doupdate();
    >      NCurses.wgetch(win);
    >      NCurses.endwin();
    >      NCurses.del_panel(pan); NCurses.delwin(win);
    > end;;
    gap> fun();

##### 2.2-9 NCurses.WBorder

`> NCurses.WBorder`( win[, chars] ) | ( function )

This is a convenient interface to the `ncurses` function `wborder`. It draws a border around the window win. If no second argument is given the default line drawing characters are used, see 2.1-6. Otherwise, chars must be a list of GAP characters or integers specifying characters, possibly with attributes. If chars has length 8 the characters are used for the left/right/top/bottom sides and top-left/top-right/bottom-left/bottom-right corners. If chars contains 2 characters the first is used for the sides and the second for all corners. If chars contains just one character it is used for all sides including the corners.

##### 2.2-10 NCurses.SaveWin

`> NCurses.SaveWin`( win ) | ( function )

`> NCurses.StringsSaveWin`( cont ) | ( function )

`> NCurses.RestoreWin`( win, cont ) | ( function )

`> NCurses.ShowSaveWin`( cont ) | ( function )

Returns: a GAP object describing the contents of a window.

These functions can be used to save and restore the contents of `ncurses` windows. `NCurses.SaveWin` returns a list `[nrows, ncols, chars]` giving the number of rows, number of columns, and a list of integers describing the content of window win. The integers in the latter contain the displayed characters plus the attributes for the display.

The function `NCurses.StringsSaveWin` translates data cont in form of the output of `NCurses.SaveWin` to a list of `nrows` strings giving the text of the rows of the saved window, and ignoring the attributes. You can view the result with `NCurses.Pager` (3.1-4).

The argument cont for `NCurses.RestoreWin` must be of the same format as the output of `NCurses.SaveWin`. The content of the saved window is copied to the window win, starting from the top-left corner as much as it fits.

The utility `NCurses.ShowSaveWin` can be used to display the output of `NCurses.SaveWin` (as much of the top-left corner as fits on the screen).

Top of Book Previous Chapter Next Chapter
Goto Chapter: Top 1 2 3 4 5 6 Bib Ind

generated by GAPDoc2HTML