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

unix.superglobalmegacorp.com

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