tterm.c - neatvi - [fork] simple vi-type editor with UTF-8 support | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
tterm.c (3557B) | |
--- | |
1 #include <poll.h> | |
2 #include <signal.h> | |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
5 #include <string.h> | |
6 #include <sys/ioctl.h> | |
7 #include <termios.h> | |
8 #include <unistd.h> | |
9 #include "vi.h" | |
10 | |
11 static struct sbuf *term_sbuf; | |
12 static int rows, cols; | |
13 static struct termios termios; | |
14 | |
15 void term_init(void) | |
16 { | |
17 struct winsize win; | |
18 struct termios newtermios; | |
19 tcgetattr(0, &termios); | |
20 newtermios = termios; | |
21 newtermios.c_lflag &= ~(ICANON | ISIG); | |
22 newtermios.c_lflag &= ~ECHO; | |
23 tcsetattr(0, TCSAFLUSH, &newtermios); | |
24 if (getenv("LINES")) | |
25 rows = atoi(getenv("LINES")); | |
26 if (getenv("COLUMNS")) | |
27 cols = atoi(getenv("COLUMNS")); | |
28 if (!ioctl(0, TIOCGWINSZ, &win)) { | |
29 cols = win.ws_col; | |
30 rows = win.ws_row; | |
31 } | |
32 cols = cols ? cols : 80; | |
33 rows = rows ? rows : 25; | |
34 term_str("\33[m"); | |
35 } | |
36 | |
37 void term_done(void) | |
38 { | |
39 term_commit(); | |
40 tcsetattr(0, 0, &termios); | |
41 } | |
42 | |
43 void term_suspend(void) | |
44 { | |
45 term_done(); | |
46 kill(getpid(), SIGSTOP); | |
47 term_init(); | |
48 } | |
49 | |
50 void term_record(void) | |
51 { | |
52 if (!term_sbuf) | |
53 term_sbuf = sbuf_make(); | |
54 } | |
55 | |
56 void term_commit(void) | |
57 { | |
58 if (term_sbuf) { | |
59 write(1, sbuf_buf(term_sbuf), sbuf_len(term_sbuf)); | |
60 sbuf_free(term_sbuf); | |
61 term_sbuf = NULL; | |
62 } | |
63 } | |
64 | |
65 static void term_out(char *s) | |
66 { | |
67 if (term_sbuf) | |
68 sbuf_str(term_sbuf, s); | |
69 else | |
70 write(1, s, strlen(s)); | |
71 } | |
72 | |
73 void term_str(char *s) | |
74 { | |
75 term_out(s); | |
76 } | |
77 | |
78 void term_chr(int ch) | |
79 { | |
80 char s[4] = {ch}; | |
81 term_out(s); | |
82 } | |
83 | |
84 void term_kill(void) | |
85 { | |
86 term_out("\33[K"); | |
87 } | |
88 | |
89 void term_room(int n) | |
90 { | |
91 char cmd[16]; | |
92 if (n < 0) | |
93 sprintf(cmd, "\33[%dM", -n); | |
94 if (n > 0) | |
95 sprintf(cmd, "\33[%dL", n); | |
96 if (n) | |
97 term_out(cmd); | |
98 } | |
99 | |
100 void term_pos(int r, int c) | |
101 { | |
102 char buf[32] = "\r"; | |
103 if (c < 0) | |
104 c = 0; | |
105 if (c >= xcols) | |
106 c = cols - 1; | |
107 if (r < 0) | |
108 sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D'); | |
109 else | |
110 sprintf(buf, "\33[%d;%dH", r + 1, c + 1); | |
111 term_out(buf); | |
112 } | |
113 | |
114 int term_rows(void) | |
115 { | |
116 return rows; | |
117 } | |
118 | |
119 int term_cols(void) | |
120 { | |
121 return cols; | |
122 } | |
123 | |
124 static char ibuf[4096]; /* input character buffer */ | |
125 static char icmd[4096]; /* read after the last term_cmd()… | |
126 static int ibuf_pos, ibuf_cnt; /* ibuf[] position and length */ | |
127 static int icmd_pos; /* icmd[] position */ | |
128 | |
129 /* read s before reading from the terminal */ | |
130 void term_push(char *s, int n) | |
131 { | |
132 n = MIN(n, sizeof(ibuf) - ibuf_cnt); | |
133 memcpy(ibuf + ibuf_cnt, s, n); | |
134 ibuf_cnt += n; | |
135 } | |
136 | |
137 /* return a static buffer containing inputs read since the last term_cmd… | |
138 char *term_cmd(int *n) | |
139 { | |
140 *n = icmd_pos; | |
141 icmd_pos = 0; | |
142 return icmd; | |
143 } | |
144 | |
145 int term_read(void) | |
146 { | |
147 struct pollfd ufds[1]; | |
148 int n, c; | |
149 if (ibuf_pos >= ibuf_cnt) { | |
150 ufds[0].fd = 0; | |
151 ufds[0].events = POLLIN; | |
152 if (poll(ufds, 1, -1) <= 0) | |
153 return -1; | |
154 /* read a single input character */ | |
155 if ((n = read(0, ibuf, 1)) <= 0) | |
156 return -1; | |
157 ibuf_cnt = n; | |
158 ibuf_pos = 0; | |
159 } | |
160 c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1; | |
161 if (icmd_pos < sizeof(icmd)) | |
162 icmd[icmd_pos++] = c; | |
163 return c; | |
164 } | |
165 | |
166 /* return a static string that changes text attributes from old to att */ | |
167 char *term_att(int att, int old) | |
168 { | |
169 static char buf[128]; | |
170 char *s = buf; | |
171 int fg = SYN_FG(att); | |
172 int bg = SYN_BG(att); | |
173 if (att == old) | |
174 return ""; | |
175 s += sprintf(s, "\33["); | |
176 if (att & SYN_BD) | |
177 s += sprintf(s, ";1"); | |
178 if (att & SYN_IT) | |
179 s += sprintf(s, ";3"); | |
180 else if (att & SYN_RV) | |
181 s += sprintf(s, ";7"); | |
182 if (SYN_FGSET(att)) { | |
183 if ((fg & 0xff) < 8) | |
184 s += sprintf(s, ";%d", 30 + (fg & 0xff)); | |
185 else | |
186 s += sprintf(s, ";38;5;%d", (fg & 0xff)); | |
187 } | |
188 if (SYN_BGSET(att)) { | |
189 if ((bg & 0xff) < 8) | |
190 s += sprintf(s, ";%d", 40 + (bg & 0xff)); | |
191 else | |
192 s += sprintf(s, ";48;5;%d", (bg & 0xff)); | |
193 } | |
194 s += sprintf(s, "m"); | |
195 return buf; | |
196 } |