korson@hubcap.clemson.edu (Timothy Korson) (02/15/90)
Reading ESC Char and the Arrow Keys from Keyboard: Problem: I want to be able to read the ESC char (^[) and also the escape sequence for the arrow keys (eg. ^[[D for Left) from the keyboard. Is there any elegant solution to this problem? I tried the following method and would not call it an elegant solution because it won't work in all cases. Here is my solution : I used System V curses library functions "nodelay" and "getch" that are explained below (excerpts from man pages) : nodelay (win, bf) This option causes wgetch() to be a non-blocking call. If no input is ready, wgetch() will return ERR. If dis- abled, wgetch() will hang until a key is pressed. getch() A character is read from the terminal associated with the window. In NODELAY mode, if there is no input waiting, the value ERR is returned. In DELAY mode, the program will hang until the system passes text through to the program. Depending on the setting of cbreak(), this will be after one character (CBREAK mode), or after the first newline (NOC- BREAK mode). In HALF-DELAY mode, the program will hang until a character is typed or the specified timeout has been reached. Unless noecho() has been set, the character will also be echoed into the designated window. If keypad (win, TRUE) has been called, and a function key is pressed, the token for that function key will be returned instead of the raw characters. (See keypad() under Input Options Setting.) Possible function keys are defined in <curses.h> with integers beginning with 0401, whose names begin with KEY_. If a character is received that could be the beginning of a function key (such as escape), curses will set a timer. If the remainder of the sequence is not received within the designated time, the character will be passed through, other- wise the function key value will be returned. For this reason, on many ter- minals, there will be a delay after a user presses the escape key before the escape is returned to the program. (Use by a programmer of the escape key for a single character routine is discouraged. Also see notimeout() below.) The following program illustrates my approach. It is necessary to compile this program with System V C-compiler since some of the above functions are defined only in System V library. On my Sun system I used the following command to make a.out: /usr/5bin/cc filename.c -lcurses -ltermlib /*---------- The program begins here ----------*/ #include <curses.h> #define ESC '\033' main () { int in, in1; /* initialise curses setup */ initscr(); cbreak (); noecho (); move (3,3); in = getch (); if (in == ESC) { nodelay (stdscr, 1); /* NODELAY mode ON */ in1 = getch (); /* returns ERR or garbage */ nodelay (stdscr, 0); /* NODELAY mode OFF */ if (in1 == ERR) printw ("ESC \n"); else { in1 = getch (); /* returns 1st char after ESC */ if (in1 = '[') { in1 = getch (); /* returns 2nd char after ESC */ if (in1 == 'D') printw ("LEFT ARROW %d \n",in1); } else printf("NONE"); } } refresh(); sleep(1); endwin(); } /*---------- The program ends here ----------*/ The above program reads the ESC and Left Arrow keys correctly when I work on the console. But it won't work correctly when I remote login and type the ESC / Arrow keys (because of transmission delay???). Another weird thing : The getch() issued to read a char, if any, after the ESC char should return the input char ('[' for Left arrow) if one is present. Instead it returns garbage and the second getch() after the ESC char returns the actual char that is present after the ESC ('[').