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