C language: NCURSES basics


NCURSES – it is a C library which control process of sending a series of bytes by terminal. It’s quite oldschool approach, but it’s widely used even right now as internet works the same way: packets sending just series of bytes. So internet is kinda ‘big’ terminal thingy 🙂

So… NCURSES (1993) – rewrite of old non-free CURSES terminal which were made to develop Rogue game (1980).

Basically it’s all about terminal’s cursor control. This article based at tldp NCURSES guide and some other resources. Let’s start!

NCURSES basic functions

initscr() init terminal in curses mode and malloc() terminal window (called stdscr)
raw() disable line buffering (so you won’t need press Enter after input)
cbreak(); disable line buffering disabled; intercept and process input
noecho() disable echo(); eg to take user input to getch() without showing it on screen
keypad(stdscr, TRUE) to be able to read arrows, F1-F12, etc unusual keys
printw("Hello") prints stuff on stdscr window within current y,x coords
addch() print single character with attributes
addstr() print strings
refresh() update terminal in particular place
halfdelay() generates timeout after which prompt not possible
getyx() gets the co-ordinates of the present cursor into the variables y, x
move() moves the cursor to the co-ordinates given to it
getch() user input similar to getchar(), but without line buffering (not need press Enter after input)
attrset() / attron() / attroff() assign attributes for output.
Also you can assign attribute macros to output directly, eg
addch(char | A_BOLD | A_UNDERLINE); 
endwin() exit curses mode doing free()

Output

mvaddch() move the cursor to y,x and print. It means:

move(row,col);
addch(ch);

waddch() is the same as addch() but in current window
mvwaddch() add a character into the given window at the given coordinates

The same goes to:

printw() print stuff
mvprintw(int y, int x, const char *fmt, ...) print at certain y,x
wprintw() print in certain window
mvwprintw() print at certain y,x in a certain window
vwprintw() print variable number of arguments

And:

addstr() print character string into given window; repeats addch()
mvaddstr() print string y,x
waddstr() print into given window
mvwaddstr() print string y,x into given window
addnstr() puts n characters into the screen

getmaxyx(stdscr,row,col) get max the number of rows and columns in a given window. It’s not a function, but macro defined in ncurses.h

Input

getch() get character; read a single character from the terminal
scanw() get formatted input; like scanf(), but mvscanw() – it can get the input from any y,x
getstr() get strings; like getch() - get stuff until a \n, CR, EOF etc. Result is a pointer to a string of characters.

Attributes

attrset() sets the attributes of window; fully overrides whatever attributes the window previously had and sets it to the new attributes
attron() / attroff() just switches on the attribute given to it
attr_set(), attr_on … the same as above, but they take parameters of type attr_t
dsd
standend() like attrset(A_NORMAL); turns off all attributes and brings normal mode

attr_get() gets the current attributes and color pair of the window (to scan areas of screen)


chgat() set attributes for a group of characters without moving cursor (changes the attributes of a given number of characters starting at the current cursor location).
Family includes wchgat(), mvchgat() etc

Example: mvchgat(0, 0, -1, A_BLINK, 1, NULL); 

  • First two parameters specify the position at which to start
  • Third parameter number of characters to update. -1 means till
    end of line
  • Forth parameter is the normal attribute you wanted to give
    to the charcter
  • Fifth is the color index. It is the index given during init_pair()
    use 0 if you didn’t want color
  • Sixth one is always NULL

Windows

Standard window is stdscr, but we can create more different windows to manipulate parts of the screen separately.

create_newwin(height, width, starty, startx); create new “window” – abstraction of an imaginary window, which can be manipulated independent of other parts of screen. It returns a pointer to structure WINDOW, which can be passed to window related functions like wprintw() etc

box() draw a border around the window. Uses special extended characters to draw it (eg ACS_ULCORNER)

delwin() destroy window (deallocates memory for window structure)

Colors

start_color() initialize colors

has_colors() check: can terminal support color at all

init_pair() initialize color pair (foreground color (to draw  characters) and background color

COLOR_PAIR() allows to use colors; eg via attron()

init_color(<color name>, <R>, <G>, <B>) change the rgb values for the colors defined by curses initially. If your terminal cannot change the color definitions, the function returns ERR.

can_change_color() check if terminal able to change colors. Returns 1 if it can do it

color_content() / pair_content() find the color content

Mouse interaction

We got into keyboard interaction in first chapter (getch stuff), so lets take a peak into mouse.

mousemask (mmask_t newmask, mmask_t *oldmask)

1st argument is the events you want to listen to (by default, all the events are turned off).
2nd is the old events mask

Example:
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);

List of events:

