K&R style function removal. Update functions to ANSI style.
[dragonfly.git] / usr.bin / doscmd / tty.c
1 /*
2  * Copyright (c) 1992, 1993, 1996
3  *      Berkeley Software Design, Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Berkeley Software
16  *      Design, Inc.
17  *
18  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      BSDI tty.c,v 2.4 1996/04/08 22:03:27 prb Exp
31  *
32  * $FreeBSD: src/usr.bin/doscmd/tty.c,v 1.8.2.2 2002/04/25 11:04:51 tg Exp $
33  * $DragonFly: src/usr.bin/doscmd/tty.c,v 1.3 2003/10/04 20:36:43 hmp Exp $
34  */
35
36 #include <sys/ioctl.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/mman.h>
40 #include <ctype.h>
41 #include <err.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <paths.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <termios.h>
48 #include <unistd.h>
49 #ifdef __FreeBSD__
50 # include <osreldate.h>
51 # if __FreeBSD_version >= 500014
52 #   include <sys/kbio.h>
53 # else
54 #   include <machine/console.h>
55 # endif
56 #else
57 # ifdef __NetBSD__
58 #  include "machine/pccons.h"
59 # else  /* BSD/OS */
60 #  include "/sys/i386/isa/pcconsioctl.h"
61 # endif
62 #endif
63
64 #ifndef NO_X
65 #include <X11/Xlib.h>
66 #include <X11/Xutil.h>
67 #include <X11/keysym.h>
68 #endif
69
70 #include "doscmd.h"
71 #include "AsyncIO.h"
72 #include "font8x8.h"
73 #include "font8x14.h"
74 #include "font8x16.h"
75 #include "mouse.h"
76 #include "trap.h"
77 #include "tty.h"
78 #include "video.h"
79
80 #ifndef NO_X
81 static int show = 1;
82 #endif
83 static int blink = 1;
84 int flipdelete = 0;             /* Flip meaning of delete and backspace */
85 static u_short break_code = 0x00;
86 static u_short scan_code = 0x00;
87 int height;
88 int width;
89 int vattr;
90 const char *xfont = 0;
91
92 #ifndef NO_X
93 Display *dpy;
94 Window win;
95 XFontStruct *font;
96 XImage *xi = 0;
97 Visual *visual;
98 unsigned int depth;
99 unsigned long black;
100 unsigned long white;
101 int FW, FH, FD;
102 GC gc;
103 GC cgc;
104 int xfd;
105
106 /* LUT for the vram -> XImage conversion */
107 u_int8_t lut[4][256][8];
108
109 /* X pixel values for the RGB triples */
110 unsigned long pixels[16];
111 #endif
112
113 typedef struct TextLine {
114     u_short     *data;
115     u_char      max_length;     /* Not used, but here for future use */
116     u_char      changed:1;
117 } TextLine;
118 TextLine *lines = NULL;
119
120 int kbd_fd = -1;
121 int kbd_read = 0;
122
123 static struct termios tty_cook, tty_raw;
124
125 #define row (CursRow0)
126 #define col (CursCol0)
127
128 /* Local functions */
129 static void     _kbd_event(int, int, void *, regcontext_t *);
130 static void     Failure(void *);
131 static void     SetVREGCur(void);
132 static void     debug_event(int, int, void *, regcontext_t *);
133 static unsigned char    inb_port60(int);
134 static int      inrange(int, int, int);
135 static void     kbd_event(int, int, void *, regcontext_t *);
136 static u_short  read_raw_kbd(int, u_short *);
137 static void     setgc(u_short);
138 static void     video_async_event(int, int, void *, regcontext_t *);
139
140 #ifndef NO_X
141 static void     dac2rgb(XColor *, int);
142 static void     prepare_lut(void);
143 static void     putchar_graphics(int, int, int);
144 static void     tty_rwrite_graphics(int, int, int);
145 static int      video_event(XEvent *ev);
146 static void     video_update_graphics(void);
147 static void     video_update_text(void);
148 static void     vram2ximage(void);
149 #endif
150
151 #define PEEKSZ  16
152
153 #define K_NEXT          *(u_short *)0x41a
154 #define K_FREE          *(u_short *)0x41c
155 #define K_BUFSTARTP     *(u_short *)0x480
156 #define K_BUFENDP       *(u_short *)0x482
157 #define K_BUFSTART      ((u_short *)(0x400 + *(u_short *)0x480))
158 #define K_BUFEND        ((u_short *)(0x400 + *(u_short *)0x482))
159 #define K_BUF(i)        *((u_short *)((u_char *)0x400 + (i)))
160
161 #define K1_STATUS       BIOSDATA[0x17]
162 #define K1_RSHIFT       0x01
163 #define K1_LSHIFT       0x02
164 #define K1_SHIFT        0x03
165 #define K1_CTRL         0x04
166 #define K1_ALT          0x08
167 #define K1_SLOCK        0x10            /* Active */
168 #define K1_NLOCK        0x20            /* Active */
169 #define K1_CLOCK        0x40            /* Active */
170 #define K1_INSERT       0x80            /* Active */
171
172 #define K2_STATUS       BIOSDATA[0x18]
173 #define K2_LCTRL        0x01
174 #define K2_LALT         0x02
175 #define K2_SYSREQ       0x04
176 #define K2_PAUSE        0x08
177 #define K2_SLOCK        0x10            /* Actually held down */
178 #define K2_NLOCK        0x20            /* Actually held down */
179 #define K2_CLOCK        0x40            /* Actually held down */
180 #define K2_INSERT       0x80            /* Actually held down */
181
182 #define K3_STATUS       BIOSDATA[0x96]
183 #define K3_E1           0x01            /* Last code read was e1 */
184 #define K3_E2           0x02            /* Last code read was e2 */
185 #define K3_RCTRL        0x04
186 #define K3_RALT         0x08
187 #define K3_ENHANCED     0x10
188 #define K3_FORCENLOCK   0x20
189 #define K3_TWOBYTE      0x40            /* last code was first of 2 */
190 #define K3_READID       0x80            /* read ID in progress */
191
192 #define K4_STATUS       BIOSDATA[0x97]
193 #define K4_SLOCK_LED    0x01
194 #define K4_NLOCK_LED    0x02
195 #define K4_CLOCK_LED    0x04
196 #define K4_ACK          0x10            /* ACK recieved from keyboard */
197 #define K4_RESEND       0x20            /* RESEND recieved from keyboard */
198 #define K4_LED          0x40            /* LED update in progress */
199 #define K4_ERROR        0x80
200
201 static void
202 Failure(void *arg __unused)
203 {
204         fprintf(stderr, "X Connection shutdown\n");
205         quit(1);
206 }
207
208 static void
209 SetVREGCur(void)
210 {
211     int cp = row * width + col;
212     VGA_CRTC[CRTC_CurLocHi] = cp >> 8;
213     VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
214 }
215
216 static void
217 console_denit(void *arg)
218 {
219     int fd = *(int *)arg;
220
221 #ifdef __FreeBSD__
222     if (ioctl(fd, KDSKBMODE, K_XLATE))
223         perror("KDSKBMODE/K_XLATE");
224 #else
225 # ifdef __NetBSD__
226     if (ioctl(fd, CONSOLE_X_MODE_OFF, 0))
227         perror("CONSOLE_X_MODE_OFF");
228 # else /* BSD/OS */
229     if (ioctl(fd, PCCONIOCCOOK, 0))
230         perror("PCCONIOCCOOK");
231 # endif
232 #endif
233     if (tcsetattr(fd, TCSANOW, &tty_cook))
234         perror("tcsetattr");
235 }
236
237 void
238 _kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
239 {
240     if (!(cond & AS_RD))
241         return;
242     printf("_kbd_event: fd=%d\n", fd);
243     kbd_read = 1;
244 }
245
246 void
247 console_init(void)
248 {
249     int fd;
250     caddr_t addr;
251
252     if ((fd = open(_PATH_DEV "vga", 2)) < 0) {
253         perror(_PATH_DEV "vga");
254         quit(1);
255     }
256     addr = mmap((caddr_t)0xA0000, 5 * 64 * 1024,
257                 PROT_EXEC | PROT_READ | PROT_WRITE,
258                 MAP_FILE | MAP_FIXED | MAP_SHARED,
259                 fd, 0);
260     if (addr != (caddr_t)0xA0000) {
261         perror("mmap");
262         quit(1);
263     }
264
265 #if 0
266     addr = mmap((caddr_t)0x100000 - 0x1000, 0x1000,
267                 PROT_EXEC | PROT_READ | PROT_WRITE,
268                 MAP_FILE | MAP_FIXED | MAP_SHARED,
269                 fd, 0);
270     if (addr != (caddr_t)(0x100000 - 0x1000)) {
271         perror("mmap");
272         quit(1);
273     }
274 #endif
275
276     if ((fd = open(_PATH_CONSOLE, 2)) < 0) {
277         perror(_PATH_CONSOLE);
278         quit(1);
279     }
280
281     fd = squirrel_fd(fd);
282     kbd_fd = fd;
283
284 #ifdef __FreeBSD__
285     if (ioctl(fd, KDSKBMODE, K_RAW)) {
286         perror("KDSKBMODE/K_RAW");
287         quit(1);    
288     }
289 #else
290 # ifdef __NetBSD__
291     if (ioctl(fd, CONSOLE_X_MODE_ON, 0)) {
292         perror("CONSOLE_X_MODE_ON");
293         quit(1);    
294     }
295 # else /* BSD/OS */
296       if (ioctl(fd, PCCONIOCRAW, 0)) {
297         perror("PCCONIOCRAW");
298         quit(1);    
299       }
300 # endif
301 #endif
302
303     call_on_quit(console_denit, &kbd_fd);
304
305     if (fcntl(fd, F_SETFL, O_NDELAY|O_ASYNC) < 0) {
306         perror("fcntl");
307         quit(1);    
308     }
309     if (tcgetattr(fd, &tty_cook)) {
310         perror("tcgetattr");
311         quit(1);    
312     }
313     tty_raw = tty_cook;
314     cfmakeraw(&tty_raw);
315     if (tcsetattr(fd, TCSANOW, &tty_raw)) {
316         perror("tcsetattr");
317         quit(1);    
318     }
319
320 #if 0
321     _RegisterIO(STDIN_FILENO, debug_event, 0, Failure);
322     _RegisterIO(fd, kbd_event, 0, Failure);
323 #endif
324     _RegisterIO(fd, _kbd_event, 0, Failure);
325 }
326
327 void
328 video_setborder(int color)
329 {
330 #ifndef NO_X
331         XSetWindowBackground(dpy, win, pixels[color & 0xf]);
332 #endif
333 }
334 void
335 video_blink(int mode)
336 {
337         blink = mode;
338 }
339
340 static void
341 setgc(u_short attr)
342 {
343 #ifndef NO_X
344         XGCValues v;
345         if (blink && !show && (attr & 0x8000))
346                 v.foreground = pixels[(attr >> 12) & 0x07];
347         else
348                 v.foreground = pixels[(attr >> 8) & 0x0f];
349
350         v.background = pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
351         XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
352 #endif
353 }
354
355 void
356 video_update(regcontext_t *REGS __unused)
357 {
358 #ifndef NO_X
359         static int icnt = 3;
360
361         if (kbd_read)
362             kbd_event(kbd_fd, AS_RD, 0, REGS);
363
364         if (--icnt == 0) {
365             icnt = 3;
366
367             lpt_poll();         /* Handle timeout on lpt code */
368
369             /* quick and dirty */
370             if (VGA_ATC[ATC_ModeCtrl] & 1)
371                 video_update_graphics();
372             else
373                 video_update_text();
374         }
375 #endif
376 }
377
378 #ifndef NO_X
379 static void
380 video_update_graphics(void)
381 {
382     vram2ximage();
383     
384     XPutImage(dpy, win, DefaultGC(dpy, DefaultScreen(dpy)),
385               xi, 0, 0, 0, 0, width, height);
386     XFlush(dpy);
387     
388     return;
389 }
390
391 static void
392 video_update_text(void)
393 {
394     static int or = -1;
395     static int oc = -1;
396
397
398     static char buf[256];
399     int r, c;
400     int attr = vmem[0] & 0xff00;
401     XGCValues v;
402
403     if (xmode) {
404         wakeup_poll();  /* Wake up anyone waiting on kbd poll */
405
406         show ^= 1;
407
408         setgc(attr);
409
410         for (r = 0; r < height; ++r) {
411             int cc = 0;
412
413             if (!lines[r].changed) {
414                 if ((r == or || r == row) && (or != row || oc != col))
415                     lines[r].changed = 1;
416                 else {
417                     for (c = 0; c < width; ++c) {
418                         if (lines[r].data[c] != vmem[r * width + c]) {
419                             lines[r].changed = 1;
420                             break;
421                         }
422                         if (blink && lines[r].data[c] & 0x8000) {
423                             lines[r].changed = 1;
424                             break;
425                         }
426                     }
427                 }
428             }
429
430             if (!lines[r].changed)
431                 continue;
432
433             reset_poll();
434             lines[r].changed = 0;
435             memcpy(lines[r].data,
436                    &vmem[r * width], sizeof(u_short) * width);
437
438             for (c = 0; c < width; ++c) {
439                 int cv = vmem[r * width + c];
440                 if ((cv & 0xff00) != attr) {
441                     if (cc < c)
442                         XDrawImageString(dpy, win, gc,
443                                          2 + cc * FW,
444                                          2 + (r + 1) * FH,
445                                          buf + cc, c - cc);
446                     cc = c;
447                     attr = cv  & 0xff00;
448                     setgc(attr);
449                 }
450                 buf[c] = (cv & 0xff) ? cv & 0xff : ' ';
451             }
452             if (cc < c) {
453                 XDrawImageString(dpy, win, gc,
454                                  2 + cc * FW,
455                                  2 + (r + 1) * FH,
456                                  buf + cc, c - cc);
457             }
458         }
459         or = row;
460         oc = col;
461
462         if (CursStart <= CursEnd && CursEnd <= FH &&
463             show && row < height && col < width) {
464
465             attr = vmem[row * width + col] & 0xff00;
466             v.foreground = pixels[(attr >> 8) & 0x0f] ^
467                 pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
468             if (v.foreground) {
469                 v.function = GXxor;
470             } else {
471                 v.foreground = pixels[7];
472                 v.function = GXcopy;
473             }
474             XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
475             XFillRectangle(dpy, win, cgc,
476                            2 + col * FW,
477                            2 + row * FH + CursStart + FD,
478                            FW, CursEnd + 1 - CursStart);
479         }
480
481         if (mouse_status.installed && mouse_status.show) {
482             c = mouse_status.x / mouse_status.hmickey;
483             r = mouse_status.y / mouse_status.vmickey;
484
485             lines[r].changed = 1;
486             attr = vmem[r * width + c] & 0xff00;
487             v.foreground = pixels[(attr >> 8) & 0x0f] ^
488                 pixels[(attr >> 12) & 0x0f];
489             if (v.foreground) {
490                 v.function = GXxor;
491             } else {
492                 v.foreground = pixels[7];
493                 v.function = GXcopy;
494             }
495             XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
496             XFillRectangle(dpy, win, cgc,
497                            2 + c * FW,
498                            2 + r * FH + 2,
499                            FW, FH);
500         }
501                 
502         XFlush(dpy);
503     }
504 }
505
506 /* Convert the contents of the video RAM into an XImage.
507
508    Bugs: - The function is way too slow.
509          - It only works for the 16 color modes.
510          - It only works on 15/16-bit TrueColor visuals. */
511 static void
512 vram2ximage(void)
513 {
514     int i, x, y, yoffset;
515     u_int16_t *image = (u_int16_t *)xi->data;
516
517     yoffset = 0;
518     for (y = 0; y < height; y++) {
519         yoffset += width / 8;
520         for (x = 0; x < width; x += 8) {
521             int offset = yoffset + x / 8;
522             for (i = 0; i < 8; i++) {
523                 int color = lut[0][vplane0[offset]][i] |
524                     lut[1][vplane1[offset]][i] |
525                     lut[2][vplane2[offset]][i] |
526                     lut[3][vplane3[offset]][i];
527                 *image++ = (u_int16_t)pixels[color];
528             }       
529         }
530     }
531     
532     return;
533 }
534 #endif
535
536 static u_short Ascii2Scan[] = {
537  0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
538  0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
539  0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
540  0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
541  0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
542  0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
543  0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
544  0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
545  0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
546  0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
547  0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
548  0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
549  0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
550  0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
551  0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
552  0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
553 };
554
555 struct {
556     u_short     base;
557     u_short     shift;
558     u_short     ctrl;
559     u_short     alt;
560 } ScanCodes[] = {
561     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key  0 */
562     {   0x011b, 0x011b, 0x011b, 0xffff }, /* key  1 - Escape key */
563     {   0x0231, 0x0221, 0xffff, 0x7800 }, /* key  2 - '1' */
564     {   0x0332, 0x0340, 0x0300, 0x7900 }, /* key  3 - '2' - special handling */
565     {   0x0433, 0x0423, 0xffff, 0x7a00 }, /* key  4 - '3' */
566     {   0x0534, 0x0524, 0xffff, 0x7b00 }, /* key  5 - '4' */
567     {   0x0635, 0x0625, 0xffff, 0x7c00 }, /* key  6 - '5' */
568     {   0x0736, 0x075e, 0x071e, 0x7d00 }, /* key  7 - '6' */
569     {   0x0837, 0x0826, 0xffff, 0x7e00 }, /* key  8 - '7' */
570     {   0x0938, 0x092a, 0xffff, 0x7f00 }, /* key  9 - '8' */
571     {   0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
572     {   0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
573     {   0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
574     {   0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
575     {   0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
576     {   0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
577     {   0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
578     {   0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
579     {   0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
580     {   0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
581     {   0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
582     {   0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
583     {   0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
584     {   0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
585     {   0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
586     {   0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
587     {   0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
588     {   0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
589     {   0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
590     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
591     {   0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
592     {   0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
593     {   0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
594     {   0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
595     {   0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
596     {   0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
597     {   0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
598     {   0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
599     {   0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
600     {   0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
601     {   0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
602     {   0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
603     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
604     {   0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
605     {   0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
606     {   0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
607     {   0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
608     {   0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
609     {   0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
610     {   0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
611     {   0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
612     {   0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
613     {   0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
614     {   0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
615     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
616     {   0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
617     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
618     {   0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
619     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock -  */
620     {   0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
621     {   0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
622     {   0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
623     {   0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
624     {   0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
625     {   0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
626     {   0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
627     {   0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
628     {   0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
629     {   0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
630     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
631     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock -  */
632     {   0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
633     {   0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
634     {   0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
635     {   0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
636     {   0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
637     {   0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
638     {   0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
639     {   0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
640     {   0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
641     {   0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
642     {   0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
643     {   0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
644     {   0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
645     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
646     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
647     {   0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
648     {   0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
649     {   0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
650 };
651
652 void
653 debug_event(int fd, int cond, void *arg, regcontext_t *REGS)
654 {
655     static char ibuf[1024];
656     static int icnt = 0;
657     static u_short ds = 0;
658     static u_short di = 0;
659     static u_short cnt = 16 * 8;
660     char *ep;
661     int r;
662     
663     if (!(cond & AS_RD))
664         return;
665
666     r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt);
667     if (r <= 0)
668         return;
669
670     icnt += r;
671
672     ibuf[icnt] = 0;
673     while ((ep = strchr(ibuf, '\n')) != 0) {
674         int ac;
675         char *_av[16];
676         char **av;
677
678         *ep++ = 0;
679         ac = ParseBuffer(ibuf, av = _av, 16);
680
681         if (ac > 0) {
682             if (!strcasecmp(av[0], "dump")) {
683                 if (ac > 1) {
684                     char *c;
685                     if ((c = strchr(av[1], ':')) != 0) {
686                         ds = strtol(av[1], 0, 16);
687                         di = strtol(c+1, 0, 16);
688                     } else
689                         di = strtol(av[1], 0, 16);
690                 }
691                 if (ac > 2)
692                     cnt = strtol(av[2], 0, 0);
693                 cnt = (cnt + 0xf) & ~0xf;
694                 if (cnt == 0)
695                     cnt = 0x10;
696                 di &= ~0xf;
697
698                 for (r = 0; r < cnt; r += 0x10, di = (di + 0x10) & 0xffff) {
699                     int i;
700                     u_char *ap = (u_char *)(((u_long)ds << 4) + di);
701
702                     printf("%04x:%04x:", ds, di);
703                     for (i = 0; i < 8; ++i)
704                         printf(" %02x", ap[i]);
705                     printf(" ");
706                     for (i = 8; i < 16; ++i)
707                         printf(" %02x", ap[i]);
708                     printf(": ");
709                     for (i = 0; i < 8; ++i)
710                         printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
711                     printf(" ");
712                     for (i = 8; i < 16; ++i)
713                         printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
714                     printf("\n");
715                 }
716             } else if (!strcasecmp(av[0], "dis")) {
717                 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
718
719                 if (ac > 1) {
720                     char *c;
721                     if ((c = strchr(av[1], ':')) != 0) {
722                         ds = strtol(av[1], 0, 16);
723                         di = strtol(c+1, 0, 16);
724                     } else
725                         di = strtol(av[1], 0, 16);
726                 }
727                 if (ac > 2)
728                     cnt = strtol(av[2], 0, 0);
729
730                 for (r = 0; r < cnt; ++r) {
731                     char buf[16];
732                     int c = i386dis(ds, di, ap, buf, 0);
733                     printf("%04x:%04x %s\n", ds, di, buf);
734                     di += c;
735                     ap += c;
736                 }
737             } else if (!strcasecmp(av[0], "regs")) {
738                 dump_regs(REGS);
739             } else if (!strcasecmp(av[0], "force")) {
740                 char *p = av[1];
741
742                 while ((p = *++av) != 0) {
743                     while (*p) {
744                         if (*p >= ' ' && *p <= '~')
745                             KbdWrite(ScanCodes[Ascii2Scan[(int)*p] & 0xff].base);
746                         ++p;
747                     }
748                 }
749                 KbdWrite(ScanCodes[28].base);
750             } else if (!strcasecmp(av[0], "bell")) {
751 #ifndef NO_X            
752                 XBell(dpy, 0);
753                 XFlush(dpy);
754 #endif
755             } else {
756                 fprintf(stderr, "%s: unknown command\n", av[0]);
757             }
758         }
759
760         if (ep < ibuf + icnt) {
761             char *f = ep;
762             char *t = ibuf;
763             icnt -= ep - ibuf;
764             while (icnt--)
765                 *t++ = *f++;
766         } else
767             icnt = 0;
768         ibuf[icnt] = 0;
769     }
770 }
771
772 unsigned char
773 inb_port60(int port __unused)
774 {       
775     int r = break_code;
776     break_code = 0;
777     scan_code = 0xffff;
778     return(r);
779 }       
780
781 void
782 kbd_event(int fd, int cond, void *arg, regcontext_t *REGS)
783 {
784     if (!(cond & AS_RD))
785        return;
786     
787     kbd_read = 0;
788
789     printf("kbd_event: fd=%d\n", fd);
790     if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff)
791         hardint(0x01);
792 }
793
794 void
795 int09(REGISTERS __unused)
796 {
797     if (raw_kbd) {
798         if (scan_code != 0xffff) {
799             KbdWrite(scan_code);
800             break_code = 0;
801             scan_code = 0xffff;
802 #if 0
803             kbd_event(kbd_fd, 0, sc, REGS);
804 #endif
805         }
806     }
807     send_eoi();
808 }
809
810 u_short
811 read_raw_kbd(int fd, u_short *code)
812 {
813     unsigned char c;
814
815     *code = 0xffff;
816
817     if (read(fd, &c, 1) == 1) {
818         if (c == 0xe0) {
819             K3_STATUS |= K3_TWOBYTE;
820             return(c);
821         }
822         switch (c) {
823         case 29:        /* Control */
824             K1_STATUS |= K1_CTRL;
825             if (K3_STATUS & K3_TWOBYTE)
826                 K3_STATUS |= K3_RCTRL;
827             else
828                 K2_STATUS |= K2_LCTRL;
829             break;
830         case 29 | 0x80: /* Control */
831             K1_STATUS &= ~K1_CTRL;
832             if (K3_STATUS & K3_TWOBYTE)
833                 K3_STATUS &= ~K3_RCTRL;
834             else
835                 K2_STATUS &= ~K2_LCTRL;
836             break;
837
838         case 42:        /* left shift */
839             K1_STATUS |= K1_LSHIFT;
840             break;
841         case 42 | 0x80: /* left shift */
842             K1_STATUS &= ~K1_LSHIFT;
843             break;
844
845         case 54:        /* right shift */
846             K1_STATUS |= K1_RSHIFT;
847             break;
848         case 54 | 0x80: /* right shift */
849             K1_STATUS &= ~K1_RSHIFT;
850             break;
851
852         case 56:        /* Alt */
853             K1_STATUS |= K1_ALT;
854             if (K3_STATUS & K3_TWOBYTE)
855                 K3_STATUS |= K3_RALT;
856             else
857                 K2_STATUS |= K2_LALT;
858             break;
859         case 56 | 0x80: /* Alt */
860             K1_STATUS &= ~K1_ALT;
861             if (K3_STATUS & K3_TWOBYTE)
862                 K3_STATUS &= ~K3_RALT;
863             else
864                 K2_STATUS &= ~K2_LALT;
865             break;
866
867         case 58:        /* caps-lock */
868             K1_STATUS ^= K1_CLOCK;
869             if (K1_STATUS & K1_CLOCK)
870                 K4_STATUS |= K4_CLOCK_LED;
871             else
872                 K4_STATUS &= ~K4_CLOCK_LED;
873             K2_STATUS |= K2_CLOCK;
874             break;
875         case 58 | 0x80: /* caps-lock */
876             K2_STATUS &= ~K2_CLOCK;
877             break;
878
879         case 69:        /* num-lock */
880             K1_STATUS ^= K1_NLOCK;
881             if (K1_STATUS & K1_NLOCK)
882                 K4_STATUS |= K4_NLOCK_LED;
883             else
884                 K4_STATUS &= ~K4_NLOCK_LED;
885             K2_STATUS |= K2_NLOCK;
886             break;
887         case 69 | 0x80: /* num-lock */
888             K2_STATUS &= ~K2_NLOCK;
889             break;
890
891         case 70:        /* scroll-lock */
892             K1_STATUS ^= K1_SLOCK;
893             if (K1_STATUS & K1_SLOCK)
894                 K4_STATUS |= K4_SLOCK_LED;
895             else
896                 K4_STATUS &= ~K4_SLOCK_LED;
897             K2_STATUS |= K2_SLOCK;
898             break;
899         case 70 | 0x80: /* scroll-lock */
900             K2_STATUS &= ~K2_SLOCK;
901             break;
902
903         case 82:        /* insert */
904             K1_STATUS ^= K1_INSERT;
905             K2_STATUS |= K2_INSERT;
906             break;
907         case 82 | 0x80: /* insert */
908             K2_STATUS &= ~K2_INSERT;
909             break;
910
911         }
912
913 #if 0 /*XXXXX*/
914         if ((K4_STATUS & 0x07) != oldled) {
915             oldled = K4_STATUS & 0x07;
916             ioctl (fd, PCCONIOCSETLED, &oldled);
917         }
918 #endif
919
920         if (c == 83 && (K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL))
921             quit(0);
922
923         if (c < 89) {
924             u_short scode;
925
926             if (K1_STATUS & K1_ALT) {
927                 scode = ScanCodes[c].alt;
928             } else if (K1_STATUS & K1_CTRL) {
929                 scode = ScanCodes[c].ctrl;
930             } else if (K1_STATUS & K1_SHIFT) {
931                 scode = ScanCodes[c].shift;
932             } else {
933                 scode = ScanCodes[c].base;
934                 if (K1_STATUS & K1_CLOCK) {
935                     if (islower(scode & 0xff)) {
936                         scode = (scode & 0xff00) | toupper(scode & 0xff);
937                     }
938                 }
939                 if ((K1_STATUS & K1_NLOCK) && (K3_STATUS & K3_TWOBYTE) == 0) {
940                     switch (c) {
941                     case 71: /* home */
942                     case 72: /* cursor up */
943                     case 73: /* page up */
944                     case 75: /* cursor left */
945                     case 76: /* center key */
946                     case 77: /* cursor right */
947                     case 79: /* end */
948                     case 80: /* cursor down */
949                     case 81: /* page down */
950                     case 82: /* insert */
951                     case 83: /* delete */
952                         scode = ScanCodes[c].shift;
953                         break;
954                     }
955                 }
956             }
957             *code = scode;
958         }
959         K3_STATUS &= ~K3_TWOBYTE;
960         if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
961             switch (c) {
962             case 0x13:  /* R */
963                 kill(getpid(), SIGALRM);        /* force redraw */
964 printf("FORCED REDRAW\n");
965                 return(0xffff);
966             case 0x14:  /* T */
967                 tmode ^= 1;
968                 if (!tmode)
969                     resettrace((regcontext_t *)&saved_sigframe->
970                         sf_uc.uc_mcontext);
971                 return(0xffff);
972             case 0x53:  /* DEL */
973                 quit(0);
974             }
975         }
976         return(c);
977     } else {
978         return(0xffff);
979     }
980 }
981
982 void
983 video_async_event(int fd, int cond, void *arg, regcontext_t *REGS)
984 {
985 #ifndef NO_X
986         int int9 = 0;
987
988         if (!(cond & AS_RD))
989             return;
990         
991         for (;;) {
992                 int x;
993                 fd_set fdset;
994                 XEvent ev;  
995                 static struct timeval tv;
996  
997                 /*
998                  * Handle any events just sitting around...
999                  */
1000                 XFlush(dpy);
1001                 while (QLength(dpy) > 0) {
1002                         XNextEvent(dpy, &ev);
1003                         int9 |= video_event(&ev);
1004                 }
1005
1006                 FD_ZERO(&fdset);
1007                 FD_SET(fd, &fdset);
1008
1009                 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1010
1011                 switch (x) {  
1012                 case -1:
1013                         /*
1014                          * Errno might be wrong, so we just select again.
1015                          * This could cause a problem is something really
1016                          * was wrong with select....
1017                          */
1018                         perror("select");
1019                         return;
1020                 case 0:
1021                         XFlush(dpy);
1022                         if (int9)
1023                             hardint(0x01);
1024                         return;
1025                 default:
1026                         if (FD_ISSET(fd, &fdset)) {
1027                                 do {
1028                                         XNextEvent(dpy, &ev);
1029                                         int9 |= video_event(&ev);
1030                                 } while (QLength(dpy));
1031                         }
1032                         break;
1033                 }
1034         }
1035 #endif
1036 }
1037
1038 #ifndef NO_X
1039 static int
1040 video_event(XEvent *ev)
1041 {
1042         switch (ev->type) {
1043         case MotionNotify: {
1044                 XMotionEvent *me = (XMotionEvent *)ev;
1045                 me->x -= 2;
1046                 me->y -= 2;
1047
1048                 mouse_status.x = (me->x < mouse_status.range.x)
1049                                     ? mouse_status.range.x
1050                                     : (me->x > mouse_status.range.w)
1051                                     ? mouse_status.range.w : me->x;
1052                 mouse_status.y = (me->y < mouse_status.range.y)
1053                                     ? mouse_status.range.y
1054                                     : (me->y > mouse_status.range.h)
1055                                     ? mouse_status.range.h : me->y;
1056                 break;
1057             }
1058         case ButtonRelease: {
1059                 XButtonEvent *be = (XButtonEvent *)ev;
1060                 be->x -= 2;
1061                 be->y -= 2;
1062
1063                 if (be->button < 3)
1064                     mouse_status.ups[be->button]++;
1065
1066                 mouse_status.x = (be->x < mouse_status.range.x)
1067                                     ? mouse_status.range.x
1068                                     : (be->x > mouse_status.range.w)
1069                                     ? mouse_status.range.w : be->x;
1070                 mouse_status.y = (be->y < mouse_status.range.y)
1071                                     ? mouse_status.range.y
1072                                     : (be->y > mouse_status.range.h)
1073                                     ? mouse_status.range.h : be->y;
1074                 break;
1075             }
1076         case ButtonPress: {
1077                 XButtonEvent *be = (XButtonEvent *)ev;
1078                 be->x -= 2;
1079                 be->y -= 2;
1080
1081                 if (be->button < 3)
1082                     mouse_status.downs[be->button]++;
1083
1084                 mouse_status.x = (be->x < mouse_status.range.x)
1085                                     ? mouse_status.range.x
1086                                     : (be->x > mouse_status.range.w)
1087                                     ? mouse_status.range.w : be->x;
1088                 mouse_status.y = (be->y < mouse_status.range.y)
1089                                     ? mouse_status.range.y
1090                                     : (be->y > mouse_status.range.h)
1091                                     ? mouse_status.range.h : be->y;
1092
1093                 if ((K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1094                     quit(0);
1095                 }
1096                 break;
1097             }
1098         case NoExpose:
1099                 break;
1100         case GraphicsExpose:
1101         case Expose: {
1102                 int r;
1103                 for (r = 0; r < height; ++r)
1104                     lines[r].changed = 1;
1105                 break;
1106             }
1107         case KeyRelease: {
1108                 static char buf[128];
1109                 KeySym ks;
1110
1111                 break_code |= 0x80;
1112
1113                 if (!(ev->xkey.state & ShiftMask)) {
1114                     K1_STATUS &= ~K1_LSHIFT;
1115                     K1_STATUS &= ~K1_RSHIFT;
1116                 }
1117                 if (!(ev->xkey.state & ControlMask)) {
1118                         K1_STATUS &= ~K1_CTRL;
1119                         K2_STATUS &= ~K2_LCTRL;
1120                         K3_STATUS &= ~K3_RCTRL;
1121                 }
1122                 if (!(ev->xkey.state & Mod1Mask)) {
1123                         K1_STATUS &= ~K1_ALT;
1124                         K2_STATUS &= ~K2_LALT;
1125                         K3_STATUS &= ~K3_RALT;
1126                 }
1127                 if (!(ev->xkey.state & LockMask)) {
1128                         K2_STATUS &= ~K2_CLOCK;
1129                 }
1130
1131                 XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1132                 switch (ks) {
1133                 case XK_Shift_L:
1134                         K1_STATUS &= ~K1_LSHIFT;
1135                         break;
1136                 case XK_Shift_R:
1137                         K1_STATUS &= ~K1_RSHIFT;
1138                         break;
1139                 case XK_Control_L:
1140                         K1_STATUS &= ~K1_CTRL;
1141                         K2_STATUS &= ~K2_LCTRL;
1142                         break;
1143                 case XK_Control_R:
1144                         K1_STATUS &= ~K1_CTRL;
1145                         K3_STATUS &= ~K3_RCTRL;
1146                         break;
1147                 case XK_Alt_L:
1148                         K1_STATUS &= ~K1_ALT;
1149                         K2_STATUS &= ~K2_LALT;
1150                         break;
1151                 case XK_Alt_R:
1152                         K1_STATUS &= ~K1_ALT;
1153                         K3_STATUS &= ~K3_RALT;
1154                         break;
1155                 case XK_Scroll_Lock:
1156                         K2_STATUS &= ~K2_SLOCK;
1157                         break;
1158                 case XK_Num_Lock:
1159                         K2_STATUS &= ~K2_NLOCK;
1160                         break;
1161                 case XK_Caps_Lock:
1162                         K2_STATUS &= ~K2_CLOCK;
1163                         break;
1164                 case XK_Insert:
1165                         K2_STATUS &= ~K2_INSERT;
1166                         break;
1167                 }
1168                 return(1);
1169             }
1170         case KeyPress: {
1171                 static char buf[128];
1172                 KeySym ks;
1173                 int n;
1174                 int nlock = 0;
1175                 u_short scan = 0xffff;
1176
1177                 if (!(ev->xkey.state & ShiftMask)) {
1178                     K1_STATUS &= ~K1_LSHIFT;
1179                     K1_STATUS &= ~K1_RSHIFT;
1180                 }
1181                 if (!(ev->xkey.state & ControlMask)) {
1182                         K1_STATUS &= ~K1_CTRL;
1183                         K2_STATUS &= ~K2_LCTRL;
1184                         K3_STATUS &= ~K3_RCTRL;
1185                 }
1186                 if (!(ev->xkey.state & Mod1Mask)) {
1187                         K1_STATUS &= ~K1_ALT;
1188                         K2_STATUS &= ~K2_LALT;
1189                         K3_STATUS &= ~K3_RALT;
1190                 }
1191                 if (!(ev->xkey.state & LockMask)) {
1192                         K2_STATUS &= ~K2_CLOCK;
1193                 }
1194
1195                 n = XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1196
1197                 switch (ks) {
1198                 case XK_Shift_L:
1199                         K1_STATUS |= K1_LSHIFT;
1200                         break;
1201                 case XK_Shift_R:
1202                         K1_STATUS |= K1_RSHIFT;
1203                         break;
1204                 case XK_Control_L:
1205                         K1_STATUS |= K1_CTRL;
1206                         K2_STATUS |= K2_LCTRL;
1207                         break;
1208                 case XK_Control_R:
1209                         K1_STATUS |= K1_CTRL;
1210                         K3_STATUS |= K3_RCTRL;
1211                         break;
1212                 case XK_Alt_L:
1213                         K1_STATUS |= K1_ALT;
1214                         K2_STATUS |= K2_LALT;
1215                         break;
1216                 case XK_Alt_R:
1217                         K1_STATUS |= K1_ALT;
1218                         K3_STATUS |= K3_RALT;
1219                         break;
1220                 case XK_Scroll_Lock:
1221                         K1_STATUS ^= K1_SLOCK;
1222                         K2_STATUS |= K2_SLOCK;
1223                         break;
1224                 case XK_Num_Lock:
1225                         K1_STATUS ^= K1_NLOCK;
1226                         K2_STATUS |= K2_NLOCK;
1227                         break;
1228                 case XK_Caps_Lock:
1229                         K1_STATUS ^= K1_CLOCK;
1230                         K2_STATUS |= K2_CLOCK;
1231                         break;
1232                 case XK_Insert:
1233                 case XK_KP_Insert:
1234                         K1_STATUS ^= K1_INSERT;
1235                         K2_STATUS |= K2_INSERT;
1236                         scan = 82;
1237                         goto docode;
1238
1239                 case XK_Escape:
1240                         scan = 1;
1241                         goto docode;
1242
1243                 case XK_Tab:
1244                 case XK_ISO_Left_Tab:
1245                         scan = 15;
1246                         goto docode;
1247                         
1248                 case XK_Return:
1249                 case XK_KP_Enter:
1250                         scan = 28;
1251                         goto docode;
1252
1253                 case XK_Print:
1254                         scan = 55;
1255                         goto docode;
1256
1257                 case XK_F1:
1258                 case XK_F2:
1259                 case XK_F3:
1260                 case XK_F4:
1261                 case XK_F5:
1262                 case XK_F6:
1263                 case XK_F7:
1264                 case XK_F8:
1265                 case XK_F9:
1266                 case XK_F10:
1267                         scan = ks - XK_F1 + 59;
1268                         goto docode;
1269
1270                 case XK_KP_7:
1271                         nlock = 1;
1272                 case XK_Home:
1273                 case XK_KP_Home:
1274                         scan = 71;
1275                         goto docode;
1276                 case XK_KP_8:
1277                         nlock = 1;
1278                 case XK_Up:
1279                 case XK_KP_Up:
1280                         scan = 72;
1281                         goto docode;
1282                 case XK_KP_9:
1283                         nlock = 1;
1284                 case XK_Prior:
1285                 case XK_KP_Prior:
1286                         scan = 73;
1287                         goto docode;
1288                 case XK_KP_Subtract:
1289                         scan = 74;
1290                         goto docode;
1291                 case XK_KP_4:
1292                         nlock = 1;
1293                 case XK_Left:
1294                 case XK_KP_Left:
1295                         scan = 75;
1296                         goto docode;
1297                 case XK_KP_5:
1298                         nlock = 1;
1299                 case XK_Begin:
1300                 case XK_KP_Begin:
1301                         scan = 76;
1302                         goto docode;
1303                 case XK_KP_6:
1304                         nlock = 1;
1305                 case XK_Right:
1306                 case XK_KP_Right:
1307                         scan = 77;
1308                         goto docode;
1309                 case XK_KP_Add:
1310                         scan = 78;
1311                         goto docode;
1312                 case XK_KP_1:
1313                         nlock = 1;
1314                 case XK_End:
1315                 case XK_KP_End:
1316                         scan = 79;
1317                         goto docode;
1318                 case XK_KP_2:
1319                         nlock = 1;
1320                 case XK_Down:
1321                 case XK_KP_Down:
1322                         scan = 80;
1323                         goto docode;
1324                 case XK_KP_3:
1325                         nlock = 1;
1326                 case XK_Next:
1327                 case XK_KP_Next:
1328                         scan = 81;
1329                         goto docode;
1330                 case XK_KP_0:
1331                         nlock = 1;
1332                 /* case XK_Insert: This is above */
1333                         scan = 82;
1334                         goto docode;
1335
1336                 case XK_KP_Decimal:
1337                         nlock = 1;
1338                         scan = 83;
1339                         goto docode;
1340
1341                 case XK_Delete:
1342                 case XK_KP_Delete:
1343                         scan = flipdelete ? 14 : 83;
1344                         goto docode;
1345
1346                 case XK_BackSpace:
1347                         scan = flipdelete ? 83 : 14;
1348                         goto docode;
1349
1350                 case XK_F11:
1351                         scan = 87;
1352                         goto docode;
1353                 case XK_F12:
1354                         scan = 88;
1355                         goto docode;
1356
1357
1358                 case XK_KP_Divide:
1359                         scan = Ascii2Scan['/'];
1360                         goto docode;
1361
1362                 case XK_KP_Multiply:
1363                         scan = Ascii2Scan['*'];
1364                         goto docode;
1365
1366                 default:
1367                         if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1368                                 if (ks == 'T' || ks == 't') {
1369                                     tmode ^= 1;
1370                                     if (!tmode)
1371                                             resettrace((regcontext_t *)&saved_sigframe->
1372                                                 sf_uc.uc_mcontext); 
1373                                     break;
1374                                 }
1375                                 if (ks == 'R' || ks == 'r') {
1376                                     kill(getpid(), SIGALRM);    /* redraw */
1377                                     break;
1378                                 }
1379                         }
1380                         if (ks < ' ' || ks > '~')
1381                                 break;
1382                         scan = Ascii2Scan[ks]; 
1383                 docode:
1384                         if (nlock)
1385                             scan |= 0x100;
1386
1387                         if ((scan & ~0x100) > 88) {
1388                             scan = 0xffff;
1389                             break;
1390                         }
1391
1392                         if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
1393                             scan = ScanCodes[scan & 0xff].shift;
1394                         } else if (K1_STATUS & K1_CTRL) {
1395                             scan = ScanCodes[scan & 0xff].ctrl;
1396                         } else if (K1_STATUS & K1_ALT) {
1397                             scan = ScanCodes[scan & 0xff].alt;
1398                         }  else
1399                             scan = ScanCodes[scan & 0xff].base;
1400
1401                         break;
1402                 }
1403                 if (scan != 0xffff) {
1404                         break_code = scan >> 8;
1405                         KbdWrite(scan);
1406                 }
1407                 return(1);
1408             }
1409         default:
1410                 break;
1411         }
1412         return(0);
1413 }
1414 #endif
1415
1416 void
1417 tty_move(int r, int c)
1418 {
1419         row = r;
1420         col = c;
1421         SetVREGCur();
1422 }
1423
1424 void
1425 tty_report(int *r, int *c)
1426 {
1427         *r = row;
1428         *c = col;
1429 }
1430
1431 void
1432 tty_flush(void)
1433 {
1434         K_NEXT = K_FREE = K_BUFSTARTP;
1435 }
1436
1437 void
1438 tty_index(int scroll)
1439 {
1440         int i;
1441
1442         if (row > (height - 1))
1443                 row = 0;
1444         else if (++row >= height) {
1445                 row = height - 1;
1446                 if (scroll) {
1447                         memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1448                         for (i = 0; i < width; ++i)
1449                                 vmem[(height - 1) * width + i] = vattr | ' ';
1450                 }
1451         }
1452         SetVREGCur();
1453 }
1454
1455 void
1456 tty_write(int c, int attr)
1457 {
1458         if (attr == TTYF_REDIRECT) {
1459                 if (redirect1) {
1460                     write(1, &c, 1);
1461                     return;
1462                 }
1463                 attr = -1;
1464         }
1465         if (capture_fd >= 0) {
1466             char cc = c;
1467             write(capture_fd, &cc, 1);
1468         }
1469         c &= 0xff;
1470         switch (c) {
1471         case 0x07:
1472                 if (xmode) {
1473 #ifndef NO_X
1474                         XBell(dpy, 0);
1475 #endif
1476                 } else
1477                         write(1, "\007", 1);
1478                 break;
1479         case 0x08:
1480                 if (row > (height - 1) || col > width)
1481                         break;
1482                 if (col > 0)
1483                         --col;
1484                 vmem[row * width + col] &= 0xff00;
1485                 break;
1486         case '\t':
1487                 if (row > (height - 1))
1488                         row = 0;
1489                 col = (col + 8) & ~0x07;
1490                 if (col > width) {
1491                         col = 0;
1492                         tty_index(1);
1493                 }
1494                 break;
1495         case '\r':
1496                 col = 0;
1497                 break;
1498         case '\n':
1499                 tty_index(1);
1500                 break;
1501         default:
1502                 if (col >= width) {
1503                         col = 0;
1504                         tty_index(1);
1505                 }
1506                 if (row > (height - 1))
1507                         row = 0;
1508                 if (attr >= 0)
1509                         vmem[row * width + col] = attr & 0xff00;
1510                 else
1511                         vmem[row * width + col] &= 0xff00;
1512                 vmem[row * width + col++] |= c;
1513                 break;
1514         }
1515         SetVREGCur();
1516 }
1517
1518 void
1519 tty_rwrite(int n, int c, int attr)
1520 {
1521     u_char srow, scol;
1522     c &= 0xff;
1523
1524 #ifndef NO_X
1525     if (VGA_ATC[ATC_ModeCtrl] & 1) {
1526         tty_rwrite_graphics(n, c, attr);
1527         return;
1528     }
1529 #endif
1530     
1531     srow = row;
1532     scol = col;
1533     while (n--) {
1534         if (col >= width) {
1535             col = 0;
1536             tty_index(0);
1537         }
1538         if (row > (height - 1))
1539             row = 0;
1540         if (attr >= 0)
1541             vmem[row * width + col] = attr & 0xff00;
1542         else
1543             vmem[row * width + col] &= 0xff00;
1544         vmem[row * width + col++] |= c;
1545     }
1546     row = srow;
1547     col = scol;
1548     SetVREGCur();
1549 }
1550
1551 #ifndef NO_X
1552 /* Write a character in graphics mode. Note that the text is put at *text*
1553    coordinates. */
1554 static void
1555 tty_rwrite_graphics(int n, int c, int attr)
1556 {
1557     u_int8_t srow, scol;
1558     int ht = height / CharHeight;
1559     int wd = width / 8;
1560
1561     srow = row;
1562     scol = col;
1563
1564     while (n--) {
1565         if (col >= wd) {
1566             col = 0;
1567             /* tty_index(0); *//* scroll up if last line is filled */
1568         }
1569         if (row > (ht - 1))
1570             row = 0;
1571         putchar_graphics(row * wd * CharHeight + col, c, attr);
1572         col++;
1573     }
1574     row = srow;
1575     col = scol;
1576     SetVREGCur();
1577
1578     return;
1579 }
1580
1581 /* Put the character together from its pixel representation in 'font8xXX[]'
1582    and write it to 'vram'. The attribute byte gives the desired color; if bit
1583    7 is set, the pixels are XOR'd with the underlying color(s).
1584
1585    XXX This must be updated for the 256 color modes. */
1586 static void
1587 putchar_graphics(int xy, int c, int attr)
1588 {
1589     int i, j;
1590     u_int8_t cline;
1591     u_int8_t *cpos;
1592     
1593     /* get char position in the pixel representation */
1594     cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1595
1596     for (i = 0; i < CharHeight; i++) {
1597         cline = cpos[i];
1598         for (j = 0; j < 4; j++) {
1599             if (attr & 0x8000) {
1600                 /* XOR */
1601                 if (attr & (0x0100 << j))
1602                     vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1603             } else {
1604                 /* replace */
1605                 if (attr & (0x0100 << j))
1606                     vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1607                 else
1608                     vram[xy + i * width / 8 + j * 0x10000] |= cline;
1609             }
1610         }
1611     }
1612
1613     return;
1614 }
1615 #endif
1616
1617 void tty_pause(void)
1618 {
1619     sigset_t set;
1620
1621     sigprocmask(0, 0, &set);
1622     sigdelset(&set, SIGIO);
1623     sigdelset(&set, SIGALRM);
1624     sigsuspend(&set);
1625 }
1626
1627 static int nextchar = 0;
1628
1629 int
1630 tty_read(REGISTERS, int flag)
1631 {
1632     int r;
1633
1634     if ((r = nextchar) != 0) {
1635         nextchar = 0;
1636         return(r & 0xff);
1637     }
1638
1639     if ((flag & TTYF_REDIRECT) && redirect0) {
1640         char c;
1641         if (read(STDIN_FILENO, &c, 1) != 1)
1642             return(-1);
1643         if (c == '\n')
1644             c = '\r';
1645         return(c);
1646     }
1647
1648     if (KbdEmpty()) {
1649         if (flag & TTYF_BLOCK) {
1650             while (KbdEmpty())
1651                 tty_pause();
1652         } else {
1653             return(-1);
1654         }
1655     }
1656
1657     r = KbdRead();
1658     if ((r & 0xff) == 0)
1659         nextchar = r >> 8;
1660     r &= 0xff;
1661     if (flag & TTYF_CTRL) {
1662         if (r == 3) {
1663             /*
1664              * XXX - Not quite sure where we should return, maybe not
1665              *       all the way to the user, but...
1666              */
1667             if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1668                 fake_int(REGS, 0x23);
1669                 R_EIP = R_EIP - 2;
1670                 return(-2);
1671             }
1672         }
1673     }
1674     if (flag & TTYF_ECHO) {
1675         if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) { 
1676             tty_write('\r', -1);
1677             tty_write('\n', -1);
1678         } else
1679             tty_write(r, -1);
1680     }
1681     return(r & 0xff);
1682 }
1683
1684 int
1685 tty_peek(REGISTERS, int flag)
1686 {
1687         int c;
1688
1689         if (c == nextchar)
1690             return(nextchar & 0xff);
1691
1692         if (KbdEmpty()) {
1693                 if (flag & TTYF_POLL) {
1694                         sleep_poll();
1695                         if (KbdEmpty())
1696                                 return(0);
1697                 } else if (flag & TTYF_BLOCK) {
1698                         while (KbdEmpty())
1699                                 tty_pause();
1700                 } else
1701                         return(0);
1702         }
1703         c = KbdPeek();
1704         if ((c & 0xff) == 3) {
1705             /*
1706              * XXX - Not quite sure where we should return, maybe not
1707              *       all the way to the user, but...
1708              */
1709             if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1710                 fake_int(REGS, 0x23);
1711                 R_EIP = R_EIP - 2;
1712                 return(-2);
1713             }
1714         }
1715         return(0xff);
1716 }
1717
1718 int
1719 tty_state(void)
1720 {
1721         return(K1_STATUS);
1722 }
1723
1724 int
1725 tty_estate(void)
1726 {
1727     int state = 0;
1728     if (K2_STATUS & K2_SYSREQ)
1729         state |= 0x80;
1730     if (K2_STATUS & K2_CLOCK)
1731         state |= 0x40;
1732     if (K2_STATUS & K2_NLOCK)
1733         state |= 0x20;
1734     if (K2_STATUS & K2_SLOCK)
1735         state |= 0x10;
1736     if (K3_STATUS & K3_RALT)
1737         state |= 0x08;
1738     if (K3_STATUS & K3_RCTRL)
1739         state |= 0x04;
1740     if (K2_STATUS & K2_LALT)
1741         state |= 0x02;
1742     if (K2_STATUS & K2_LCTRL)
1743         state |= 0x01;
1744     return(state);
1745 }
1746
1747 static int
1748 inrange(int a, int n, int x)
1749 {
1750         return(a < n ? n : a > x ? x : a);
1751 }
1752
1753 void
1754 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
1755 {
1756         int i, j;
1757
1758         sr = inrange(sr, 0, height);
1759         er = inrange(er, 0, height);
1760         sc = inrange(sc, 0, width);
1761         ec = inrange(ec, 0, width);
1762         if (sr > er || sc > ec)
1763                 return;
1764         ++er;
1765         ++ec;
1766
1767         attr &= 0xff00;
1768         attr |= ' ';
1769
1770         if (n > 0 && n < er - sr) {
1771                 for (j = sr; j < er - n; ) {
1772                         memcpy(&vmem[j * width + sc],
1773                                &vmem[(j + n) * width + sc],
1774                                sizeof(vmem[0]) * (ec - sc));
1775                         ++j;
1776                 }
1777         } else
1778                 n = er - sr;
1779         for (j = er - n; j < er; ) {
1780                 for (i = sc; i < ec; ++i)
1781                         vmem[j * width + i] = attr;
1782                 ++j;
1783         }
1784 }
1785
1786 void
1787 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
1788 {
1789         int i, j;
1790
1791         sr = inrange(sr, 0, height);
1792         er = inrange(er, 0, height);
1793         sc = inrange(sc, 0, width);
1794         ec = inrange(ec, 0, width);
1795         if (sr > er || sc > ec)
1796                 return;
1797         ++er;
1798         ++ec;
1799
1800         attr &= 0xff00;
1801         attr |= ' ';
1802
1803         if (n > 0 && n < er - sr) {
1804                 for (j = er; j > sr + n; ) {
1805                         --j;
1806                         memcpy(&vmem[j * width + sc],
1807                                &vmem[(j - n) * width + sc],
1808                                sizeof(vmem[0]) * (ec - sc));
1809                 }
1810         } else
1811                 n = er - sr;
1812         for (j = sr + n; j > sr; ) {
1813                 --j;
1814                 for (i = sc; i < ec; ++i)
1815                         vmem[j * width + i] = attr;
1816         }
1817 }
1818
1819 int
1820 tty_char(int r, int c)
1821 {
1822         if (r == -1)
1823                 r = row;
1824         if (c == -1)
1825                 c = col;
1826         r = inrange(r, 0, height);
1827         c = inrange(c, 0, width);
1828         return(vmem[r * width + c]);
1829 }
1830
1831 int
1832 KbdEmpty(void)
1833 {
1834         return(K_NEXT == K_FREE);
1835 }
1836
1837 void
1838 KbdWrite(u_short code)
1839 {
1840         int kf;
1841
1842         kf = K_FREE + 2;
1843         if (kf == K_BUFENDP)
1844                 kf = K_BUFSTARTP;
1845
1846         if (kf == K_NEXT) {
1847 #ifndef NO_X
1848                 XBell(dpy, 0);
1849 #endif
1850                 return;
1851         }
1852         K_BUF(K_FREE) = code;
1853         K_FREE = kf;
1854 }
1855
1856 u_short
1857 KbdRead(void)
1858 {
1859         int kf = K_NEXT;
1860
1861         K_NEXT = K_NEXT + 2;
1862         if (K_NEXT == K_BUFENDP)
1863                 K_NEXT = K_BUFSTARTP;
1864
1865         return(K_BUF(kf));
1866 }
1867
1868 u_short
1869 KbdPeek(void)
1870 {
1871         return(K_BUF(K_NEXT));
1872 }
1873
1874 void
1875 kbd_init(void)
1876 {
1877         u_long vec;
1878         
1879         define_input_port_handler(0x60, inb_port60);
1880
1881         K_BUFSTARTP = 0x1e;     /* Start of keyboard buffer */
1882         K_BUFENDP = 0x3e;       /* End of keyboard buffer */
1883         K_NEXT = K_FREE = K_BUFSTARTP;
1884         
1885         vec = insert_hardint_trampoline();
1886         ivec[0x09] = vec;
1887         register_callback(vec, int09, "int 09");
1888
1889         return;
1890 }
1891
1892 void
1893 kbd_bios_init(void)
1894 {
1895         BIOSDATA[0x96] = 0x10;  /* MF II kbd, 101 keys */
1896         K1_STATUS = 0;
1897         K2_STATUS = 0;
1898         K3_STATUS = 0;
1899         K4_STATUS = 0;
1900 }
1901
1902 #ifndef NO_X
1903 /* Calculate 16 bit RGB values for X from the 6 bit DAC values and the
1904    palette. This works for 16 and 256 color modes, although we don't really
1905    support the latter yet. */
1906 static void
1907 dac2rgb(XColor *color, int i)
1908 {
1909     int n, m;
1910
1911     /* 256 colors are easy; just take the RGB values from the DAC and
1912        shift left. For the pedants: multiplication with 65535./63. and
1913        rounding makes a difference of less than two percent. */
1914     if (VGA_ATC[ATC_ModeCtrl] & 0x40) {
1915         color->red   = dac_rgb[i].red << 10;
1916         color->green = dac_rgb[i].green << 10;
1917         color->blue  = dac_rgb[i].blue << 10;
1918
1919         return;
1920     }
1921
1922     /* For the 16 color modes, check bit 7 of the Mode Control register in
1923        the ATC. If set, we take bits 0-3 of the Color Select register and
1924        bits 0-3 of the palette register 'i' to build the index into the
1925        DAC table; otherwise, bits 2 and 3 of the CS reg and bits 0-5 of
1926        the palette register are used. Note that the entries in 'palette[]'
1927        are supposed to be already masked to 6 bits. */
1928     if (VGA_ATC[ATC_ModeCtrl] & 0x80) {
1929         n = VGA_ATC[ATC_ColorSelect] & 0x0f;
1930         m = palette[i] & 0x0f;
1931     } else {
1932         n = VGA_ATC[ATC_ColorSelect] & 0x0c;
1933         m = palette[i];
1934     }
1935     color->red   = dac_rgb[16*n + m].red << 10;
1936     color->green = dac_rgb[16*n + m].green << 10;
1937     color->blue  = dac_rgb[16*n + m].blue << 10;
1938 }
1939 #endif
1940
1941 /* Get a connection to the X server and create the window. */
1942 void
1943 init_window(void)
1944 {
1945 #ifndef NO_X
1946     XGCValues gcv;
1947     int i;
1948
1949     {
1950         /*
1951          * Arg...  I can no longer change X's fd out from under it.
1952          * Open up all the available fd's, leave 3 behind for X
1953          * to play with, open X and then release all the other fds
1954          */
1955         int nfds = sysconf(_SC_OPEN_MAX);
1956         int *fds = malloc(sizeof(int) * nfds);
1957         i = 0;
1958         if (fds)
1959             for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1960                 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
1961                     break;
1962         /*
1963          * Leave 3 fds behind for X to play with
1964          */
1965         if (i > 0) close(fds[--i]);
1966         if (i > 0) close(fds[--i]);
1967         if (i > 0) close(fds[--i]);
1968                 
1969         dpy = XOpenDisplay(NULL);
1970                 
1971         while (i > 0)
1972             close(fds[--i]);
1973     }
1974     if (dpy == NULL)
1975         err(1, "Could not open display ``%s''\n", XDisplayName(NULL));
1976     xfd = ConnectionNumber(dpy);
1977
1978     _RegisterIO(xfd, video_async_event, 0, Failure);
1979     if (debug_flags & D_DEBUGIN)
1980         _RegisterIO(0, debug_event, 0, Failure);
1981
1982     /* Create window, but defer setting a size and GC. */
1983     win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1984                               1, 1, 2, black, black);
1985
1986     gcv.foreground = white;
1987     gcv.background = black;
1988     gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1989
1990     gcv.foreground = 1;
1991     gcv.background = 0;
1992     gcv.function = GXxor;
1993     cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1994
1995     if (raw_kbd) {
1996         XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1997                      | ButtonReleaseMask | PointerMotionMask );
1998     } else {
1999         XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
2000                      ExposureMask | ButtonPressMask
2001                      | ButtonReleaseMask | PointerMotionMask );
2002     }
2003
2004     XStoreName(dpy, win, "DOS");
2005
2006     /* Get the default visual and depth for later use. */
2007     depth = DefaultDepth(dpy, DefaultScreen(dpy));
2008     visual = DefaultVisual(dpy, DefaultScreen(dpy));
2009
2010     prepare_lut();
2011
2012 #if 0
2013     /* While we are developing the graphics code ... */
2014     call_on_quit(write_vram, NULL);
2015 #endif
2016 #endif
2017 }
2018
2019 void
2020 load_font(void)
2021 {
2022 #ifndef NO_X
2023     XGCValues gcv;
2024     
2025     if (!xfont)
2026         xfont = FONTVGA;
2027
2028     font = XLoadQueryFont(dpy, xfont);
2029
2030     if (font == NULL)
2031         font = XLoadQueryFont(dpy, FONTVGA);
2032
2033     if (font == NULL)
2034         err(1, "Could not open font ``%s''\n", xfont);
2035
2036     gcv.font = font->fid;
2037     XChangeGC(dpy, gc, GCFont, &gcv);
2038     
2039     FW = font->max_bounds.width;
2040     FH = font->max_bounds.ascent + font->max_bounds.descent;
2041     FD = font->max_bounds.descent;
2042
2043     /* Put the pixel representation at c000:3000. */
2044     switch (CharHeight) {
2045     case 8:
2046         memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2047         break;
2048     case 14:
2049         memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2050         break;
2051     case 16:
2052         memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2053         break;
2054     default:
2055         err(1, "load_font: CharHeight = %d?", CharHeight);
2056     }
2057     
2058     return;
2059 #endif
2060 }
2061
2062 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2063 void
2064 get_ximage(void)
2065 {
2066 #ifndef NO_X
2067     if (xi != NULL)
2068         XFree(xi);
2069     
2070     xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2071                       width, height, 32, 0);
2072     if (xi == NULL)
2073         err(1, "Could not get ximage");
2074
2075     xi->data = malloc(width * height * depth / 8);
2076     if (xi->data == NULL) {
2077         XDestroyImage(xi);
2078         err(1, "Could not get memory for ximage data");
2079     }
2080
2081     return;
2082 #endif
2083 }
2084
2085 /* Get memory for the text line buffer. */
2086 void
2087 get_lines(void)
2088 {
2089     int i;
2090     
2091     if (lines == NULL) {
2092         lines = (TextLine *)malloc(sizeof(TextLine) * height);
2093         if (lines == NULL)
2094             err(1, "Could not allocate data structure for text lines\n");
2095
2096         for (i = 0; i < height; ++i) {
2097             lines[i].max_length = width;
2098             lines[i].data = (u_short *)malloc(width * sizeof(u_short));
2099             if (lines[i].data == NULL)
2100                 err(1, "Could not allocate data structure for text lines\n");
2101             lines[i].changed = 1;
2102         }
2103     } else {
2104         lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
2105         if (lines == NULL)
2106             err(1, "Could not allocate data structure for text lines\n");
2107
2108         for (i = 0; i < height; ++i) {
2109             lines[i].max_length = width;
2110             lines[i].data = (u_short *)realloc(lines[i].data,
2111                                                width * sizeof(u_short));
2112             if (lines[i].data == NULL)
2113                 err(1, "Could not allocate data structure for text lines\n");
2114             lines[i].changed = 1;
2115         }
2116     }
2117 }
2118
2119 #ifndef NO_X
2120 /* Prepare the LUT for the VRAM -> XImage conversion. */
2121 static void
2122 prepare_lut(void)
2123 {
2124     int i, j, k;
2125
2126     for (i = 0; i < 4; i++) {
2127         for (j = 0; j < 256; j++) {
2128             for (k = 0; k < 8; k++) {
2129                 lut[i][j][7 - k] = ((j & (1 << k)) ? (1 << i) : 0);
2130             }
2131         }
2132     }
2133
2134     return;
2135 }
2136 #endif
2137
2138 /* Resize the window, using information from 'vga_status[]'. This function is
2139    called after a mode change. */
2140 void
2141 resize_window(void)
2142 {
2143 #ifndef NO_X
2144     XSizeHints *sh;
2145     vmode_t vmode;
2146     
2147     sh = XAllocSizeHints();
2148     if (sh == NULL)
2149         err(1, "Could not get XSizeHints structure");
2150 #endif
2151     
2152     width = DpyCols;
2153     height = DpyRows + 1;
2154
2155 #ifndef NO_X
2156     vmode = vmodelist[find_vmode(VideoMode)];
2157     if (vmode.type == TEXT) {
2158         sh->base_width = FW * width + 4;
2159         sh->base_height = FH * height + 4;
2160         sh->base_width += 4;
2161         sh->base_height += 4;
2162     } else {
2163         width *= 8;
2164         height *= CharHeight;
2165         sh->base_width = width;
2166         sh->base_height = height;
2167     }
2168     
2169     sh->min_width = sh->max_width = sh->base_width;
2170     sh->min_height = sh->max_height = sh->base_height;
2171     sh->flags = USSize | PMinSize | PMaxSize | PSize;
2172
2173     debug(D_VIDEO, "VGA: Set window size %dx%d\n",
2174           sh->base_width, sh->base_height);
2175     
2176     XSetWMNormalHints(dpy, win, sh);
2177     XResizeWindow(dpy, win, sh->base_width, sh->base_height);
2178     XMapWindow(dpy, win);
2179     XFlush(dpy);
2180     
2181     XFree(sh);
2182     
2183     return;
2184 #endif
2185 }
2186
2187 /* Calculate 'pixels[]' from the current DAC table and palette.
2188
2189    To do: do not use 'pixels[]', use an array of 'XColor's which we can
2190    allocate and free on demand. Install a private colormap if necessary. */
2191 void
2192 update_pixels(void)
2193 {
2194 #ifndef NO_X
2195     int i;
2196
2197     /* We support only 16 colors for now. */
2198     for (i = 0; i < 16; i++) {
2199         XColor color;
2200
2201         dac2rgb(&color, i);
2202         if (XAllocColor(dpy,
2203                         DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2204             pixels[i] = color.pixel;
2205         } else if (i < 7)
2206             pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2207         else
2208             pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2209     }
2210 #endif
2211 }
2212
2213 void
2214 write_vram(void *arg __unused)
2215 {
2216     int fd;
2217
2218     if ((fd = open("vram", O_WRONLY | O_CREAT, 0644)) == -1)
2219         err(1, "Can't open vram file");
2220     (void)write(fd, (void *)vram, 256 * 1024);
2221
2222     return;
2223 }