ropesim tool minor progr.
[dosdemo] / src / console.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdarg.h>
5 #include <ctype.h>
6 #include "console.h"
7 #include "demo.h"
8 #include "screen.h"
9
10 static int runcmd(void);
11 static int cmd_list(const char *args);
12 static int cmd_help(const char *args);
13
14 #define CBUF_SIZE       64
15 #define CBUF_MASK       (CBUF_SIZE - 1)
16
17 #define HIST_SIZE       32
18 #define SBUF_SIZE       4
19
20 static char cbuf[CBUF_SIZE];
21 static char inp[CBUF_SIZE + 1], *dptr;
22 static int rd, wr;
23
24 static char hist[HIST_SIZE][CBUF_SIZE + 1];
25 static int hist_head, hist_tail;
26
27 static char sbuf[SBUF_SIZE][CBUF_SIZE + 1];
28 static int sbuf_head, sbuf_tail;
29 static int sbuf_size;
30
31
32 int con_init(void)
33 {
34         wr = rd = 0;
35         hist_head = hist_tail = 0;
36         sbuf_head = sbuf_tail = 0;
37         sbuf_size = 0;
38         return 0;
39 }
40
41 void con_start(void)
42 {
43         wr = rd = 0;
44 }
45
46 void con_stop(void)
47 {
48 }
49
50 void con_draw(uint16_t *fb)
51 {
52         int x, y, sidx, cidx;
53
54         /* print output buffer */
55         y = 1;
56         sidx = sbuf_head;
57         while(sidx != sbuf_tail) {
58                 cs_cputs(fb, 1, y, sbuf[sidx]);
59                 sidx = (sidx + 1) & (SBUF_SIZE - 1);
60                 y += 8;
61         }
62
63         memset(fb + y++ * 320, 0xff, 640);
64
65         cs_confont(fb, 1, y, '>' - 32);
66         cidx = rd;
67         x = 10;
68         while(cidx != wr) {
69                 cs_confont(fb, x, y, cbuf[cidx] - 32);
70                 x += 6;
71                 cidx = (cidx + 1) & CBUF_MASK;
72         }
73         memset(fb + (y + 8) * 320, 0xff, 640);
74 }
75
76 int con_input(int key)
77 {
78         switch(key) {
79         case '\b':
80                 if(wr != rd) {
81                         wr = (wr + CBUF_SIZE - 1) & CBUF_MASK;
82                 }
83                 break;
84
85         case '\n':
86         case '\r':
87                 dptr = inp;
88                 while(rd != wr) {
89                         *dptr++ = cbuf[rd];
90                         rd = (rd + 1) & CBUF_MASK;
91                 }
92                 *dptr = 0;
93                 if(inp[0]) {
94                         /* add to history */
95                         memcpy(hist[hist_tail], inp, dptr - inp + 1);
96                         hist_tail = (hist_tail + 1) & (HIST_SIZE - 1);
97                         if(hist_tail == hist_head) {    /* ovf */
98                                 hist_head = (hist_head + 1) & (HIST_SIZE - 1);
99                         }
100
101                         return runcmd();
102                 }
103                 break;
104
105         case KB_UP:
106                 if(hist_head == hist_tail) break;
107                 hist_tail = (hist_tail + HIST_SIZE - 1) & (HIST_SIZE - 1);
108                 strcpy(inp, hist[hist_tail]);
109                 break;
110
111         default:
112                 if(key < 256 && isprint(key)) {
113                         cbuf[wr] = key;
114                         wr = (wr + 1) & CBUF_MASK;
115                         if(wr == rd) { /* overflow */
116                                 rd = (rd + 1) & CBUF_MASK;
117                         }
118                 }
119                 break;
120         }
121
122         return 1;
123 }
124
125 void con_printf(const char *fmt, ...)
126 {
127         int len;
128         va_list ap;
129
130         va_start(ap, fmt);
131         len = vsprintf(sbuf[sbuf_tail], fmt, ap);
132         sbuf[sbuf_tail][len] = 0;
133         va_end(ap);
134
135         sbuf_tail = (sbuf_tail + 1) & (SBUF_SIZE - 1);
136         if(sbuf_tail == sbuf_head) {    /* ovf */
137                 sbuf_head = (sbuf_head + 1) & (SBUF_SIZE - 1);
138         }
139
140         if(sbuf_size < SBUF_SIZE) sbuf_size++;
141 }
142
143 static struct {
144         const char *name;
145         int (*func)(const char*);
146 } cmd[] = {
147         {"ls", cmd_list},
148         {"help", cmd_help},
149         {"?", cmd_help},
150         {0, 0}
151 };
152
153 static int runcmd(void)
154 {
155         int i, nscr;
156         char *endp, *args;
157
158         switch(inp[0]) {
159         case '/':
160                 nscr = scr_num_screens();
161                 for(i=0; i<nscr; i++) {
162                         if(strstr(scr_screen(i)->name, inp + 1)) {
163                                 change_screen(i);
164                                 return 0;
165                         }
166                 }
167                 con_printf("no such screen: %s\n", inp + 1);
168                 break;
169
170         case '#':
171                 i = strtol(inp + 1, &endp, 10);
172                 if(endp == inp + 1) {
173                         con_printf("usage: #<screen number>\n");
174                         break;
175                 }
176                 nscr = scr_num_screens();
177                 if(i < 0 || i >= nscr) {
178                         con_printf("no such screen: %d\n", i);
179                         break;
180                 }
181                 change_screen(i);
182                 return 0;
183
184         default:
185                 endp = inp;
186                 while(*endp && isspace(*endp)) endp++;
187                 while(*endp && !isspace(*endp)) endp++;
188
189                 args = *endp ? endp + 1 : 0;
190                 *endp = 0;
191
192                 for(i=0; cmd[i].name; i++) {
193                         if(strcmp(inp, cmd[i].name) == 0) {
194                                 cmd[i].func(args);
195                                 return 1;
196                         }
197                 }
198
199                 con_printf("?%s\n", inp);
200         }
201
202         return 1;
203 }
204
205 static int cmd_list(const char *args)
206 {
207         int i, nscr, len;
208         char buf[512], *ptr = buf;
209
210         nscr = scr_num_screens();
211         for(i=0; i<nscr; i++) {
212                 char *sname = scr_screen(i)->name;
213                 len = strlen(sname);
214
215                 if(ptr - buf + len > 53) {
216                         *ptr = 0;
217                         con_printf("%s", buf);
218                         ptr = buf;
219                 }
220
221                 len = sprintf(ptr, "%s ", sname);
222                 ptr += len;
223         }
224         if(ptr > buf) {
225                 *ptr = 0;
226                 con_printf("%s", buf);
227         }
228         return 0;
229 }
230
231 static int cmd_help(const char *args)
232 {
233         con_printf("cmds: /, #, ls, help, ?\n");
234         return 0;
235 }