Annotation of sbbs/conio/console.c, revision 1.1.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.