123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- #include <iostream>
- // raw mode
- #include <termios.h>
- #include <unistd.h>
- #include "door.h"
- // let's try this!
- #include <signal.h>
- #include <unistd.h>
- /**
- * @file
- * @brief Key and door input routines
- */
- void done(int signal) {
- std::cout << "\r\nWORP WORP\r\n";
- std::cout.flush();
- }
- #include <ctype.h>
- struct termios tio_default;
- void raw(void) {
- // enable terminal RAW mode
- struct termios tio_raw;
- tcgetattr(STDIN_FILENO, &tio_default);
- tio_raw = tio_default;
- cfmakeraw(&tio_raw);
- /*
- This works in the console, but fails with a terminal.
- Ok, I am getting (what I would expect), but we're never timing out
- now. (So it has to fill up the buffer before exiting...)
- CRAP!
- */
- // Ok! I need the extra sauce here
- tio_raw.c_cc[VMIN] = 0;
- tio_raw.c_cc[VTIME] = 1;
- // tio_raw.c_iflag &= ~(ICRNL | IXON);
- tcsetattr(STDIN_FILENO, TCSANOW, &tio_raw);
- }
- void reset(void) { tcsetattr(STDIN_FILENO, TCOFLUSH, &tio_default); }
- #define CRNL "\r\n"
- /*
- NOTE: cr (from syncterm), gives 0x0d 0x00
- */
- signed int getch(void) {
- fd_set socket_set;
- struct timeval tv;
- int select_ret = -1;
- int recv_ret;
- char key;
- while (select_ret == -1) {
- FD_ZERO(&socket_set);
- FD_SET(STDIN_FILENO, &socket_set);
- tv.tv_sec = 0;
- tv.tv_usec = 100;
- select_ret = select(STDIN_FILENO + 1, &socket_set, NULL, NULL, &tv);
- // select(STDIN_FILENO + 1, &socket_set, NULL, NULL, bWait ? NULL : &tv);
- if (select_ret == -1) {
- if (errno == EINTR)
- continue;
- return (-2);
- }
- if (select_ret == 0)
- return (-1);
- }
- recv_ret = read(STDIN_FILENO, &key, 1);
- if (recv_ret != 1) {
- std::cout << "eof?" << CRNL;
- std::cout.flush();
- return -2;
- }
- return key;
- }
- char buffer[10];
- int bpos = 0;
- void unget(char c) {
- if (bpos < sizeof(buffer) - 1) {
- buffer[bpos] = c;
- bpos++;
- }
- }
- char get(void) {
- if (bpos == 0) {
- return 0;
- }
- bpos--;
- char c = buffer[bpos];
- return c;
- }
- signed int getkey(void) {
- signed int c, c2;
- if (bpos != 0) {
- c = get();
- } else {
- c = getch();
- };
- if (c < 0)
- return c;
- /*
- What happens: syncterm gives us 0x0d 0x00 on [Enter].
- This strips out the possible null.
- */
- if (c == 0x0d) {
- c2 = getch();
- if ((c2 != 0) and (c2 >= 0))
- unget(c2);
- return c;
- }
- if (c == 0x1b) {
- // possible extended key
- c2 = getch();
- if (c2 < 0) {
- // nope, just plain ESC
- return c;
- }
- char extended[10];
- int pos = 0;
- extended[pos] = (char)c2;
- extended[pos + 1] = 0;
- pos++;
- while ((pos < sizeof(extended) - 1) and ((c2 = getch()) >= 0)) {
- // handle special case when I'm smashing out cursor location requests
- // and \x1b[X;YR strings get buffered
- if (c2 == 0x1b) {
- unget(c2);
- break;
- }
- extended[pos] = (char)c2;
- extended[pos + 1] = 0;
- pos++;
- }
- // FUTURE: Display debug when we fail to identify the key
- #ifdef DEBUGGS
- std::cout << CRNL "DEBUG:" CRNL "ESC + ";
- for (int x = 0; x < pos; x++) {
- char z = extended[x];
- if (iscntrl(z)) {
- std::cout << (int)z << " ";
- } else {
- std::cout << "'" << (char)z << "'"
- << " ";
- };
- }
- #endif
- if (extended[0] == '[') {
- switch (extended[1]) {
- case 'A':
- return XKEY_UP_ARROW;
- case 'B':
- return XKEY_DOWN_ARROW;
- case 'C':
- return XKEY_RIGHT_ARROW;
- case 'D':
- return XKEY_LEFT_ARROW;
- case 'H':
- return XKEY_HOME;
- case 'F':
- return XKEY_END; // terminal
- case 'K':
- return XKEY_END;
- case 'U':
- return XKEY_PGUP;
- case 'V':
- return XKEY_PGDN;
- case '@':
- return XKEY_INSERT;
- };
- if (extended[pos - 1] == '~') {
- // This ends with ~
- int number = atoi(extended + 1);
- switch (number) {
- case 2:
- return XKEY_INSERT; // terminal
- case 3:
- return XKEY_DELETE; // terminal
- case 5:
- return XKEY_PGUP; // terminal
- case 6:
- return XKEY_PGDN; // terminal
- case 15:
- return XKEY_F5; // terminal
- case 17:
- return XKEY_F6; // terminal
- case 18:
- return XKEY_F7; // terminal
- case 19:
- return XKEY_F8; // terminal
- case 20:
- return XKEY_F9; // terminal
- case 21:
- return XKEY_F10; // terminal
- case 23:
- return XKEY_F11;
- case 24:
- return XKEY_F12; // terminal
- }
- }
- }
- if (extended[0] == 'O') {
- switch (extended[1]) {
- case 'P':
- return XKEY_F1;
- case 'Q':
- return XKEY_F2;
- case 'R':
- return XKEY_F3;
- case 'S':
- return XKEY_F4;
- case 't':
- return XKEY_F5; // syncterm
- }
- }
- // unknown -- display debug output
- std::cout << CRNL "DEBUG:" CRNL "ESC + ";
- for (int x = 0; x < pos; x++) {
- char z = extended[x];
- if (iscntrl(z)) {
- std::cout << (int)z << " ";
- } else {
- std::cout << "'" << (char)z << "'"
- << " ";
- };
- }
- return XKEY_UNKNOWN;
- }
- return c;
- }
|