|
|
1.1 root 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: * July 22, 1999
31: *
32: * To All Licensees, Distributors of Any Version of BSD:
33: *
34: * As you know, certain of the Berkeley Software Distribution ("BSD") source
35: * code files require that further distributions of products containing all or
36: * portions of the software, acknowledge within their advertising materials
37: * that such products contain software developed by UC Berkeley and its
38: * contributors.
39: *
40: * Specifically, the provision reads:
41: *
42: * " * 3. All advertising materials mentioning features or use of this software
43: * * must display the following acknowledgement:
44: * * This product includes software developed by the University of
45: * * California, Berkeley and its contributors."
46: *
47: * Effective immediately, licensees and distributors are no longer required to
48: * include the acknowledgement within advertising materials. Accordingly, the
49: * foregoing paragraph of those BSD Unix files containing it is hereby deleted
50: * in its entirety.
51: *
52: * William Hoskins
53: * Director, Office of Technology Licensing
54: * University of California, Berkeley
55: *
56: *
57: */
58:
59: /* $Id: console.c,v 1.25 2004/09/22 05:06:59 deuce Exp $ */
60:
61: /****************************************************************************
62: * @format.tab-size 4 (Plain Text/Source Code File Header) *
63: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
64: * *
65: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
66: * *
67: * This library is free software; you can redistribute it and/or *
68: * modify it under the terms of the GNU Lesser General Public License *
69: * as published by the Free Software Foundation; either version 2 *
70: * of the License, or (at your option) any later version. *
71: * See the GNU Lesser General Public License for more details: lgpl.txt or *
72: * http://www.fsf.org/copyleft/lesser.html *
73: * *
74: * Anonymous FTP access to the most recent released source is available at *
75: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
76: * *
77: * Anonymous CVS access to the development source and modification history *
78: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
79: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
80: * (just hit return, no password is necessary) *
81: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
82: * *
83: * For Synchronet coding style and modification guidelines, see *
84: * http://www.synchro.net/source.html *
85: * *
86: * You are encouraged to submit any modifications (preferably in Unix diff *
87: * format) via e-mail to [email protected] *
88: * *
89: * Note: If this box doesn't appear square, then you need to fix your tabs. *
90: ****************************************************************************/
91:
92: #include <sys/param.h>
93: #include <sys/time.h>
94: #include <sys/types.h>
95: #include <sys/user.h>
96:
97: #include <dlfcn.h>
98: #include <fcntl.h>
99: #include <limits.h>
100: #include <paths.h>
101: #include <stdio.h>
102: #include <unistd.h> /* sysconf() */
103:
104: #include <X11/Xlib.h>
105: #include <X11/Xutil.h>
106: #include <X11/keysym.h>
107:
108: #include <genwrap.h>
109:
110: #include "console.h"
111: #include "vidmodes.h"
112:
113: #include "keys.h"
114: #include "mouse.h"
115: #include "vgafont.h"
116:
117: /* Console definition variables */
118: int console_new_mode=NO_NEW_MODE;
119: int CurrMode;
120: sem_t console_mode_changed;
121: sem_t x11_beep;
122: sem_t x11_title;
123: int InitCS;
124: int InitCE;
125: int FW, FH;
126: WORD DpyCols;
127: BYTE DpyRows;
128: BYTE *palette;
129: BYTE CursStart;
130: BYTE CursEnd;
131: WORD *vmem=NULL;
132: static int show = 1;
133: BYTE CursRow=0;
134: BYTE CursCol=0;
135: typedef struct TextLine {
136: WORD *data;
137: u_char max_length; /* Not used, but here for future use */
138: u_char changed:1;
139: } TextLine;
140: TextLine *lines = NULL;
141:
142: /* X Variables */
143: Display *dpy=NULL;
144: Window win;
145: XImage *xi = 0;
146: Pixmap pfnt=0;
147: Visual *visual;
148: unsigned int depth;
149: unsigned long black;
150: unsigned long white;
151: GC gc;
152: GC cgc;
153: int xfd;
154: char window_title[81];
155:
156: /* X functions */
157: struct x11 {
158: int (*XChangeGC) (Display*, GC, unsigned long, XGCValues*);
159: int (*XCopyPlane) (Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
160: int (*XFillRectangle) (Display*, Drawable, GC, int, int, unsigned int, unsigned int);
161: int (*XFlush) (Display*);
162: int (*XBell) (Display*, int);
163: int (*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
164: int (*XNextEvent) (Display*, XEvent *);
165: XSizeHints* (*XAllocSizeHints)(void);
166: void (*XSetWMNormalHints) (Display*, Window, XSizeHints*);
167: int (*XResizeWindow)(Display*, Window, unsigned int, unsigned int);
168: int (*XMapWindow) (Display*, Window);
169: int (*XFree) (void *data);
170: int (*XFreePixmap) (Display*, Pixmap);
171: int (*XCreateBitmapFromData) (Display*, Drawable, _Xconst char*, unsigned int, unsigned int);
172: Status (*XAllocColor) (Display*, Colormap, XColor*);
173: Display*(*XOpenDisplay) (_Xconst char*);
174: Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
175: GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*);
176: int (*XSelectInput) (Display*, Window, long);
177: int (*XStoreName) (Display*, Window, _Xconst char*);
178: };
179: struct x11 x11;
180:
181: /* X pixel values for the RGB triples */
182: DWORD pixels[16];
183:
184: static fd_set fdset; /* File Descriptors to select on */
185:
186: /* Keyboard stuff */
187: WORD keybuf[0x25];
188: #define K_NEXT keybuf[0x21] /* *(WORD *)0x41a */
189: #define K_FREE keybuf[0x22] /* *(WORD *)0x41c */
190: #define K_BUFSTARTP keybuf[0x23] /* *(WORD *)0x480 */
191: #define K_BUFENDP keybuf[0x24] /* *(WORD *)0x482 */
192: #define K_BUFSTART (&keybuf[K_BUFSTARTP]) /* ((WORD *)(0x400 + K_BUFSTARTP)) */
193: #define K_BUFEND (&keybuf[K_BUFENDP]) /* ((WORD *)(0x400 + keybuf[3])) */
194: #define K_BUF(i) keybuf[i] /* *((WORD *)((u_char *)0x400 + (i))) */
195:
196: BYTE K1_STATUS;
197: #define K1_RSHIFT 0x01
198: #define K1_LSHIFT 0x02
199: #define K1_SHIFT 0x03
200: #define K1_CTRL 0x04
201: #define K1_ALT 0x08
202: #define K1_SLOCK 0x10 /* Active */
203: #define K1_NLOCK 0x20 /* Active */
204: #define K1_CLOCK 0x40 /* Active */
205: #define K1_INSERT 0x80 /* Active */
206:
207: BYTE K2_STATUS;
208: #define K2_LCTRL 0x01
209: #define K2_LALT 0x02
210: #define K2_SYSREQ 0x04
211: #define K2_PAUSE 0x08
212: #define K2_SLOCK 0x10 /* Actually held down */
213: #define K2_NLOCK 0x20 /* Actually held down */
214: #define K2_CLOCK 0x40 /* Actually held down */
215: #define K2_INSERT 0x80 /* Actually held down */
216:
217: BYTE K3_STATUS;
218: #define K3_E1 0x01 /* Last code read was e1 */
219: #define K3_E2 0x02 /* Last code read was e2 */
220: #define K3_RCTRL 0x04
221: #define K3_RALT 0x08
222: #define K3_ENHANCED 0x10
223: #define K3_FORCENLOCK 0x20
224: #define K3_TWOBYTE 0x40 /* last code was first of 2 */
225: #define K3_READID 0x80 /* read ID in progress */
226:
227: BYTE K4_STATUS;
228: #define K4_SLOCK_LED 0x01
229: #define K4_NLOCK_LED 0x02
230: #define K4_CLOCK_LED 0x04
231: #define K4_ACK 0x10 /* ACK recieved from keyboard */
232: #define K4_RESEND 0x20 /* RESEND recieved from keyboard */
233: #define K4_LED 0x40 /* LED update in progress */
234: #define K4_ERROR 0x80
235:
236: int flipdelete = 0; /* Flip meaning of delete and backspace */
237: static WORD break_code = 0x00;
238:
239: static WORD Ascii2Scan[] = {
240: 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
241: 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
242: 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
243: 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
244: 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
245: 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
246: 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
247: 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
248: 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
249: 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
250: 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
251: 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
252: 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
253: 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
254: 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
255: 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
256: };
257:
258: struct {
259: WORD base;
260: WORD shift;
261: WORD ctrl;
262: WORD alt;
263: } ScanCodes[] = {
264: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
265: { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
266: { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
267: { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */
268: { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
269: { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
270: { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
271: { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
272: { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
273: { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
274: { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
275: { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
276: { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
277: { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
278: { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
279: { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
280: { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
281: { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
282: { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
283: { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
284: { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
285: { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
286: { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
287: { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
288: { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
289: { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
290: { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
291: { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
292: { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
293: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
294: { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
295: { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
296: { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
297: { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
298: { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
299: { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
300: { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
301: { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
302: { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
303: { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
304: { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
305: { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
306: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
307: { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
308: { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
309: { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
310: { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
311: { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
312: { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
313: { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
314: { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
315: { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
316: { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
317: { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
318: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
319: { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
320: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
321: { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
322: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
323: { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
324: { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
325: { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
326: { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
327: { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
328: { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
329: { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
330: { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
331: { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
332: { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
333: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
334: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
335: { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
336: { 0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
337: { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
338: { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
339: { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
340: { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
341: { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
342: { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
343: { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
344: { 0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
345: { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
346: { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
347: { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
348: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
349: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
350: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
351: { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
352: { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
353: };
354:
355: #define HWM 16
356:
357: void tty_pause()
358: {
359: usleep(1000);
360: }
361:
362: volatile int poll_cnt = 0;
363:
364: void
365: wakeup_poll(void)
366: {
367: if (poll_cnt <= 0)
368: poll_cnt = HWM;
369: }
370:
371: void
372: reset_poll(void)
373: {
374: poll_cnt = HWM;
375: }
376:
377: void
378: sleep_poll(void)
379: {
380: if (--poll_cnt <= 0) {
381: poll_cnt = 0;
382: while (KbdEmpty() && poll_cnt <= 0) {
383: if (KbdEmpty() && poll_cnt <= 0)
384: tty_pause();
385: }
386: }
387: }
388:
389: static void
390: setgc(WORD attr)
391: {
392: XGCValues v;
393:
394: v.background = pixels[(attr >> 12) & 0x07];
395: if ((!show) && (attr & 0x8000))
396: v.foreground = v.background;
397: else
398: v.foreground = pixels[(attr >> 8) & 0x0f];
399:
400: x11.XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
401: }
402:
403: static void
404: video_update_text()
405: {
406: static int or = -1;
407: static int oc = -1;
408: static int os = -1;
409:
410: static char buf[256];
411: int r, c;
412: int attr = vmem[0] & 0xff00;
413: XGCValues v;
414:
415: wakeup_poll(); /* Wake up anyone waiting on kbd poll */
416:
417: setgc(attr);
418:
419: for (r = 0; r < (DpyRows+1); ++r) {
420: int cc = 0;
421:
422: if (!lines[r].changed) {
423: if ((r == or || r == CursRow) && (or != CursRow || oc !=CursCol))
424: lines[r].changed=1;
425: else {
426: for (c = 0; c < DpyCols; ++c) {
427: if (lines[r].data[c] != vmem[r * DpyCols + c]) {
428: lines[r].changed = 1;
429: break;
430: }
431: if (lines[r].data[c] & 0x8000 && show != os) {
432: lines[r].changed = 1;
433: break;
434: }
435: }
436: }
437: }
438:
439: if (!lines[r].changed)
440: continue;
441:
442: reset_poll();
443: lines[r].changed = 0;
444: memcpy(lines[r].data,
445: &vmem[r * DpyCols], sizeof(WORD) * DpyCols);
446:
447: for (c = 0; c < DpyCols; ++c) {
448: setgc(vmem[r * DpyCols + c] & 0xff00);
449: x11.XCopyPlane(dpy,pfnt,win,gc,0,FH*(vmem[r * DpyCols + c]&0xff),FW,FH,c*FW+2,r*FH+2,1);
450: }
451: }
452:
453: if (CursStart <= CursEnd && CursEnd <= FH &&
454: (show != os) && CursRow < (DpyRows+1) &&CursCol < DpyCols) {
455:
456: attr = vmem[CursRow * DpyCols +CursCol] & 0xff00;
457: v.foreground = pixels[(attr >> 8) & 0x0f] ^
458: pixels[(attr >> 12) & 0x07];
459: if (v.foreground) {
460: v.function = GXxor;
461: } else {
462: v.foreground = pixels[7];
463: v.function = GXcopy;
464: }
465: x11.XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
466: x11.XFillRectangle(dpy, win, cgc,
467: 2 +CursCol * FW,
468: 2 + CursRow * FH + CursStart,
469: FW, CursEnd + 1 - CursStart);
470: }
471:
472: or =CursRow;
473: oc =CursCol;
474: os =show;
475:
476: x11.XFlush(dpy);
477: }
478:
479: void
480: video_update()
481: {
482: static clock_t lastupd=-1;
483: static clock_started=0;
484: clock_t upd;
485:
486: upd=msclock();
487: if(!clock_started) {
488: lastupd=upd;
489: clock_started=1;
490: }
491: if(upd-lastupd>(MSCLOCKS_PER_SEC/2)) {
492: show ^= 1;
493: lastupd=upd;
494: }
495:
496: /* quick and dirty */
497: video_update_text();
498: }
499:
500: /* Get memory for the text line buffer. */
501: void
502: get_lines()
503: {
504: int i;
505:
506: if (lines == NULL) {
507: lines = (TextLine *)malloc(sizeof(TextLine) * (DpyRows+1));
508: if (lines == NULL)
509: err(1, "Could not allocate data structure for text lines\n");
510:
511: for (i = 0; i < (DpyRows+1); ++i) {
512: lines[i].max_length = DpyCols;
513: lines[i].data = (WORD *)malloc(DpyCols * sizeof(WORD));
514: if (lines[i].data == NULL)
515: err(1, "Could not allocate data structure for text lines\n");
516: lines[i].changed = 1;
517: }
518: } else {
519: lines = (TextLine *)realloc(lines, sizeof(TextLine) * (DpyRows+1));
520: if (lines == NULL)
521: err(1, "Could not allocate data structure for text lines\n");
522:
523: for (i = 0; i < (DpyRows+1); ++i) {
524: lines[i].max_length = DpyCols;
525: lines[i].data = (WORD *)realloc(lines[i].data,
526: DpyCols * sizeof(WORD));
527: if (lines[i].data == NULL)
528: err(1, "Could not allocate data structure for text lines\n");
529: lines[i].changed = 1;
530: }
531: }
532: }
533:
534: void
535: KbdWrite(WORD code)
536: {
537: int kf;
538:
539: kf = K_FREE + 2;
540: if (kf == K_BUFENDP)
541: kf = K_BUFSTARTP;
542:
543: if (kf == K_NEXT) {
544: x11.XBell(dpy, 0);
545: return;
546: }
547: K_BUF(K_FREE) = code;
548: K_FREE = kf;
549: }
550:
551: void tty_beep(void)
552: {
553: sem_post(&x11_beep);
554: }
555:
556: static int
557: video_event(XEvent *ev)
558: {
559: switch (ev->type) {
560: case MotionNotify: {
561: XMotionEvent *me = (XMotionEvent *)ev;
562: me->x -= 2;
563: me->y -= 2;
564: me->x/=FW;
565: me->y/=FH;
566: me->x++;
567: me->y++;
568: if(me->x<1)
569: me->x=1;
570: if(me->y<1)
571: me->y=1;
572: if(me->x>DpyCols)
573: me->x=DpyCols;
574: if(me->y>DpyRows+1)
575: me->y=DpyRows+1;
576: ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y);
577: break;
578: }
579: case ButtonRelease: {
580: XButtonEvent *be = (XButtonEvent *)ev;
581: be->x -= 2;
582: be->y -= 2;
583: be->x/=FW;
584: be->y/=FH;
585: be->x++;
586: be->y++;
587: if(be->x<1)
588: be->x=1;
589: if(be->y<1)
590: be->y=1;
591: if(be->x>DpyCols)
592: be->x=DpyCols;
593: if(be->y>DpyRows+1)
594: be->y=DpyRows+1;
595: if (be->button <= 3) {
596: ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y);
597: }
598: break;
599: }
600: case ButtonPress: {
601: XButtonEvent *be = (XButtonEvent *)ev;
602: be->x -= 2;
603: be->y -= 2;
604: be->x/=FW;
605: be->y/=FH;
606: be->x++;
607: be->y++;
608: if(be->x<1)
609: be->x=1;
610: if(be->y<1)
611: be->y=1;
612: if(be->x>DpyCols)
613: be->x=DpyCols;
614: if(be->y>DpyRows+1)
615: be->y=DpyRows+1;
616: if (be->button <= 3) {
617: ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y);
618: }
619: break;
620: }
621: case NoExpose:
622: break;
623: case GraphicsExpose:
624: case Expose: {
625: int r;
626: for (r = 0; r < (DpyRows+1); ++r)
627: lines[r].changed = 1;
628: break;
629: }
630: case KeyRelease: {
631: static char buf[128];
632: KeySym ks;
633:
634: break_code |= 0x80;
635:
636: if (!(ev->xkey.state & ShiftMask)) {
637: K1_STATUS &= ~K1_LSHIFT;
638: K1_STATUS &= ~K1_RSHIFT;
639: }
640: if (!(ev->xkey.state & ControlMask)) {
641: K1_STATUS &= ~K1_CTRL;
642: K2_STATUS &= ~K2_LCTRL;
643: K3_STATUS &= ~K3_RCTRL;
644: }
645: if (!(ev->xkey.state & Mod1Mask)) {
646: K1_STATUS &= ~K1_ALT;
647: K2_STATUS &= ~K2_LALT;
648: K3_STATUS &= ~K3_RALT;
649: }
650: if (!(ev->xkey.state & LockMask)) {
651: K2_STATUS &= ~K2_CLOCK;
652: }
653:
654: x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
655: switch (ks) {
656: case XK_Shift_L:
657: K1_STATUS &= ~K1_LSHIFT;
658: break;
659: case XK_Shift_R:
660: K1_STATUS &= ~K1_RSHIFT;
661: break;
662: case XK_Control_L:
663: K1_STATUS &= ~K1_CTRL;
664: K2_STATUS &= ~K2_LCTRL;
665: break;
666: case XK_Control_R:
667: K1_STATUS &= ~K1_CTRL;
668: K3_STATUS &= ~K3_RCTRL;
669: break;
670: case XK_Alt_L:
671: K1_STATUS &= ~K1_ALT;
672: K2_STATUS &= ~K2_LALT;
673: break;
674: case XK_Alt_R:
675: K1_STATUS &= ~K1_ALT;
676: K3_STATUS &= ~K3_RALT;
677: break;
678: case XK_Scroll_Lock:
679: K2_STATUS &= ~K2_SLOCK;
680: break;
681: case XK_Num_Lock:
682: K2_STATUS &= ~K2_NLOCK;
683: break;
684: case XK_Caps_Lock:
685: K2_STATUS &= ~K2_CLOCK;
686: break;
687: case XK_Insert:
688: K2_STATUS &= ~K2_INSERT;
689: break;
690: }
691: return(1);
692: }
693: case KeyPress: {
694: static char buf[128];
695: KeySym ks;
696: int n;
697: int nlock = 0;
698: WORD scan = 0xffff;
699:
700: if (!(ev->xkey.state & ShiftMask)) {
701: K1_STATUS &= ~K1_LSHIFT;
702: K1_STATUS &= ~K1_RSHIFT;
703: }
704: if (!(ev->xkey.state & ControlMask)) {
705: K1_STATUS &= ~K1_CTRL;
706: K2_STATUS &= ~K2_LCTRL;
707: K3_STATUS &= ~K3_RCTRL;
708: }
709: if (!(ev->xkey.state & Mod1Mask)) {
710: K1_STATUS &= ~K1_ALT;
711: K2_STATUS &= ~K2_LALT;
712: K3_STATUS &= ~K3_RALT;
713: }
714: if (!(ev->xkey.state & LockMask)) {
715: K2_STATUS &= ~K2_CLOCK;
716: }
717:
718: n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
719:
720: switch (ks) {
721: case XK_Shift_L:
722: K1_STATUS |= K1_LSHIFT;
723: break;
724: case XK_Shift_R:
725: K1_STATUS |= K1_RSHIFT;
726: break;
727: case XK_Control_L:
728: K1_STATUS |= K1_CTRL;
729: K2_STATUS |= K2_LCTRL;
730: break;
731: case XK_Control_R:
732: K1_STATUS |= K1_CTRL;
733: K3_STATUS |= K3_RCTRL;
734: break;
735: case XK_Alt_L:
736: K1_STATUS |= K1_ALT;
737: K2_STATUS |= K2_LALT;
738: break;
739: case XK_Alt_R:
740: K1_STATUS |= K1_ALT;
741: K3_STATUS |= K3_RALT;
742: break;
743: case XK_Scroll_Lock:
744: K1_STATUS ^= K1_SLOCK;
745: K2_STATUS |= K2_SLOCK;
746: break;
747: case XK_Num_Lock:
748: K1_STATUS ^= K1_NLOCK;
749: K2_STATUS |= K2_NLOCK;
750: break;
751: case XK_Caps_Lock:
752: K1_STATUS ^= K1_CLOCK;
753: K2_STATUS |= K2_CLOCK;
754: break;
755: case XK_Insert:
756: case XK_KP_Insert:
757: K1_STATUS ^= K1_INSERT;
758: K2_STATUS |= K2_INSERT;
759: scan = 82;
760: goto docode;
761:
762: case XK_Escape:
763: scan = 1;
764: goto docode;
765:
766: case XK_Tab:
767: case XK_ISO_Left_Tab:
768: scan = 15;
769: goto docode;
770:
771: case XK_Return:
772: case XK_KP_Enter:
773: scan = 28;
774: goto docode;
775:
776: case XK_Print:
777: scan = 55;
778: goto docode;
779:
780: case XK_F1:
781: case XK_F2:
782: case XK_F3:
783: case XK_F4:
784: case XK_F5:
785: case XK_F6:
786: case XK_F7:
787: case XK_F8:
788: case XK_F9:
789: case XK_F10:
790: scan = ks - XK_F1 + 59;
791: goto docode;
792:
793: case XK_KP_7:
794: nlock = 1;
795: case XK_Home:
796: case XK_KP_Home:
797: scan = 71;
798: goto docode;
799: case XK_KP_8:
800: nlock = 1;
801: case XK_Up:
802: case XK_KP_Up:
803: scan = 72;
804: goto docode;
805: case XK_KP_9:
806: nlock = 1;
807: case XK_Prior:
808: case XK_KP_Prior:
809: scan = 73;
810: goto docode;
811: case XK_KP_Subtract:
812: scan = 74;
813: goto docode;
814: case XK_KP_4:
815: nlock = 1;
816: case XK_Left:
817: case XK_KP_Left:
818: scan = 75;
819: goto docode;
820: case XK_KP_5:
821: nlock = 1;
822: case XK_Begin:
823: case XK_KP_Begin:
824: scan = 76;
825: goto docode;
826: case XK_KP_6:
827: nlock = 1;
828: case XK_Right:
829: case XK_KP_Right:
830: scan = 77;
831: goto docode;
832: case XK_KP_Add:
833: scan = 78;
834: goto docode;
835: case XK_KP_1:
836: nlock = 1;
837: case XK_End:
838: case XK_KP_End:
839: scan = 79;
840: goto docode;
841: case XK_KP_2:
842: nlock = 1;
843: case XK_Down:
844: case XK_KP_Down:
845: scan = 80;
846: goto docode;
847: case XK_KP_3:
848: nlock = 1;
849: case XK_Next:
850: case XK_KP_Next:
851: scan = 81;
852: goto docode;
853: case XK_KP_0:
854: nlock = 1;
855: /* case XK_Insert: This is above */
856: scan = 82;
857: goto docode;
858:
859: case XK_KP_Decimal:
860: nlock = 1;
861: scan = 83;
862: goto docode;
863:
864: case XK_Delete:
865: case XK_KP_Delete:
866: scan = flipdelete ? 14 : 83;
867: goto docode;
868:
869: case XK_BackSpace:
870: scan = flipdelete ? 83 : 14;
871: goto docode;
872:
873: case XK_F11:
874: scan = 87;
875: goto docode;
876: case XK_F12:
877: scan = 88;
878: goto docode;
879:
880:
881: case XK_KP_Divide:
882: scan = Ascii2Scan['/'];
883: goto docode;
884:
885: case XK_KP_Multiply:
886: scan = Ascii2Scan['*'];
887: goto docode;
888:
889: default:
890: if (ks < ' ' || ks > '~')
891: break;
892: scan = Ascii2Scan[ks];
893: docode:
894: if (nlock)
895: scan |= 0x100;
896:
897: if ((scan & ~0x100) > 88) {
898: scan = 0xffff;
899: break;
900: }
901:
902: if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
903: scan = ScanCodes[scan & 0xff].shift;
904: } else if (K1_STATUS & K1_CTRL) {
905: scan = ScanCodes[scan & 0xff].ctrl;
906: } else if (K1_STATUS & K1_ALT) {
907: scan = ScanCodes[scan & 0xff].alt;
908: } else
909: scan = ScanCodes[scan & 0xff].base;
910:
911: break;
912: }
913: if (scan != 0xffff) {
914: break_code = scan >> 8;
915: KbdWrite(scan);
916: }
917: return(1);
918: }
919:
920: default:
921: break;
922: }
923: return(0);
924: }
925:
926: void
927: video_async_event(void *crap)
928: {
929: int x;
930: fd_set fdset;
931: XEvent ev;
932: static struct timeval tv;
933:
934: for (;;) {
935: video_update();
936:
937: if(console_new_mode!=NO_NEW_MODE)
938: init_mode(console_new_mode);
939: while(!sem_trywait(&x11_beep))
940: x11.XBell(dpy, 0);
941: if(!sem_trywait(&x11_title))
942: x11.XStoreName(dpy, win, window_title);
943:
944: tv.tv_sec=0;
945: tv.tv_usec=54925;
946: /*
947: * Handle any events just sitting around...
948: */
949: while (QLength(dpy) > 0) {
950: x11.XNextEvent(dpy, &ev);
951: video_event(&ev);
952: }
953:
954: FD_ZERO(&fdset);
955: FD_SET(xfd, &fdset);
956:
957: x = select(xfd+1, &fdset, 0, 0, &tv);
958:
959: switch (x) {
960: case -1:
961: /*
962: * Errno might be wrong, so we just select again.
963: * This could cause a problem is something really
964: * was wrong with select....
965: */
966:
967: perror("select");
968: break;
969: case 0:
970: break;
971: default:
972: if (FD_ISSET(xfd, &fdset)) {
973: do {
974: x11.XNextEvent(dpy, &ev);
975: video_event(&ev);
976: } while (QLength(dpy));
977: }
978: }
979: }
980: }
981:
982: /* Resize the window, using information from 'vga_status[]'. This function is
983: called after a mode change. */
984: void
985: resize_window()
986: {
987: XSizeHints *sh;
988:
989: sh = x11.XAllocSizeHints();
990: if (sh == NULL)
991: err(1, "Could not get XSizeHints structure");
992:
993: sh->base_width = FW * DpyCols + 4;
994: sh->base_height = FH * (DpyRows+1) + 4;
995:
996: sh->min_width = sh->max_width = sh->base_width;
997: sh->min_height = sh->max_height = sh->base_height;
998: sh->flags = USSize | PMinSize | PMaxSize | PSize;
999:
1000: x11.XSetWMNormalHints(dpy, win, sh);
1001: x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height);
1002: x11.XMapWindow(dpy, win);
1003: x11.XFlush(dpy);
1004:
1005: x11.XFree(sh);
1006:
1007: return;
1008: }
1009:
1010: /* No longer uses X fonts - pass NULL to use VGA 8x16 font */
1011: int
1012: load_font(char *filename, int width, int height)
1013: {
1014: XGCValues gcv;
1015: char *font;
1016:
1017: /* I don't actually do this yet! */
1018: if(filename != NULL) {
1019: return(1);
1020: }
1021:
1022: switch(width) {
1023: case 8:
1024: switch(height) {
1025: case 8:
1026: font=vga_font_bitmap8;
1027: break;
1028: case 14:
1029: font=vga_font_bitmap14;
1030: break;
1031: case 16:
1032: font=vga_font_bitmap;
1033: break;
1034: default:
1035: return(1);
1036: }
1037: break;
1038: default:
1039: return(1);
1040: }
1041: FW = width;
1042: FH = height;
1043:
1044: if(pfnt!=0)
1045: x11.XFreePixmap(dpy,pfnt);
1046: pfnt=x11.XCreateBitmapFromData(dpy, win, font, FW, FH*256);
1047:
1048: return(0);
1049: }
1050:
1051: /* Calculate 'pixels[]' from the current DAC table and palette.
1052:
1053: To do: do not use 'pixels[]', use an array of 'XColor's which we can
1054: allocate and free on demand. Install a private colormap if necessary. */
1055: void
1056: update_pixels()
1057: {
1058: int i;
1059: Colormap cm;
1060:
1061: /* We support only 16 colors for now. */
1062: for (i = 0; i < 16; i++) {
1063: XColor color;
1064:
1065: color.red = dac_default16[palette[i]].red << 10;
1066: color.green = dac_default16[palette[i]].green << 10;
1067: color.blue = dac_default16[palette[i]].blue << 10;
1068: if (x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
1069: pixels[i] = color.pixel;
1070: } else if (i < 7)
1071: pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
1072: else
1073: pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
1074: }
1075: }
1076:
1077: int
1078: init_mode(int mode)
1079: {
1080: struct video_params vmode;
1081: int idx; /* Index into vmode */
1082: int i;
1083:
1084: idx = find_vmode(mode);
1085: if (idx == -1) {
1086: console_new_mode=NO_NEW_MODE;
1087: sem_post(&console_mode_changed);
1088: return(-1);
1089: }
1090: vmode = vparams[idx];
1091:
1092: DpyCols = vmode.cols;
1093: CursStart = vmode.curs_start;
1094: CursEnd = vmode.curs_end;
1095: DpyRows = vmode.rows-1;
1096: InitCS = CursStart;
1097: InitCE = CursEnd;
1098:
1099: vmem = (WORD *)realloc(vmem,vmode.cols*vmode.rows*sizeof(WORD));
1100:
1101: /* Point 'palette[]' to the Attribute Controller space. We will only use
1102: the first 16 slots. */
1103: palette = palettes[vmode.palette];
1104:
1105: /* Load 'pixels[]' from default DAC values. */
1106: update_pixels();
1107:
1108: /* Update font. */
1109: if(load_font(NULL,vmode.charwidth,vmode.charheight)) {
1110: sem_post(&console_mode_changed);
1111: return(-1);
1112: }
1113:
1114: /* Resize window if necessary. */
1115: resize_window();
1116:
1117: get_lines();
1118:
1119: /* Initialize video memory with black background, white foreground */
1120: for (i = 0; i < DpyCols*DpyRows; ++i)
1121: vmem[i] = 0x0700;
1122:
1123: CurrMode=mode;
1124: console_new_mode=NO_NEW_MODE;
1125: sem_post(&console_mode_changed);
1126: return(0);
1127: }
1128:
1129: /* Get a connection to the X server and create the window. */
1130: int
1131: init_window()
1132: {
1133: XGCValues gcv;
1134: int i;
1135:
1136: dpy = x11.XOpenDisplay(NULL);
1137: if (dpy == NULL) {
1138: return(-1);
1139: }
1140: xfd = ConnectionNumber(dpy);
1141:
1142: /* Create window, but defer setting a size and GC. */
1143: win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1144: 1, 1, 2, black, black);
1145:
1146: gcv.foreground = white;
1147: gcv.background = black;
1148: gc = x11.XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1149:
1150: gcv.foreground = 1;
1151: gcv.background = 0;
1152: gcv.function = GXxor;
1153: cgc = x11.XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1154:
1155: x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
1156: ExposureMask | ButtonPressMask
1157: | ButtonReleaseMask | PointerMotionMask );
1158:
1159: SAFECOPY(window_title,"SyncConsole");
1160: x11.XStoreName(dpy, win, window_title);
1161:
1162: /* Get the default visual and depth for later use. */
1163: depth = DefaultDepth(dpy, DefaultScreen(dpy));
1164: visual = DefaultVisual(dpy, DefaultScreen(dpy));
1165:
1166: return(0);
1167: }
1168:
1169: int
1170: kbd_init()
1171: {
1172: K_BUFSTARTP = 0x0000; /* Start of keyboard buffer */
1173: K_BUFENDP = 0x20; /* End of keyboard buffer */
1174: K_NEXT = K_FREE = K_BUFSTARTP;
1175:
1176: return(0);
1177: }
1178:
1179: int
1180: console_init()
1181: {
1182: int fd;
1183: int i;
1184: void *dl;
1185:
1186: if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL)
1187: return(-1);
1188: if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) {
1189: dlclose(dl);
1190: return(-1);
1191: }
1192: if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) {
1193: dlclose(dl);
1194: return(-1);
1195: }
1196: if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) {
1197: dlclose(dl);
1198: return(-1);
1199: }
1200: if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) {
1201: dlclose(dl);
1202: return(-1);
1203: }
1204: if((x11.XBell=dlsym(dl,"XBell"))==NULL) {
1205: dlclose(dl);
1206: return(-1);
1207: }
1208: if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) {
1209: dlclose(dl);
1210: return(-1);
1211: }
1212: if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) {
1213: dlclose(dl);
1214: return(-1);
1215: }
1216: if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) {
1217: dlclose(dl);
1218: return(-1);
1219: }
1220: if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) {
1221: dlclose(dl);
1222: return(-1);
1223: }
1224: if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) {
1225: dlclose(dl);
1226: return(-1);
1227: }
1228: if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) {
1229: dlclose(dl);
1230: return(-1);
1231: }
1232: if((x11.XFree=dlsym(dl,"XFree"))==NULL) {
1233: dlclose(dl);
1234: return(-1);
1235: }
1236: if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) {
1237: dlclose(dl);
1238: return(-1);
1239: }
1240: if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) {
1241: dlclose(dl);
1242: return(-1);
1243: }
1244: if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) {
1245: dlclose(dl);
1246: return(-1);
1247: }
1248: if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) {
1249: dlclose(dl);
1250: return(-1);
1251: }
1252: if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) {
1253: dlclose(dl);
1254: return(-1);
1255: }
1256: if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) {
1257: dlclose(dl);
1258: return(-1);
1259: }
1260: if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) {
1261: dlclose(dl);
1262: return(-1);
1263: }
1264: if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) {
1265: dlclose(dl);
1266: return(-1);
1267: }
1268:
1269: if(dpy!=NULL)
1270: return(0);
1271:
1272: sem_init(&console_mode_changed,0,0);
1273: sem_init(&x11_beep,0,0);
1274: sem_init(&x11_title,0,0);
1275:
1276: if(kbd_init()) {
1277: return(-1);
1278: }
1279:
1280: if(video_init()) {
1281: return(-1);
1282: }
1283:
1284: _beginthread(video_async_event,1<<16,NULL);
1285: return(0);
1286: }
1287:
1288: int
1289: video_init()
1290: {
1291: /* If we are running under X, get a connection to the X server and create
1292: an empty window of size (1, 1). It makes a couple of init functions a
1293: lot easier. */
1294: if(init_window())
1295: return(-1);
1296:
1297: /* Initialize mode 3 (text, 80x25, 16 colors) */
1298: if(init_mode(3)) {
1299: return(-1);
1300: }
1301: sem_wait(&console_mode_changed);
1302:
1303: return(0);
1304: }
1305:
1306: WORD
1307: KbdPeek()
1308: {
1309: return(K_BUF(K_NEXT));
1310: }
1311:
1312: WORD
1313: KbdRead()
1314: {
1315: int kf = K_NEXT;
1316:
1317: K_NEXT = K_NEXT + 2;
1318: if (K_NEXT == K_BUFENDP)
1319: K_NEXT = K_BUFSTARTP;
1320:
1321: return(K_BUF(kf));
1322: }
1323:
1324: int
1325: KbdEmpty()
1326: {
1327: return(K_NEXT == K_FREE);
1328: }
1329:
1330: int x_nextchar = 0;
1331:
1332: int
1333: tty_read(int flag)
1334: {
1335: int r;
1336:
1337: if ((r = x_nextchar) != 0) {
1338: x_nextchar = 0;
1339: return(r & 0xff);
1340: }
1341:
1342: if (KbdEmpty() && !mouse_pending()) {
1343: if (flag & TTYF_BLOCK) {
1344: while (KbdEmpty() && !mouse_pending())
1345: tty_pause();
1346: } else {
1347: return(-1);
1348: }
1349: }
1350:
1351: if(mouse_pending()) {
1352: x_nextchar=CIO_KEY_MOUSE>>8;
1353: return(CIO_KEY_MOUSE&0xff);
1354: }
1355: else {
1356: r = KbdRead();
1357: if ((r & 0xff) == 0)
1358: x_nextchar = r >> 8;
1359: r &= 0xff;
1360: return(r & 0xff);
1361: }
1362: }
1363:
1364: int
1365: tty_peek(int flag)
1366: {
1367: int c;
1368:
1369: if (c == x_nextchar)
1370: return(x_nextchar & 0xff);
1371:
1372: if (KbdEmpty()) {
1373: if (flag & TTYF_POLL) {
1374: sleep_poll();
1375: if (KbdEmpty())
1376: return(0);
1377: } else if (flag & TTYF_BLOCK) {
1378: while (KbdEmpty())
1379: tty_pause();
1380: } else
1381: return(0);
1382: }
1383: c = KbdPeek();
1384: return(0xff);
1385: }
1386:
1387: int
1388: tty_kbhit(void)
1389: {
1390: if(x_nextchar || !KbdEmpty())
1391: return(1);
1392: return(0);
1393: }
1394:
1395: void x_win_title(const char *title)
1396: {
1397: SAFECOPY(window_title,title);
1398: sem_post(&x11_title);
1399: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.