kbhit.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /* ***************************************************************************
  22. *
  23. * Copyright 1992-2002 by Pete Wilson All Rights Reserved
  24. * 50 Staples Street : Lowell Massachusetts 01851 : USA
  25. * http://www.pwilson.net/ [email protected] +1 978-454-4547
  26. *
  27. * This item is free software: you can redistribute it and/or modify it as
  28. * long as you preserve this copyright notice. Pete Wilson prepared this item
  29. * hoping it might be useful, but it has NO WARRANTY WHATEVER, not even any
  30. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  31. *
  32. *************************************************************************** */
  33. /* ***************************************************************************
  34. *
  35. * KBHIT.C
  36. *
  37. * Based on the work of W. Richard Stevens, Advanced Programming in
  38. * the Unix Environment," Addison-Wesley; and of Floyd Davidson.
  39. *
  40. * Contains these functions:
  41. *
  42. * To set the TTY mode:
  43. * tty_set_raw() Unix setup to read a character at a time.
  44. * tty_set_cooked() Unix setup to reverse tty_set_raw()
  45. *
  46. * To read keyboard input:
  47. * kb_getc() keyboard get character, NON-BLOCKING. If a char
  48. * has been typed, return it. Else return 0.
  49. * kb_getc_w() kb get char with wait: BLOCKING. Wait for a char
  50. * to be typed and return it.
  51. *
  52. * How to use:
  53. * tty_set_raw() set the TTY mode to read one char at a time.
  54. * kb_getc() read chars one by one.
  55. * tty_set_cooked() VERY IMPORTANT: restore cooked mode when done.
  56. *
  57. * Revision History:
  58. *
  59. * DATE DESCRIPTION
  60. * ----------- --------------------------------------------
  61. * 12-jan-2002 new
  62. * 20-aug-2002 cleanup
  63. *
  64. *************************************************************************** */
  65. #ifdef __cplusplus
  66. extern "C" {
  67. #endif
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #include <termios.h>
  72. #include <unistd.h>
  73. #include <errno.h>
  74. #ifndef STDIN_FILENO
  75. #define STDIN_FILENO 0
  76. #endif
  77. extern int errno;
  78. static struct termios termattr, save_termattr;
  79. static int ttysavefd = -1;
  80. static enum
  81. {
  82. RESET, RAW, CBREAK
  83. } ttystate = RESET;
  84. /* ***************************************************************************
  85. *
  86. * set_tty_raw(), put the user's TTY in one-character-at-a-time mode.
  87. * returns 0 on success, -1 on failure.
  88. *
  89. *************************************************************************** */
  90. int
  91. set_tty_raw(void)
  92. {
  93. int i;
  94. i = tcgetattr (STDIN_FILENO, &termattr);
  95. if (i < 0)
  96. {
  97. printf("tcgetattr() returned %d for fildes=%d\n",i,STDIN_FILENO);
  98. perror ("");
  99. return -1;
  100. }
  101. save_termattr = termattr;
  102. termattr.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
  103. termattr.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
  104. termattr.c_cflag &= ~(CSIZE | PARENB);
  105. termattr.c_cflag |= CS8;
  106. termattr.c_oflag &= ~(OPOST);
  107. termattr.c_cc[VMIN] = 1;
  108. termattr.c_cc[VTIME] = 0;
  109. i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
  110. if (i < 0)
  111. {
  112. printf("tcsetattr() returned %d for fildes=%d\n",i,STDIN_FILENO);
  113. perror("");
  114. return -1;
  115. }
  116. ttystate = RAW;
  117. ttysavefd = STDIN_FILENO;
  118. return 0;
  119. }
  120. /* ***************************************************************************
  121. *
  122. * set_tty_cbreak(), put the user's TTY in cbreak mode.
  123. * returns 0 on success, -1 on failure.
  124. *
  125. *************************************************************************** */
  126. int
  127. set_tty_cbreak()
  128. {
  129. int i;
  130. i = tcgetattr (STDIN_FILENO, &termattr);
  131. if (i < 0)
  132. {
  133. printf("tcgetattr() returned %d for fildes=%d\n",i,STDIN_FILENO);
  134. perror ("");
  135. return -1;
  136. }
  137. save_termattr = termattr;
  138. termattr.c_lflag &= ~(ECHO | ICANON);
  139. termattr.c_cc[VMIN] = 1;
  140. termattr.c_cc[VTIME] = 0;
  141. i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
  142. if (i < 0)
  143. {
  144. printf("tcsetattr() returned %d for fildes=%d\n",i,STDIN_FILENO);
  145. perror ("");
  146. return -1;
  147. }
  148. ttystate = CBREAK;
  149. ttysavefd = STDIN_FILENO;
  150. return 0;
  151. }
  152. /* ***************************************************************************
  153. *
  154. * set_tty_cooked(), restore normal TTY mode. Very important to call
  155. * the function before exiting else the TTY won't be too usable.
  156. * returns 0 on success, -1 on failure.
  157. *
  158. *************************************************************************** */
  159. int
  160. set_tty_cooked()
  161. {
  162. int i;
  163. if (ttystate != CBREAK && ttystate != RAW)
  164. {
  165. return 0;
  166. }
  167. i = tcsetattr (STDIN_FILENO, TCSAFLUSH, &save_termattr);
  168. if (i < 0)
  169. {
  170. return -1;
  171. }
  172. ttystate = RESET;
  173. return 0;
  174. }
  175. /* ***************************************************************************
  176. *
  177. * kb_getc(), if there's a typed character waiting to be read,
  178. * return it; else return 0.
  179. *
  180. *************************************************************************** */
  181. unsigned char
  182. kb_getc(void)
  183. {
  184. unsigned char ch;
  185. ssize_t size;
  186. size = read (STDIN_FILENO, &ch, 1);
  187. if (size == 0)
  188. {
  189. return 0;
  190. }
  191. else
  192. {
  193. return ch;
  194. }
  195. }
  196. /* ***************************************************************************
  197. *
  198. * kb_getc_w(), wait for a character to be typed and return it.
  199. *
  200. *************************************************************************** */
  201. unsigned char
  202. kb_getc_w(void)
  203. {
  204. unsigned char ch;
  205. size_t size;
  206. while (1)
  207. {
  208. usleep(20000); /* 1/50th second: thanks, Floyd! */
  209. size = read (STDIN_FILENO, &ch, 1);
  210. if (size > 0)
  211. {
  212. break;
  213. }
  214. }
  215. return ch;
  216. }
  217. #define TEST
  218. #ifdef TEST
  219. void echo(unsigned char ch);
  220. static enum
  221. {
  222. CH_ONLY, CH_HEX
  223. } how_echo = CH_ONLY;
  224. int
  225. main(int argc, char * argv[])
  226. {
  227. unsigned char ch;
  228. printf("Test Unix single-character input.\n");
  229. set_tty_raw(); /* set up character-at-a-time */
  230. while (1) /* wait here for a typed char */
  231. {
  232. usleep(20000); /* 1/50th second: thanks, Floyd! */
  233. ch = kb_getc(); /* char typed by user? */
  234. if (0x03 == ch) /* might be control-C */
  235. {
  236. set_tty_cooked(); /* control-C, restore normal TTY mode */
  237. return 1; /* and get out */
  238. }
  239. echo(ch); /* not control-C, echo it */
  240. }
  241. }
  242. void
  243. echo(unsigned char ch)
  244. {
  245. switch (how_echo)
  246. {
  247. case CH_HEX:
  248. printf("%c,0x%x ",ch,ch);
  249. break;
  250. default:
  251. case CH_ONLY:
  252. printf("%c", ch);
  253. break;
  254. }
  255. fflush(stdout); /* push it out */
  256. }
  257. #endif /* test */
  258. #ifdef __cplusplus
  259. }
  260. #endif