1 /*
2 * Copyright (C) 2014 haru <uobikiemukot at gmail dot com>
3 * Copyright (C) 2014 Hayaki Saito <user@zuse.jp>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20 #include "yaft.h"
21 #include "util.h"
22 #include "terminal.h"
23 #include "function.h"
24
25 #include <stdio.h>
26 #if HAVE_STRING_H
27 # include <string.h>
28 #endif
29
30 /* misc */
sum(struct parm_t * parm)31 int sum(struct parm_t *parm)
32 {
33 int i, sum = 0;
34
35 for (i = 0; i < parm->argc; i++)
36 sum += dec2num(parm->argv[i]);
37
38 return sum;
39 }
40
41 /* function for control character */
bs(struct terminal * term)42 void bs(struct terminal *term)
43 {
44 move_cursor(term, 0, -1);
45 }
46
tab(struct terminal * term)47 void tab(struct terminal *term)
48 {
49 int i;
50
51 for (i = term->cursor.x + 1; i < term->cols; i++) {
52 if (term->tabstop[i]) {
53 set_cursor(term, term->cursor.y, i);
54 return;
55 }
56 }
57 set_cursor(term, term->cursor.y, term->cols - 1);
58 }
59
nl(struct terminal * term)60 void nl(struct terminal *term)
61 {
62 move_cursor(term, 1, 0);
63 }
64
cr(struct terminal * term)65 void cr(struct terminal *term)
66 {
67 set_cursor(term, term->cursor.y, 0);
68 }
69
enter_esc(struct terminal * term)70 void enter_esc(struct terminal *term)
71 {
72 term->esc.state = STATE_ESC;
73 }
74
75 /* function for escape sequence */
save_state(struct terminal * term)76 void save_state(struct terminal *term)
77 {
78 term->state.mode = term->mode & MODE_ORIGIN;
79 term->state.cursor = term->cursor;
80 term->state.attribute = term->attribute;
81 }
82
restore_state(struct terminal * term)83 void restore_state(struct terminal *term)
84 {
85 /* restore state */
86 if (term->state.mode & MODE_ORIGIN)
87 term->mode |= MODE_ORIGIN;
88 else
89 term->mode &= ~MODE_ORIGIN;
90 term->cursor = term->state.cursor;
91 term->attribute = term->state.attribute;
92 }
93
crnl(struct terminal * term)94 void crnl(struct terminal *term)
95 {
96 cr(term);
97 nl(term);
98 }
99
set_tabstop(struct terminal * term)100 void set_tabstop(struct terminal *term)
101 {
102 term->tabstop[term->cursor.x] = true;
103 }
104
reverse_nl(struct terminal * term)105 void reverse_nl(struct terminal *term)
106 {
107 move_cursor(term, -1, 0);
108 }
109
enter_csi(struct terminal * term)110 void enter_csi(struct terminal *term)
111 {
112 term->esc.state = STATE_CSI;
113 }
114
enter_osc(struct terminal * term)115 void enter_osc(struct terminal *term)
116 {
117 term->esc.state = STATE_OSC;
118 }
119
enter_dcs(struct terminal * term)120 void enter_dcs(struct terminal *term)
121 {
122 term->esc.state = STATE_DCS;
123 }
124
ris(struct terminal * term)125 void ris(struct terminal *term)
126 {
127 reset(term);
128 }
129
130 /* function for csi sequence */
insert_blank(struct terminal * term,struct parm_t * parm)131 void insert_blank(struct terminal *term, struct parm_t *parm)
132 {
133 int i, num = sum(parm);
134
135 if (num <= 0)
136 num = 1;
137
138 for (i = term->cols - 1; term->cursor.x <= i; i--) {
139 if (term->cursor.x <= (i - num))
140 copy_cell(term, term->cursor.y, i, term->cursor.y, i - num);
141 else
142 erase_cell(term, term->cursor.y, i);
143 }
144 }
145
curs_up(struct terminal * term,struct parm_t * parm)146 void curs_up(struct terminal *term, struct parm_t *parm)
147 {
148 int num = sum(parm);
149
150 if (num <= 0)
151 num = 1;
152 move_cursor(term, -num, 0);
153 }
154
curs_down(struct terminal * term,struct parm_t * parm)155 void curs_down(struct terminal *term, struct parm_t *parm)
156 {
157 int num = sum(parm);
158
159 if (num <= 0)
160 num = 1;
161 move_cursor(term, num, 0);
162 }
163
curs_forward(struct terminal * term,struct parm_t * parm)164 void curs_forward(struct terminal *term, struct parm_t *parm)
165 {
166 int num = sum(parm);
167
168 if (num <= 0)
169 num = 1;
170 move_cursor(term, 0, num);
171 }
172
curs_back(struct terminal * term,struct parm_t * parm)173 void curs_back(struct terminal *term, struct parm_t *parm)
174 {
175 int num = sum(parm);
176
177 if (num <= 0)
178 num = 1;
179 move_cursor(term, 0, -num);
180 }
181
curs_nl(struct terminal * term,struct parm_t * parm)182 void curs_nl(struct terminal *term, struct parm_t *parm)
183 {
184 int num = sum(parm);
185
186 if (num <= 0)
187 num = 1;
188 move_cursor(term, num, 0);
189 cr(term);
190 }
191
curs_pl(struct terminal * term,struct parm_t * parm)192 void curs_pl(struct terminal *term, struct parm_t *parm)
193 {
194 int num = sum(parm);
195
196 if (num <= 0)
197 num = 1;
198 move_cursor(term, -num, 0);
199 cr(term);
200 }
201
curs_col(struct terminal * term,struct parm_t * parm)202 void curs_col(struct terminal *term, struct parm_t *parm)
203 {
204 int num, last = parm->argc - 1;
205
206 if (parm->argc <= 0)
207 num = 0;
208 else
209 num = dec2num(parm->argv[last]) - 1;
210
211 set_cursor(term, term->cursor.y, num);
212 }
213
curs_pos(struct terminal * term,struct parm_t * parm)214 void curs_pos(struct terminal *term, struct parm_t *parm)
215 {
216 int line, col;
217
218 if (parm->argc <= 0) {
219 set_cursor(term, 0, 0);
220 return;
221 }
222
223 if (parm->argc != 2)
224 return;
225
226 line = dec2num(parm->argv[0]) - 1;
227 col = dec2num(parm->argv[1]) - 1;
228 set_cursor(term, line, col);
229 }
230
erase_display(struct terminal * term,struct parm_t * parm)231 void erase_display(struct terminal *term, struct parm_t *parm)
232 {
233 int i, j, mode, last = parm->argc - 1;
234
235 mode = (parm->argc == 0) ? 0: dec2num(parm->argv[last]);
236
237 if (mode < 0 || 2 < mode)
238 return;
239
240 if (mode == 0) {
241 for (i = term->cursor.y; i < term->lines; i++)
242 for (j = 0; j < term->cols; j++)
243 if (i > term->cursor.y || (i == term->cursor.y && j >= term->cursor.x))
244 erase_cell(term, i, j);
245 }
246 else if (mode == 1) {
247 for (i = 0; i <= term->cursor.y; i++)
248 for (j = 0; j < term->cols; j++)
249 if (i < term->cursor.y || (i == term->cursor.y && j <= term->cursor.x))
250 erase_cell(term, i, j);
251 }
252 else if (mode == 2) {
253 for (i = 0; i < term->lines; i++)
254 for (j = 0; j < term->cols; j++)
255 erase_cell(term, i, j);
256 }
257 }
258
erase_line(struct terminal * term,struct parm_t * parm)259 void erase_line(struct terminal *term, struct parm_t *parm)
260 {
261 int i, mode, last = parm->argc - 1;
262
263 mode = (parm->argc == 0) ? 0: dec2num(parm->argv[last]);
264
265 if (mode < 0 || 2 < mode)
266 return;
267
268 if (mode == 0) {
269 for (i = term->cursor.x; i < term->cols; i++)
270 erase_cell(term, term->cursor.y, i);
271 }
272 else if (mode == 1) {
273 for (i = 0; i <= term->cursor.x; i++)
274 erase_cell(term, term->cursor.y, i);
275 }
276 else if (mode == 2) {
277 for (i = 0; i < term->cols; i++)
278 erase_cell(term, term->cursor.y, i);
279 }
280 }
281
insert_line(struct terminal * term,struct parm_t * parm)282 void insert_line(struct terminal *term, struct parm_t *parm)
283 {
284 int num = sum(parm);
285
286 if (term->mode & MODE_ORIGIN) {
287 if (term->cursor.y < term->scroll.top
288 || term->cursor.y > term->scroll.bottom)
289 return;
290 }
291
292 num = (num <= 0) ? 1 : num;
293 scroll(term, term->cursor.y, term->scroll.bottom, -num);
294 }
295
delete_line(struct terminal * term,struct parm_t * parm)296 void delete_line(struct terminal *term, struct parm_t *parm)
297 {
298 int num = sum(parm);
299
300 if (term->mode & MODE_ORIGIN) {
301 if (term->cursor.y < term->scroll.top
302 || term->cursor.y > term->scroll.bottom)
303 return;
304 }
305
306 num = (num <= 0) ? 1 : num;
307 scroll(term, term->cursor.y, term->scroll.bottom, num);
308 }
309
delete_char(struct terminal * term,struct parm_t * parm)310 void delete_char(struct terminal *term, struct parm_t *parm)
311 {
312 int i, num = sum(parm);
313
314 num = (num <= 0) ? 1 : num;
315
316 for (i = term->cursor.x; i < term->cols; i++) {
317 if ((i + num) < term->cols)
318 copy_cell(term, term->cursor.y, i, term->cursor.y, i + num);
319 else
320 erase_cell(term, term->cursor.y, i);
321 }
322 }
323
erase_char(struct terminal * term,struct parm_t * parm)324 void erase_char(struct terminal *term, struct parm_t *parm)
325 {
326 int i, num = sum(parm);
327
328 if (num <= 0)
329 num = 1;
330 else if (num + term->cursor.x > term->cols)
331 num = term->cols - term->cursor.x;
332
333 for (i = term->cursor.x; i < term->cursor.x + num; i++)
334 erase_cell(term, term->cursor.y, i);
335 }
336
curs_line(struct terminal * term,struct parm_t * parm)337 void curs_line(struct terminal *term, struct parm_t *parm)
338 {
339 int num, last = parm->argc - 1;
340
341 if (parm->argc == 0)
342 num = 0;
343 else
344 num = dec2num(parm->argv[last]) - 1;
345
346 set_cursor(term, num, term->cursor.x);
347 }
348
set_attr(struct terminal * term,struct parm_t * parm)349 void set_attr(struct terminal *term, struct parm_t *parm)
350 {
351 int i, num;
352
353 if (parm->argc == 0) {
354 term->attribute = ATTR_RESET;
355 term->color_pair.fg = term->default_fg;
356 term->color_pair.bg = term->default_bg;
357 return;
358 }
359
360 for (i = 0; i < parm->argc; i++) {
361 num = dec2num(parm->argv[i]);
362
363 if (num == 0) { /* reset all attribute and color */
364 term->attribute = ATTR_RESET;
365 term->color_pair.fg = term->default_fg;
366 term->color_pair.bg = term->default_bg;
367 }
368 else if (1 <= num && num <= 7) /* set attribute */
369 term->attribute |= attr_mask[num];
370 else if (21 <= num && num <= 27) /* reset attribute */
371 term->attribute &= ~attr_mask[num - 20];
372 else if (30 <= num && num <= 37) /* set foreground */
373 term->color_pair.fg = (num - 30);
374 else if (num == 38) { /* set 256 color to foreground */
375 if ((i + 2) < parm->argc && dec2num(parm->argv[i + 1]) == 5) {
376 term->color_pair.fg = dec2num(parm->argv[i + 2]);
377 i += 2;
378 }
379 }
380 else if (num == 39) /* reset foreground */
381 term->color_pair.fg = term->default_fg;
382 else if (40 <= num && num <= 47) /* set background */
383 term->color_pair.bg = (num - 40);
384 else if (num == 48) { /* set 256 color to background */
385 if ((i + 2) < parm->argc && dec2num(parm->argv[i + 1]) == 5) {
386 term->color_pair.bg = dec2num(parm->argv[i + 2]);
387 i += 2;
388 }
389 }
390 else if (num == 49) /* reset background */
391 term->color_pair.bg = term->default_bg;
392 else if (90 <= num && num <= 97) /* set bright foreground */
393 term->color_pair.fg = (num - 90) + BRIGHT_INC;
394 else if (100 <= num && num <= 107) /* set bright background */
395 term->color_pair.bg = (num - 100) + BRIGHT_INC;
396 }
397 }
398
set_mode(struct terminal * term,struct parm_t * parm)399 void set_mode(struct terminal *term, struct parm_t *parm)
400 {
401 int i, mode;
402
403 for (i = 0; i < parm->argc; i++) {
404 mode = dec2num(parm->argv[i]);
405 if (*(term->esc.buf + 1) != '?')
406 continue; /* not supported */
407
408 if (mode == 6) { /* private mode */
409 term->mode |= MODE_ORIGIN;
410 set_cursor(term, 0, 0);
411 }
412 else if (mode == 7)
413 term->mode |= MODE_AMRIGHT;
414 else if (mode == 25)
415 term->mode |= MODE_CURSOR;
416 }
417
418 }
419
reset_mode(struct terminal * term,struct parm_t * parm)420 void reset_mode(struct terminal *term, struct parm_t *parm)
421 {
422 int i, mode;
423
424 for (i = 0; i < parm->argc; i++) {
425 mode = dec2num(parm->argv[i]);
426 if (*(term->esc.buf + 1) != '?')
427 continue; /* not supported */
428
429 if (mode == 6) { /* private mode */
430 term->mode &= ~MODE_ORIGIN;
431 set_cursor(term, 0, 0);
432 }
433 else if (mode == 7) {
434 term->mode &= ~MODE_AMRIGHT;
435 term->wrap_occured = false;
436 }
437 else if (mode == 25)
438 term->mode &= ~MODE_CURSOR;
439 }
440
441 }
442
set_margin(struct terminal * term,struct parm_t * parm)443 void set_margin(struct terminal *term, struct parm_t *parm)
444 {
445 int top, bottom;
446
447 if (parm->argc != 2)
448 return;
449
450 top = dec2num(parm->argv[0]) - 1;
451 bottom = dec2num(parm->argv[1]) - 1;
452
453 if (top >= bottom)
454 return;
455
456 top = (top < 0) ? 0 : (top >= term->lines) ? term->lines - 1 : top;
457
458 bottom = (bottom < 0) ? 0 :
459 (bottom >= term->lines) ? term->lines - 1 : bottom;
460
461 term->scroll.top = top;
462 term->scroll.bottom = bottom;
463
464 set_cursor(term, 0, 0); /* move cursor to home */
465 }
466
clear_tabstop(struct terminal * term,struct parm_t * parm)467 void clear_tabstop(struct terminal *term, struct parm_t *parm)
468 {
469 int i, j, num;
470
471 if (parm->argc == 0)
472 term->tabstop[term->cursor.x] = false;
473 else {
474 for (i = 0; i < parm->argc; i++) {
475 num = dec2num(parm->argv[i]);
476 if (num == 0)
477 term->tabstop[term->cursor.x] = false;
478 else if (num == 3) {
479 for (j = 0; j < term->cols; j++)
480 term->tabstop[j] = false;
481 return;
482 }
483 }
484 }
485 }
486
487 /* emacs, -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
488 /* vim: set expandtab ts=4 : */
489 /* EOF */
490