<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML ><HEAD ><TITLE >Interfacing with the key board</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE=" NCURSES Programming HOWTO " HREF="index.html"><LINK REL="PREVIOUS" TITLE="Colors" HREF="color.html"><LINK REL="NEXT" TITLE="Interfacing with the mouse " HREF="mouse.html"></HEAD ><BODY CLASS="SECT1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >NCURSES Programming HOWTO</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="color.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="mouse.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="SECT1" ><H1 CLASS="SECT1" ><A NAME="KEYS" ></A >11. Interfacing with the key board</H1 ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="KEYSBASICS" ></A >11.1. The Basics</H2 ><P >No GUI is complete without a strong user interface and to interact with the user, a curses program should be sensitive to key presses or the mouse actions done by the user. Let's deal with the keys first.</P ><P >As you have seen in almost all of the above examples, it's very easy to get key input from the user. A simple way of getting key presses is to use <TT CLASS="LITERAL" >getch()</TT > function. The cbreak mode should be enabled to read keys when you are interested in reading individual key hits rather than complete lines of text (which usually end with a carriage return). keypad should be enabled to get the Functions keys, arrow keys etc. See the initialization section for details.</P ><P ><TT CLASS="LITERAL" >getch()</TT > returns an integer corresponding to the key pressed. If it is a normal character, the integer value will be equivalent to the character. Otherwise it returns a number which can be matched with the constants defined in <TT CLASS="LITERAL" >curses.h</TT >. For example if the user presses F1, the integer returned is 265. This can be checked using the macro KEY_F() defined in curses.h. This makes reading keys portable and easy to manage.</P ><P >For example, if you call getch() like this</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > int ch; ch = getch();</PRE ></FONT ></TD ></TR ></TABLE ><P >getch() will wait for the user to press a key, (unless you specified a timeout) and when user presses a key, the corresponding integer is returned. Then you can check the value returned with the constants defined in curses.h to match against the keys you want.</P ><P >The following code piece will do that job.</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > if(ch == KEY_LEFT) printw("Left arrow is pressed\n");</PRE ></FONT ></TD ></TR ></TABLE ><P >Let's write a small program which creates a menu which can be navigated by up and down arrows.</P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="SIMPLEKEYEX" ></A >11.2. A Simple Key Usage example</H2 ><DIV CLASS="EXAMPLE" ><A NAME="BSIKE" ></A ><P ><B >Example 10. A Simple Key Usage example </B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" ><SPAN CLASS="INLINEMEDIAOBJECT" >#include <stdio.h> #include <ncurses.h> #define WIDTH 30 #define HEIGHT 10 int startx = 0; int starty = 0; char *choices[] = { "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit", }; int n_choices = sizeof(choices) / sizeof(char *); void print_menu(WINDOW *menu_win, int highlight); int main() { WINDOW *menu_win; int highlight = 1; int choice = 0; int c; initscr(); clear(); noecho(); cbreak(); /* Line buffering disabled. pass on everything */ startx = (80 - WIDTH) / 2; starty = (24 - HEIGHT) / 2; menu_win = newwin(HEIGHT, WIDTH, starty, startx); keypad(menu_win, TRUE); mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice"); refresh(); print_menu(menu_win, highlight); while(1) { c = wgetch(menu_win); switch(c) { case KEY_UP: if(highlight == 1) highlight = n_choices; else --highlight; break; case KEY_DOWN: if(highlight == n_choices) highlight = 1; else ++highlight; break; case 10: choice = highlight; break; default: mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c); refresh(); break; } print_menu(menu_win, highlight); if(choice != 0) /* User did a choice come out of the infinite loop */ break; } mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]); clrtoeol(); refresh(); endwin(); return 0; } void print_menu(WINDOW *menu_win, int highlight) { int x, y, i; x = 2; y = 2; box(menu_win, 0, 0); for(i = 0; i < n_choices; ++i) { if(highlight == i + 1) /* High light the present choice */ { wattron(menu_win, A_REVERSE); mvwprintw(menu_win, y, x, "%s", choices[i]); wattroff(menu_win, A_REVERSE); } else mvwprintw(menu_win, y, x, "%s", choices[i]); ++y; } wrefresh(menu_win); } </SPAN ></PRE ></FONT ></TD ></TR ></TABLE ></DIV ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="color.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="mouse.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Colors</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" > </TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Interfacing with the mouse</TD ></TR ></TABLE ></DIV ></BODY ></HTML >