term: handle DECSTBM to set scrolling region
[fbpad.git] / term.c
blob80f7930c2d3b074583580125d17dcf58c30ac5b7
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 static pid_t pid;
17 static int fd;
18 static int row, col;
19 static int fg, bg;
20 static struct square screen[MAXCHARS];
21 static int top, bot;
23 static void setsize(void)
25 struct winsize size;
26 size.ws_col = pad_cols();
27 size.ws_row = pad_rows();
28 size.ws_xpixel = 0;
29 size.ws_ypixel = 0;
30 ioctl(fd, TIOCSWINSZ, &size);
33 static int readpty(void)
35 char b;
36 if (read(fd, &b, 1) > 0)
37 return (int) b;
38 return -1;
41 static void term_show(int r, int c, int cursor)
43 struct square *sqr = SQRADDR(r, c);
44 int fgcolor = sqr->c ? sqr->fg : fg;
45 int bgcolor = sqr->c ? sqr->bg : bg;
46 if (cursor) {
47 int t = fgcolor;
48 fgcolor = bgcolor;
49 bgcolor = t;
51 pad_put(sqr->c, r, c, fgcolor, bgcolor);
54 void term_put(int ch, int r, int c)
56 struct square *sqr = SQRADDR(r, c);
57 sqr->c = ch;
58 sqr->fg = fg;
59 sqr->bg = bg;
60 term_show(r, c, 0);
63 static void empty_rows(int sr, int er)
65 memset(SQRADDR(sr, 0), 0, (er - sr) * sizeof(screen[0]) * pad_cols());
68 static void blank_rows(int sr, int er)
70 int i;
71 empty_rows(sr, er);
72 for (i = sr * pad_cols(); i < er * pad_cols(); i++)
73 term_show(i / pad_cols(), i % pad_cols(), 0);
74 term_show(row, col, 1);
77 static void scroll_screen(int sr, int nr, int n)
79 term_show(row, col, 0);
80 memmove(SQRADDR(sr + n, 0), SQRADDR(sr, 0),
81 nr * pad_cols() * sizeof(screen[0]));
82 if (n > 0)
83 empty_rows(sr, sr + n);
84 else
85 empty_rows(sr + nr + n, sr + nr);
86 pad_scroll(sr, nr, n, bg);
87 term_show(row, col, 1);
90 static void insert_lines(int n)
92 int sr = MAX(top, row);
93 int nr = bot - row - n;
94 if (nr > 0)
95 scroll_screen(sr, nr, n);
98 static void delete_lines(int n)
100 int r = MAX(top, row);
101 int sr = r + n;
102 int nr = bot - r - n;
103 if (nr > 0)
104 scroll_screen(sr, nr, -n);
107 static void move_cursor(int r, int c)
109 term_show(row, col, 0);
110 if (c >= pad_cols()) {
111 r++;
112 c = 0;
114 if (r >= bot) {
115 int n = bot - r - 1;
116 int nr = (bot - top) + n;
117 scroll_screen(-n, nr, n);
118 r = bot - 1;
120 row = MAX(0, MIN(r, pad_rows() - 1));
121 col = MAX(0, MIN(c, pad_cols() - 1));
122 term_show(row, col, 1);
125 static void advance(int dr, int dc)
127 int r = row + dr;
128 int c = col + dc;
129 move_cursor(MAX(0, r), MAX(0, c));
132 void term_send(int c)
134 unsigned char b = (unsigned char) c;
135 if (fd)
136 write(fd, &b, 1);
139 static void setmode(int m)
141 if (m == 0) {
142 fg = FGCOLOR;
143 bg = BGCOLOR;
145 if (m == 1)
146 fg = fg | 0x08;
147 if (m == 7) {
148 int t = fg;
149 fg = bg;
150 bg = t;
152 if (m >= 30 && m <= 37)
153 fg = m - 30;
154 if (m >= 40 && m <= 47)
155 bg = m - 40;
158 static void kill_chars(int sc, int ec)
160 int i;
161 memmove(SQRADDR(row, sc), SQRADDR(row, ec),
162 (pad_cols() - ec) * sizeof(screen[0]));
163 memset(SQRADDR(row, sc + pad_cols() - ec), 0,
164 (ec - sc) * sizeof(screen[0]));
165 for (i = col; i < pad_cols(); i++)
166 term_show(row, i, 0);
167 move_cursor(row, col);
170 void term_blank(void)
172 pad_blank(bg);
173 memset(screen, 0, sizeof(screen));
176 static void ctlseq(void);
177 void term_read(void)
179 ctlseq();
182 void term_exec(char *cmd)
184 if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1)
185 xerror("failed to create a pty");
186 if (!pid) {
187 setenv("TERM", "linux", 1);
188 execl(cmd, cmd, NULL);
189 exit(1);
191 setsize();
192 setmode(0);
193 term_blank();
196 void term_save(struct term_state *state)
198 state->row = row;
199 state->col = col;
200 state->fd = fd;
201 state->pid = pid;
202 state->fg = fg;
203 state->bg = bg;
204 memcpy(state->screen, screen,
205 pad_rows() * pad_cols() * sizeof(screen[0]));
208 void term_load(struct term_state *state)
210 int i;
211 row = state->row;
212 col = state->col;
213 fd = state->fd;
214 pid = state->pid;
215 fg = state->fg;
216 bg = state->bg;
217 memcpy(screen, state->screen,
218 pad_rows() * pad_cols() * sizeof(screen[0]));
219 for (i = 0; i < pad_rows() * pad_cols(); i++)
220 term_show(i / pad_cols(), i % pad_cols(), 0);
221 term_show(row, col, 1);
224 int term_fd(void)
226 return fd;
229 void term_init(void)
231 pad_init();
232 bot = pad_rows();
233 term_blank();
236 void term_free(void)
238 pad_free();
241 void term_end(void)
243 fd = 0;
244 row = col = 0;
245 fg = 0;
246 bg = 0;
247 term_blank();
250 #include "vt102.c"