Fawkes API Fawkes Development Version
getkey.cpp
1/***************************************************************************
2 * getkey.cpp - getkey returns a keypress in non-blocking manner
3 *
4 * Created: Thu Jun 04 19:08:13 2009 (from RCSoftX)
5 * Copyright 2009 Masrur Doostdar <doostdar@kbsg.rwth-aachen.de>
6 *
7 ****************************************************************************/
8
9/* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Library General Public License for more details.
18 *
19 * Read the full text in the LICENSE.GPL file in the doc directory.
20 */
21
22#include <core/exception.h>
23#include <utils/system/getkey.h>
24
25#include <cerrno>
26#include <cstdio>
27#include <fcntl.h>
28#include <termios.h>
29#include <unistd.h>
30
31namespace fawkes {
32
33/** Set non-blocking flag on STDIN.
34 * Sets the 0_NONBLOCK Flag to 1, so that the read command in the
35 * getkey()-method wont block the programm till a input is made (see also
36 * libc manual, pages 105 and 117).
37 */
38static void
40{
41 int oldflags;
42
43 oldflags = fcntl(STDIN_FILENO, F_GETFL, 0);
44 oldflags |= O_NONBLOCK;
45 fcntl(STDIN_FILENO, F_SETFL, oldflags);
46}
47
48/** Clear non-blocking flag on STDIN. */
49static void
51{
52 int oldflags;
53
54 oldflags = fcntl(STDIN_FILENO, F_GETFL, 0);
55 oldflags &= ~O_NONBLOCK;
56 fcntl(STDIN_FILENO, F_SETFL, oldflags);
57}
58
59/** Get value of a single key-press non-blocking.
60 * This method checks if a new keypress has happened and returns the value in
61 * this case. Otherwise it returns 0. The method does not block.
62 * @param timeout_decisecs If less than 0 wait forever, if 0 non-blocking
63 * (returns 0 if no key pressed immediately, if greater than 0 it is the
64 * timeout in deciseconds.
65 * @return key pressed or 0 (no key read)
66 */
67char
68getkey(int timeout_decisecs)
69{
70 bool blocking = (timeout_decisecs != 0);
71 char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
72 struct termios tattr, // new terminal attributes
73 saved_attributes; // restore the original settings
74
75 if (!blocking)
77 tcgetattr(STDIN_FILENO, &saved_attributes); // save the original attributes
78
79 tcgetattr(STDIN_FILENO, &tattr); // set the new attributes
80 tattr.c_lflag &= ~(ICANON); // Clear ICANON
81 tattr.c_lflag &= ~(ECHO); // and ECHO
82 if (timeout_decisecs < 0) {
83 tattr.c_cc[VMIN] = 1; // wait for one byte
84 tattr.c_cc[VTIME] = 0; // no timeout
85 } else if (timeout_decisecs > 0) {
86 tattr.c_cc[VMIN] = 0; // do not wait for incoming bytes
87 tattr.c_cc[VTIME] = timeout_decisecs; // timeout
88 } else {
89 tattr.c_cc[VMIN] = 0; // do not wait for incoming bytes
90 tattr.c_cc[VTIME] = 0; // no timeout
91 }
92 tcsetattr(STDIN_FILENO, TCSANOW, &tattr);
93
94 ssize_t read_bytes = read(STDIN_FILENO, buf, 1);
95
96 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes);
97 if (!blocking)
99
100 if (read_bytes == 1) {
101 return buf[0];
102 } else if (read_bytes < 0) {
103 throw Exception(errno, "Failed to read key from keyboard (getkey)");
104 } else {
105 return 0;
106 }
107}
108
109} // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
Fawkes library namespace.
static void clear_nonblock_flag()
Clear non-blocking flag on STDIN.
Definition: getkey.cpp:50
char getkey(int timeout_decisecs)
Get value of a single key-press non-blocking.
Definition: getkey.cpp:68
static void set_nonblock_flag()
Set non-blocking flag on STDIN.
Definition: getkey.cpp:39