term.c - iomenu - interactive terminal-based selection menu HTML git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- term.c (1806B) --- 1 #include "term.h" 2 #include <ctype.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <sys/ioctl.h> 7 #include <termios.h> 8 #include "compat.h" 9 #include "utf8.h" 10 11 struct term term; 12 13 static int 14 term_codepoint_width(uint32_t codepoint, int pos) 15 { 16 if (codepoint == '\t') 17 return 8 - pos % 8; 18 return wcwidth(codepoint); 19 } 20 21 int 22 term_at_width(char const *s, int width, int pos) 23 { 24 char const *beg = s; 25 26 for (uint32_t state = 0, codepoint; *s != '\0'; s++) { 27 if (utf8_decode(&state, &codepoint, *s) == UTF8_ACCEPT) { 28 pos += term_codepoint_width(codepoint, pos); 29 if (pos > width) 30 break; 31 } 32 } 33 return s - beg; 34 } 35 36 int 37 term_raw_on(int fd) 38 { 39 static char *seq = "\x1b[s\x1b[?1049h\x1b[H"; 40 struct termios termios; 41 ssize_t len = strlen(seq); 42 43 if (write(fd, seq, len) < len) 44 return -1; 45 46 memset(&termios, 0, sizeof termios); 47 if (tcgetattr(fd, &term.termios) < 0) 48 return -1; 49 memcpy(&termios, &term.termios, sizeof termios); 50 51 termios.c_lflag &= ~(ICANON | ECHO | IEXTEN | IGNBRK | ISIG); 52 if (tcsetattr(fd, TCSANOW, &termios) == -1) 53 return -1; 54 return 0; 55 } 56 57 int 58 term_raw_off(int fd) 59 { 60 static char *seq = "\x1b[2J\x1b[u\033[?1049l"; 61 ssize_t len = strlen(seq); 62 63 if (tcsetattr(fd, TCSANOW, &term.termios) < 0) 64 return -1; 65 if (write(fd, seq, len) < len) 66 return -1; 67 return 0; 68 } 69 70 int 71 term_get_key(FILE *fp) 72 { 73 int key, num; 74 75 key = fgetc(fp); 76 top: 77 switch (key) { 78 case EOF: 79 return -1; 80 case TERM_KEY_ALT('['): 81 key = getc(fp); 82 if (key == EOF) 83 return -1; 84 85 for (num = 0; isdigit(key);) { 86 num *= 10; 87 num += key - '0'; 88 89 key = fgetc(fp); 90 if (key == EOF) 91 return -1; 92 } 93 94 key = TERM_KEY_CSI(key, num); 95 96 goto top; 97 case TERM_KEY_ESC: 98 key = getc(fp); 99 if (key == EOF) 100 return -1; 101 key = TERM_KEY_ALT(key); 102 goto top; 103 default: 104 return key; 105 } 106 }