fbpad: write to stdin to hide the cursor
[fbpad.git] / term.c
blobd9acebf83eca2fff2fc38798fb5cfcbf4fcba3d3
1 #include <ctype.h>
2 #include <pty.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include "pad.h"
9 #include "util.h"
10 #include "term.h"
12 #define FGCOLOR 0
13 #define BGCOLOR 7
14 #define SQRADDR(r, c) (&screen[(r) * pad_cols() + (c)])
16 #define MODE_NOCURSOR 0x01
17 #define MODE_NOWRAP 0x02
18 #define MODE_ORIGIN 0x04
19 #define MODE_NOAUTOCR 0x08
20 #define BIT_SET(i, b, val) ((val) ? ((i) | (b)) : ((i) & ~(b)))
22 static pid_t pid;
23 static int fd;
24 static int row, col;
25 static int fg, bg;
26 static struct square screen[MAXCHARS];
27 static int top, bot;
28 static int mode;
29 static struct miscterm_state saved;
31 static int origin(void)
33 return mode & MODE_ORIGIN;
36 static void setsize(void)
38 struct winsize size;
39 size.ws_col = pad_cols();
40 size.ws_row = pad_rows();
41 size.ws_xpixel = 0;
42 size.ws_ypixel = 0;
43 ioctl(fd, TIOCSWINSZ, &size);
46 static int readpty(void)
48 char b;
49 if (read(fd, &b, 1) > 0)
50 return (int) b;
51 return -1;
54 static void term_show(int r, int c, int cursor)
56 struct square *sqr = SQRADDR(r, c);
57 int fgcolor = sqr->c ? sqr->fg : fg;
58 int bgcolor = sqr->c ? sqr->bg : bg;
59 if (cursor && !(mode & MODE_NOCURSOR)) {
60 int t = fgcolor;
61 fgcolor = bgcolor;
62 bgcolor = t;
64 pad_put(sqr->c, r, c, fgcolor, bgcolor);
67 void term_put(int ch, int r, int c)
69 struct square *sqr = SQRADDR(r, c);
70 sqr->c = ch;
71 sqr->fg = fg;
72 sqr->bg = bg;
73 term_show(r, c, 0);
76 static void empty_rows(int sr, int er)
78 memset(SQRADDR(sr, 0), 0, (er - sr) * sizeof(screen[0]) * pad_cols());
81 static void blank_rows(int sr, int er)
83 int i;
84 empty_rows(sr, er);
85 for (i = sr * pad_cols(); i < er * pad_cols(); i++)
86 term_show(i / pad_cols(), i % pad_cols(), 0);
87 term_show(row, col, 1);
90 static void scroll_screen(int sr, int nr, int n)
92 term_show(row, col, 0);
93 memmove(SQRADDR(sr + n, 0), SQRADDR(sr, 0),
94 nr * pad_cols() * sizeof(screen[0]));
95 if (n > 0)
96 empty_rows(sr, sr + n);
97 else
98 empty_rows(sr + nr + n, sr + nr);
99 pad_scroll(sr, nr, n, bg);
100 term_show(row, col, 1);
103 static void insert_lines(int n)
105 int sr = MAX(top, row);
106 int nr = bot - row - n;
107 if (nr > 0)
108 scroll_screen(sr, nr, n);
111 static void delete_lines(int n)
113 int r = MAX(top, row);
114 int sr = r + n;
115 int nr = bot - r - n;
116 if (nr > 0)
117 scroll_screen(sr, nr, -n);
120 static void move_cursor(int r, int c)
122 term_show(row, col, 0);
123 row = MAX(origin() ? top : 0, MIN(r, (origin() ? bot : pad_rows()) - 1));
124 col = MAX(0, MIN(c, pad_cols() - 1));
125 term_show(row, col, 1);
128 static void advance(int dr, int dc, int scrl)
130 int r = row + dr;
131 int c = col + dc;
132 int t = origin() ? top : 0;
133 int b = origin() ? bot : pad_rows();
134 if (c >= pad_cols()) {
135 if (!scrl || (mode & MODE_NOWRAP)) {
136 c = pad_cols() - 1;
137 } else {
138 r++;
139 c = 0;
142 if (r >= b && scrl) {
143 int n = b - r - 1;
144 int nr = (b - t) + n;
145 scroll_screen(-n, nr, n);
147 if (r < t && scrl) {
148 int n = t - r;
149 int nr = (b - t) - n;
150 scroll_screen(t, nr, n);
152 r = MIN(b - 1, MAX(t, r));
153 move_cursor(r, MAX(0, c));
156 void term_send(int c)
158 unsigned char b = (unsigned char) c;
159 if (fd)
160 write(fd, &b, 1);
163 void term_sendstr(char *s)
165 if (fd)
166 write(fd, s, strlen(s));
169 static void setmode(int m)
171 if (m == 0) {
172 fg = FGCOLOR;
173 bg = BGCOLOR;
175 if (m == 1)
176 fg = fg | 0x08;
177 if (m == 7) {
178 int t = fg;
179 fg = bg;
180 bg = t;
182 if (m >= 30 && m <= 37)
183 fg = m - 30;
184 if (m >= 40 && m <= 47)
185 bg = m - 40;
188 static void kill_chars(int sc, int ec)
190 int i;
191 memset(SQRADDR(row, sc), 0, (ec - sc) * sizeof(screen[0]));
192 for (i = sc; i < ec; i++)
193 term_show(row, i, 0);
194 move_cursor(row, col);
197 static void move_chars(int sc, int nc, int n)
199 int i;
200 term_show(row, col, 0);
201 memmove(SQRADDR(row, sc + n), SQRADDR(row, sc),
202 nc * sizeof(screen[0]));
203 if (n > 0)
204 memset(SQRADDR(row, sc), 0, n * sizeof(screen[0]));
205 else
206 memset(SQRADDR(row, pad_rows() + n), 0, -n * sizeof(screen[0]));
207 for (i = MIN(sc, sc + n); i < pad_cols(); i++)
208 term_show(row, i, 0);
209 term_show(row, col, 1);
212 static void delete_chars(int n)
214 move_chars(col + n, pad_cols(), -n);
217 static void insert_chars(int n)
219 int nc = pad_cols() - col - n;
220 move_chars(col, nc, n);
223 void term_blank(void)
225 pad_blank(bg);
226 memset(screen, 0, sizeof(screen));
229 static void ctlseq(void);
230 void term_read(void)
232 ctlseq();
235 void term_exec(char *cmd)
237 if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1)
238 xerror("failed to create a pty");
239 if (!pid) {
240 setenv("TERM", "linux", 1);
241 execl(cmd, cmd, NULL);
242 exit(1);
244 setsize();
245 setmode(0);
246 term_blank();
249 static void misc_save(struct miscterm_state *state)
251 state->row = row;
252 state->col = col;
253 state->fg = fg;
254 state->bg = bg;
255 state->top = top;
256 state->bot = bot;
257 state->mode = mode;
260 static void misc_load(struct miscterm_state *state)
262 row = state->row;
263 col = state->col;
264 fg = state->fg;
265 bg = state->bg;
266 top = state->top;
267 bot = state->bot;
268 mode = state->mode;
271 void term_save(struct term_state *state)
273 state->fd = fd;
274 state->pid = pid;
275 memcpy(state->screen, screen,
276 pad_rows() * pad_cols() * sizeof(screen[0]));
277 state->sav = saved;
278 misc_save(&state->cur);
281 void term_load(struct term_state *state)
283 int i;
284 fd = state->fd;
285 pid = state->pid;
286 misc_load(&state->cur);
287 saved = state->sav;
288 memcpy(screen, state->screen,
289 pad_rows() * pad_cols() * sizeof(screen[0]));
290 for (i = 0; i < pad_rows() * pad_cols(); i++)
291 term_show(i / pad_cols(), i % pad_cols(), 0);
292 term_show(row, col, 1);
295 int term_fd(void)
297 return fd;
300 void term_init(void)
302 pad_init();
303 bot = pad_rows();
304 term_blank();
307 void term_free(void)
309 pad_free();
312 void term_end(void)
314 fd = 0;
315 row = col = 0;
316 fg = 0;
317 bg = 0;
318 term_blank();
321 void set_region(int t, int b)
323 top = MIN(pad_rows(), MAX(0, t - 1));
324 bot = MIN(pad_rows(), MAX(0, b ? b : pad_rows()));
325 if (origin())
326 move_cursor(top, 0);
329 #include "vt102.c"