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