]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/vga/vgagui.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / vga / vgagui.c
1 #include <stdio.h>
2 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <assert.h>
6 #include <string.h>
7 #include <malloc.h>
8 #include <fcntl.h>
9 #include <ctype.h>
10 #include <i86.h>
11 #include <dos.h>
12
13 #include <hw/cpu/cpu.h>
14 #include <hw/dos/dos.h>
15 #include <hw/vga/vga.h>
16 #include <hw/vga/vgatty.h>
17 #include <hw/vga/vgagui.h>
18
19 #ifdef TARGET_WINDOWS
20 # include <hw/dos/winfcon.h>
21 # include <windows/apihelp.h>
22 # include <windows/dispdib/dispdib.h>
23 # include <windows/win16eb/win16eb.h>
24 #endif
25
26 struct vga_menu_bar_state       vga_menu_bar = {NULL,-1,0};
27 void                            (*vga_menu_idle)() = NULL;
28
29 int vga_menu_item_nonselectable(const struct vga_menu_item *m) {
30         if (m->text == (char*)1) return 1;
31         return 0;
32 }
33
34 void vga_menu_bar_draw() {
35         VGA_ALPHA_PTR vga = vga_alpha_ram + (80*vga_menu_bar.row);
36         const struct vga_menu_bar_item *m = vga_menu_bar.bar;
37         unsigned int x,i,color,colorh,ti;
38         unsigned char hi;
39         const char *msg;
40
41         /* start */
42         x = 0;
43         i = 0;
44         if (m != NULL) {
45                 while (x < 80 && m->name != NULL) {
46                         ti = 1;
47                         msg = m->name;
48                         hi = (i == vga_menu_bar.sel);
49                         color = hi ? 0x1F00 : 0x7000;
50                         colorh = hi ? 0x1E00 : 0x7100;
51                         if (m->x >= 80) break;
52                         while (x < m->x) vga[x++] = color | 0x20;
53                         while (x < (m->x+m->w) && *msg != 0) {
54                                 if (ti && *msg == m->shortcut_key) {
55                                         vga[x++] = colorh | (*msg++);
56                                         ti = 0;
57                                 }
58                                 else {
59                                         vga[x++] = color | (*msg++);
60                                 }
61                         }
62                         while (x < (m->x+m->w)) vga[x++] = color | 0x20;
63                         m++;
64                         i++;
65                 }
66         }
67
68         /* finish the bar */
69         while (x < 80) vga[x++] = 0x7020;
70 }
71
72 void vga_menu_draw_item(VGA_ALPHA_PTR screen,const struct vga_menu_item **scan,unsigned int i,unsigned int w,unsigned int color,unsigned int tcolor) {
73         const struct vga_menu_item *sci = scan[i];
74         const char *txt = sci->text;
75         unsigned int x,ti=1;
76
77         screen += (i * vga_width) + 1;
78         if (txt == (char*)1) {
79                 screen[-1] = 204 | color;
80                 for (x=0;x < w;x++) screen[x] = 205 | color;
81                 screen[w] = 185 | color;
82         }
83         else {
84                 for (x=0;x < w && txt[x] != 0;x++) {
85                         if (ti && tolower(txt[x]) == tolower(sci->shortcut_key)) {
86                                 screen[x] = txt[x] | tcolor;
87                                 ti = 0;
88                         }
89                         else {
90                                 screen[x] = txt[x] | color;
91                         }
92                 }
93                 for (;x < w;x++) screen[x] = 0x20 | color;
94         }
95 }
96
97 const struct vga_menu_item *vga_menu_bar_menuitem(const struct vga_menu_bar_item *menu,unsigned char row,unsigned int *spec) {
98         const struct vga_menu_item *ret = NULL,**scan,*sci;
99         unsigned int w,h,i,l,x,y,o,ks,nks,items,sel,c,altup=0;
100         static const unsigned int hicolor = 0x7000;
101         static const unsigned int hitcolor = 0x7100;
102         static const unsigned int color = 0x1700;
103         static const unsigned int tcolor = 0x1E00;
104         VGA_ALPHA_PTR screen,buf;
105         unsigned char loop = 1;
106
107         /* FIX: If re-inited because of arrow keys, then one more alt-up should trigger release */
108         if (*spec == 0x4B00 || *spec == 0x4D00)
109                 altup++;
110
111         *spec = 0;
112         if (menu != NULL) {
113                 sel = 0;
114                 w = h = 1;
115                 ks = (read_bios_keystate() & BIOS_KS_ALT);
116                 scan = menu->items;
117                 for (i=0;(sci=scan[i]) != NULL;i++) {
118                         if (sci->text == (char*)1) l = 1;
119                         else l = (unsigned int)strlen(sci->text);
120                         if (l > 78) l = 78;
121                         if (w < (l+2)) w = (l+2);
122                         if (h < (i+2) && (h+2+row) <= 25) h = i+2;
123                 }
124                 items = i;
125
126 #if TARGET_MSDOS == 32
127                 buf = malloc(w * h * 2);
128 #else
129                 buf = _fmalloc(w * h * 2);
130 #endif
131                 screen = vga_alpha_ram + (row * vga_width) + menu->x;
132                 if (buf != NULL) {
133                         /* copy off the screen contents */
134                         for (y=0;y < h;y++) {
135                                 o = w * y;
136                                 i = vga_width * y;
137                                 for (x=0;x < w;x++,o++,i++) buf[o] = screen[i];
138                         }
139
140                         /* draw the box */
141                         for (y=0;y < (h-1);y++) {
142                                 o = vga_width * y;
143                                 screen[o+0] = 186 | color;
144                                 screen[o+w-1] = 186 | color;
145                         }
146                         o = vga_width * (h-1);
147                         screen[o+0] = 200 | color;
148                         for (x=1;x < (w-1);x++) screen[o+x] = 205 | color;
149                         screen[o+w-1] = 188 | color;
150
151                         /* draw the items */
152                         for (i=0;i < items;i++)
153                                 vga_menu_draw_item(screen,scan,i,w-2,i == sel ? hicolor : color,i == sel ? hitcolor : tcolor);
154
155                         while (loop) {
156                                 nks = (read_bios_keystate() & BIOS_KS_ALT);
157                                 vga_menu_idle();
158
159                                 if (ks && !nks) {
160                                         if (++altup >= 2) break;
161                                 }
162                                 ks = nks;
163
164                                 if (kbhit()) {
165                                         c = getch();
166                                         if (c == 0) c = getch() << 8;
167
168                                         if (c == 27)
169                                                 break;
170                                         else if (c == 13) {
171                                                 ret = scan[sel];
172                                                 break;
173                                         }
174                                         else if (c == 0x4800) {
175                                                 vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor);
176                                                 do {
177                                                         if (sel == 0) sel = items-1;
178                                                         else sel--;
179                                                 } while (vga_menu_item_nonselectable(scan[sel]));
180                                                 vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor);
181                                         }
182                                         else if (c == 0x5000) {
183                                                 vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor);
184                                                 do {
185                                                         if (++sel >= items) sel = 0;
186                                                 } while (vga_menu_item_nonselectable(scan[sel]));
187                                                 vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor);
188                                         }
189                                         else if (c == 0x4B00 || c == 0x4D00) {
190                                                 *spec = c;
191                                                 ret = NULL;
192                                                 break;
193                                         }
194                                         else if (c > 32 && c < 127) {
195                                                 int patience = items;
196
197                                                 vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor);
198                                                 /* look for the first menu item with that shortcut key */
199                                                 if (++sel >= items) sel = 0;
200                                                 while (tolower(scan[sel]->shortcut_key) != tolower(c)) {
201                                                         if (--patience == 0) {
202                                                                 sel = 0;
203                                                                 break;
204                                                         }
205
206                                                         if (++sel >= items) sel = 0;
207                                                 }
208                                                 vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor);
209                                                 if (patience > 0) {
210                                                         ret = scan[sel];
211                                                         break;
212                                                 }
213                                         }
214                                 }
215                         }
216
217                         /* copy screen contents back */
218                         for (y=0;y < h;y++) {
219                                 i = w * y;
220                                 o = vga_width * y;
221                                 for (x=0;x < w;x++,o++,i++) screen[o] = buf[i];
222                         }
223
224 #if TARGET_MSDOS == 32
225                         free(buf);
226 #else
227                         _ffree(buf);
228 #endif
229                 }
230         }
231
232         return ret;
233 }
234
235 const struct vga_menu_item *vga_menu_bar_keymon() {
236         const struct vga_menu_bar_item *m = NULL;
237         const struct vga_menu_item *ret = NULL;
238         unsigned int spec=0;
239         int c,i;
240
241         if (vga_menu_bar.bar == NULL)
242                 return ret;
243
244         if (read_bios_keystate() & BIOS_KS_ALT) {
245                 vga_menu_bar.sel = 0;
246                 vga_menu_bar_draw();
247
248 again:
249                 do {
250                         vga_menu_idle();
251                         if (kbhit()) {
252                                 c = getch();
253                                 if (c == 0) {
254                                         i = 0;
255                                         c = getch();
256                                         if (c == 0x9B) { /* ALT-left */
257                                                 if (--vga_menu_bar.sel < 0) {
258                                                         vga_menu_bar.sel = 0;
259                                                         while (vga_menu_bar.bar[vga_menu_bar.sel].name != NULL) vga_menu_bar.sel++;
260                                                         vga_menu_bar.sel--;
261                                                 }
262                                                 m = &vga_menu_bar.bar[vga_menu_bar.sel];
263                                                 vga_menu_bar_draw();
264                                         }
265                                         else if (c == 0x9D) { /* ALT-right */
266                                                 if (vga_menu_bar.bar[++vga_menu_bar.sel].name == NULL) vga_menu_bar.sel = 0;
267                                                 m = &vga_menu_bar.bar[vga_menu_bar.sel];
268                                                 vga_menu_bar_draw();
269                                         }
270                                         else {
271                                                 int oi = vga_menu_bar.sel;
272
273                                                 for (m=vga_menu_bar.bar;m->name != NULL;m++,i++) {
274                                                         if (c == m->shortcut_scan)
275                                                                 break;
276                                                 }
277                                                 if (m->name == NULL) {
278                                                         m = NULL;
279                                                         vga_menu_bar.sel = -1;
280                                                 }
281                                                 else {
282                                                         vga_menu_bar.sel = i;
283                                                 }
284
285                                                 if (oi != vga_menu_bar.sel)
286                                                         vga_menu_bar_draw();
287
288                                                 if (m != NULL)
289                                                         break;
290                                         }
291                                 }
292                         }
293                 } while (read_bios_keystate() & BIOS_KS_ALT);
294
295                 if (!(read_bios_keystate() & BIOS_KS_ALT)) {
296                         while (kbhit()) getch();
297                 }
298
299                 if (m != NULL) {
300                         ret = vga_menu_bar_menuitem(m,vga_menu_bar.row+1,&spec);
301                         if (ret == NULL) {
302                                 if (spec == 0x4B00) {
303                                         if (--vga_menu_bar.sel < 0) {
304                                                 vga_menu_bar.sel = 0;
305                                                 while (vga_menu_bar.bar[vga_menu_bar.sel].name != NULL) vga_menu_bar.sel++;
306                                                 vga_menu_bar.sel--;
307                                         }
308                                         m = &vga_menu_bar.bar[vga_menu_bar.sel];
309                                         vga_menu_bar_draw();
310                                         goto again;
311                                 }
312                                 else if (spec == 0x4D00) {
313                                         if (vga_menu_bar.bar[++vga_menu_bar.sel].name == NULL) vga_menu_bar.sel = 0;
314                                         m = &vga_menu_bar.bar[vga_menu_bar.sel];
315                                         vga_menu_bar_draw();
316                                         goto again;
317                                 }
318                         }
319                 }
320
321                 while (read_bios_keystate() & BIOS_KS_ALT);
322                 vga_menu_bar.sel = -1;
323                 vga_menu_bar_draw();
324         }
325
326         return ret;
327 }
328
329 int vga_msg_box_create(struct vga_msg_box *b,const char *msg,unsigned int extra_y,unsigned int min_x) {
330         unsigned int w=min_x,h=max(1,extra_y),x=0,y,px,py,i,o;
331         static const unsigned int color = 0x1E00;
332         const char *scan;
333
334         scan = msg;
335         while (*scan != 0) {
336                 if (*scan == '\n') {
337                         x=0;
338                         h++;
339                 }
340                 else if ((unsigned char)(*scan) >= 32) {
341                         x++;
342                         if (w < x) w = x;
343                 }
344                 scan++;
345         }
346         w += 4; if (w > 80) w = 80;
347         h += 2; if (h > 25) h = 25;
348         px = (vga_width - w) / 2;
349         py = (vga_height - h) / 2;
350         b->screen = vga_alpha_ram + (py * vga_width) + px;
351         b->x = px;
352         b->y = py;
353         b->w = w;
354         b->h = h;
355
356 #if TARGET_MSDOS == 32
357         b->buf = malloc(w * h * 2);
358 #else
359         b->buf = _fmalloc(w * h * 2);
360 #endif
361         if (b->buf != NULL) {
362                 /* copy the screen to buffer */
363                 for (y=0;y < h;y++) {
364                         i = y * vga_width;
365                         o = y * w;
366                         for (x=0;x < w;x++,i++,o++) b->buf[o] = b->screen[i];
367                 }
368         }
369
370         /* draw border */
371         for (y=1;y < (h-1);y++) {
372                 o = y * vga_width;
373                 b->screen[o+0] = 186 | color;
374                 b->screen[o+1] = 32 | color;
375                 b->screen[o+w-2] = 32 | color;
376                 b->screen[o+w-1] = 186 | color;
377         }
378         o = (h-1)*vga_width;
379         for (x=1;x < (w-1);x++) {
380                 b->screen[x] = 205 | color;
381                 b->screen[x+o] = 205 | color;
382         }
383         b->screen[0] = 201 | color;
384         b->screen[w-1] = 187 | color;
385         b->screen[o] = 200 | color;
386         b->screen[o+w-1] = 188 | color;
387
388         x = 0;
389         y = 0;
390         o = vga_width + 2;
391         scan = msg;
392         while (*scan != 0) {
393                 if (*scan == '\n') {
394                         while (x < (w-4)) {
395                                 b->screen[o+x] = 32 | color;
396                                 x++;
397                         }
398                         if (++y >= (h-2)) break;
399                         x = 0;
400                         o += vga_width;
401                 }
402                 else if ((unsigned char)(*scan) >= 32) {
403                         if (x < (w-4)) b->screen[o+x] = *scan | color;
404                         x++;
405                 }
406                 scan++;
407         }
408         while (y < (h-2)) {
409                 while (x < (w-4)) {
410                         b->screen[o+x] = 32 | color;
411                         x++;
412                 }
413                 ++y;
414                 x = 0;
415                 o += vga_width;
416         }
417
418         b->w = w;
419         b->h = h;
420         return 1;
421 }
422
423 void vga_msg_box_destroy(struct vga_msg_box *b) {
424         unsigned int x,y,i,o;
425
426         if (b) {
427                 if (b->buf) {
428                         /* copy screen back */
429                         for (y=0;y < b->h;y++) {
430                                 i = y * b->w;
431                                 o = y * vga_width;
432                                 for (x=0;x < b->w;x++,i++,o++) b->screen[o] = b->buf[i];
433                         }
434
435 #if TARGET_MSDOS == 32
436                         free(b->buf);
437 #else
438                         _ffree(b->buf);
439 #endif
440                         b->buf = NULL;
441                 }
442                 b->screen = NULL;
443         }
444 }
445
446 int confirm_yes_no_dialog(const char *message) {
447         struct vga_msg_box box = {NULL,NULL,0,0};
448         unsigned int x,bw;
449         int ret = 1,c;
450
451         bw = 8;
452         if (vga_msg_box_create(&box,message,2,(bw*2)+2)) {
453                 x = ((box.w+2-(bw*2))/2)+box.x;
454                 vga_write_color(0x70);
455                 vga_moveto(x,box.y+box.h-2);
456                 vga_write("  ");
457                 vga_write_color(0x71);
458                 vga_write("Y");
459                 vga_write_color(0x70);
460                 vga_write("es  ");
461                 vga_moveto(x+bw,box.y+box.h-2);
462                 vga_write("  ");
463                 vga_write_color(0x71);
464                 vga_write("N");
465                 vga_write_color(0x70);
466                 vga_write("o  ");
467
468                 while (1) {
469                         vga_menu_idle();
470                         if (kbhit()) {
471                                 c = getch();
472                                 if (c == 0) c = getch() << 8;
473
474                                 if (c == 'Y' || c == 'y') {
475                                         ret = 1;
476                                         break;
477                                 }
478                                 else if (c == 'N' || c == 'n') {
479                                         ret = 0;
480                                         break;
481                                 }
482                                 else if (c == 27) {
483                                         ret = 0;
484                                         break;
485                                 }
486                         }
487                 }
488
489                 vga_msg_box_destroy(&box);
490         }
491
492         return ret;
493 }
494