fbpad: basic term switching command
[fbpad.git] / term.c
blobc42a0b542db090a507b068594f876773cbbf0b29
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 draw_rows(int sr, int er)
83 int i = 0;
84 for (i = sr * pad_cols(); i < er * pad_cols(); i++)
85 term_show(i / pad_cols(), i % pad_cols(), 0);
88 static void blank_rows(int sr, int er)
90 empty_rows(sr, er);
91 draw_rows(sr, er);
92 term_show(row, col, 1);
95 static void scroll_screen(int sr, int nr, int n)
97 term_show(row, col, 0);
98 memmove(SQRADDR(sr + n, 0), SQRADDR(sr, 0),
99 nr * pad_cols() * sizeof(screen[0]));
100 if (n > 0)
101 empty_rows(sr, sr + n);
102 else
103 empty_rows(sr + nr + n, sr + nr);
104 /* draw_rows(MIN(sr, sr + n), MAX(sr + nr, sr + nr +n)); */
105 pad_scroll(sr, nr, n, bg);
106 term_show(row, col, 1);
109 static void insert_lines(int n)
111 int sr = MAX(top, row);
112 int nr = bot - row - n;
113 if (nr > 0)
114 scroll_screen(sr, nr, n);
117 static void delete_lines(int n)
119 int r = MAX(top, row);
120 int sr = r + n;
121 int nr = bot - r - n;
122 if (nr > 0)
123 scroll_screen(sr, nr, -n);
126 static void move_cursor(int r, int c)
128 term_show(row, col, 0);
129 row = MAX(origin() ? top : 0, MIN(r, (origin() ? bot : pad_rows()) - 1));
130 col = MAX(0, MIN(c, pad_cols() - 1));
131 term_show(row, col, 1);
134 static void advance(int dr, int dc, int scrl)
136 int r = row + dr;
137 int c = col + dc;
138 int t = origin() ? top : 0;
139 int b = origin() ? bot : pad_rows();
140 if (c >= pad_cols()) {
141 if (!scrl || (mode & MODE_NOWRAP)) {
142 c = pad_cols() - 1;
143 } else {
144 r++;
145 c = 0;
148 if (r >= b && scrl) {
149 int n = b - r - 1;
150 int nr = (b - t) + n;
151 scroll_screen(-n, nr, n);
153 if (r < t && scrl) {
154 int n = t - r;
155 int nr = (b - t) - n;
156 scroll_screen(t, nr, n);
158 r = MIN(b - 1, MAX(t, r));
159 move_cursor(r, MAX(0, c));
162 void term_send(int c)
164 unsigned char b = (unsigned char) c;
165 if (fd)
166 write(fd, &b, 1);
169 void term_sendstr(char *s)
171 if (fd)
172 write(fd, s, strlen(s));
175 static void setmode(int m)
177 if (m == 0) {
178 fg = FGCOLOR;
179 bg = BGCOLOR;
181 if (m == 1)
182 fg = fg | 0x08;
183 if (m == 7) {
184 int t = fg;
185 fg = bg;
186 bg = t;
188 if (m >= 30 && m <= 37)
189 fg = m - 30;
190 if (m >= 40 && m <= 47)
191 bg = m - 40;
194 static void kill_chars(int sc, int ec)
196 int i;
197 memset(SQRADDR(row, sc), 0, (ec - sc) * sizeof(screen[0]));
198 for (i = sc; i < ec; i++)
199 term_show(row, i, 0);
200 move_cursor(row, col);
203 static void move_chars(int sc, int nc, int n)
205 int i;
206 term_show(row, col, 0);
207 memmove(SQRADDR(row, sc + n), SQRADDR(row, sc),
208 nc * sizeof(screen[0]));
209 if (n > 0)
210 memset(SQRADDR(row, sc), 0, n * sizeof(screen[0]));
211 else
212 memset(SQRADDR(row, pad_rows() + n), 0, -n * sizeof(screen[0]));
213 for (i = MIN(sc, sc + n); i < pad_cols(); i++)
214 term_show(row, i, 0);
215 term_show(row, col, 1);
218 static void delete_chars(int n)
220 move_chars(col + n, pad_cols(), -n);
223 static void insert_chars(int n)
225 int nc = pad_cols() - col - n;
226 move_chars(col, nc, n);
229 void term_blank(void)
231 pad_blank(bg);
232 memset(screen, 0, sizeof(screen));
235 static void ctlseq(void);
236 void term_read(void)
238 ctlseq();
241 void term_exec(char *cmd)
243 if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1)
244 xerror("failed to create a pty");
245 if (!pid) {
246 setenv("TERM", "linux", 1);
247 execl(cmd, cmd, NULL);
248 exit(1);
250 setsize();
251 setmode(0);
252 term_blank();
255 static void misc_save(struct miscterm_state *state)
257 state->row = row;
258 state->col = col;
259 state->fg = fg;
260 state->bg = bg;
261 state->top = top;
262 state->bot = bot;
263 state->mode = mode;
266 static void misc_load(struct miscterm_state *state)
268 row = state->row;
269 col = state->col;
270 fg = state->fg;
271 bg = state->bg;
272 top = state->top;
273 bot = state->bot;
274 mode = state->mode;
277 void term_save(struct term_state *state)
279 state->fd = fd;
280 state->pid = pid;
281 memcpy(state->screen, screen,
282 pad_rows() * pad_cols() * sizeof(screen[0]));
283 state->sav = saved;
284 misc_save(&state->cur);
287 void term_load(struct term_state *state)
289 fd = state->fd;
290 pid = state->pid;
291 misc_load(&state->cur);
292 saved = state->sav;
293 memcpy(screen, state->screen,
294 pad_rows() * pad_cols() * sizeof(screen[0]));
295 draw_rows(0, pad_rows());
296 term_show(row, col, 1);
299 int term_fd(void)
301 return fd;
304 void term_init(void)
306 pad_init();
307 bot = pad_rows();
308 term_blank();
311 void term_free(void)
313 pad_free();
316 void term_end(void)
318 fd = 0;
319 row = col = 0;
320 fg = 0;
321 bg = 0;
322 term_blank();
325 void set_region(int t, int b)
327 top = MIN(pad_rows(), MAX(0, t - 1));
328 bot = MIN(pad_rows(), MAX(0, b ? b : pad_rows()));
329 if (origin())
330 move_cursor(top, 0);
333 #include "vt102.c"