============================================================================== C-Scene Issue #3 Curses Tutorial Tim Gerla ==============================================================================
If you take a look at programs like dselect, tcd, or top, you'll notice that they are all full screen, with different attributes such as bold, reverse, even color. These programs use the curses library.
Curses is a portable video manipulation library, much like the CONIO.H system for DOS platforms, but much more powerful. This tutorial won't try to teach you everything you need to know, but it will get you started, and you can use the curses manpage, curses(3) or ncurses(3) to figure out the rest.
(Disclaimer, I've noticed that Un*x setups never seem to be equal, so your mileage with manpages/include files/libraries may be different. Check around, and if you have problems, mail me. I am using Debian/Linux)
To start out, you must include curses.h, or possibly, depending on your setup, ncurses.h. With other Unices, check in /usr/include, or wherever those files are stored.
To use curses in your program, you must first initialize the library by calling 'initscr'. Initscr returns a pointer to a window that you may use later on in the program.
If you have many seperate routines that need to use curses, consider making your window pointer a gobal variable, or pass a WINDOW * to your routine.
WINDOW *mywindow; ... mywindow = initscr(); ...
The code above initializes the curses library. It also places a pointer to a window (This will be the entire screen for now.) into mywindow. Other curses routines need a WIN * argument, so save mywindow.
Before we can get into the meat of the tutorial, here are a few notes. Most curses routines have several versions . For example, if you type man printw, you'll see something like this:
int printw(char *fmt [, arg] ...); int wprintw(WINDOW *win, char *fmt [, arg] ...); int mvprintw(int y, int x, char *fmt [, arg] ...); int mvwprintw(WINDOW *win, int y, int x, char *fmt [, arg] ...);What are all these printws for?
printw: This just prints to the current window, at the current cursor position. wprintw: This allows you to specify the window you want printed to. mvprintw: This prints to the current window, but allows you to specify the cursor position to print at. notice that this also moves the cursor to the end of the string it prints. mvwprintw: This allows you to specify everything, window and cursor position.Others curses routines have the same format, for example, wline has mwline and mvwline. From now on, I'll write routine names with their siblings like (mvw)printw.
int printw(char *fmt [, arg] ...); int wprintw(WINDOW *win, char *fmt [, arg] ...); int mvprintw(int y, int x, char *fmt [, arg] ...); int mvwprintw(WINDOW *win, int y, int x, char *fmt [, arg] ...);
This is what you would use to print the historic ``Hello World'' in the upper left corner of the screen:
mvwprintw( mywindow, 0, 0, "Hello World %d", 123 );
Notice that y and x start at 0, unlike the DOS conio routines that start at 1. Also, y is always before x. This is different from most graphics libraries, where x is before y. Luckily, this is consistent throughout the entire curses library.
Notice that a \n is not needed at the end of the line, in most cases. Strange things may happen if you do that without noticing.
This draws a box out of straight lines from 0,0 to MAX_X to MAX_Y. Prototype:
int box(WINDOW *win, chtype verch, chtype horch);
You should recognize the first argument, but what is chtype and verch/horch? It's the character that's used to draw the lines. If you want a nice looking box, use ACS_VLINE as verch, and ACS_HLINE as horch. There are also corners, check the man page for details.
Here's a snippet that you can use:
box( mywindow, ACS_VLINE, ACS_HLINE );
If you don't want a plain box, just lines, check out (mw)hline and (mw)vline.
This is a very simple routine, it just moves the current cursor position. Here are the prototype:
int move(int y, int x); int wmove(WINDOW *win, int y, int x);
move( 10,10 ); ...
You should be able to figure this out. Just remember that y and x start at 0, not 1.
Getch works exactly like it's DOS counterpart. In standard operation, it simply waits for a key and returns the keycode once one has been pressed. If there's one in the buffer already, it returns at once. Getch can be configured (man 3 inopts) to wait only a few 10ths of a second, or not wait at all. It can be told to echo ([no]echo), or wait for the ENTER key to be pressed ([no]cbreak). Here are the prototypes:
int getch(void); int wgetch(WINDOW *win); int mvgetch(int y, int x); int mvwgetch(WINDOW *win, int y, int x);
One final function that should be introduced is
endwin(). This ends the curses session, returning the terminal to normal. It needs to be called, or when the app terminates, you will have a messed up shell. :)
Anyway, that's about it for the curses tutorial. If you have any questions, please come into #c on any Efnet IRC server and look for Tybstar. Please check out the manpages and the example programs that come with curses, and the example program I have written up, that uses the above functions.