|
|
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.68 2006/05/08 18:25:34 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:
96: #ifndef STATIC_LINK
97: #include <dlfcn.h>
98: #endif
99: #include <fcntl.h>
100: #include <limits.h>
101: #include <stdio.h>
102: #include <stdlib.h> /* malloc */
103: #include <unistd.h> /* sysconf() */
104:
105: #include <X11/Xlib.h>
106: #include <X11/Xutil.h>
107: #include <X11/keysym.h>
108: #include <X11/Xatom.h>
109:
110: #define CONSOLE_CLIPBOARD XA_PRIMARY
111:
112: #include <threadwrap.h>
113: #include <genwrap.h>
114: #include <dirwrap.h>
115:
116: #include "console.h"
117: #include "vidmodes.h"
118: #include "allfonts.h"
119:
120: #include "keys.h"
121: #include "mouse.h"
122:
123: #define CONSOLE_MAX_ROWS 61
124: #define CONSOLE_MAX_COLS 81
125:
126: /* Console definition variables */
127: int console_new_mode=NO_NEW_MODE;
128: int CurrMode;
129: sem_t console_mode_changed;
130: sem_t copybuf_set;
131: sem_t pastebuf_set;
132: sem_t pastebuf_request;
133: sem_t font_set;
134: sem_t x11_loadfont;
135: sem_t x11_fontloaded;
136: int x_load_font_ret;
137: char font_filename[MAX_PATH];
138: int new_font=-1;
139: int font_force;
140: int setfont_return;
141: pthread_mutex_t copybuf_mutex;
142: pthread_mutex_t lines_mutex;
143: char *copybuf=NULL;
144: char *pastebuf=NULL;
145: sem_t x11_beep;
146: sem_t x11_title;
147: sem_t x11_name;
148: int InitCS;
149: int InitCE;
150: int FW, FH;
151: int FontScale=1;
152: #define MAX_SCALE 2
153: WORD DpyCols;
154: BYTE DpyRows;
155: BYTE *palette;
156: BYTE CursStart;
157: BYTE CursEnd;
158: WORD *vmem=NULL;
159: static int show = 1;
160: BYTE CursRow=0;
161: BYTE CursCol=0;
162: static int x_current_font=-99;
163: typedef struct TextLine {
164: WORD *data;
165: u_char max_length; /* Not used, but here for future use */
166: u_char *exposed;
167: } TextLine;
168: TextLine *lines = NULL;
169: unsigned int x_pending_mousekeys=0;
170:
171: /* X Variables */
172: Display *dpy=NULL;
173: Window win;
174: XImage *xi = 0;
175: Pixmap pfnt=0;
176: Visual *visual;
177: unsigned int depth;
178: unsigned long black;
179: unsigned long white;
180: GC gc;
181: GC cgc;
182: int xfd;
183: char window_title[81];
184: char window_name[81];
185:
186: /* X functions */
187: struct x11 {
188: int (*XChangeGC) (Display*, GC, unsigned long, XGCValues*);
189: int (*XCopyPlane) (Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
190: int (*XFillRectangle) (Display*, Drawable, GC, int, int, unsigned int, unsigned int);
191: int (*XFlush) (Display*);
192: int (*XBell) (Display*, int);
193: int (*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
194: int (*XNextEvent) (Display*, XEvent *);
195: XSizeHints* (*XAllocSizeHints)(void);
196: void (*XSetWMNormalHints) (Display*, Window, XSizeHints*);
197: int (*XResizeWindow)(Display*, Window, unsigned int, unsigned int);
198: int (*XMapWindow) (Display*, Window);
199: int (*XFree) (void *data);
200: int (*XFreePixmap) (Display*, Pixmap);
201: Pixmap (*XCreateBitmapFromData) (Display*, Drawable, _Xconst char*, unsigned int, unsigned int);
202: Status (*XAllocColor) (Display*, Colormap, XColor*);
203: Display*(*XOpenDisplay) (_Xconst char*);
204: Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
205: GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*);
206: int (*XSelectInput) (Display*, Window, long);
207: int (*XStoreName) (Display*, Window, _Xconst char*);
208: Window (*XGetSelectionOwner) (Display*, Atom);
209: int (*XConvertSelection) (Display*, Atom, Atom, Atom, Window, Time);
210: int (*XGetWindowProperty) (Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **);
211: int (*XChangeProperty) (Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int);
212: Status (*XSendEvent) (Display*, Window, Bool, long, XEvent*);
213: int (*XSetSelectionOwner) (Display*, Atom, Window, Time);
214: int (*XSetIconName) (Display*, Window, _Xconst char *);
215: };
216: struct x11 x11;
217:
218: /* X pixel values for the RGB triples */
219: DWORD pixels[16];
220:
221: static fd_set fdset; /* File Descriptors to select on */
222:
223: /* Keyboard stuff */
224: WORD keybuf[0x25];
225: #define K_NEXT keybuf[0x21] /* *(WORD *)0x41a */
226: #define K_FREE keybuf[0x22] /* *(WORD *)0x41c */
227: #define K_BUFSTARTP keybuf[0x23] /* *(WORD *)0x480 */
228: #define K_BUFENDP keybuf[0x24] /* *(WORD *)0x482 */
229: #define K_BUFSTART (&keybuf[K_BUFSTARTP]) /* ((WORD *)(0x400 + K_BUFSTARTP)) */
230: #define K_BUFEND (&keybuf[K_BUFENDP]) /* ((WORD *)(0x400 + keybuf[3])) */
231: #define K_BUF(i) keybuf[i] /* *((WORD *)((u_char *)0x400 + (i))) */
232:
233: BYTE K1_STATUS;
234: #define K1_RSHIFT 0x01
235: #define K1_LSHIFT 0x02
236: #define K1_SHIFT 0x03
237: #define K1_CTRL 0x04
238: #define K1_ALT 0x08
239: #define K1_SLOCK 0x10 /* Active */
240: #define K1_NLOCK 0x20 /* Active */
241: #define K1_CLOCK 0x40 /* Active */
242: #define K1_INSERT 0x80 /* Active */
243:
244: BYTE K2_STATUS;
245: #define K2_LCTRL 0x01
246: #define K2_LALT 0x02
247: #define K2_SYSREQ 0x04
248: #define K2_PAUSE 0x08
249: #define K2_SLOCK 0x10 /* Actually held down */
250: #define K2_NLOCK 0x20 /* Actually held down */
251: #define K2_CLOCK 0x40 /* Actually held down */
252: #define K2_INSERT 0x80 /* Actually held down */
253:
254: BYTE K3_STATUS;
255: #define K3_E1 0x01 /* Last code read was e1 */
256: #define K3_E2 0x02 /* Last code read was e2 */
257: #define K3_RCTRL 0x04
258: #define K3_RALT 0x08
259: #define K3_ENHANCED 0x10
260: #define K3_FORCENLOCK 0x20
261: #define K3_TWOBYTE 0x40 /* last code was first of 2 */
262: #define K3_READID 0x80 /* read ID in progress */
263:
264: BYTE K4_STATUS;
265: #define K4_SLOCK_LED 0x01
266: #define K4_NLOCK_LED 0x02
267: #define K4_CLOCK_LED 0x04
268: #define K4_ACK 0x10 /* ACK recieved from keyboard */
269: #define K4_RESEND 0x20 /* RESEND recieved from keyboard */
270: #define K4_LED 0x40 /* LED update in progress */
271: #define K4_ERROR 0x80
272:
273: int flipdelete = 0; /* Flip meaning of delete and backspace */
274: static WORD break_code = 0x00;
275:
276: static WORD Ascii2Scan[] = {
277: 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
278: 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
279: 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
280: 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
281: 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
282: 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
283: 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
284: 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
285: 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
286: 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
287: 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
288: 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
289: 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
290: 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
291: 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
292: 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
293: };
294:
295: struct {
296: WORD base;
297: WORD shift;
298: WORD ctrl;
299: WORD alt;
300: } ScanCodes[] = {
301: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
302: { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
303: { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
304: { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */
305: { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
306: { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
307: { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
308: { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
309: { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
310: { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
311: { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
312: { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
313: { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
314: { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
315: { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
316: { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
317: { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
318: { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
319: { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
320: { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
321: { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
322: { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
323: { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
324: { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
325: { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
326: { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
327: { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
328: { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
329: { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
330: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
331: { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
332: { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
333: { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
334: { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
335: { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
336: { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
337: { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
338: { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
339: { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
340: { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
341: { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
342: { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
343: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
344: { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
345: { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
346: { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
347: { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
348: { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
349: { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
350: { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
351: { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
352: { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
353: { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
354: { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
355: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
356: { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
357: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
358: { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
359: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
360: { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
361: { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
362: { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
363: { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
364: { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
365: { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
366: { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
367: { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
368: { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
369: { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
370: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
371: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
372: { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
373: { 0x4800, 0x4838, 0x8d00, 0x9800 }, /* key 72 - cursor up */
374: { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
375: { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
376: { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
377: { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
378: { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
379: { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
380: { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
381: { 0x5000, 0x5032, 0x9100, 0xa000 }, /* key 80 - cursor down */
382: { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
383: { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
384: { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
385: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
386: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
387: { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
388: { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
389: { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
390: };
391:
392: #define HWM 16
393: void resize_window(void);
394: int KbdEmpty(void);
395: int load_font(char *filename, int width, int height, int scale, int *newmode);
396:
397: void tty_pause()
398: {
399: usleep(1000);
400: }
401:
402: volatile int poll_cnt = 0;
403:
404: void
405: wakeup_poll(void)
406: {
407: if (poll_cnt <= 0)
408: poll_cnt = HWM;
409: }
410:
411: void
412: reset_poll(void)
413: {
414: poll_cnt = HWM;
415: }
416:
417: void
418: sleep_poll(void)
419: {
420: if (--poll_cnt <= 0) {
421: poll_cnt = 0;
422: while (KbdEmpty() && poll_cnt <= 0) {
423: if (KbdEmpty() && poll_cnt <= 0)
424: tty_pause();
425: }
426: }
427: }
428:
429: static void
430: setgc(WORD attr)
431: {
432: XGCValues v;
433:
434: v.background = pixels[(attr >> 12) & 0x07];
435: if ((!show) && (attr & 0x8000))
436: v.foreground = v.background;
437: else
438: v.foreground = pixels[(attr >> 8) & 0x0f];
439:
440: x11.XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
441: }
442:
443: static void
444: video_update_text()
445: {
446: static int or = -1;
447: static int oc = -1;
448: static int os = -1;
449:
450: static char buf[256];
451: int r, c;
452: int attr;
453: XGCValues v;
454: WORD *vmemc;
455: int cursrow;
456: int curscol;
457: int flush=0;
458:
459: cursrow=CursRow;
460: curscol=CursCol;
461: wakeup_poll(); /* Wake up anyone waiting on kbd poll */
462:
463: vmemc = (WORD *)alloca(DpyCols*(DpyRows+1)*sizeof(WORD));
464: pthread_mutex_lock(&lines_mutex);
465: memcpy(vmemc, vmem, DpyCols*(DpyRows+1)*sizeof(WORD));
466: for (r = 0; r < (DpyRows+1); ++r) {
467: for (c = 0; c < DpyCols; ++c) {
468: if ((lines[r].data[c] != vmemc[r * DpyCols + c])
469: || (lines[r].data[c] & 0x8000 && show != os)
470: || (lines[r].exposed[c])
471: || (((r == or && c==oc) || (r == cursrow && c==curscol)) && (or != cursrow || oc !=curscol))) {
472: setgc(vmemc[r * DpyCols + c] & 0xff00);
473: x11.XCopyPlane(dpy,pfnt,win,gc,0,FH*(vmemc[r * DpyCols + c]&0xff),FW,FH,c*FW+2,r*FH+2,1);
474: lines[r].exposed[c]=0;
475: lines[r].data[c]=vmemc[r * DpyCols + c];
476: flush=1;
477: }
478: }
479:
480: reset_poll();
481: }
482: pthread_mutex_unlock(&lines_mutex);
483:
484: if (CursStart <= CursEnd && CursEnd <= FH &&
485: (show != os) && cursrow < (DpyRows+1) &&curscol < DpyCols) {
486:
487: attr = vmemc[cursrow * DpyCols +curscol] & 0xff00;
488: v.foreground = pixels[(attr >> 8) & 0x0f] ^
489: pixels[(attr >> 12) & 0x07];
490: if (v.foreground) {
491: v.function = GXxor;
492: } else {
493: v.foreground = pixels[7];
494: v.function = GXcopy;
495: }
496: x11.XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
497: x11.XFillRectangle(dpy, win, cgc,
498: 2 +curscol * FW,
499: 2 + cursrow * FH + CursStart * FontScale,
500: FW, (CursEnd + 1)*FontScale - (CursStart*FontScale));
501: flush=1;
502: }
503:
504: or =cursrow;
505: oc =curscol;
506: os =show;
507: if(flush)
508: x11.XFlush(dpy);
509: }
510:
511: void
512: video_update()
513: {
514: static clock_t lastupd=-1;
515: static int clock_started=0;
516: clock_t upd;
517:
518: upd=msclock();
519: if(!clock_started) {
520: lastupd=upd;
521: clock_started=1;
522: }
523: if(upd-lastupd>(MSCLOCKS_PER_SEC/2)) {
524: show ^= 1;
525: lastupd=upd;
526: }
527:
528: /* quick and dirty */
529: video_update_text();
530: }
531:
532: /* Get memory for the text line buffer. */
533: void
534: get_lines()
535: {
536: int i;
537: TextLine *newlines;
538:
539: if (lines == NULL) {
540: pthread_mutex_lock(&lines_mutex);
541: lines = (TextLine *)malloc(sizeof(TextLine) * (CONSOLE_MAX_ROWS+1));
542: if (lines == NULL) {
543: fprintf(stderr, "Could not allocate data structure for text lines\n");
544: exit(1);
545: }
546: for (i = 0; i < (CONSOLE_MAX_ROWS+1); ++i) {
547: lines[i].max_length = DpyCols;
548: lines[i].data = (WORD *)malloc(CONSOLE_MAX_COLS * sizeof(WORD));
549: if (lines[i].data == NULL) {
550: fprintf(stderr, "Could not allocate data structure for text lines\n");
551: exit(1);
552: }
553: lines[i].exposed = (u_char *)malloc(CONSOLE_MAX_COLS * sizeof(u_char));
554: if (lines[i].exposed == NULL) {
555: fprintf(stderr, "Could not allocate data structure for text lines\n");
556: exit(1);
557: }
558: memset(lines[i].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char));
559: }
560: pthread_mutex_unlock(&lines_mutex);
561: }
562: }
563:
564: void
565: KbdWrite(WORD code)
566: {
567: int kf;
568:
569: kf = K_FREE + 2;
570: if (kf == K_BUFENDP)
571: kf = K_BUFSTARTP;
572:
573: if (kf == K_NEXT) {
574: if(code==CIO_KEY_MOUSE)
575: x_pending_mousekeys++;
576: else {
577: x11.XBell(dpy, 0);
578: return;
579: }
580: }
581: K_BUF(K_FREE) = code;
582: K_FREE = kf;
583: }
584:
585: void tty_beep(void)
586: {
587: sem_post(&x11_beep);
588: }
589:
590: void expose_chars(int x, int y, int width, int height)
591: {
592: int sx,sy,ex,ey;
593: int r,c;
594:
595: sx=x;
596: sx-=2;
597: if(sx<0)
598: sx=0;
599: sy=y;
600: sy-=2;
601: if(sy<0)
602: sy=0;
603: ex=sx+width+FW-1;
604: ey=sy+height+FH-1;
605: sx/=FW;
606: ex/=FW;
607: if(ex>=DpyCols)
608: ex=DpyCols-1;
609: sy/=FH;
610: ey/=FH;
611: if(ey>DpyRows)
612: ey=DpyRows;
613:
614: for(r=sy;r<=ey;r++) {
615: pthread_mutex_lock(&lines_mutex);
616: for(c=sx;c<=ex;c++) {
617: lines[r].exposed[c]=1;
618: }
619: pthread_mutex_unlock(&lines_mutex);
620: }
621: }
622:
623: static int
624: video_event(XEvent *ev)
625: {
626: switch (ev->type) {
627: case ConfigureNotify: {
628: int newFSH=1;
629: int newFSW=1;
630: int oldFS;
631: int r;
632:
633: oldFS=FontScale;
634: if((ev->xconfigure.width == FW * DpyCols + 4)
635: && (ev->xconfigure.height == FH * (DpyRows+1) + 4))
636: break;
637:
638: FW=FW/FontScale;
639: FH=FH/FontScale;
640: newFSH=(ev->xconfigure.width+(FW*DpyCols)/2)/(FW*DpyCols);
641: newFSW=(ev->xconfigure.height+(FH*(DpyRows+1))/2)/(FH*(DpyRows+1));
642: if(newFSW<1)
643: newFSW=1;
644: if(newFSW>MAX_SCALE)
645: newFSW=MAX_SCALE;
646: if(newFSH<1)
647: newFSH=1;
648: if(newFSH>MAX_SCALE)
649: newFSH=MAX_SCALE;
650: if(newFSH<newFSW)
651: FontScale=newFSH;
652: else
653: FontScale=newFSW;
654: load_font(NULL,FW,FH,FontScale,NULL);
655: resize_window();
656: break;
657: }
658: case SelectionClear: {
659: XSelectionClearEvent *req;
660:
661: req=&(ev->xselectionclear);
662: pthread_mutex_lock(©buf_mutex);
663: if(req->selection==CONSOLE_CLIPBOARD && copybuf!=NULL) {
664: free(copybuf);
665: copybuf=NULL;
666: }
667: pthread_mutex_unlock(©buf_mutex);
668: break;
669: }
670: case SelectionNotify: {
671: int format;
672: unsigned long len, bytes_left, dummy;
673: Atom type;
674:
675: if(ev->xselection.requestor!=win)
676: break;
677: x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf));
678: if(bytes_left > 0 && format==8)
679: x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf);
680: else
681: pastebuf=NULL;
682:
683: /* Set paste buffer */
684: sem_post(&pastebuf_set);
685: sem_wait(&pastebuf_request);
686: x11.XFree(pastebuf);
687: pastebuf=NULL;
688: break;
689: }
690: case SelectionRequest: {
691: XSelectionRequestEvent *req;
692: XEvent respond;
693:
694: req=&(ev->xselectionrequest);
695: pthread_mutex_lock(©buf_mutex);
696: if(copybuf==NULL) {
697: respond.xselection.property=None;
698: }
699: else {
700: if(req->target==XA_STRING) {
701: x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf));
702: respond.xselection.property=req->property;
703: }
704: else
705: respond.xselection.property=None;
706: }
707: respond.xselection.type=SelectionNotify;
708: respond.xselection.display=req->display;
709: respond.xselection.requestor=req->requestor;
710: respond.xselection.selection=req->selection;
711: respond.xselection.target=req->target;
712: respond.xselection.time=req->time;
713: x11.XSendEvent(dpy,req->requestor,0,0,&respond);
714: pthread_mutex_unlock(©buf_mutex);
715: break;
716: }
717: case MotionNotify: {
718: XMotionEvent *me = (XMotionEvent *)ev;
719: me->x -= 2;
720: me->y -= 2;
721: me->x/=FW;
722: me->y/=FH;
723: me->x++;
724: me->y++;
725: if(me->x<1)
726: me->x=1;
727: if(me->y<1)
728: me->y=1;
729: if(me->x>DpyCols)
730: me->x=DpyCols;
731: if(me->y>DpyRows+1)
732: me->y=DpyRows+1;
733: ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y);
734: break;
735: }
736: case ButtonRelease: {
737: XButtonEvent *be = (XButtonEvent *)ev;
738: be->x -= 2;
739: be->y -= 2;
740: be->x/=FW;
741: be->y/=FH;
742: be->x++;
743: be->y++;
744: if(be->x<1)
745: be->x=1;
746: if(be->y<1)
747: be->y=1;
748: if(be->x>DpyCols)
749: be->x=DpyCols;
750: if(be->y>DpyRows+1)
751: be->y=DpyRows+1;
752: if (be->button <= 3) {
753: ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y);
754: }
755: break;
756: }
757: case ButtonPress: {
758: XButtonEvent *be = (XButtonEvent *)ev;
759: be->x -= 2;
760: be->y -= 2;
761: be->x/=FW;
762: be->y/=FH;
763: be->x++;
764: be->y++;
765: if(be->x<1)
766: be->x=1;
767: if(be->y<1)
768: be->y=1;
769: if(be->x>DpyCols)
770: be->x=DpyCols;
771: if(be->y>DpyRows+1)
772: be->y=DpyRows+1;
773: if (be->button <= 3) {
774: ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y);
775: }
776: break;
777: }
778: case NoExpose:
779: break;
780: case GraphicsExpose: {
781: expose_chars(ev->xgraphicsexpose.x,ev->xgraphicsexpose.y
782: ,ev->xgraphicsexpose.width,ev->xgraphicsexpose.height);
783: break;
784: }
785: case Expose: {
786: expose_chars(ev->xexpose.x,ev->xexpose.y,ev->xexpose.width,ev->xexpose.height);
787: break;
788: }
789: case KeyRelease: {
790: static char buf[128];
791: KeySym ks;
792:
793: break_code |= 0x80;
794:
795: if (!(ev->xkey.state & ShiftMask)) {
796: K1_STATUS &= ~K1_LSHIFT;
797: K1_STATUS &= ~K1_RSHIFT;
798: }
799: if (!(ev->xkey.state & ControlMask)) {
800: K1_STATUS &= ~K1_CTRL;
801: K2_STATUS &= ~K2_LCTRL;
802: K3_STATUS &= ~K3_RCTRL;
803: }
804: if (!(ev->xkey.state & Mod1Mask)) {
805: K1_STATUS &= ~K1_ALT;
806: K2_STATUS &= ~K2_LALT;
807: K3_STATUS &= ~K3_RALT;
808: }
809: if (!(ev->xkey.state & LockMask)) {
810: K2_STATUS &= ~K2_CLOCK;
811: }
812:
813: x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
814: switch (ks) {
815: case XK_Shift_L:
816: K1_STATUS &= ~K1_LSHIFT;
817: break;
818: case XK_Shift_R:
819: K1_STATUS &= ~K1_RSHIFT;
820: break;
821: case XK_Control_L:
822: K1_STATUS &= ~K1_CTRL;
823: K2_STATUS &= ~K2_LCTRL;
824: break;
825: case XK_Control_R:
826: K1_STATUS &= ~K1_CTRL;
827: K3_STATUS &= ~K3_RCTRL;
828: break;
829: case XK_Alt_L:
830: K1_STATUS &= ~K1_ALT;
831: K2_STATUS &= ~K2_LALT;
832: break;
833: case XK_Alt_R:
834: K1_STATUS &= ~K1_ALT;
835: K3_STATUS &= ~K3_RALT;
836: break;
837: case XK_Scroll_Lock:
838: K2_STATUS &= ~K2_SLOCK;
839: break;
840: case XK_Num_Lock:
841: K2_STATUS &= ~K2_NLOCK;
842: break;
843: case XK_Caps_Lock:
844: K2_STATUS &= ~K2_CLOCK;
845: break;
846: case XK_Insert:
847: K2_STATUS &= ~K2_INSERT;
848: break;
849: }
850: return(1);
851: }
852: case KeyPress: {
853: static char buf[128];
854: KeySym ks;
855: int n;
856: int nlock = 0;
857: WORD scan = 0xffff;
858:
859: if (!(ev->xkey.state & ShiftMask)) {
860: K1_STATUS &= ~K1_LSHIFT;
861: K1_STATUS &= ~K1_RSHIFT;
862: }
863: if (!(ev->xkey.state & ControlMask)) {
864: K1_STATUS &= ~K1_CTRL;
865: K2_STATUS &= ~K2_LCTRL;
866: K3_STATUS &= ~K3_RCTRL;
867: }
868: if (!(ev->xkey.state & Mod1Mask)) {
869: K1_STATUS &= ~K1_ALT;
870: K2_STATUS &= ~K2_LALT;
871: K3_STATUS &= ~K3_RALT;
872: }
873: if (!(ev->xkey.state & LockMask)) {
874: K2_STATUS &= ~K2_CLOCK;
875: }
876:
877: n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
878:
879: switch (ks) {
880: case XK_Shift_L:
881: K1_STATUS |= K1_LSHIFT;
882: break;
883: case XK_Shift_R:
884: K1_STATUS |= K1_RSHIFT;
885: break;
886: case XK_Control_L:
887: K1_STATUS |= K1_CTRL;
888: K2_STATUS |= K2_LCTRL;
889: break;
890: case XK_Control_R:
891: K1_STATUS |= K1_CTRL;
892: K3_STATUS |= K3_RCTRL;
893: break;
894: case XK_Alt_L:
895: K1_STATUS |= K1_ALT;
896: K2_STATUS |= K2_LALT;
897: break;
898: case XK_Alt_R:
899: K1_STATUS |= K1_ALT;
900: K3_STATUS |= K3_RALT;
901: break;
902: case XK_Scroll_Lock:
903: K1_STATUS ^= K1_SLOCK;
904: K2_STATUS |= K2_SLOCK;
905: break;
906: case XK_Num_Lock:
907: K1_STATUS ^= K1_NLOCK;
908: K2_STATUS |= K2_NLOCK;
909: break;
910: case XK_Caps_Lock:
911: K1_STATUS ^= K1_CLOCK;
912: K2_STATUS |= K2_CLOCK;
913: break;
914: case XK_Insert:
915: case XK_KP_Insert:
916: K1_STATUS ^= K1_INSERT;
917: K2_STATUS |= K2_INSERT;
918: scan = 82;
919: goto docode;
920:
921: case XK_Escape:
922: scan = 1;
923: goto docode;
924:
925: case XK_Tab:
926: case XK_ISO_Left_Tab:
927: scan = 15;
928: goto docode;
929:
930: case XK_Return:
931: case XK_KP_Enter:
932: scan = 28;
933: goto docode;
934:
935: case XK_Print:
936: scan = 55;
937: goto docode;
938:
939: case XK_F1:
940: case XK_F2:
941: case XK_F3:
942: case XK_F4:
943: case XK_F5:
944: case XK_F6:
945: case XK_F7:
946: case XK_F8:
947: case XK_F9:
948: case XK_F10:
949: scan = ks - XK_F1 + 59;
950: goto docode;
951:
952: case XK_KP_7:
953: nlock = 1;
954: case XK_Home:
955: case XK_KP_Home:
956: scan = 71;
957: goto docode;
958: case XK_KP_8:
959: nlock = 1;
960: case XK_Up:
961: case XK_KP_Up:
962: scan = 72;
963: goto docode;
964: case XK_KP_9:
965: nlock = 1;
966: case XK_Prior:
967: case XK_KP_Prior:
968: scan = 73;
969: goto docode;
970: case XK_KP_Subtract:
971: scan = 74;
972: goto docode;
973: case XK_KP_4:
974: nlock = 1;
975: case XK_Left:
976: case XK_KP_Left:
977: scan = 75;
978: goto docode;
979: case XK_KP_5:
980: nlock = 1;
981: case XK_Begin:
982: case XK_KP_Begin:
983: scan = 76;
984: goto docode;
985: case XK_KP_6:
986: nlock = 1;
987: case XK_Right:
988: case XK_KP_Right:
989: scan = 77;
990: goto docode;
991: case XK_KP_Add:
992: scan = 78;
993: goto docode;
994: case XK_KP_1:
995: nlock = 1;
996: case XK_End:
997: case XK_KP_End:
998: scan = 79;
999: goto docode;
1000: case XK_KP_2:
1001: nlock = 1;
1002: case XK_Down:
1003: case XK_KP_Down:
1004: scan = 80;
1005: goto docode;
1006: case XK_KP_3:
1007: nlock = 1;
1008: case XK_Next:
1009: case XK_KP_Next:
1010: scan = 81;
1011: goto docode;
1012: case XK_KP_0:
1013: nlock = 1;
1014: /* case XK_Insert: This is above */
1015: scan = 82;
1016: goto docode;
1017:
1018: case XK_KP_Decimal:
1019: nlock = 1;
1020: scan = 83;
1021: goto docode;
1022:
1023: case XK_Delete:
1024: case XK_KP_Delete:
1025: scan = flipdelete ? 14 : 83;
1026: goto docode;
1027:
1028: case XK_BackSpace:
1029: scan = flipdelete ? 83 : 14;
1030: goto docode;
1031:
1032: case XK_F11:
1033: scan = 87;
1034: goto docode;
1035: case XK_F12:
1036: scan = 88;
1037: goto docode;
1038:
1039:
1040: case XK_KP_Divide:
1041: scan = Ascii2Scan['/'];
1042: goto docode;
1043:
1044: case XK_KP_Multiply:
1045: scan = Ascii2Scan['*'];
1046: goto docode;
1047:
1048: default:
1049: if (ks < ' ' || ks > '~')
1050: break;
1051: scan = Ascii2Scan[ks];
1052: docode:
1053: if (nlock)
1054: scan |= 0x100;
1055:
1056: if ((scan & ~0x100) > 88) {
1057: scan = 0xffff;
1058: break;
1059: }
1060:
1061: if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
1062: scan = ScanCodes[scan & 0xff].shift;
1063: } else if (K1_STATUS & K1_CTRL) {
1064: scan = ScanCodes[scan & 0xff].ctrl;
1065: } else if (K1_STATUS & K1_ALT) {
1066: scan = ScanCodes[scan & 0xff].alt;
1067: } else
1068: scan = ScanCodes[scan & 0xff].base;
1069:
1070: break;
1071: }
1072: if (scan != 0xffff) {
1073: break_code = scan >> 8;
1074: KbdWrite(scan);
1075: }
1076: return(1);
1077: }
1078:
1079: default:
1080: break;
1081: }
1082: return(0);
1083: }
1084:
1085: void
1086: mouse_event(void *crap)
1087: {
1088: while(1) {
1089: if(mouse_wait())
1090: KbdWrite(CIO_KEY_MOUSE);
1091: }
1092: }
1093:
1094: void
1095: video_async_event(void *crap)
1096: {
1097: int x;
1098: fd_set fdset;
1099: XEvent ev;
1100: static struct timeval tv;
1101:
1102: for (;;) {
1103: video_update();
1104:
1105: tv.tv_sec=0;
1106: tv.tv_usec=54925;
1107: /*
1108: * Handle any events just sitting around...
1109: */
1110: while (QLength(dpy) > 0) {
1111: x11.XNextEvent(dpy, &ev);
1112: video_event(&ev);
1113: }
1114:
1115: FD_ZERO(&fdset);
1116: FD_SET(xfd, &fdset);
1117:
1118: x = select(xfd+1, &fdset, 0, 0, &tv);
1119:
1120: switch (x) {
1121: case -1:
1122: /*
1123: * Errno might be wrong, so we just select again.
1124: * This could cause a problem is something really
1125: * was wrong with select....
1126: */
1127:
1128: /* perror("select"); */
1129: break;
1130: case 0:
1131: if(console_new_mode!=NO_NEW_MODE)
1132: init_mode(console_new_mode);
1133: if(x_current_font!=new_font) {
1134: int oldfont=x_current_font;
1135: int newmode=0;
1136:
1137: x_current_font=new_font;
1138: if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,&newmode)) {
1139: if(font_force && newmode) {
1140: init_mode(newmode);
1141: sem_wait(&console_mode_changed);
1142: if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL)) {
1143: setfont_return=-1;
1144: x_current_font=oldfont;
1145: new_font=oldfont;
1146: load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL);
1147: }
1148: else
1149: setfont_return=0;
1150: }
1151: else {
1152: setfont_return=-1;
1153: x_current_font=oldfont;
1154: new_font=oldfont;
1155: load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL);
1156: }
1157: }
1158: else
1159: setfont_return=0;
1160: resize_window();
1161: sem_post(&font_set);
1162: }
1163: while(!sem_trywait(&x11_beep))
1164: x11.XBell(dpy, 0);
1165: if(!sem_trywait(&x11_name))
1166: x11.XSetIconName(dpy, win, window_name);
1167: if(!sem_trywait(&x11_loadfont)) {
1168: int oldfont=x_current_font;
1169: x_load_font_ret=load_font(font_filename,FW/FontScale,FH/FontScale,FontScale,NULL);
1170: if(x_load_font_ret)
1171: x_current_font=oldfont;
1172: new_font=x_current_font;
1173: resize_window();
1174: sem_post(&x11_fontloaded);
1175: }
1176: if(!sem_trywait(&x11_title))
1177: x11.XStoreName(dpy, win, window_title);
1178: if(!sem_trywait(©buf_set)) {
1179: /* Copybuf has been set and isn't NULL */
1180: x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime);
1181: }
1182: if(!sem_trywait(&pastebuf_request)) {
1183: Window sowner=None;
1184:
1185: sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD);
1186: if(sowner==win) {
1187: /* Get your own primary selection */
1188: if(copybuf==NULL)
1189: pastebuf=NULL;
1190: else
1191: pastebuf=(unsigned char *)malloc(strlen(copybuf)+1);
1192: if(pastebuf!=NULL)
1193: strcpy(pastebuf,copybuf);
1194: /* Set paste buffer */
1195: sem_post(&pastebuf_set);
1196: sem_wait(&pastebuf_request);
1197: if(pastebuf!=NULL)
1198: free(pastebuf);
1199: pastebuf=NULL;
1200: }
1201: else if(sowner!=None) {
1202: x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, None, win, CurrentTime);
1203: }
1204: else {
1205: /* Set paste buffer */
1206: pastebuf=NULL;
1207: sem_post(&pastebuf_set);
1208: sem_wait(&pastebuf_request);
1209: }
1210: }
1211: break;
1212: default:
1213: if (FD_ISSET(xfd, &fdset)) {
1214: do {
1215: x11.XNextEvent(dpy, &ev);
1216: video_event(&ev);
1217: } while (QLength(dpy));
1218: }
1219: }
1220: }
1221: }
1222:
1223: /* Resize the window, using information from 'vga_status[]'. This function is
1224: called after a mode change. */
1225: void
1226: resize_window()
1227: {
1228: XSizeHints *sh;
1229: int r;
1230:
1231: sh = x11.XAllocSizeHints();
1232: if (sh == NULL) {
1233: fprintf(stderr, "Could not get XSizeHints structure");
1234: exit(1);
1235: }
1236:
1237: sh->base_width = FW * DpyCols + 4;
1238: sh->base_height = FH * (DpyRows+1) + 4;
1239:
1240: sh->min_width = (FW/FontScale) * DpyCols + 4;
1241: sh->max_width = (FW/FontScale) * MAX_SCALE * DpyCols + 4;
1242: sh->min_height = (FH/FontScale) * (DpyRows+1) +4;
1243: sh->max_height = (FH/FontScale) * MAX_SCALE * (DpyRows+1) +4;
1244: sh->flags = USSize | PMinSize | PMaxSize | PSize;
1245:
1246: x11.XSetWMNormalHints(dpy, win, sh);
1247: x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height);
1248: x11.XMapWindow(dpy, win);
1249:
1250: x11.XFree(sh);
1251:
1252: if(lines != NULL) {
1253: pthread_mutex_lock(&lines_mutex);
1254: for (r = 0; r < (CONSOLE_MAX_ROWS+1); ++r) {
1255: memset(lines[r].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char));
1256: }
1257: pthread_mutex_unlock(&lines_mutex);
1258: }
1259:
1260: return;
1261: }
1262:
1263: /* Scales a bitmap up to 2x it's current size */
1264: char *
1265: scale_bitmap(char *bitmap, int width, int height, int *multiplier)
1266: {
1267: char *ret;
1268: char *outbyte;
1269: int pos;
1270: int origbmpsize;
1271: int origbytesperline=1;
1272: int scaledbmpsize;
1273: int scaledbytesperline=1;
1274:
1275: while(origbytesperline*8<width)
1276: origbytesperline++;
1277:
1278: if(*multiplier>MAX_SCALE)
1279: *multiplier=MAX_SCALE;
1280: if(*multiplier < 1)
1281: *multiplier=1;
1282: while(scaledbytesperline * 8<width*(*multiplier))
1283: scaledbytesperline++;
1284:
1285: origbmpsize=origbytesperline*height;
1286: scaledbmpsize=scaledbytesperline*height*(*multiplier);
1287:
1288: ret=(char *)malloc(scaledbmpsize);
1289: if(ret==NULL)
1290: return(NULL);
1291: outbyte=ret;
1292: for(pos=0;pos<origbmpsize;pos++) {
1293: switch(*multiplier) {
1294: case 1:
1295: *(outbyte++)=bitmap[pos];
1296: break;
1297: case 2:
1298: *outbyte=
1299: ((bitmap[pos]&0x08)<<4)
1300: |((bitmap[pos]&0x08)<<3)
1301: |((bitmap[pos]&0x04)<<3)
1302: |((bitmap[pos]&0x04)<<2)
1303: |((bitmap[pos]&0x02)<<2)
1304: |((bitmap[pos]&0x02)<<1)
1305: |((bitmap[pos]&0x01)<<1)
1306: |((bitmap[pos]&0x01));
1307: outbyte++;
1308: *outbyte=
1309: ((bitmap[pos]&0x80))
1310: |((bitmap[pos]&0x80)>>1)
1311: |((bitmap[pos]&0x40)>>1)
1312: |((bitmap[pos]&0x40)>>2)
1313: |((bitmap[pos]&0x20)>>2)
1314: |((bitmap[pos]&0x20)>>3)
1315: |((bitmap[pos]&0x10)>>3)
1316: |((bitmap[pos]&0x10)>>4);
1317: outbyte++;
1318: *outbyte=
1319: ((bitmap[pos]&0x08)<<4)
1320: |((bitmap[pos]&0x08)<<3)
1321: |((bitmap[pos]&0x04)<<3)
1322: |((bitmap[pos]&0x04)<<2)
1323: |((bitmap[pos]&0x02)<<2)
1324: |((bitmap[pos]&0x02)<<1)
1325: |((bitmap[pos]&0x01)<<1)
1326: |((bitmap[pos]&0x01));
1327: outbyte++;
1328: *outbyte=
1329: ((bitmap[pos]&0x80))
1330: |((bitmap[pos]&0x80)>>1)
1331: |((bitmap[pos]&0x40)>>1)
1332: |((bitmap[pos]&0x40)>>2)
1333: |((bitmap[pos]&0x20)>>2)
1334: |((bitmap[pos]&0x20)>>3)
1335: |((bitmap[pos]&0x10)>>3)
1336: |((bitmap[pos]&0x10)>>4);
1337: outbyte++;
1338: break;
1339: }
1340: }
1341: return(ret);
1342: }
1343:
1344: /* No longer uses X fonts - pass NULL to use VGA 8x16 font */
1345: int
1346: load_font(char *filename, int width, int height, int scale, int *newmode)
1347: {
1348: XGCValues gcv;
1349: char *font;
1350: char *scaledfont;
1351: char fontdata[256*16];
1352: int i,j;
1353: static char current_filename[MAX_PATH];
1354: FILE *fontfile;
1355:
1356: if(height > 16)
1357: return(-1);
1358:
1359: if(x_current_font==-99 || x_current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) {
1360: for(i=0; conio_fontdata[i].desc != NULL; i++) {
1361: if(!strcmp(conio_fontdata[i].desc, "Codepage 437 English")) {
1362: x_current_font=i;
1363: break;
1364: }
1365: }
1366: if(conio_fontdata[i].desc==NULL)
1367: x_current_font=0;
1368: new_font=x_current_font;
1369: }
1370: if(x_current_font==-1)
1371: filename=current_filename;
1372: else if(conio_fontdata[x_current_font].desc==NULL)
1373: return(-1);
1374:
1375: if(filename != NULL) {
1376: int fl=flength(filename);
1377:
1378: if(newmode != NULL) {
1379: switch(fl/256) {
1380: case 8:
1381: *newmode=C80X50;
1382: break;
1383: case 14:
1384: *newmode=C80X28;
1385: break;
1386: case 16:
1387: *newmode=C80;
1388: break;
1389: }
1390: }
1391: if(fl!=height*256)
1392: return(-1);
1393: if((fontfile=fopen(filename,"rb"))==NULL)
1394: return(-1);
1395: if(fread(fontdata, 1, height*256, fontfile)!=height*256) {
1396: fclose(fontfile);
1397: return(-1);
1398: }
1399: fclose(fontfile);
1400: x_current_font=new_font=-1;
1401: if(filename != current_filename)
1402: SAFECOPY(current_filename,filename);
1403: }
1404: else {
1405: if(newmode != NULL) {
1406: if(conio_fontdata[x_current_font].eight_by_sixteen!=NULL)
1407: *newmode=C80;
1408: else if(conio_fontdata[x_current_font].eight_by_fourteen!=NULL)
1409: *newmode=C80X28;
1410: else if(conio_fontdata[x_current_font].eight_by_eight!=NULL)
1411: *newmode=C80X50;
1412: }
1413: switch(width) {
1414: case 8:
1415: switch(height) {
1416: case 8:
1417: font=conio_fontdata[x_current_font].eight_by_eight;
1418: break;
1419: case 14:
1420: font=conio_fontdata[x_current_font].eight_by_fourteen;
1421: break;
1422: case 16:
1423: font=conio_fontdata[x_current_font].eight_by_sixteen;
1424: break;
1425: default:
1426: return(1);
1427: }
1428: break;
1429: default:
1430: return(1);
1431: }
1432: if(font==NULL)
1433: return(1);
1434: memcpy(fontdata, font, height*256);
1435: }
1436: FW = width;
1437: FH = height;
1438: /* Swap bit order... leftmost bit is most significant, X11 wants it the
1439: * other way. */
1440: for(i=0; i<256; i++) {
1441: for(j=0; j<height; j++) {
1442: fontdata[i*height+j]= ((fontdata[i*height+j] & 0x80) >> 7)
1443: | ((fontdata[i*height+j] & 0x40) >> 5)
1444: | ((fontdata[i*height+j] & 0x20) >> 3)
1445: | ((fontdata[i*height+j] & 0x10) >> 1)
1446: | ((fontdata[i*height+j] & 0x08) << 1)
1447: | ((fontdata[i*height+j] & 0x04) << 3)
1448: | ((fontdata[i*height+j] & 0x02) << 5)
1449: | ((fontdata[i*height+j] & 0x01) << 7);
1450: }
1451: }
1452: if(pfnt!=0)
1453: x11.XFreePixmap(dpy,pfnt);
1454: scaledfont=scale_bitmap(fontdata, FW, FH*256, &FontScale);
1455: if(scaledfont==NULL)
1456: pfnt=x11.XCreateBitmapFromData(dpy, win, fontdata, FW, FH*256);
1457: else {
1458: FW*=scale;
1459: FH*=scale;
1460: pfnt=x11.XCreateBitmapFromData(dpy, win, scaledfont, FW, FH*256);
1461: free(scaledfont);
1462: }
1463:
1464: return(0);
1465: }
1466:
1467: /* Calculate 'pixels[]' from the current DAC table and palette.
1468:
1469: To do: do not use 'pixels[]', use an array of 'XColor's which we can
1470: allocate and free on demand. Install a private colormap if necessary. */
1471: void
1472: update_pixels()
1473: {
1474: int i;
1475: Colormap cm;
1476:
1477: /* We support only 16 colors for now. */
1478: for (i = 0; i < 16; i++) {
1479: XColor color;
1480:
1481: color.red = dac_default16[palette[i]].red << 10;
1482: color.green = dac_default16[palette[i]].green << 10;
1483: color.blue = dac_default16[palette[i]].blue << 10;
1484: if (x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
1485: pixels[i] = color.pixel;
1486: } else if (i < 7)
1487: pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
1488: else
1489: pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
1490: }
1491: }
1492:
1493: int
1494: init_mode(int mode)
1495: {
1496: struct video_params vmode;
1497: int idx; /* Index into vmode */
1498: int i;
1499:
1500: idx = find_vmode(mode);
1501: if (idx == -1) {
1502: console_new_mode=NO_NEW_MODE;
1503: sem_post(&console_mode_changed);
1504: return(-1);
1505: }
1506: vmode = vparams[idx];
1507:
1508: DpyCols = vmode.cols;
1509: CursStart = vmode.curs_start;
1510: CursEnd = vmode.curs_end;
1511: DpyRows = vmode.rows-1;
1512: InitCS = CursStart;
1513: InitCE = CursEnd;
1514:
1515: vmem = (WORD *)realloc(vmem,vmode.cols*vmode.rows*sizeof(WORD));
1516:
1517: /* Point 'palette[]' to the Attribute Controller space. We will only use
1518: the first 16 slots. */
1519: palette = palettes[vmode.palette];
1520:
1521: /* Load 'pixels[]' from default DAC values. */
1522: update_pixels();
1523:
1524: /* Update font. */
1525: if(load_font(NULL,vmode.charwidth,vmode.charheight,FontScale,NULL)) {
1526: sem_post(&console_mode_changed);
1527: return(-1);
1528: }
1529:
1530: /* Resize window if necessary. */
1531: resize_window();
1532:
1533: get_lines();
1534:
1535: /* Initialize video memory with black background, white foreground */
1536: for (i = 0; i < DpyCols*DpyRows; ++i)
1537: vmem[i] = 0x0700;
1538:
1539: CurrMode=mode;
1540: console_new_mode=NO_NEW_MODE;
1541: sem_post(&console_mode_changed);
1542: return(0);
1543: }
1544:
1545: /* Get a connection to the X server and create the window. */
1546: int
1547: init_window()
1548: {
1549: XGCValues gcv;
1550: int i;
1551:
1552: dpy = x11.XOpenDisplay(NULL);
1553: if (dpy == NULL) {
1554: return(-1);
1555: }
1556: xfd = ConnectionNumber(dpy);
1557:
1558: /* Create window, but defer setting a size and GC. */
1559: win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1560: 1, 1, 2, black, black);
1561:
1562: gcv.foreground = white;
1563: gcv.background = black;
1564: gc = x11.XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1565:
1566: gcv.foreground = 1;
1567: gcv.background = 0;
1568: gcv.function = GXxor;
1569: cgc = x11.XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1570:
1571: x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
1572: ExposureMask | ButtonPressMask
1573: | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
1574:
1575: SAFECOPY(window_title,"SyncConsole");
1576: x11.XStoreName(dpy, win, window_title);
1577:
1578: /* Get the default visual and depth for later use. */
1579: depth = DefaultDepth(dpy, DefaultScreen(dpy));
1580: visual = DefaultVisual(dpy, DefaultScreen(dpy));
1581:
1582: return(0);
1583: }
1584:
1585: int
1586: kbd_init()
1587: {
1588: K_BUFSTARTP = 0x0000; /* Start of keyboard buffer */
1589: K_BUFENDP = 0x20; /* End of keyboard buffer */
1590: K_NEXT = K_FREE = K_BUFSTARTP;
1591:
1592: return(0);
1593: }
1594:
1595: int
1596: console_init()
1597: {
1598: int fd;
1599: int i;
1600: void *dl;
1601:
1602: if(dpy!=NULL)
1603: return(0);
1604:
1605: #ifdef STATIC_LINK
1606: x11.XChangeGC=XChangeGC;
1607: x11.XCopyPlane=XCopyPlane;
1608: x11.XFillRectangle=XFillRectangle;
1609: x11.XFlush=XFlush;
1610: x11.XBell=XBell;
1611: x11.XLookupString=XLookupString;
1612: x11.XNextEvent=XNextEvent;
1613: x11.XAllocSizeHints=XAllocSizeHints;
1614: x11.XSetWMNormalHints=XSetWMNormalHints;
1615: x11.XResizeWindow=XResizeWindow;
1616: x11.XMapWindow=XMapWindow;
1617: x11.XFree=XFree;
1618: x11.XFreePixmap=XFreePixmap;
1619: x11.XCreateBitmapFromData=XCreateBitmapFromData;
1620: x11.XAllocColor=XAllocColor;
1621: x11.XOpenDisplay=XOpenDisplay;
1622: x11.XCreateSimpleWindow=XCreateSimpleWindow;
1623: x11.XCreateGC=XCreateGC;
1624: x11.XSelectInput=XSelectInput;
1625: x11.XStoreName=XStoreName;
1626: x11.XGetSelectionOwner=XGetSelectionOwner;
1627: x11.XConvertSelection=XConvertSelection;
1628: x11.XGetWindowProperty=XGetWindowProperty;
1629: x11.XChangeProperty=XChangeProperty;
1630: x11.XSendEvent=XSendEvent;
1631: x11.XSetSelectionOwner=XSetSelectionOwner;
1632: x11.XSetIconName=XSetIconName;
1633: #else
1634: #if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
1635: if((dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL))==NULL)
1636: #else
1637: if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL)
1638: #endif
1639: return(-1);
1640: if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) {
1641: dlclose(dl);
1642: return(-1);
1643: }
1644: if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) {
1645: dlclose(dl);
1646: return(-1);
1647: }
1648: if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) {
1649: dlclose(dl);
1650: return(-1);
1651: }
1652: if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) {
1653: dlclose(dl);
1654: return(-1);
1655: }
1656: if((x11.XBell=dlsym(dl,"XBell"))==NULL) {
1657: dlclose(dl);
1658: return(-1);
1659: }
1660: if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) {
1661: dlclose(dl);
1662: return(-1);
1663: }
1664: if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) {
1665: dlclose(dl);
1666: return(-1);
1667: }
1668: if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) {
1669: dlclose(dl);
1670: return(-1);
1671: }
1672: if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) {
1673: dlclose(dl);
1674: return(-1);
1675: }
1676: if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) {
1677: dlclose(dl);
1678: return(-1);
1679: }
1680: if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) {
1681: dlclose(dl);
1682: return(-1);
1683: }
1684: if((x11.XFree=dlsym(dl,"XFree"))==NULL) {
1685: dlclose(dl);
1686: return(-1);
1687: }
1688: if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) {
1689: dlclose(dl);
1690: return(-1);
1691: }
1692: if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) {
1693: dlclose(dl);
1694: return(-1);
1695: }
1696: if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) {
1697: dlclose(dl);
1698: return(-1);
1699: }
1700: if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) {
1701: dlclose(dl);
1702: return(-1);
1703: }
1704: if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) {
1705: dlclose(dl);
1706: return(-1);
1707: }
1708: if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) {
1709: dlclose(dl);
1710: return(-1);
1711: }
1712: if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) {
1713: dlclose(dl);
1714: return(-1);
1715: }
1716: if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) {
1717: dlclose(dl);
1718: return(-1);
1719: }
1720: if((x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) {
1721: dlclose(dl);
1722: return(-1);
1723: }
1724: if((x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) {
1725: dlclose(dl);
1726: return(-1);
1727: }
1728: if((x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) {
1729: dlclose(dl);
1730: return(-1);
1731: }
1732: if((x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) {
1733: dlclose(dl);
1734: return(-1);
1735: }
1736: if((x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) {
1737: dlclose(dl);
1738: return(-1);
1739: }
1740: if((x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) {
1741: dlclose(dl);
1742: return(-1);
1743: }
1744: if((x11.XSetIconName=dlsym(dl,"XSetIconName"))==NULL) {
1745: dlclose(dl);
1746: return(-1);
1747: }
1748: #endif
1749:
1750: sem_init(&console_mode_changed,0,0);
1751: sem_init(©buf_set,0,0);
1752: sem_init(&pastebuf_request,0,0);
1753: sem_init(&pastebuf_set,0,0);
1754: sem_init(&x11_beep,0,0);
1755: sem_init(&x11_title,0,0);
1756: sem_init(&x11_name,0,0);
1757: sem_init(&font_set,0,0);
1758: sem_init(&x11_loadfont,0,0);
1759: sem_init(&x11_fontloaded,0,0);
1760:
1761: pthread_mutex_init(©buf_mutex, NULL);
1762: pthread_mutex_init(&lines_mutex, NULL);
1763:
1764: if(kbd_init()) {
1765: return(-1);
1766: }
1767:
1768: if(video_init()) {
1769: return(-1);
1770: }
1771:
1772: _beginthread(video_async_event,1<<16,NULL);
1773: _beginthread(mouse_event,1<<16,NULL);
1774: return(0);
1775: }
1776:
1777: int
1778: video_init()
1779: {
1780: /* If we are running under X, get a connection to the X server and create
1781: an empty window of size (1, 1). It makes a couple of init functions a
1782: lot easier. */
1783: if(init_window())
1784: return(-1);
1785:
1786: /* Initialize mode 3 (text, 80x25, 16 colors) */
1787: if(init_mode(3)) {
1788: return(-1);
1789: }
1790: sem_wait(&console_mode_changed);
1791:
1792: return(0);
1793: }
1794:
1795: WORD
1796: KbdPeek()
1797: {
1798: return(K_BUF(K_NEXT));
1799: }
1800:
1801: WORD
1802: KbdRead()
1803: {
1804: int kf = K_NEXT;
1805: WORD ret;
1806:
1807: K_NEXT = K_NEXT + 2;
1808: if (K_NEXT == K_BUFENDP)
1809: K_NEXT = K_BUFSTARTP;
1810:
1811: ret=K_BUF(kf);
1812: if(x_pending_mousekeys) {
1813: KbdWrite(CIO_KEY_MOUSE);
1814: x_pending_mousekeys--;
1815: }
1816: return(ret);
1817: }
1818:
1819: int
1820: KbdEmpty(void)
1821: {
1822: return(K_NEXT == K_FREE);
1823: }
1824:
1825: int x_nextchar = 0;
1826:
1827: int
1828: tty_read(int flag)
1829: {
1830: int r;
1831:
1832: if ((r = x_nextchar) != 0) {
1833: x_nextchar = 0;
1834: return(r & 0xff);
1835: }
1836:
1837: if (KbdEmpty()) {
1838: if (flag & TTYF_BLOCK) {
1839: while (KbdEmpty())
1840: tty_pause();
1841: } else {
1842: return(-1);
1843: }
1844: }
1845:
1846: r = KbdRead();
1847: if ((r & 0xff) == 0 || (r & 0xff) == 0xff)
1848: x_nextchar = r >> 8;
1849: r &= 0xff;
1850: return(r & 0xff);
1851: }
1852:
1853: int
1854: tty_peek(int flag)
1855: {
1856: int c;
1857:
1858: if (c == x_nextchar)
1859: return(x_nextchar & 0xff);
1860:
1861: if (KbdEmpty()) {
1862: if (flag & TTYF_POLL) {
1863: sleep_poll();
1864: if (KbdEmpty())
1865: return(0);
1866: } else if (flag & TTYF_BLOCK) {
1867: while (KbdEmpty())
1868: tty_pause();
1869: } else
1870: return(0);
1871: }
1872: c = KbdPeek();
1873: return(0xff);
1874: }
1875:
1876: int
1877: tty_kbhit(void)
1878: {
1879: if(x_nextchar || !KbdEmpty())
1880: return(1);
1881: return(0);
1882: }
1883:
1884: void x_win_title(const char *title)
1885: {
1886: SAFECOPY(window_title,title);
1887: sem_post(&x11_title);
1888: }
1889:
1890: void x_win_name(const char *name)
1891: {
1892: SAFECOPY(window_name,name);
1893: sem_post(&x11_name);
1894: }
1895:
1896: int x_load_font(const char *filename)
1897: {
1898: SAFECOPY(font_filename, filename);
1899: sem_post(&x11_loadfont);
1900: sem_wait(&x11_fontloaded);
1901: return(x_load_font_ret);
1902: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.