diff --git a/.hgignore b/.hgignore index 6f7beca..0110280 100644 --- a/.hgignore +++ b/.hgignore @@ -1 +1,2 @@ .o$ +ke/ke diff --git a/ke/Makefile b/ke/Makefile index 87d40de..e608d82 100644 --- a/ke/Makefile +++ b/ke/Makefile @@ -1,5 +1,9 @@ BIN := ke -OBJS := main.o terminal.o util.o +OBJS := main.o \ + display.o \ + keys.o \ + terminal.o \ + util.o LDFLAGS := -static CFLAGS := -pedantic -Wall -Werror -Wextra -O2 -std=c99 diff --git a/ke/main.c b/ke/main.c index 2baaffc..388c690 100644 --- a/ke/main.c +++ b/ke/main.c @@ -5,6 +5,8 @@ #include #include +#include "display.h" +#include "keys.h" #include "terminal.h" #include "util.h" @@ -12,42 +14,8 @@ void loop() { - char c; - int command = 0; - while (1) { - c = '\0'; - /* - * Note that Cygwin, apparently, will treat a read time- - * out as an error with errno == EAGAIN. I don't really - * have any interest in supporting code for Cygwin. - */ - if ((read(STDIN_FILENO, &c, 1) == -1)) { - die("failed to read from the terminal"); - } - - if (c == 0x00) { - continue; - } - - if (command && ((c == 'q') || (c == 0x11))) { - break; - } - - if (c == 0x0b) { - if (!command) { - command = 1; - continue; - } - } else { - command = 0; - } - - if (iscntrl(c)) { - printf("%02x\r\n", c); - } else { - printf("%02x ('%c')\r\n", c, c); - } + process_keypress(); } } @@ -56,6 +24,8 @@ int main() { setup_terminal(); + + display_clear(); loop(); return 0; diff --git a/ke/notes.txt b/ke/notes.txt new file mode 100644 index 0000000..95be4ce --- /dev/null +++ b/ke/notes.txt @@ -0,0 +1,87 @@ +static void +enable_termraw() +{ + struct termios raw; + + /* Read the current terminal parameters for standard input. */ + if (tcgetattr(STDIN_FILENO, &raw) == -1) { + die("tcgetattr while enabling raw mode"); + } + + /* + * Turn off software flow control. IXON: disable flow control, + * so named because XON and XOFF :) + * + * ICRNL: Don't interpret carriage returns as newlines. + * + * raw.c_iflag &= ~(ICRNL|IXON|BRKINT|INPCK|ISTRIP); + */ + + /* + * Turn off the terminal's conversion of newlines -> carriage + * return + newline. + * + * raw.c_oflag &= ~(OPOST); + */ + + /* + * Turn off the local ECHO mode, which we need to do in raw mode + * because what gets displayed is going to need extra control. + * + * ICANON: Turn off canonical mode. + * + * ISIG: Turn off SIGINT / SIGSTP processing. + * + * IEXTEN: turn off ^v processing. + * + * NOTE(kyle): look into cfmakeraw, which will require + * snapshotting. However, this skips all the notes about what + * it takes to put the terminal in raw mode. + * + * raw.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN); + */ + + /* + * The following are probably not really needed on modern + * terminals, but it's fashionable to do as much. + * + * BRKINT: break conditions trigger SIGINT. + * + * INPCK: parity checking, which might be useful over serial + * terminals? + * + * ISTRIP strips the high bit. + * + * CS: set character size to 8-bit. + * raw.c_iflag &= ~(BRKINT | INPCK | ISTRIP); + * + * NOTE(kyle): I had this set here, but then it turns out + * that it fuckled my terminal. + * raw.c_cflag |= CS8; + */ + + /* + * Switched over to cfmakeraw. + */ + cfmakeraw(&raw); + + /* + * Set timeout for read(2). + * + * VMIN: what is the minimum number of bytes required for read + * to return? + * + * VTIME: max time before read(2) returns in hundreds of milli- + * seconds. + */ + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + /* + * Now write the terminal parameters to the current terminal, + * after flushing any waiting input out. + */ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { + die("tcsetattr while enabling raw mode"); + } +} diff --git a/ke/terminal.c b/ke/terminal.c index 0adf61c..d573420 100644 --- a/ke/terminal.c +++ b/ke/terminal.c @@ -5,6 +5,9 @@ #include "util.h" +#define ESCSEQ "\x1b[" + + static struct termios entry_term; @@ -68,3 +71,11 @@ setup_terminal() atexit(disable_termraw); enable_termraw(); } + + +void +display_clear() +{ + write(STDOUT_FILENO, ESCSEQ "2J", 4); + write(STDOUT_FILENO, ESCSEQ "H", 3); +} diff --git a/ke/terminal.h b/ke/terminal.h index 8d4b472..1bb47d9 100644 --- a/ke/terminal.h +++ b/ke/terminal.h @@ -3,6 +3,7 @@ void setup_terminal(); +void display_clear(); #endif /* KE_TERMINAL_H */ diff --git a/ke/util.c b/ke/util.c index 446297e..1f13abf 100644 --- a/ke/util.c +++ b/ke/util.c @@ -5,6 +5,13 @@ void die(const char *s) { + /* + * NOTE(kyle): this is a duplication of the code in display.c + * but I would like to be able to import these files from there. + */ + write(STDOUT_FILENO, "\x1b[2J", 4); + write(STDOUT_FILENO, "\x1b[H", 3); + perror(s); exit(1); }