1#include "koh_term.h"23#include <poll.h>4#include <stdio.h>5#include <sys/ioctl.h>6#include <termios.h>7#include <unistd.h>89static struct termios koh_saved;10static int koh_have_saved = 0;1112int koh_term_raw(int enable) {13 if (enable) {14 if (!isatty(STDIN_FILENO)) {15 return 0;16 }17 if (tcgetattr(STDIN_FILENO, &koh_saved) != 0) {18 return 0;19 }20 koh_have_saved = 1;21 struct termios raw = koh_saved;222324 raw.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ISIG | IEXTEN);25 raw.c_iflag &= (tcflag_t) ~(IXON | ICRNL | BRKINT | INPCK | ISTRIP);26 raw.c_cc[VMIN] = 1;27 raw.c_cc[VTIME] = 0;28 return tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == 0;29 }30 if (koh_have_saved) {31 tcsetattr(STDIN_FILENO, TCSAFLUSH, &koh_saved);32 koh_have_saved = 0;33 }34 return 1;35}3637int koh_term_size(int *rows, int *cols) {38 struct winsize size;39 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == 0 && size.ws_row > 0 && size.ws_col > 0) {40 *rows = (int)size.ws_row;41 *cols = (int)size.ws_col;42 return 1;43 }44 *rows = 24;45 *cols = 80;46 return 0;47}4849static int koh_poll_input(int milliseconds) {50 struct pollfd p;51 p.fd = STDIN_FILENO;52 p.events = POLLIN;53 p.revents = 0;54 return poll(&p, 1, milliseconds) > 0;55}5657int koh_read_key(char *buf, int cap) {58 if (cap <= 0) {59 return 0;60 }61 ssize_t n = read(STDIN_FILENO, buf, 1);62 if (n <= 0) {63 return 0;64 }65 int total = 1;666768 if (buf[0] == 0x1b) {69 if (koh_poll_input(25)) {70 ssize_t m = read(STDIN_FILENO, buf + 1, (size_t)(cap - 1));71 if (m > 0) {72 total += (int)m;73 }74 }75 return total;76 }7778798081 int remaining = 0;82 unsigned char first = (unsigned char)buf[0];83 if ((first & 0xf8) == 0xf0) {84 remaining = 3;85 } else if ((first & 0xf0) == 0xe0) {86 remaining = 2;87 } else if ((first & 0xe0) == 0xc0) {88 remaining = 1;89 }90 while (remaining > 0 && total < cap) {91 if (!koh_poll_input(10)) {92 break;93 }94 ssize_t m = read(STDIN_FILENO, buf + total, 1);95 if (m <= 0) {96 break;97 }98 total += (int)m;99 remaining--;100 }101 return total;102}