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