Fawkes API
Fawkes Development Version
|
00001 /*************************************************************************** 00002 * getkey.cpp - getkey returns a keypress in non-blocking manner 00003 * 00004 * Created: Thu Jun 04 19:08:13 2009 (from RCSoftX) 00005 * Copyright 2009 Masrur Doostdar <doostdar@kbsg.rwth-aachen.de> 00006 * 00007 ****************************************************************************/ 00008 00009 /* This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU Library General Public License for more details. 00018 * 00019 * Read the full text in the LICENSE.GPL file in the doc directory. 00020 */ 00021 00022 #include <utils/system/getkey.h> 00023 #include <core/exception.h> 00024 #include <cerrno> 00025 #include <cstdio> 00026 #include <unistd.h> 00027 #include <termios.h> 00028 #include <fcntl.h> 00029 00030 00031 namespace fawkes { 00032 00033 /** Set non-blocking flag on STDIN. 00034 * Sets the 0_NONBLOCK Flag to 1, so that the read command in the 00035 * getkey()-method wont block the programm till a input is made (see also 00036 * libc manual, pages 105 and 117). 00037 */ 00038 static void 00039 set_nonblock_flag() 00040 { 00041 int oldflags; 00042 00043 oldflags = fcntl(STDIN_FILENO, F_GETFL, 0); 00044 oldflags |= O_NONBLOCK; 00045 fcntl(STDIN_FILENO, F_SETFL, oldflags); 00046 } 00047 00048 00049 /** Clear non-blocking flag on STDIN. */ 00050 static void 00051 clear_nonblock_flag() 00052 { 00053 int oldflags; 00054 00055 oldflags = fcntl(STDIN_FILENO, F_GETFL, 0); 00056 oldflags &= ~O_NONBLOCK; 00057 fcntl(STDIN_FILENO, F_SETFL, oldflags); 00058 } 00059 00060 00061 /** Get value of a single key-press non-blocking. 00062 * This method checks if a new keypress has happened and returns the value in 00063 * this case. Otherwise it returns 0. The method does not block. 00064 * @param timeout_decisecs If less than 0 wait forever, if 0 non-blocking 00065 * (returns 0 if no key pressed immediately, if greater than 0 it is the 00066 * timeout in deciseconds. 00067 * @return key pressed or 0 (no key read) 00068 */ 00069 char 00070 getkey(int timeout_decisecs) 00071 { 00072 bool blocking = (timeout_decisecs != 0); 00073 char buf[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 00074 struct termios tattr, // new terminal attributes 00075 saved_attributes; // restore the original settings 00076 00077 if (! blocking) set_nonblock_flag(); 00078 tcgetattr(STDIN_FILENO, &saved_attributes); // save the original attributes 00079 00080 tcgetattr(STDIN_FILENO, &tattr); // set the new attributes 00081 tattr.c_lflag &= ~(ICANON); // Clear ICANON 00082 tattr.c_lflag &= ~(ECHO); // and ECHO 00083 if (timeout_decisecs < 0) { 00084 tattr.c_cc[VMIN] = 1; // wait for one byte 00085 tattr.c_cc[VTIME]= 0; // no timeout 00086 } else if (timeout_decisecs > 0) { 00087 tattr.c_cc[VMIN] = 0; // do not wait for incoming bytes 00088 tattr.c_cc[VTIME]= timeout_decisecs; // timeout 00089 } else { 00090 tattr.c_cc[VMIN] = 0; // do not wait for incoming bytes 00091 tattr.c_cc[VTIME]= 0; // no timeout 00092 } 00093 tcsetattr(STDIN_FILENO, TCSANOW, &tattr); 00094 00095 ssize_t read_bytes = read(STDIN_FILENO, buf, 1); 00096 00097 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes); 00098 if (! blocking) clear_nonblock_flag(); 00099 00100 if (read_bytes == 1) { 00101 return buf[0]; 00102 } else { 00103 throw Exception(errno, "Failed to read key from keyboard (getkey)"); 00104 } 00105 } 00106 00107 } // end namespace fawkes 00108