Annotation of sbbs/conio/console.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.