Introduction
In PDCurses there is a halfdelay(TENTHS) mode which implements a small delay (TENTHS tenths of a second) after each input. If there is no input after this time, the corresponding input function returns ERR. Somewhat confusingly, the symbol ERR doesn't actually mean an "error" occured in this case. Only that no input has been received yet. In this mode, it is possible to call the input function as part of a loop -- we can be sure that the function will exit after at most TENTHS tenths of a second. Then we can do some intermediate processing and then repeat the input function in a loop.Example
Let's write a program that uses curses in halfdelay mode to get an input string from the user. As intermediate processing we will echo the characters to the screen and store them in a buffer. Additionally, we will also check to see if a timeout has occured, and abort the input early if this is the case. Notice that our notion of "timeout" (specified by the parameter TIMEOUT) is independent from the curses notion of "timeout" (specified by the parameter TENTHS).Note
In halfdelay mode, functions like scanw(3) do not seem to work properly, at least with pdcurses. Therefore, in halfdelay mode, we must obligate ourselves to "roll our own" line input functions as demonstrated in the below example.Usage
The program takes two parameters: the PROMPT and the TIMEOUT. If the timeout is reached, the input aborts early. The input finishes normally when the user types a newline. The erase key (e.g. "backspace") is interpreted as normally would be expected, and all other special characters are ignored.Source Listing
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <ctype.h>
#define TENTHS 1
#define MAX 80
void do_endwin(void) {endwin();}
#define SELF_EXE argv[0]
#define PROMPT argv[1]
#define TIMEOUT argv[2]
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "Usage: %s PROMPT TIMEOUT\n", SELF_EXE);
exit(EXIT_FAILURE);
}
if (initscr() == NULL) {
fprintf(stderr, "Could not initialize screen\n");
exit(EXIT_FAILURE);
}
atexit(do_endwin);
halfdelay(TENTHS); // halfdelay mode ON
keypad(stdscr, TRUE); // keypad mode ON
noecho(); // echo mode OFF
// Parameters for custom input routine
int timeout = atoi(TIMEOUT);
char buf[MAX] = {'\0'};
bool timeout_occured = false;
// Begin custom input routine
// Show PROMPT and receive input from the user into buf
// Abort if timeout seconds have elapsed; in this case timeout_occured
// is set to true
// Up to MAX-1 characters may be typed or stored in buf
printw("%s\n", PROMPT);
refresh();
time_t now = time(NULL);
int i=0;
for (;;) {
// check for timeout
time_t diff = time(NULL) - now;
struct tm *t = localtime(&diff);
if (t->tm_sec >= timeout) {
timeout_occured = true;
buf[i] = '\0';
break;
}
// Read a character into ch and check for various errors
// ERR is not really an error; it just means there was no input yet
// erasechar() returns this terminal's "erase key" (e.g. backspace)
int ch = getch();
if (ch == ERR) {
continue;
}else if (ch == erasechar() && i==0) { // erase key at line start
flash();
continue;
}else if (ch == erasechar()) { // erase key at non-line start
i--;
printw("%c %c", ch, ch); // delete the previous character
refresh();
continue;
}else if (ch == '\n') { // newline was pressed
buf[i] = '\0';
break;
}else if (iscntrl(ch)) { // control key (e.g. CTRL-C) pressed
flash();
continue;
}else if (ch != (char)ch) { // non-character key pressed
flash();
continue;
}else if (i == MAX-1) { // other key pressed but no more room in buf
flash();
continue;
}
// store and echo the character
buf[i++] = ch;
printw("%c", ch);
refresh();
}
printw("\n");
refresh();
// End custom input routine
// Results of the custom input routine
printw("\nInput string received:\n");
printw("%s\n", buf);
printw("\nTimeout occured: %s\n", timeout_occured ? "YES" : "NO");
refresh();
// Print message and wait for user to press a key
printw("Press any key to end the program...");
refresh();
for (;;) {
int ch = getch();
if (ch == ERR)
continue;
break;
}
exit(EXIT_SUCCESS);
}
References
http://www.mkssoftware.com/docs/man3/curs_beep.3.asphttp://tldp.org/HOWTO/NCURSES-Programming-HOWTO/init.html
Keine Kommentare:
Kommentar veröffentlichen