tterm.c - iomenu - interactive terminal-based selection menu
(HTM) 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 }