ncurses Notes
Table of Contents
What is ncurses
"new curses" is a library that allows you to manipulate the character display of your terminal. Curses originally was pun on "cursor optimization". It is primarily used to create nice UIs in text mode terminals.
Resources
Basic ncurses program
Setup
To initialize ncurses you should call initscr
Tear down
Make sure to call endwin at the end of your program to clean up ncurses
Hiding user key presses
Use noecho and echo to enable or disable the keys the user types
from showing up in the terminal.
Configuring the cursor visibility
Use curs_set to set the visibility level of the cursor. It can be
invisible <0>, visible <1>, or very visible <2>. Not all terminals
support this feature (for instance term.el in Emacs always shows the
cursor no matter what this is set to).
Refreshing
You will need to call refresh to flush the back buffer to the terminal
Printing to the screen
You can use printw or mvprintw to print a string to the
screen. printw uses the current cursor position. mvprintw allows
you to specify where to print the string in the terminal. Caution the
ncurses functions that accept a coordinate pair want the y
coordinate before the x, always double check the manpage. The
ncurses print functions support formats the same way printf does.
Moving the cursor
Use the move function to set the cursor position in the
terminal. The y coordinate is the first argument and represents the
number of characters down from the top. The second argument is x and
represents the number of characters from the left.
Waiting for user input
If you want to wait for the user to press a key before continuing use
the getch function. This function will also return the char that the
user typed on the keyboard.
Clearing the screen
Use the clear function to clear the screen.
Code
#include <ncurses.h> int main (int argc, char **argv) { char c; int x, y; x = 2; y = 3; initscr(); noecho(); curs_set(0); move(y, x); printw("Hello"); mvprintw(y + 1, x + 5, "ncurses!"); refresh(); c = getch(); clear(); mvprintw(0, 0, "You pressed char code: %d", c); mvprintw(2, 0, "Press any key to exit"); refresh(); getch(); endwin(); return 0; }
Compiling the code
#!/bin/sh set -e ../../config/tangle.sh ncurses.org cd ~/tmp gcc -o basic_ncurses basic_ncurses.c -lncurses
Using Windows
Windows
In ncurses bounding rectangles are known as windows. A window can be
created with the newwin function. Like most ncurses functions y
comes before x and height comes before width when specifying the
rectangle. The newwin function should be called after initscr.
Drawing a box border around a window
Use the box function to draw a box border around a window. This will
clear any characters that might be on the screen when you call it so
make sure to draw the box before putting any content into the
window. The box function accepts the window as well as the vertical
and horizontal characters to use when drawing the border. Use zeroes
as the arguments if you just want to use the terminal default border.
Refreshing the window
An individual window can be refreshed with wrefresh. This function
takes the window as an argument. Refreshing the window is needed
anytime you draw to the window. This includes box or any of the w*
functions.
Drawing in the window
There are window equivalents of all the normal ncurses draw
functions. The functions that accept coordinates will be relative to
the window.
Code
#include <ncurses.h> int main (int argc, char **argv) { int c; WINDOW *char_win; WINDOW *code_win; initscr(); noecho(); curs_set(0); char_win = newwin(5, 10, 2, 2); code_win = newwin(5, 10, 2, 14); refresh(); box(char_win, 0, 0); mvwprintw(char_win, 0, 2, "char"); wrefresh(char_win); box(code_win, 0, 0); mvwprintw(code_win, 0, 2, "code"); wrefresh(code_win); printw("Press q to exit"); refresh(); do { c = getch(); wclear(char_win); box(char_win, 0, 0); mvwprintw(char_win, 0, 2, "char"); mvwprintw(char_win, 2, 4, "%c", c); wrefresh(char_win); wclear(code_win); box(code_win, 0, 0); mvwprintw(code_win, 0, 2, "code"); mvwprintw(code_win, 2, 4, "%d", c); wrefresh(code_win); } while (c != 'q'); endwin(); return 0; }
Compiling the code
#!/bin/sh set -e ../../config/tangle.sh ncurses.org cd ~/tmp gcc -o win_ncurses win_ncurses.c -lncurses
Attributes
Use the attron and attroff function to set the desired
attributes. Use bit-wise or to combine multiple attributes. Some
examples of the attributes you can can are underline, bold, reverse
(swap foreground and background colors), etc. You can see a complete
table of the attributes in the manpage for attron.
Colors
If a terminal supports colors you can change the color of various
characters. The has_colors function is a good check to run to see if
a terminal supports various colors. If you want to use colors and your
terminal supports it use start_color function to initialize color
support. From there color pairs (foreground, background) need to be
defined with the init_pair. When defining a color pair you will
specify and id. This id will be used in the attribute COLOR_PAIR to
specify which color pair you are using.  Some terminals also support
redefining colors. You can use can_change_color to see if you can
redefine the color.
Example
.... if (!has_colors()) { printw("Colors not supported"); getch(); endwin(); return -1; } start_color(); init_pair(1, COLOR_CYAN, COLOR_WHITE); attron(COLOR_PAIR(1)); printw("Light blue"); attroff(COLOR_PAIR(1)); mvprintw(2, 0, "Press any key to continue"); getch(); ...
Querying Cursor position
You can query the size, cursor position, and top left offset of a
window using getmaxyx, getxy and getbegxy. Each of these functions
accepts a window as the argument but if you want to query the default
window use stdscr. The getmaxyx using the stdscr is a good way to get
the size of the current terminal window. These functions are actually
macros and they accept as arguments the x and y variables to hold the
return values. Since they are macros you do not need to pass by
reference to them. So don't do this getmaxy(stdscr, &x, &y) but rather
do this getmaxy(stdscr, x, y).
Reading non char keys
When you run getch normally it will not return usefule values for the
arrow or function keys. In order to get this information you need to
call the keypad function. Once enabled you can use wgetch to compare
the returned key with KEY_UP or KEY_LEFT. All the available keys are
listed in curses.h.