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