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