|
CS 256 - Principles of Structured Design
Summer 2021
| Video Attributes:
Each character can have one or more attributes associated with it, these
include:
Name |
Description |
A_NORMAL |
Normal display (no highlight) |
A_STANDOUT |
Best highlighting mode of the terminal. |
A_UNDERLINE |
Underlining |
A_REVERSE |
Reverse video |
A_BLINK |
Blinking |
A_DIM |
Half bright |
A_BOLD |
Extra bright or bold |
A_PROTECT |
Protected mode |
A_INVIS |
Invisible or blank mode |
A_ALTCHARSET |
Alternate character set |
A_ITALIC |
Italics |
Attributes can be turned on or off using:
int attron(int attrs);
- Turns on the attributes given by attrs
int attroff(int attrs);
- Turns off the attributes given by attrs
int attrset(int attrs);
attrset(A_BOLD | A_UNDERLINE);
printw("Highlighted and underlined");
// Back to normal:
attrset(A_NORMAL);
Attributes can be applied directly to a character when using addch() or
mvaddch(), ex:
// Adds an x to the screen that is both bold and underlined.
addch('x' | A_BOLD | A_UNDERLINE);
An aside about the binary OR operator
The Binary OR operator or single vertical bar (| ) logically ORs all the binary
bits both the left and right operands together, the result being where each
bit in the result is a 1 (i.e. set) if the same bit in either the left or
right operand has the same bit set to a 1 and will be 0 (zero) if neither
the left or right operand has that bit set.
Example:
153 | 77 == 221 (decimal)
10011001 (153 in binary)
| 01001101 ( 77 in binary)
──────────
11011101 (221 in binary)
For the purposes of curses programming (and in many other C programming
circumstances,) it is enough to think of the binary OR operator as being
addition (in fact, + is sometimes used as the OR operation in Boolean
algebra,) and often addition could be used in lieu of binary OR. In our case
we want to add one or more attributes to a character, so we use the binary
OR operator when doing so.
The alternate character-set
In curses we can use some semi-graphical characters, known as the
Alternate Character Set (ACS) characters. Such characters can only be added
to the screen using the *addch() functions or by setting the A_ALTCHARSET
attribute before . The characters are referred to by their ACS name, a table
of which is shown here.
ACS Name |
Rendered character |
Description |
ACS_BTEE |
┴ |
bottom tee |
ACS_BULLET |
· |
bullet |
ACS_CKBOARD |
▒ |
checker board (stipple) |
ACS_DARROW |
v |
arrow pointing down |
ACS_DEGREE |
° |
degree symbol |
ACS_DIAMOND |
◆ |
diamond |
ACS_GEQUAL |
≥ |
greater-than-or-equal-to |
ACS_HLINE |
─ |
horizontal line |
ACS_LANTERN |
␋ |
lantern symbol |
ACS_LARROW |
< |
arrow pointing left |
ACS_LEQUAL |
≤ |
less-than-or-equal-to |
ACS_LLCORNER |
└ |
lower left-hand corner |
ACS_LRCORNER |
┘ |
lower right-hand corner |
ACS_LTEE |
├ |
left tee |
ACS_NEQUAL |
≠ |
not-equal |
ACS_PI |
π |
greek pi |
ACS_PLMINUS |
± |
plus/minus |
ACS_PLUS |
┼ |
plus |
ACS_RARROW |
> |
arrow pointing right |
ACS_RTEE |
┤ |
right tee |
ACS_STERLING |
£ |
pound-sterling symbol |
ACS_TTEE |
┬ |
top tee |
ACS_UARROW |
^ |
arrow pointing up |
ACS_ULCORNER |
┌ |
upper left-hand corner |
ACS_URCORNER |
┐ |
upper right-hand corner |
ACS_VLINE |
│ |
vertical line |
Example:
// This:
move(0,0);
addch(ACS_ULCORNER); addch(ACS_HLINE); addch(ACS_TTEE); addch(ACS_HLINE); addch(ACS_URCORNER);
move(1,0);
addch(ACS_VLINE); addch(' '); addch(ACS_VLINE); addch(' '); addch(ACS_VLINE);
move(2,0);
addch(ACS_LTEE); addch(ACS_HLINE); addch(ACS_PLUS); addch(ACS_HLINE); addch(ACS_RTEE);
move(3,0);
addch(ACS_VLINE); addch(' '); addch(ACS_VLINE); addch(' '); addch(ACS_VLINE);
move(4,0);
addch(ACS_LLCORNER); addch(ACS_HLINE); addch(ACS_BTEE); addch(ACS_HLINE); addch(ACS_LRCORNER);
// Would render this:
┌─┬─┐
│ │ │
├─┼─┤
│ │ │
└─┴─┘
Colors:
To use colors on your terminal, your terminal type must be set to a terminal
type that can support colors. Typically 'xterm' is the preferred terminal
type. This is done by setting your 'term' shell variable:
set term=xterm
To make this permanent, edit your ~/.cshrc file to either add or edit the
term variable to make it xterm. (this should already be the case for your
CS256 accounts.)
In curses a color has two components, the foreground or text color and the
background color. These colors cannot be set individually, they are set in
what is called a color pair.
To tell curses to enable colors, use:
int start_color(void);
The default colors available are:
|
COLOR_BLACK |
COLOR_RED |
COLOR_GREEN |
COLOR_YELLOW |
COLOR_BLUE |
COLOR_MAGENTA |
COLOR_CYAN |
COLOR_WHITE |
To produce a color pair, we use the function:
int init_pair(short pair, short f, short b);
|
|
pair |
The number for this particular combination of colors. |
f |
The foreground (text) color |
b |
The background color |
example:
init_pair(1, COLOR_RED, COLOR_WHITE); // Makes color pair #1 red on white
Note: color pair #0 is a special pair that defaults to the terminals normal
foreground and background color.
The following loop will initialize all 8 x 8 combinations of colors
for(int fg=0; fg < 8; fg++)
for(int bg=0; bg < 8; bg++)
init_pair( (fg*8 + bg), fg, bg );
To apply a color pair to a character or characters it must be applied as an
attribute, which can be done with the attron , attroff and attrset
functions or directly on a character via the addch functions. However it
must fist be converted to an attribute form, which is done with the
COLOR_PAIR() macro function:
COLOR_PAIR(int n);
The COLOR_PAIR() function takes a color pair number and returns that color
as an attribute which can be given to functions that take attributes.
Examples:
// Apply color pair 5 to the character 'x':
addch('x' | COLOR_PAIR(5));
// Make red on black the current color for all characters that follow:
// This assumes we setup our color pairs using the fg/bg loop above:
attron(COLOR_PAIR(COLOR_RED*8 + COLOR_BLACK));
color.c
#include <curses.h>
#include <string.h>
int main(void)
{
int fg, bg;
initscr();
start_color();
// Define all the foreground and background combinations:
for(fg=0; fg < 8; fg++)
for(bg=0; bg < 8; bg++)
init_pair( (fg*8 + bg), fg, bg );
clear();
move(2, 20);
// Draw the background color numbers across the top:
for(bg=0; bg < 8; bg++) {
printw("%3d", bg);
}
move(3, 19);
// Draws a line under the top numbers:
addch(ACS_ULCORNER);
for(bg=0; bg < 8; bg++) {
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
}
// For every foreground color (one each row):
for(fg=0; fg < 8; fg++) {
attrset(A_NORMAL);
mvprintw(4+fg,16, "%2d ", fg);
addch(ACS_VLINE);
// All the background colors for each foreground color (columns):
for(bg=0; bg < 8; bg++) {
attrset(COLOR_PAIR(fg*8 + bg));
addch('x'|A_DIM);
addch('x');
addch('x'|A_BOLD);
}
}
attrset(A_NORMAL);
getch();
endwin();
return 0;
}
Setting the visibility of the cursor:
int curs_set(int visibility);
where visibility is on of:
visibility |
|
0 |
Invisible |
1 |
Normal visibility |
2 |
Very visible |
Inspecting characters that are on the screen:
We can read back a character that is on the screen using the inch() or
mvinch() functions. Since these functions return encoded data about a
character, which includes the character, it's attributes and color, we
need to use the Binary AND (& , not to be confused with the address of
operator) operator to separate out just the information we want from the
function, examples of this are shown below:
chtype inch();
- Returns character at current cursor position
chtype mvinch(int y, int x);
// Gets the character at 10,10:
char ch = mvinch(10,10) & A_CHARTEXT;
// Gets the Attributes and colors in use at the current cursor position:
char attr = inch() & A_ATTRIBUTES;
char color = inch() & A_COLOR;
|