NCurses "new curses" is a successor to the curses library. It's a C library to write text-based interfaces (e.g. interfaces in a terminal).

It's commonly used by Linux programs such as vim.

$ # see also, [...]5-dev and [...]w5-dev
$ sudo apt-get install libncurses-dev

And, in your program, use:

#include <ncurses.h> // or, use curses.h

Features ⭐

  • 🎨 Background/Foreground color for the text
  • πŸͺŸ Multiple windows
  • 🎹 Keyboard/Mouse input
  • 🎯 Cursor implementation
  • 🐸 Extensions for forms, menus...
  • ...

Documentation πŸ“š

Window system

Creating windows

To use ncurses within a terminal, you first need to initialize it:

if ( initscr() == NULL ) {
    // handle error

This will fill a global variable stdscr of type Window* which is the screen of your terminal. You may divide it into multiple separate windows:

WINDOW* w = subwin(stdscr, height, width, pos_x, pos_y);
box(w, ACS_VLINE, ACS_HLINE); // show borders

➑️ It uses a coordinate system with the origin in the top-left corner. Use the global variables LINES/COLS to get the height/width of stdscr.

Using windows

There are two kinds of macro/functions:

  • those taking a window (Window*)
  • those not taking a window (stdscr is implicit)

Common functions are:

  • refresh()/wrefresh(w): redraw the window
  • clear()/wclear(w): empty the window
  • endwin()/delwin(w): destroy a window

πŸ‘‰ Don't forget to call endwin() at the end of your program. It will automatically destroy all sub-windows.

Display text


The position of the cursor is where the text will be displayed, unless you specify a position explicitly.

// get
int cursor_x = getcurx(w); // cursor column
int cursor_y = getcury(w); // cursor line
// set
move(cursor_x, cursor_y);

Display a text using a sort of printf

// print where the cursor is
printw(format, args...);
// print at a specific location
mvwprintw(w, pos_x, pos_y, format);
mvwprintw(w, pos_x, pos_y, format, args...);

Display characters

// print where the cursor is
addch(char); // or, waddch(w, char); 
addstr(char); // or, waddstr(w, char*);
// print at a specific location
mvwaddch(w, pos_x, pos_y, char);
mvwaddstr(w, pos_x, pos_y, char*);

Delete characters

deleteln();                // delete a line
mvwdelch(w, pos_x, pos_y); // delete a character


Colors can only be used if the terminal supports them.

if ( has_colors() == FALSE ) {
    // don't support colors
} else {
    // support colors, enable them

Colors are represented by a number. It can go from 0 to 256, but some terminals only support 0 to 8. To use a color, you need to wrap it inside a pair. A pair has a foreground color, and a background color.

init_pair(pair_id, foreground, background);

➑️ There are aliases for basic constants: COLOR_BLACK...

To create new colors, use:

init_color(color_id, 0, 0, 0); // not support by all

To use a pair:

attron(COLOR_PAIR(pair_id)); // use for following text
attroff(COLOR_PAIR(pair_id)); // stop
wattron(w, COLOR_PAIR(pair_id)); // ...

Other text effects that can be enabled: A_BOLD, A_STANDOUT...

Reading input

You have to call some methods according to the behavior you want and the default settings (βœ…).

noecho();    // don't print pressed keys
echo();      // βœ… do print pressed keys

nocbreak();  // wait for <enter> to process input
cbreak();    // βœ… don't wait for <enter> to process input

curs_set(TRUE);   // βœ… show cursor
curs_set(FALSE);  // hide cursor

keypad(w, TRUE);  // handle arrow keys as characters
keypad(w, FALSE); // βœ… don't handle arrow keys as characters




If you're using cbreak(), you'll most likely read character by character using getch(). Otherwise, refer to getstr(buffer) documentation.

πŸ€– Both calls are blocking the program until they receive input.

int ch = getch();

switch(ch) {
    case KEY_UP: // if keypad enabled
        // ...
    case 'r': // normal key pressed
        // ...
    case KEY_SEND: case KEY_ENTER: // enter pressed
        // ...

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.