This document describes ncurses, a free implementation of the System V
curses API with some clearly marked extensions. It includes the
following System V curses features:
-
* Support for multiple screen highlights (BSD curses could only
handle one `standout' highlight, usually reverse-video).
* Support for line- and box-drawing using forms characters.
function names and parameters as mentioned above.
Here is a sample program to motivate the discussion:
-
#include <curses.h>
#include <signal.h>
static void finish(int sig);
+int
main(int argc, char *argv[])
{
+ int num = 0;
+
/* initialize your non-curses data structures here */
(void) signal(SIGINT, finish); /* arrange interrupts to terminate */
keypad(stdscr, TRUE); /* enable keyboard mapping */
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
(void) cbreak(); /* take input chars one at a time, no wait for \n */
- (void) noecho(); /* don't echo input */
+ (void) echo(); /* echo input - in color */
if (has_colors())
{
start_color();
/*
- * Simple color assignment, often all we need.
+ * Simple color assignment, often all we need. Color pair 0 cannot
+ * be redefined. This example uses the same value for the color
+ * pair as for the foreground color, though of course that is not
+ * necessary:
*/
- init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
- init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
- init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
- init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
- init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
- init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
- init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
- init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(1, COLOR_RED, COLOR_BLACK);
+ init_pair(2, COLOR_GREEN, COLOR_BLACK);
+ init_pair(3, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(4, COLOR_BLUE, COLOR_BLACK);
+ init_pair(5, COLOR_CYAN, COLOR_BLACK);
+ init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(7, COLOR_WHITE, COLOR_BLACK);
}
for (;;)
{
int c = getch(); /* refresh, accept single keystroke of input */
+ attrset(COLOR_PAIR(num % 8));
+ num++;
/* process the command keystroke */
}
The menu library calculates a minimum display size for your window,
based on the following variables:
-
* The number and maximum length of the menu items
* Whether the O_ROWMAJOR option is enabled
* Whether display of descriptions is enabled
Creating and Freeing Fields and Forms
The basic function for creating fields is new_field():
-
FIELD *new_field(int height, int width, /* new field size */
int top, int left, /* upper left corner */
int offscreen, /* number of offscreen rows */
position in the field plus a NUL terminator. The sixth argument is the
number of additional data buffers to allocate for the field; your
application can use them for its own purposes.
-
FIELD *dup_field(FIELD *field, /* field to copy */
int top, int left); /* location of new copy */
location. Size and buffering information are copied; some attribute
flags and status bits are not (see the form_field_new(3X) for
details).
-
FIELD *link_field(FIELD *field, /* field to copy */
int top, int left); /* location of new copy */
out-of-bounds arguments.
To connect fields to a form, use
-
FORM *new_form(FIELD **fields);
This function expects to see a NULL-terminated array of field
Fetching Size and Location Data
You can retrieve field sizes and locations through:
-
int field_info(FIELD *field, /* field from which to fetch */
int *height, *int width, /* field size */
int *top, int *left, /* upper left corner */
Changing the Field Location
It is possible to move a field's location on the screen:
-
int move_field(FIELD *field, /* field to alter */
int top, int left); /* new upper-left corner */
One-line fields may be unjustified, justified right, justified left,
or centered. Here is how you manipulate this attribute:
-
int set_field_just(FIELD *field, /* field to alter */
int justmode); /* mode to set */
This group of four field attributes controls the visual appearance of
the field on the screen, without affecting in any way the data in the
field buffer.
-
int set_field_fore(FIELD *field, /* field to alter */
chtype attr); /* attribute to set */
Every field has a status flag, which is set to FALSE when the field is
created and TRUE when the value in field buffer 0 changes. This flag
can be queried and set directly:
-
int set_field_status(FIELD *field, /* field to alter */
int status); /* mode to set */
Normally, a dynamic field is allowed to grow without limit. But it is
possible to set an upper limit on the size of a dynamic field. You do
it with this function:
-
int set_max_field(FIELD *field, /* field to alter (may not be NULL) */
int max_size); /* upper limit on field size */
and gives you the capability to define custom ones of your own. You
can examine and change field validation attributes with the following
functions:
-
int set_field_type(FIELD *field, /* field to alter */
FIELDTYPE *ftype, /* type to associate */
...); /* additional arguments*/
This field type accepts alphabetic data; no blanks, no digits, no
special characters (this is checked at character-entry time). It is
set up with:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_ALPHA, /* type to associate */
int width); /* maximum width of field */
This field type accepts alphabetic data and digits; no blanks, no
special characters (this is checked at character-entry time). It is
set up with:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_ALNUM, /* type to associate */
int width); /* maximum width of field */
This type allows you to restrict a field's values to be among a
specified set of string values (for example, the two-letter postal
codes for U.S. states). It is set up with:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_ENUM, /* type to associate */
char **valuelist; /* list of possible values */
TYPE_INTEGER
This field type accepts an integer. It is set up as follows:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_INTEGER, /* type to associate */
int padding, /* # places to zero-pad to */
TYPE_NUMERIC
This field type accepts a decimal number. It is set up as follows:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_NUMERIC, /* type to associate */
int padding, /* # places of precision */
This field type accepts data matching a regular expression. It is set
up as follows:
-
int set_field_type(FIELD *field, /* field to alter */
TYPE_REGEXP, /* type to associate */
char *regexp); /* expression to match */
The chief attribute of a field is its buffer contents. When a form has
been completed, your application usually needs to know the state of
each field buffer. You can find this out with:
-
char *field_buffer(FIELD *field, /* field to query */
int bufindex); /* number of buffer to query */
The principal attribute of a form is its field list. You can query and
change this list with:
-
int set_form_fields(FORM *form, /* form to alter */
FIELD **fields); /* fields to connect */
In order to declare your own frame window for a form, you'll need to
know the size of the form's bounding rectangle. You can get this
information with:
-
int scale_form(FORM *form, /* form to query */
int *rows, /* form rows */
int *cols); /* form cols */
It is possible to check from your application whether all of a
scrollable field is actually displayed within the menu subwindow. Use
these functions:
-
int data_ahead(FORM *form); /* form to be queried */
int data_behind(FORM *form); /* form to be queried */
Finally, there is a function to restore the form window's cursor to
the value expected by the forms driver:
-
int pos_form_cursor(FORM *) /* form to be queried */
If your application changes the form window cursor, call this function
The function form_driver() handles virtualized input requests for form
navigation, editing, and validation requests, just as menu_driver does
for menus (see the section on menu input handling).
-
int form_driver(FORM *form, /* form to pass input to */
int request); /* form request code */
It is possible to set function hooks to be executed whenever the
current field or form changes. Here are the functions that support
this:
-
typedef void (*HOOK)(); /* pointer to function returning void */
int set_form_init(FORM *form, /* form to alter */
focus for editing and viewing under control of your application, or
ask which field it currently is in. The following functions help you
accomplish this:
-
int set_current_field(FORM *form, /* form to alter */
FIELD *field); /* field to shift to */
first page. The function set_form_fields() resets this.
It is also possible to move around by pages.
-
int set_form_page(FORM *form, /* form to alter */
int page); /* page to go to (0-origin) */
Like fields, forms may have control option bits. They can be changed
or queried with these functions:
-
int set_form_opts(FORM *form, /* form to alter */
int attr); /* attribute to set */
The simplest way to create a custom data type is to compose it from
two preexisting ones:
-
FIELD *link_fieldtype(FIELDTYPE *type1,
FIELDTYPE *type2);
To create a field type from scratch, you need to specify one or both
of the following things:
-
* A character-validation function, to check each character as it is
entered.
* A field-validation function to be applied on exit from the field.
Here's how you do that:
-
typedef int (*HOOK)(); /* pointer to function returning int */
FIELDTYPE *new_fieldtype(HOOK f_validate, /* field validator */
and a pointer to the pile will be passed to the validation functions.
Here is how you make the association:
-
typedef char *(*PTRHOOK)(); /* pointer to function returning (char *) */
typedef void (*VOIDHOOK)(); /* pointer to function returning void */
way that TYPE_ENUM is. For such types, it is possible to define
successor and predecessor functions to support the REQ_NEXT_CHOICE and
REQ_PREV_CHOICE requests. Here's how:
-
typedef int (*INTHOOK)(); /* pointer to function returning int */
int set_fieldtype_arg(FIELDTYPE *type, /* type to alter */