BUTTON1_PRESSED          mouse button 1 down
BUTTON1_RELEASED         mouse button 1 up
BUTTON1_CLICKED          mouse button 1 clicked
BUTTON1_DOUBLE_CLICKED   mouse button 1 double clicked
BUTTON1_TRIPLE_CLICKED   mouse button 1 triple clicked
...
BUTTON4_TRIPLE_CLICKED   mouse button 4 triple clicked
BUTTON_SHIFT             shift was down during button state change
BUTTON_CTRL              control was down during button state change
BUTTON_ALT               alt was down during button state change
ALL_MOUSE_EVENTS         report all button state changes
REPORT_MOUSE_POSITION    report mouse movement

getmouse() retrieve mouse event; returns the event into the pointer given to it; such structure:

    typedef struct
    {
        short id;         /* ID to distinguish multiple devices */
        int x, y, z;      /* event coordinates */
        mmask_t bstate;   /* button state bits */
    }

mouse_trafo() / wmouse_trafo() convert mouse co-ordinates to screen relative co-ordinates (see curs_mouse() in man)

mouseinterval function sets the maximum time (in thousands of a second) that can elapse between press and release events in order for them to be recognized as a click

Note: Seems that some old code examples for mouse in NCURSES works a bit glitchy. I’ve tested in Ubuntu and Cygwin and some stuff didn’t work.

Screen manipulation

getyx(win, y, x); gets the co-ordinates of the present cursor into the variables y, x.
win – window pointer
y, x co-ordinates will be put into this variables

getparyx() gets the beginning co-ordinates of the sub window relative to the main window

getbegyx() / getmaxyx() store current window’s beginning and maximum co-ordinates

scr_dump() dump the screen contents to a file given as an argument

scr_restore() restore the dump of the screen contents

putwin()getwin() store and restore windows

copywin() copy a window completely onto another window; takes the source and destination windows as parameters and according to the rectangle specified, it copies the rectangular region from source to destination window. It’s last parameter specifies whether to overwrite or just overlay the contents on to the destination window. If this argument is true, then the copying is non-destructive.

Misc NCURSES stuff

curs_set() make the cursor invisible. Params:
0 invisible / 1 normal / 2 very visible

How to leave Curses mode temporarily:
def_prog_mode() save the tty modes → endwin()

To go back: reset_prog_mode()refresh()


Useful libraries

panel.h Panel object is a window that is implicitly treated as part of a deck including all other panel objects. The deck is treated as a stack with the top panel being completely visible and the other panels may or may not be obscured according to their positions:

  1. newwin() create the windows attached to the panels
  2. new_panel() create panels with the chosen visibility order. Stack them up according to the desired visibility.
  3. update_panels() write the panels to the virtual screen in correct visibility order. doupdate() to show it on the screen.
  4. show_panel(), hide_panel(), move_panel() etc. Make use of helper functions like panel_hidden() and panel_window(). Make use of user pointer to store custom data for a panel. Use the functions set_panel_userptr() and panel_userptr() to set and get the user pointer for a panel
  5. del_panel() delete the panel

menu.h extension to basic curses to create menus. First you create items, and then post the menu to the display. After that, all the processing of user responses is done in an elegant function menu_driver() which is the work horse of any menu program. Algorythm:

  1. new_item() create items; you can specify a name and description for them
  2. new_menu() create menu and specify the items to be attached with.
  3. menu_post() post menu and refresh the screen.
  4. menu_driver() process the user requests with a loop and do necessary updates to menu
  5. menu_unpost() unpost the menu
  6. free_menu() free the memory allocated to menu
  7. free_item() free the memory allocated to the items

form.h forms created with fields with new_field(); the form is manipulated with form_driver() – to send requests to move focus to a certain field, move cursor to end of the field etc. Algorythm kinda similar to menues:

  1. new_field() (you can specify the height and width of the field, and its position on the form)
  2. new_form() by specifying the fields to be attached with.
  3. form_post() and refresh the screen
  4. form_driver() process the user requests with a loop and do necessary updates to form
  5. form_unpost()
  6. free_form()
  7. free_field()

CDK (Curses Development Kit) https://invisible-island.net/cdk/

dialog.h to create dialog boxes http://invisible-island.net/dialog/

Perl Curses Modules CURSES::FORM and CURSES::WIDGETS:
http://cpan.org/modules/01modules.index.html

Default colors:

0. Black
1. Blue
2. Green
3. Cyan
4. Red
5. Magenta
6. Brown
7. White (Light Gray)
8. Bright Black (Gray)
9. Bright Blue
10. Bright Green
11. Bright Cyan
12. Bright Red
13. Bright Magenta
14. Yellow
15. Bright White

Useful resources

This article based at: https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

Manual https://invisible-island.net/ncurses/man/index.html

FAQ https://invisible-island.net/ncurses/ncurses.faq.html

Tutorial https://invisible-island.net/ncurses/ncurses-intro.html

Another variant of this library is PDCurses which works well at Windows OS


This entry was posted in C language (en), Programming (en). Bookmark the permalink.

Leave a Reply

🇬🇧 Attention! Comments with URLs/email are not allowed.
🇷🇺 Комментарии со ссылками/email удаляются автоматически.