|
|
term.c - iomenu - interactive terminal-based selection menu |
|
|
 |
git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu (git://bitreich.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
 |
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 } |
|