|
|
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.