getkey.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include <iostream>
  2. // raw mode
  3. #include <termios.h>
  4. #include <unistd.h>
  5. #include "door.h"
  6. // let's try this!
  7. #include <signal.h>
  8. #include <unistd.h>
  9. void done(int signal) {
  10. std::cout << "\r\nWORP WORP\r\n";
  11. std::cout.flush();
  12. }
  13. #include <ctype.h>
  14. struct termios tio_default;
  15. void raw(void) {
  16. // enable terminal RAW mode
  17. struct termios tio_raw;
  18. tcgetattr(STDIN_FILENO, &tio_default);
  19. tio_raw = tio_default;
  20. cfmakeraw(&tio_raw);
  21. /*
  22. This works in the console, but fails with a terminal.
  23. Ok, I am getting (what I would expect), but we're never timing out
  24. now. (So it has to fill up the buffer before exiting...)
  25. CRAP!
  26. */
  27. // Ok! I need the extra sauce here
  28. tio_raw.c_cc[VMIN] = 0;
  29. tio_raw.c_cc[VTIME] = 1;
  30. // tio_raw.c_iflag &= ~(ICRNL | IXON);
  31. tcsetattr(STDIN_FILENO, TCSANOW, &tio_raw);
  32. }
  33. void reset(void) { tcsetattr(STDIN_FILENO, TCOFLUSH, &tio_default); }
  34. #define CRNL "\r\n"
  35. /*
  36. NOTE: cr (from syncterm), gives 0x0d 0x00
  37. */
  38. signed int getch(void) {
  39. fd_set socket_set;
  40. struct timeval tv;
  41. int select_ret = -1;
  42. int recv_ret;
  43. char key;
  44. while (select_ret == -1) {
  45. FD_ZERO(&socket_set);
  46. FD_SET(STDIN_FILENO, &socket_set);
  47. tv.tv_sec = 0;
  48. tv.tv_usec = 100;
  49. select_ret = select(STDIN_FILENO + 1, &socket_set, NULL, NULL, &tv);
  50. // select(STDIN_FILENO + 1, &socket_set, NULL, NULL, bWait ? NULL : &tv);
  51. if (select_ret == -1) {
  52. if (errno == EINTR)
  53. continue;
  54. return (-2);
  55. }
  56. if (select_ret == 0)
  57. return (-1);
  58. }
  59. recv_ret = read(STDIN_FILENO, &key, 1);
  60. if (recv_ret != 1) {
  61. std::cout << "eof?" << CRNL;
  62. std::cout.flush();
  63. return -2;
  64. }
  65. return key;
  66. }
  67. char buffer[10];
  68. int bpos = 0;
  69. void unget(char c) {
  70. if (bpos < sizeof(buffer) - 1) {
  71. buffer[bpos] = c;
  72. bpos++;
  73. }
  74. }
  75. char get(void) {
  76. if (bpos == 0) {
  77. return 0;
  78. }
  79. bpos--;
  80. char c = buffer[bpos];
  81. return c;
  82. }
  83. signed int getkey(void) {
  84. signed int c, c2;
  85. if (bpos != 0) {
  86. c = get();
  87. } else {
  88. c = getch();
  89. };
  90. if (c < 0)
  91. return c;
  92. /*
  93. What happens: syncterm gives us 0x0d 0x00 on [Enter].
  94. This strips out the possible null.
  95. */
  96. if (c == 0x0d) {
  97. c2 = getch();
  98. if ((c2 != 0) and (c2 >= 0))
  99. unget(c2);
  100. return c;
  101. }
  102. if (c == 0x1b) {
  103. // possible extended key
  104. c2 = getch();
  105. if (c2 < 0) {
  106. // nope, just plain ESC
  107. return c;
  108. }
  109. char extended[10];
  110. int pos = 0;
  111. extended[pos] = (char)c2;
  112. extended[pos + 1] = 0;
  113. pos++;
  114. while ((pos < sizeof(extended) - 1) and ((c2 = getch()) >= 0)) {
  115. // handle special case when I'm smashing out cursor location requests
  116. // and \x1b[X;YR strings get buffered
  117. if (c2 == 0x1b) {
  118. unget(c2);
  119. break;
  120. }
  121. extended[pos] = (char)c2;
  122. extended[pos + 1] = 0;
  123. pos++;
  124. }
  125. // FUTURE: Display debug when we fail to identify the key
  126. #ifdef DEBUGGS
  127. std::cout << CRNL "DEBUG:" CRNL "ESC + ";
  128. for (int x = 0; x < pos; x++) {
  129. char z = extended[x];
  130. if (iscntrl(z)) {
  131. std::cout << (int)z << " ";
  132. } else {
  133. std::cout << "'" << (char)z << "'"
  134. << " ";
  135. };
  136. }
  137. #endif
  138. if (extended[0] == '[') {
  139. switch (extended[1]) {
  140. case 'A':
  141. return XKEY_UP_ARROW;
  142. case 'B':
  143. return XKEY_DOWN_ARROW;
  144. case 'C':
  145. return XKEY_RIGHT_ARROW;
  146. case 'D':
  147. return XKEY_LEFT_ARROW;
  148. case 'H':
  149. return XKEY_HOME;
  150. case 'F':
  151. return XKEY_END; // terminal
  152. case 'K':
  153. return XKEY_END;
  154. case 'U':
  155. return XKEY_PGUP;
  156. case 'V':
  157. return XKEY_PGDN;
  158. case '@':
  159. return XKEY_INSERT;
  160. };
  161. if (extended[pos - 1] == '~') {
  162. // This ends with ~
  163. int number = atoi(extended + 1);
  164. switch (number) {
  165. case 2:
  166. return XKEY_INSERT; // terminal
  167. case 3:
  168. return XKEY_DELETE; // terminal
  169. case 5:
  170. return XKEY_PGUP; // terminal
  171. case 6:
  172. return XKEY_PGDN; // terminal
  173. case 15:
  174. return XKEY_F5; // terminal
  175. case 17:
  176. return XKEY_F6; // terminal
  177. case 18:
  178. return XKEY_F7; // terminal
  179. case 19:
  180. return XKEY_F8; // terminal
  181. case 20:
  182. return XKEY_F9; // terminal
  183. case 21:
  184. return XKEY_F10; // terminal
  185. case 23:
  186. return XKEY_F11;
  187. case 24:
  188. return XKEY_F12; // terminal
  189. }
  190. }
  191. }
  192. if (extended[0] == 'O') {
  193. switch (extended[1]) {
  194. case 'P':
  195. return XKEY_F1;
  196. case 'Q':
  197. return XKEY_F2;
  198. case 'R':
  199. return XKEY_F3;
  200. case 'S':
  201. return XKEY_F4;
  202. case 't':
  203. return XKEY_F5; // syncterm
  204. }
  205. }
  206. // unknown -- display debug output
  207. std::cout << CRNL "DEBUG:" CRNL "ESC + ";
  208. for (int x = 0; x < pos; x++) {
  209. char z = extended[x];
  210. if (iscntrl(z)) {
  211. std::cout << (int)z << " ";
  212. } else {
  213. std::cout << "'" << (char)z << "'"
  214. << " ";
  215. };
  216. }
  217. return XKEY_UNKNOWN;
  218. }
  219. return c;
  220. }