font: don't segfault if font is wider than specified
[fbpad.git] / term.c
blobaf8f21a6bb29a218073d4d7fcd21f74875f565b1
1 #include <ctype.h>
2 #include <pty.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include "pad.h"
8 #include "util.h"
9 #include "term.h"
11 #define MAXESCARGS 32
12 #define FGCOLOR 0
13 #define BGCOLOR 7
15 static pid_t pid;
16 static int fd;
17 static int row, col;
19 static void setsize(void)
21 struct winsize size;
22 size.ws_col = pad_cols();
23 size.ws_row = pad_rows();
24 size.ws_xpixel = 0;
25 size.ws_ypixel = 0;
26 ioctl(fd, TIOCSWINSZ, &size);
29 static int readpty(void)
31 char b;
32 if (read(fd, &b, 1) > 0)
33 return (int) b;
34 return -1;
37 static void move_cursor(int r, int c)
39 pad_show(row, col, 0);
40 row = MIN(r, pad_rows() - 1);
41 col = MIN(c, pad_cols() - 1);
42 pad_show(row, col, 1);
45 static void scroll_screen(int sr, int nr, int n)
47 pad_show(row, col, 0);
48 pad_scroll(sr, nr, n);
49 pad_show(row, col, 1);
52 static void advance(int ch)
54 int r = row;
55 int c = col;
56 switch (ch) {
57 case '\n':
58 r++;
59 c = 0;
60 break;
61 case '\t':
62 c = (c / 8 + 1) * 8;
63 break;
64 case '\b':
65 if (c)
66 c--;
67 break;
68 case '\r':
69 c = 0;
70 break;
71 case '\a':
72 case '\f':
73 case '\v':
74 break;
75 default:
76 c++;
78 if (c >= pad_cols()) {
79 r++;
80 c = 0;
82 if (r >= pad_rows()) {
83 int n = pad_rows() - r - 1;
84 int nr = r + n;
85 r = pad_rows() - 1;
86 scroll_screen(-n, nr, n);
88 move_cursor(r, c);
91 void term_send(int c)
93 unsigned char b = (unsigned char) c;
94 if (fd)
95 write(fd, &b, 1);
98 static void writepty(int c)
100 pad_put(c, row, col);
101 advance(c);
104 static void setmode(int m)
106 if (m == 0) {
107 pad_fg(FGCOLOR);
108 pad_bg(BGCOLOR);
110 if (m >= 30 && m <= 37)
111 pad_fg(m - 30);
112 if (m >= 40 && m <= 47)
113 pad_bg(m - 40);
116 static void kill_line(void)
118 int i;
119 for (i = col; i < pad_cols(); i++)
120 pad_put('\0', row, i);
121 move_cursor(row, col);
124 static void delete_lines(int n)
126 int sr = row + n;
127 int nr = pad_rows() - row - n;
128 scroll_screen(sr, nr, -n);
131 static void insert_lines(int n)
133 int nr = pad_rows() - row - n;
134 scroll_screen(row, nr, n);
137 static void escape_bracket(void)
139 int args[MAXESCARGS] = {0};
140 int i;
141 int n = 0;
142 int c = 0;
143 for (i = 0; i < ARRAY_SIZE(args) && !isalpha(c); i++) {
144 int arg = 0;
145 while (isdigit((c = readpty())))
146 arg = arg * 10 + (c - '0');
147 args[n++] = arg;
149 switch (c) {
150 case 'H':
151 case 'f':
152 move_cursor(MAX(0, args[0] - 1), MAX(0, args[1] - 1));
153 break;
154 case 'J':
155 pad_blank();
156 move_cursor(0, 0);
157 break;
158 case 'A':
159 move_cursor(row - MAX(1, args[0]), col);
160 break;
161 case 'B':
162 move_cursor(row + MAX(1, args[0]), col);
163 break;
164 case 'C':
165 move_cursor(row, col + MAX(1, args[0]));
166 break;
167 case 'D':
168 move_cursor(row, col - MAX(1, args[0]));
169 break;
170 case 'K':
171 kill_line();
172 break;
173 case 'L':
174 insert_lines(MAX(1, args[0]));
175 break;
176 case 'M':
177 delete_lines(MAX(1, args[0]));
178 break;
179 case 'c':
180 break;
181 case 'h':
182 break;
183 case 'l':
184 break;
185 case 'm':
186 for (i = 0; i < n; i++)
187 setmode(args[i]);
188 if (!n)
189 setmode(0);
190 break;
191 case 'r':
192 break;
193 default:
194 printf("unknown escape bracket char <%c>\n", c);
198 static void reverse_index()
200 scroll_screen(0, pad_rows() - 1, 1);
203 static int escape_alone(int c)
205 switch (c) {
206 case 'M':
207 reverse_index();
208 return 0;
209 default:
210 printf("unknown escape char <%c>\n", c);
212 return 1;
215 static void escape(void)
217 int c = readpty();
218 if (c == '[') {
219 escape_bracket();
220 } else if (escape_alone(c)) {
221 writepty(ESC);
222 writepty(c);
223 return;
227 void term_read(void)
229 int c = readpty();
230 if (c == ESC)
231 escape();
232 else
233 writepty(c);
236 void term_exec(char *cmd)
238 if ((pid = forkpty(&fd, NULL, NULL, NULL)) == -1)
239 xerror("failed to create a pty");
240 if (!pid) {
241 setenv("TERM", "linux", 1);
242 execl(cmd, cmd, NULL);
243 exit(1);
245 setsize();
246 setmode(0);
247 pad_blank();
250 void term_save(struct term_state *state)
252 state->row = row;
253 state->col = col;
254 state->fd = fd;
255 state->pid = pid;
256 pad_save(&state->pad);
259 void term_load(struct term_state *state)
261 row = state->row;
262 col = state->col;
263 fd = state->fd;
264 pid = state->pid;
265 pad_load(&state->pad);
266 move_cursor(row, col);
269 int term_fd(void)
271 return fd;
274 void term_end(void)
276 fd = 0;
277 row = col = 0;
278 pad_fg(0);
279 pad_bg(0);
280 pad_blank();