We created a menu interface with basic curses library in C, the menu library in curses provides a nice extension and functions dedicated to create more advanced menus. A menu is a set of items displayed on the screen that assists the user to choose an option or subset from the given items. To put it in simple terms a menu is a collection of items from which one or more items can be chosen.

Yes, you read it right, menu library in curses provides the functionality to choose more than one item as a preferred choice. Though multi-select menus are for later topics, we will look at the rudiments of the curses menu library in this article.

Curses Menu Library Basics

To create menus, you must first create the menu items then create the menu by linking the items to the menu and post the menu to the display, then the function menu_driver() processes the user responses to navigate and select the menu items.

Let us see the general flow of curses menu programming ( ref the image ).

Curses Menu Programming
Curses Menu Programming
  • Initialize curses, which is usually initscr()
  • Create items using the new_item() function, you can give a name and description for the items.
  • Create the menu with new_menu(), with the items to be displayed in the menu.
  • Post the menu with menu_post() and refresh the screen.
  • Process the user requests with a loop and do necessary updates to menu with menu_driver.
  • Unpost the menu with menu_unpost()
  • Free the memory allocated to menu by free_menu()
  • Free the memory allocated to the items with free_item()
  • End curses

Let us take a look into the code, we will be basically creating a curses window with 7 rows, 15 cols originating at 5th row and 5th column on the screen, then we will derive a window with 6 rows, 14 cols originating at 1st row and 1st column of the parent window, which will be used to display the menu. We are going to create a menu with scroll functionality which is achieved with set_menu_format() from menu library.

The function set_menu_format() sets the maximum display size of the given menu. If this size is too small to display all menu items, the menu will be made scrollable. If this size is larger than the menu window or if the window is too small to display all menu items, post_menu() will fail.

Here is the code with curses menu library

#include<curses.h>
#include<menu.h>
#include<stdlib.h>
void main()
{
char *options[]={ 
"Red",
"Blue",
"Green",
"Orange",
"Brown",
"White",
"Black",
"Yellow",
"Violet",
"Purple",
"Aqua",
"Slate"
};
int i;
int ch;
MENU *menu;
ITEM **items;
WINDOW *w;
initscr(); /* initialize curses */
curs_set(0); /* hide the blinking cursor */
noecho(); /* hide the keyboard input */
/* Create Items */
items = (ITEM **)calloc( 12, sizeof(ITEM *));
for( i=0; i<12; i++ )
items[i] = new_item(options[i], "" );
/* Create Menu */
menu = new_menu( items );
/* Create Window for the menu */
w = newwin( 7, 15, 5, 5);
box( w, 0, 0 );
keypad(w, TRUE);
/* set menu window */
set_menu_win( menu, w );
/*set menu sub window */
set_menu_sub( menu, derwin(w, 6, 14, 1, 1));
set_menu_mark(menu, " "); /* string used as menu marker */
/* set menu format - no of items to be displayed */
set_menu_format(menu, 5, 1);
/*post the menu */
post_menu(menu);
wrefresh(w);
while((ch = wgetch(w))!=27 ) /* 27 is the key code for ESC */
{
switch(ch) {
case KEY_DOWN:
menu_driver(menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(menu, REQ_UP_ITEM);
break;
case KEY_NPAGE:
menu_driver(menu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(menu, REQ_SCR_UPAGE);
break;
}
wrefresh(w);
}
unpost_menu(menu);
free_menu(menu);
for(i=0; i<12; i++)
free_item(items[i]);
endwin();
}

You might have noticed the set_menu_format(menu, 5, 1) called to set the menu size of 5 rows and 1 column, we have 12 options, so the rest of the menu items are hidden and become scrollable.

We have also used derwin to derive a sub window, which is used to display the menu. Calling derwin() is the same as calling subwin(), except that begin_y and begin_x in derwin() are relative to the origin of the window, rather than the screen. There is no difference between the sub windows and the derived windows. Refer the image below for clear understanding of derwin().

derwin curses programming
derwin curses programming

Note: compile the code with -lcurses and -lmenu (curses and menu libraries), so you will compile the code as follows

gcc menu.c -lcurses -lmenu

Creating menu with Curses menu library in C

Leave a Reply

Your email address will not be published. Required fields are marked *