This chapter explains the numerous functions that enable you to do I/O under the ETI environment. It also covers the set of video attributes and options which can enhance ETI output with striking visual effects.
The routines that low-level ETI provides for writing to stdscr are similar to those provided by the stdio(3S) library for writing to a file. They let you
Following are descriptions and examples of these routines.
CAUTION: The ETI library provides its own set of output and input functions. You should not use other I/O routines or system calls, like printf(3S)and scanf(3S), in an ETI program. They may cause undesirable results when you run the program.
SYNOPSIS #include <curses.h> int addch(ch) chtype ch;
NOTES
EXAMPLE
#include <curses.h> main() { initscr(); addch('a'); refresh(); endwin(); }
The output from this program will appear as follows, with a in position 0, 0:
a $[]
See also the show program in Appendix D of this document.
SYNOPSIS #include <curses.h> int addstr(str) char *str;
NOTES
EXAMPLE
Recall the sample program that prints the character string BullsEye. See examples in Chapter 6, "Basic ETI Programming."
SYNOPSIS #include <curses.h> int printw (fmt [,arg...]) char *fmt
NOTES
EXAMPLE
#include <curses.h> main() { char* title = "Not specified"; int no = 0; /* Missing code. */ initscr(); /* Missing code. */ printw("%s is not in stock.\n", title); printw("Please ask the cashier to order %d for you.\n", no); refresh(); endwin(); }
The output from this program will appear as follows:
Not specified is not in stock. Please ask the cashier to order 0 for you. $[]
SYNOPSIS #include <curses.h> int move (y, x); int y, x;
NOTES
EXAMPLE
#include <curses.h> main() { initscr(); addstr("Cursor should be here --> if move() works."); printw("\n\n\n Press RETURN to end test."); move(0,25); refresh(); getch(); /* Gets RETURN; discussed below. */ endwin(); }
Here's the output generated by running this program:
Cursor should be here -->[]if move () works. Press RETURN to end test.
After you press RETURN, the screen looks like this:
Cursor should be here --> if move() works. Press RETURN to end test. $[]
See the scatter program in Appendix D of this document for another example using move().
SYNOPSIS #include <curses.h> int clear() int erase()
NOTES
SYNOPSIS #include <curses.h> int clrtoeol() int clrtobot()
NOTES
EXAMPLE
The following sample program uses clrtobot().
#include <curses.h> main() { initscr(); addstr("Press RETURN to delete from here to the end of the line and on."); addstr("\n Delete this too.\n And this."); move(0,30); refresh(); getch(); clrtobot(); refresh(); endwin(); }
Here's the output generated by running this program:
Press RETURN to delete from here[]to the end of the line and on. Delete this too. And this.
Notice the two calls to refresh(): one to send the full screen of text to a terminal, the other to clear from the position indicated to the bottom of a screen.
Here's what the screen looks like when you press RETURN:
Press RETURN to delete from here $[]
See the show and two programs in Appendix D of this document for other uses of clrtoeol().
Low-level ETI routines for reading from the current terminal are similar to those provided by the stdio(3S) library for reading from a file. They let you
The primary routine is getch(), which processes a single input character and then returns that character. This routine is like the C library routine getchar(), described on the getc(3S) manual page, except that it makes several terminal- or system-dependent options available that are not possible with getchar(). For example, you can use getch() with the ETI routine keypad(), which allows a low-level ETI program to interpret extra keys on a user's terminal, such as arrow keys, function keys, and other special keys that transmit escape sequences, and treat them as just another key. See the curs_inopts(3X) manual page for more information about keypad().
The following pages describe and give examples of the basic routines for getting input in a screen program.
SYNOPSIS #include <curses.h> int getch()
NOTES
EXAMPLE
#include <curses.h> main() { int ch; initscr(); cbreak(); /* Explained later in the section "Input Options" */ addstr("Press any character: "); refresh(); ch = getch(); printw("\n\n\n The character entered was a '%c'.\n", ch); refresh(); endwin(); }
The output from this program follows. The first refresh() sends the addstr() character string from stdscr to the terminal:
Press any character: []
Now assume that a w is typed at the keyboard. getch() accepts the character and assigns it to ch. Finally, the second refresh() is called and the screen appears as follows:
Press any character: w The character entered was a 'w'. $[]
For another example of getch(), see the show program in Appendix D, "ETI Program Examples" of this document.
SYNOPSIS #include <curses.h> int getstr(str) char *str;
NOTES
EXAMPLE
#include <curses.h> main() { char str [256]; initscr(); cbreak(); /*Explained later in the section "Input Options" */ addstr ("Enter a character string terminated by <CR>:\n\n"); refresh(); getstr(str); printw("\n\n\n The string entered was \n' %s' \n",str); refresh(); endwin(); }
Assume you entered the string 'I enjoy learning about the UNIX system'. The final screen (after entering RETURN) would appear as follows:
Enter a character string terminated by RETURN: I enjoy learning about the UNIX system. The string entered was 'I enjoy learning about the UNIX system.' $[]
SYNOPSIS #include <curses.h> int scanw(fmt [, arg...]) char *fmt;
NOTES
EXAMPLE
#include <curses.h> main() { char string[100]; float number; initscr(); cbreak(); /* Explained later in the */ echo(); /* section "Input Options" */ addstr("Enter a number and a string separated by a comma: "); refresh(); scanw("%f,%s",&number,string); clear(); printw("The string was \"%s\" and the number was %f., string,number); refresh(); endwin(); }
Notice the two calls to refresh(). The first call updates the screen with the character string passed to addstr(), the second with the string returned from scanw(). Also notice the call to clear(). Assume you entered the following when prompted: 2,twin. After running this program, your terminal screen would appear as follows:
The string was "twin" and the number was 2.000000. $[]
When we talked about addch(), we said that it writes a single character of the type chtype to stdscr. chtype has two parts: a part with information about the character itself and another part with information about a set of attributes associated with the character. The attributes allow a character to be printed in reverse video, bold, underlined, in colors and so on.
stdscr always has a set of current attributes that it associates with each character as it is written. However, using the routine attrset() and related ETI routines described below, you can change the current attributes. Below is a list of the attributes and what they mean:
(See "Color Manipulation" below for information on using colors.)
To use these attributes, you must pass them as arguments to attrset() and related routines; they can also be ORed with the bitwise OR (| ) to addch.
NOTE: Not all terminals are capable of displaying all attributes. If a particular terminal cannot display a requested attribute, an ETI program attempts to find a substitute attribute. If none is possible, the attribute is ignored.
Let's consider a use of one of these attributes. To display a word in bold, you would use the following code:
... <rintw("A word in "); attrset(A_BOLD); printw("boldface"); attrset(0); printw(" really stands out.\n"); ... refresh();
Attributes can be turned on singly, such as attrset (A_BOLD) in the example, or in combination. To turn on blinking bold text, for example, you would use attrset(A_BLINK|A_BOLD). Individual attributes can be turned on and off with the ETI routines attron() and attroff() without affecting other attributes. attrset(0) turns all attributes off.
Notice the attribute called A_STANDOUT. You might use it to make text attract the attention of a user. The particular hardware attribute used for standout is the most visually pleasing attribute a terminal has. Standout is typically implemented as reverse video or bold. Many programs don't really need a specific attribute, such as bold or reverse video, but instead just need to highlight some text. For such applications, the A_STANDOUT attribute is recommended. Two convenient functions, standout() and standend() can be used to turn on and off this attribute.standend(), in fact, turns off all attributes.
In addition to the attributes listed above, there are two bit masks called A_CHARTEXT and A_ATTRIBUTES. You can use these bit masks with the ETI function inch() and the C logical AND ( & ) operator to extract the character or attributes of a position on a terminal screen. See the discussion of inch() on the curses(3X) manual pages.
Following are descriptions of attrset() and the other ETI routines that you can use to manipulate attributes.
SYNOPSIS #include <curses.h> int attron( attrs ) chtype attrs; int attrset( attrs ) chtype attrs; int attroff( attrs ) chtype attrs;
NOTES
EXAMPLE
See the "The highlight Program" program in Appendix D of this document.
SYNOPSIS #include <curses.h> int standout() int standend()
NOTES
EXAMPLE
Again, see the "The highlight Program" program in Appendix D of this document.
The curses color manipulation routines allow you to use colors on an alphanumeric terminal as you would use any other video attribute. You can find out if the curses library on your system supports the color routines by checking the file /usr/include/curses.h to see if it defines the macro COLOR_PAIR(n).
This section begins with a description of the color feature at a general level. Then the use of color as an attribute is explained. Next, the ways to define color-pairs and change the definitions of colors is explained. Finally, there are guidelines for ensuring the portability of your program, and a section describing the color manipulation routines and macros, with examples.
Colors are always used in pairs, consisting of a foreground color (used for the character) and a background color (used for the field the character is displayed on). curses uses this concept of color-pairs to manipulate colors. In order to use color in a curses program, you must first define (initialize) the individual colors, then create color-pairs using those colors, and finally, use the color-pairs as attributes.
Actually, the process is even simpler, since curses maintains a table of initialized colors for you. This table has as many entries as the number of colors your terminal can display at one time. Each entry in the table has three fields: one each for the intensity of the red, green, and blue components in that color.
NOTE: curses uses RGB (Red, Green, Blue) color notation.This notation allows you to specify directly the intensity of red, green, and blue light to be generated in an additive system. Some terminals use an alternative notation, known as HSL (Hue, Saturation, Luminosity) color notation. Terminals that use HSL can be identified in the terminfo database, and curses will make conversions to RGB notation automatically.
At the beginning of any curses program that uses color, all entries in the colors table are initialized with eight basic colors, as shown in the following table.
The Default Colors Table
Intensity of Component | |||
( R)ed |
(G)reen |
(B)lue |
|
/* black: 0 */ |
0 |
0 |
0 |
/* red: 1 */ |
1000 |
0 |
0 |
/* green: 2 */ |
0 |
1000 |
0 |
/* yellow: 3 */ |
1000 |
1000 |
0 |
/* blue: 4 */ |
0 |
0 |
1000 |
/* magenta: 5 */ |
1000 |
0 |
1000 |
/* cyan: 6 */ |
0 |
1000 |
1000 |
/* white: 7 */ |
1000 |
1000 |
1000 |
Most color alphanumeric terminals can display eight colors at the same time, but if your terminal can display more than eight, then the table will have more than eight entries. The same eight colors will be used to initialize additional entries. If your terminal can display only N colors, where N is less than eight, then only the first N colors shown in the colors table will be used.
You can change these color definitions with the routine init_color(), if your terminal is capable of redefining colors. (See the section "Changing the Definitions of Colors" for more information.)
The following color macros are defined in curses.h and have numeric values corresponding to their position in the colors table.
COLOR_BLACK 0 COLOR_RED 1 COLOR_GREEN 2 COLOR_YELLOW 3 COLOR_BLUE 4 COLOR_MAGENTA 5 COLOR_CYAN 6 COLOR_WHITE 7
curses also maintains a table of color-pairs, which has space allocated for as many entries as the number of color-pairs that can be displayed on your terminal screen at the same time. Unlike the colors table, however, there are no default entries in the pairs table: it is your responsibility to initialize any color-pair you want to use, with init_pair(), before you use it as an attribute.
Each entry in the pairs table has two fields: the foreground color, and the background color. For each color-pair that you initialize, these two fields will each contain a number representing a color in the colors table. (Note that color-pairs can only be made from previously initialized colors.)
In the following figure, the pairs table shows that a programmer has used init_pair() to initialize color-pair 1 as a red foreground(entry 1 in the default color table) on cyan background (entry 6 in the default color table). Similarly, the programmer has initialized color-pair 2 as a yellow foreground on a magenta background. Not- initialized entries in the pairs table would actually contain zeros, which corresponds to black on black.
Note that color-pair 0 is reserved for use by curses and should not be changed or used in application programs.
Example of a Pairs Table
Color-Pair Number |
Foreground |
Background |
0 (reserved) |
0 |
0 |
1 |
1 |
6 |
2 |
3 |
5 |
3 |
0 |
0 |
4 |
0 |
0 |
5 |
0 |
0 |
.
|
.
|
.
|
Two global variables used by the color routines are defined in curses.h. They are COLORS, which contains the maximum number of colors the terminal supports, and COLOR_PAIRS, which contains the maximum number of color-pairs the terminal supports. Both are initialized by the start_color() routine to values it gets from the terminfo database.
Upon termination of your curses program, all colors and/or color-pairs will be restored to the values they had when the terminal was just turned on.
If you choose to use the default color definitions, there are only two things you need to do before you can use the attribute COLOR_PAIR(n). First, you must call the routine start_color(). Once you've done that, you can initialize color-pairs with the routine init_pair(pair, f, b). The first argument, pair, is the number of the color-pair to be initialized (or changed), and must be between 1 and COLOR_PAIRS-1. The arguments f and b are the foreground color number and the background color number. The value of these arguments must be between 0 and COLORS-1. For example, the two color-pairs in the pairs table described earlier can be initialized in the following way:
init_pair (1, COLOR_RED, COLOR_CYAN); init_pair (2, COLOR_YELLOW, COLOR_MAGENTA);
Once you've initialized a color-pair, the attribute COLOR_PAIR(n) can be used as you would use any other attribute. COLOR_PAIR(n) is a macro, defined in curses.h. The argument, n, is the number of a previously initialized color-pair. For example, you can use the routine attron to turn on a color-pair in addition to any other attributes you may currently have turned on:
attron() (COLOR_PAIR(1));
If you had initialized color-pair 1 in the way shown in the example pairs table, then characters displayed after you turned on color-pair 1 with attron() would be displayed as blue characters on a yellow background.
You can also combine COLOR_PAIR(n) with other attributes, for example:
attrset(A_BLINK|COLOR_PAIR(1));
would turn on blinking and whatever you have initialized color-pair 1 to be. (attron() and attrset() are described earlier in this chapter and also on the curses(3X) manual pages in this guide.
If your terminal is capable of redefining colors, you can change the predefined colors with the routine init_color(color, r, g, b). The first argument, color, is the numeric value of the color you want to change, and the last three, r, g, and b, are the intensities of the red, green, and blue components, respectively, that the new color will contain. Once you change the definition of a color, all occurrences of that color on your screen change immediately.
So, for example, you could change the definition of color 4 (COLOR_BLUE by default), to be light blue, in the following way.
init_color (COLOR_BLUE, 0, 700, 1000);
If your terminal is not able to change the definition of a color, use of init_color() returns ERR.
Like the rest of curses, the color manipulation routines have been designed to be terminal independent. But it must be remembered that the capabilities of terminals vary. For example, if you write a program for a terminal that can support 64 color-pairs, that program would not be able to produce the same color effects on a terminal that supports at most eight color-pairs.
When you are writing a program that may be used on different terminals, you should follow these guidelines:
Programs that follow this guideline will run on most color terminals. Only seven, not eight, color-pairs should be used, even though many terminals support eight color-pairs, because curses reserves color-pair 0 for its own use.
This is recommended because on some terminals, no matter what color you have defined it to be, color 0 will always be converted to black when used for a background.
Programs that follow this guideline will provide some sort of highlighting, even if the terminal is monochrome. On color terminals, as many of the listed attributes as possible would be used. On monochrome terminals, only the video attributes would be used, and the color attribute would be ignored.
Use the global variables COLORS and COLOR-PAIRS rather than constants when deciding how many colors or color-pairs your program should use.
There are two other macros defined in curses.h that you can use to obtain information from the color-pair field in characters of type chtype.
There are two color routines that give you information about the terminal your program is running on. The routine has_colors() returns a Boolean value: TRUE if the terminal supports colors, FALSE otherwise. The routine can_change_colors() also returns a Boolean value:TRUE if the terminal supports colors and can change their definitions, FALSE otherwise.
There are two color routines that give you information about the colors and color-pairs that are currently defined on your terminal. The routine color_content() gives you a way to find the intensity of the RGB components in an initialized color. It returns ERR if the color does not exist or if the terminal cannot change color definitions, OK otherwise. The routine pair_content() allows you to find out what colors a given color-pair consists of. It returns ERR is the color-pair has not been initialized, OK otherwise.
These routines are explained in more detail on the curses(3X) manual pages in this guide.
The routines start_color(), init_color(), and init_pair() are described on the following pages, with examples of their use. You can also refer to the program colors in Appendix D for an example of using the attribute of color in windows.
SYNOPSIS #include <curses.h> int start_color()
NOTES
EXAMPLE
See the example under init_pair().
SYNOPSIS #include <curses.h> init init_pair (pair, f, b) short pair, f, b;
NOTES
EXAMPLE
#include <curses.h> main() { initscr (); if (start_color () == OK) { init_pair (1, COLOR_RED, COLOR_GREEN); attron (COLOR_PAIR (1)); addstr ("Red on Green"); getch(); } endwin(); }
Also see the program colors in Appendix D of this document.
SYNOPSIS #include <curses.h> init init_color(color, r, g, b) short color, r, g, b;
NOTES
EXAMPLE
#include <curses.h> main() { initscr(); if (start_color() == OK) { init_pair (1, COLOR_RED, COLOR_GREEN); attron (COLOR_PAIR (1)); if (init_color (COLOR_RED, 0, 0, 1000) == OK) addstr ("BLUE ON GREEN"); else addstr ("RED ON GREEN"); getch (); } endwin(); }
Occasionally, you may want to get a user's attention. Two low-level ETI routines are designed to help you do this-they let you ring the terminal's chimes and flash its screen.
flash() flashes the screen if possible, and otherwise rings the bell. Flashing the screen is intended as a bell replacement, and is particularly useful if the bell bothers someone within ear shot of the user. The routine beep() can be called when a real beep is desired. (If for some reason the terminal is unable to beep, but able to flash, a call to beep() will flash the screen.)
SYNOPSIS #include <curses.h> int flash() int beep()
NOTES
The UNIX system does a considerable amount of processing on input before an application ever sees a character. For example, it does the following:
Because an ETI program maintains total control over the screen, low- level ETI turns off echoing on the UNIX system and does echoing itself. At times, you may not want the UNIX system to process other characters in the standard way in an interactive screen management program. Some ETI routines, noecho and cbreak(), for example, have been designed so that you can change the standard character processing. Using these routines in an application controls how input is interpreted. The following table shows some of the major routines for controlling input.
Every low-level ETI program accepting input should set some input options. This is because when the program starts running, the terminal on which it runs may be in cbreak(), raw(), nocbreak(), or noraw() mode. Although the low-level ETI program starts up in echo() mode, none of the other modes are guaranteed.
The combination of noecho() and cbreak() is most common in interactive screen management programs. Suppose, for instance, that you don't want the characters sent to your application program to be echoed wherever the cursor currently happens to be; instead, you want them echoed at the bottom of the screen. The ETI routine noecho() is designed for this purpose. However, when noecho() turns off echoing, normal erase and kill processing is still on. Using the routine cbreak() causes these characters to be uninterpreted.
Input Option Settings for ETI Programs
Characters | ||
Input Options |
Interpreted |
Uninterpreted |
Normal 'out of ETI state' |
interrupt, quit stripping <CR> to <NL> echoing erase, kill EOF | |
Normal ETI 'start up state' |
Echoing (simulated) |
All else undefined. |
cbreak() and echo() |
interrupt, quit stripping echoing |
Erase, kill EOF |
cbreak() and noecho() |
interrupt, quit stripping |
echoing erase, kill EOF |
nocbreak() and noecho() |
break, quit stripping erase, kill EOF |
echoing |
nocbreak() and echo() |
See caution below. | |
nl() |
<CR> to <NL> | |
nonl() |
<CR> to <NL> |
|
raw() (instead of cbreak()) |
break, quit stripping |
CAUTION: Do not use the combination nocbreak() and echo() . If you use it in a program and also use getch() , the program will go in and out of cbreak() mode to get each character. Depending on the state of the tty driver when each character is typed, the program may produce undesirable output.
In addition to the routines noted in the previous table, you can use the ETI routines noraw(), halfdelay(), and nodelay() to control input. See the curses(3X) manual pages for discussions of these routines.
The next few pages describe noecho(), cbreak(), and the related routines echo() and nocbreak() in more detail.
SYNOPSIS #include <curses.h> int echo() int noecho()
NOTES
EXAMPLE
See the "The editor Program" and "The show Program" programs in Appendix D of this document.
SYNOPSIS #include <curses.h> int cbreak() int nocbreak()
NOTES
EXAMPLE
See the "The editor Program" and "The show Program" programs in Appendix D of this document.