fixed cursor addressing limit checking
[termu] / src / term.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include "term.h"
5
6 static void clearscr(void);
7 static void scroll(void);
8
9 int cursor_x, cursor_y, cursor_vis, cursor_blink;
10 unsigned char scrbuf[TERM_COLS * TERM_ROWS];
11
12 void term_init(void)
13 {
14         cursor_vis = 1;
15         cursor_blink = 0;
16         clearscr();
17 }
18
19 void term_cleanup(void)
20 {
21 }
22
23 static void clearscr(void)
24 {
25         memset(scrbuf, ' ', sizeof scrbuf);
26         cursor_x = cursor_y = 0;
27 }
28
29 static void scroll(void)
30 {
31         memmove(scrbuf, scrbuf + TERM_COLS, (TERM_ROWS - 1) * TERM_COLS);
32         memset(scrbuf + (TERM_ROWS - 1) * TERM_COLS, ' ', TERM_COLS);
33 }
34
35 static int proc_char(int c)
36 {
37         static int cbuf[8], clen;
38
39         /*
40         if(isprint(c)) {
41                 printf(" %c", c);
42         } else {
43                 printf(" %xh", (unsigned int)c);
44         }
45         fflush(stdout);
46         */
47
48         if(clen) {
49                 if(cbuf[0] == 0x1b) {
50                         switch(clen) {
51                         case 1:
52                                 if(c != '=') {
53                                         clen = 0;
54                                         return 0;
55                                 }
56                                 break;
57                         case 2:
58                                 if(c < ' ' || c > '7') {
59                                         clen = 0;
60                                         return 0;
61                                 }
62                                 break;
63                         case 3:
64                                 if(c < ' ' || c > 'o') {
65                                         clen = 0;
66                                         return 0;
67                                 }
68                                 cursor_x = c - ' ';
69                                 cursor_y = cbuf[2] - ' ';
70                                 clen = 0;
71                                 return 1;
72                         }
73                         cbuf[clen++] = c;
74                         return 0;
75                 }
76         }
77
78         switch(c) {
79         case 0:
80                 break;
81
82         case '\a':
83                 putchar('\a');
84                 break;
85
86         case '\b':
87                 if(cursor_x > 0) {
88                         cursor_x--;
89                         return 1;
90                 }
91                 break;
92
93         case '\n':
94                 if(cursor_y >= TERM_ROWS - 1) {
95                         scroll();
96                         cursor_y = TERM_ROWS - 1;
97                 } else {
98                         cursor_y++;
99                 }
100                 cursor_x = 0;
101                 return 1;
102
103         case '\v':
104                 if(cursor_y > 0) {
105                         cursor_y--;
106                         return 1;
107                 }
108                 break;
109
110         case 0xc:       /* FF */
111                 if(cursor_x < TERM_COLS - 1) {
112                         cursor_x++;
113                         return 1;
114                 }
115                 break;
116
117         case '\r':
118                 cursor_x = 0;
119                 return 1;
120
121         case 0xe:       /* SO TODO */
122                 break;
123         case 0xf:       /* SI TODO */
124                 break;
125
126         case 0x1a:      /* SUB */
127                 clearscr();
128                 return 1;
129
130         case 0x1b:      /* ESC */
131                 cbuf[clen++] = c;
132                 break;
133
134         case 0x1e:      /* RS */
135                 cursor_x = cursor_y = 0;
136                 return 1;
137
138         default:
139                 scrbuf[cursor_y * TERM_COLS + cursor_x] = c;
140                 if(++cursor_x >= TERM_COLS) {
141                         proc_char('\n');
142                 }
143                 return 1;
144         }
145
146         return 0;
147 }
148
149 int term_proc(char *buf, int sz)
150 {
151         int redisp = 0;
152
153         while(sz-- > 0) {
154                 redisp |= proc_char(*buf++);
155         }
156
157         return redisp;
158 }