term: clear the screen when nothing to show
[fbpad.git] / term.c
blob60debc02172feef6fffedec8eb8c2066f1b196e6
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 struct term *term;
23 static struct square *screen;
24 static int row, col;
25 static int fg, bg;
26 static int top, bot;
27 static int mode;
28 static int visible;
30 static int origin(void)
32 return mode & MODE_ORIGIN;
35 static void setsize(void)
37 struct winsize size;
38 size.ws_col = pad_cols();
39 size.ws_row = pad_rows();
40 size.ws_xpixel = 0;
41 size.ws_ypixel = 0;
42 ioctl(term->fd, TIOCSWINSZ, &size);
45 static int readpty(void)
47 char b;
48 if (read(term->fd, &b, 1) > 0)
49 return (int) b;
50 return -1;
53 static void term_show(int r, int c, int cursor)
55 struct square *sqr = SQRADDR(r, c);
56 int fgcolor = sqr->c ? sqr->fg : fg;
57 int bgcolor = sqr->c ? sqr->bg : bg;
58 if (cursor && !(mode & MODE_NOCURSOR)) {
59 int t = fgcolor;
60 fgcolor = bgcolor;
61 bgcolor = t;
63 if (visible)
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) * 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));
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 if (visible)
106 pad_scroll(sr, nr, n, bg);
107 term_show(row, col, 1);
110 static void insert_lines(int n)
112 int sr = MAX(top, row);
113 int nr = bot - row - n;
114 if (nr > 0)
115 scroll_screen(sr, nr, n);
118 static void delete_lines(int n)
120 int r = MAX(top, row);
121 int sr = r + n;
122 int nr = bot - r - n;
123 if (nr > 0)
124 scroll_screen(sr, nr, -n);
127 static void move_cursor(int r, int c)
129 int t, b;
130 term_show(row, col, 0);
131 t = origin() ? top : 0;
132 b = origin() ? bot : pad_rows();
133 row = MAX(t, MIN(r, b - 1));
134 col = MAX(0, MIN(c, pad_cols() - 1));
135 term_show(row, col, 1);
138 static void advance(int dr, int dc, int scrl)
140 int r = row + dr;
141 int c = col + dc;
142 if (c >= pad_cols()) {
143 if (!scrl || (mode & MODE_NOWRAP)) {
144 c = pad_cols() - 1;
145 } else {
146 r++;
147 c = 0;
150 if (r >= bot && scrl) {
151 int n = bot - r - 1;
152 int nr = (bot - top) + n;
153 scroll_screen(top + -n, nr, n);
155 if (r < top && scrl) {
156 int n = top - r;
157 int nr = (bot - top) - n;
158 scroll_screen(top, nr, n);
160 r = MIN(bot - 1, MAX(top, r));
161 move_cursor(r, MAX(0, c));
164 void term_send(int c)
166 unsigned char b = (unsigned char) c;
167 if (term->fd)
168 write(term->fd, &b, 1);
171 void term_sendstr(char *s)
173 if (term->fd)
174 write(term->fd, s, strlen(s));
177 static void setmode(int m)
179 if (m == 0) {
180 fg = FGCOLOR;
181 bg = BGCOLOR;
183 if (m == 1)
184 fg = fg | 0x08;
185 if (m == 7) {
186 int t = fg;
187 fg = bg;
188 bg = t;
190 if (m >= 30 && m <= 37)
191 fg = m - 30;
192 if (m >= 40 && m <= 47)
193 bg = m - 40;
196 static void kill_chars(int sc, int ec)
198 int i;
199 memset(SQRADDR(row, sc), 0, (ec - sc) * sizeof(*screen));
200 for (i = sc; i < ec; i++)
201 term_show(row, i, 0);
202 move_cursor(row, col);
205 static void move_chars(int sc, int nc, int n)
207 int i;
208 term_show(row, col, 0);
209 memmove(SQRADDR(row, sc + n), SQRADDR(row, sc),
210 nc * sizeof(*screen));
211 if (n > 0)
212 memset(SQRADDR(row, sc), 0, n * sizeof(*screen));
213 else
214 memset(SQRADDR(row, pad_rows() + n), 0, -n * sizeof(*screen));
215 for (i = MIN(sc, sc + n); i < pad_cols(); i++)
216 term_show(row, i, 0);
217 term_show(row, col, 1);
220 static void delete_chars(int n)
222 move_chars(col + n, pad_cols(), -n);
225 static void insert_chars(int n)
227 int nc = pad_cols() - col - n;
228 move_chars(col, nc, n);
231 static void term_blank(void)
233 memset(screen, 0, MAXCHARS * sizeof(*screen));
234 if (visible)
235 pad_blank(bg);
238 static void ctlseq(void);
239 void term_read(void)
241 ctlseq();
244 void term_exec(char *cmd)
246 bot = pad_rows();
247 if ((term->pid = forkpty(&term->fd, NULL, NULL, NULL)) == -1)
248 xerror("failed to create a pty");
249 if (!term->pid) {
250 setenv("TERM", "linux", 1);
251 execl(cmd, cmd, NULL);
252 exit(1);
254 setsize();
255 setmode(0);
256 term_blank();
259 static void misc_save(struct term_state *state)
261 state->row = row;
262 state->col = col;
263 state->fg = fg;
264 state->bg = bg;
265 state->top = top;
266 state->bot = bot;
267 state->mode = mode;
270 static void misc_load(struct term_state *state)
272 row = state->row;
273 col = state->col;
274 fg = state->fg;
275 bg = state->bg;
276 top = state->top;
277 bot = state->bot;
278 mode = state->mode;
281 void term_save(struct term *term)
283 misc_save(&term->cur);
286 void term_load(struct term *t, int flags)
288 term = t;
289 misc_load(&term->cur);
290 screen = term->screen;
291 visible = flags;
292 if (term->fd && flags == TERM_REDRAW) {
293 draw_rows(0, pad_rows());
294 term_show(row, col, 1);
296 if (!term->fd && flags)
297 pad_blank(0);
300 void term_end(void)
302 term->fd = 0;
303 row = col = 0;
304 fg = 0;
305 bg = 0;
306 term_blank();
309 void set_region(int t, int b)
311 top = MIN(pad_rows(), MAX(0, t - 1));
312 bot = MIN(pad_rows(), MAX(0, b ? b : pad_rows()));
313 if (origin())
314 move_cursor(top, 0);
317 #include "vt102.c"