Annotation of sbbs/src/conio/console.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1992, 1993, 1996
                      3:  *      Berkeley Software Design, Inc.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *      This product includes software developed by Berkeley Software
                     16:  *      Design, Inc.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
                     19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
                     22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  *
                     30:  * July 22, 1999
                     31:  *
                     32:  * To All Licensees, Distributors of Any Version of BSD:
                     33:  *
                     34:  * As you know, certain of the Berkeley Software Distribution ("BSD") source
                     35:  * code files require that further distributions of products containing all or
                     36:  * portions of the software, acknowledge within their advertising materials
                     37:  * that such products contain software developed by UC Berkeley and its
                     38:  * contributors.
                     39:  * 
                     40:  * Specifically, the provision reads:
                     41:  * 
                     42:  * "     * 3. All advertising materials mentioning features or use of this software
                     43:  *       *    must display the following acknowledgement:
                     44:  *       *    This product includes software developed by the University of
                     45:  *       *    California, Berkeley and its contributors."
                     46:  * 
                     47:  * Effective immediately, licensees and distributors are no longer required to
                     48:  * include the acknowledgement within advertising materials.  Accordingly, the
                     49:  * foregoing paragraph of those BSD Unix files containing it is hereby deleted
                     50:  * in its entirety.
                     51:  * 
                     52:  * William Hoskins
                     53:  * Director, Office of Technology Licensing
                     54:  * University of California, Berkeley
                     55:  *
                     56:  *
                     57:  */ 
                     58: 
                     59: /* $Id: console.c,v 1.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.