/*
 *  This file is part of x48, an emulator of the HP-48sx Calculator.
 *  Copyright (C) 1994  Eddie C. Dost  (ecd@dressler.de)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* $Log: x48_x11.c,v $
 * Revision 1.13  1995/01/11  18:20:01  ecd
 * major update to support HP48 G/GX
 *
 * Revision 1.12  1994/12/08  22:17:24  ecd
 * display and menu images now correctly drawn according to disp.lines
 *
 * Revision 1.11  1994/12/07  20:20:50  ecd
 * better handling of resources
 *
 * Revision 1.10  1994/11/28  02:00:51  ecd
 * implemented WM_SAVE_YOURSELF protocol.
 * added support for mono and gray in color_t.
 * added support for all possible Visualclasses.
 * changed handling of KeyPress and KeyRelease.
 * added color icon stuff.
 * added support for contrast changes (ON_-, ON_+)
 * read in all those Xresources before running off.
 * use own icon window, no name-decor on icon.
 * show state of x48 in the icon's display
 * added support for setting the window title with the connections.
 *
 * Revision 1.9  1994/11/04  03:42:34  ecd
 * changed includes
 *
 * Revision 1.8  1994/11/02  14:44:28  ecd
 * works on machines that don't support backing store
 *
 * Revision 1.7  1994/10/09  20:32:02  ecd
 * changed refresh_display to support bit offset.
 *
 * Revision 1.6  1994/10/06  16:30:05  ecd
 * added XShm - Extension stuff
 *
 * Revision 1.5  1994/10/05  08:36:44  ecd
 * added backing_store = Always for subwindows
 *
 * Revision 1.4  1994/09/30  12:37:09  ecd
 * added support for interrupt detection in GetEvent,
 * faster display updates,
 * update display window only when mapped.
 *
 * Revision 1.3  1994/09/18  22:47:20  ecd
 * added version information
 *
 * Revision 1.2  1994/09/18  15:29:22  ecd
 * started Real Time support
 *
 * Revision 1.1  1994/09/13  15:05:05  ecd
 * Initial revision
 *
 * $Id: x48_x11.c,v 1.13 1995/01/11 18:20:01 ecd Exp ecd $
 */


#include "global.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/types.h>
#ifdef SYSV
#include <sys/utsname.h>
#endif
#ifdef SUNOS
#include <memory.h>
#endif

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>

#include "hp48.h"
#include "x48_x11.h"
#include "icon.h"
#include "small.h"
#include "buttons.h"
#include "hp.h"

#include "device.h"
#include "constants.h"
#include "options.h"
#include "resources.h"
#include "errors.h"
#include "romio.h"
#include "entriesio.h"
#include "rpl.h"
#include "hp48_emu.h"
#include "gui.h"
#include "disasm.h"
#include "debugger.h"

static char *defaults[] = {
#include "X48.ad.h"
  0
};
#ifdef HAVE_XSHM
extern int XShmQueryExtension __ProtoType__((Display *));
extern int XShmGetEventBase   __ProtoType__((Display *));
static int CompletionType = -1;
#endif

extern int      saved_argc;
extern char   **saved_argv;

Display	       *dpy;
int		screen;
unsigned int	depth;
Colormap	cmap;
GC		gc;
GC		gc_stack;
GC              gc_stack_erase;
Window		mainW;
Window          menuWin;
Window          stackWin;
Window		regWin;
Window          asmWin;
XFontStruct     *DispFont;
Window		iconW = 0;
int             font_height; 
disp_t		disp;
Atom		wm_delete_window, wm_save_yourself, wm_protocols;
Atom		ol_decor_del, ol_decor_icon_name;
Atom		atom_type;
Visual         *visual;
Pixmap		icon_pix;
Pixmap		icon_text_pix;
Pixmap		icon_disp_pix;
static int      last_icon_state = -1;
int             Menu;
int		Register;
int             Stack;
int		Disassembly;

#ifdef HAVE_XSHM
int      shm_flag;
int	 xerror_flag;
#endif

int	 dynamic_color;
int	 direct_color;
int	 does_backing_store;
int	 color_mode;
int	 icon_color_mode;

/* #define DEBUG_XEVENT 1 */
/* #define DEBUG_BUTTONS 1 */
/* #define DEBUG_FOCUS 1 */
/* #define DEBUG_BACKING_STORE 1 */
/* #define DEBUG_SHM 1 */

#define KEYBOARD_HEIGHT (buttons[LAST_BUTTON].y + buttons[LAST_BUTTON].h)
#define KEYBOARD_WIDTH  (buttons[LAST_BUTTON].x + buttons[LAST_BUTTON].w)

#define TOP_SKIP                65
#define SIDE_SKIP               20
#define BOTTOM_SKIP             25
#define DISP_KBD_SKIP           65

#define DISPLAY_WIDTH           (264 + 8)
#define DISPLAY_HEIGHT          (128 + 16 + 8)
#define DISPLAY_OFFSET_X        (SIDE_SKIP+(KEYBOARD_WIDTH-DISPLAY_WIDTH)/2)
#define DISPLAY_OFFSET_Y        TOP_SKIP

#define DISP_FRAME              8

#define KEYBOARD_OFFSET_X       SIDE_SKIP
#define KEYBOARD_OFFSET_Y       (TOP_SKIP + DISPLAY_HEIGHT + DISP_KBD_SKIP)

#define MENUOFFSET_Y            (TOP_SKIP+16)

#define REGSIZE_Y               500;
#define REG_DISPLAY_Y           240;

typedef struct keypad_t {
  unsigned int	width;
  unsigned int	height;
  Pixmap	pixmap;
} keypad_t;

keypad_t  keypad;
keypad_t  menupad;
keypad_t  regpad;
keypad_t  stackpad;
keypad_t  asmpad;

color_t  *colors;

color_t colors_sx[] = {
  { "white", 255, 255, 255, 255, 255,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "left", 255, 166, 0, 255, 230,
     { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "right", 0, 210, 255, 255, 169,
     { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "but_top", 109, 93, 93, 0, 91,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "button", 90, 77, 77, 0, 81,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "but_bot", 76, 65, 65, 0, 69,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "lcd_col", 202, 221, 92, 255, 205,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pix_col", 0, 0, 128, 0, 20,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad_top", 109, 78, 78, 0, 88,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad", 90, 64, 64, 0, 73,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad_bot", 76, 54, 54, 0, 60,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad_top", 155, 118, 84, 0, 124,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad", 124, 94, 67, 0, 99,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad_bot", 100, 75, 53, 0, 79,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "logo", 204, 169, 107, 255, 172,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "logo_back", 64, 64, 64, 0, 65,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "label", 202, 184, 144, 255, 185,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "frame", 0, 0, 0, 255, 0,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "underlay", 60, 42, 42, 0, 48,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "black", 0, 0, 0, 0, 0,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { 0 }
};

color_t colors_gx[] = {
  { "white", 255, 255, 255, 255, 255,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "left", 255, 186, 255, 255, 220,
     { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "right", 0, 255, 204, 255, 169,
     { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "but_top", 104, 104, 104, 0, 104,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "button", 88, 88, 88, 0, 88,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "but_bot", 74, 74, 74, 0, 74,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "lcd_col", 202, 221, 92, 255, 205,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pix_col", 0, 0, 128, 0, 20,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad_top", 88, 88, 88, 0, 88,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad", 74, 74, 74, 0, 74,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "pad_bot", 64, 64, 64, 0, 64,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad_top", 128, 128, 138, 0, 128,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad", 104, 104, 110, 0, 104,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "disp_pad_bot", 84, 84, 90, 0, 84,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "logo", 176, 176, 184, 255, 176,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "logo_back", 104, 104, 110, 0, 104,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "label", 240, 240, 240, 255, 240,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "frame", 0, 0, 0, 255, 0,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "underlay", 104, 104, 110, 0, 104,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { "black", 0, 0, 0, 0, 0,
    { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 } },
  { 0 }
};

typedef struct button_t {

  char		*name;
  short		pressed;
  short		key_down;

  int		code;
  int		x, y;
  unsigned int	w, h;

  int		lc;
  char		*label;
  short		font_size;
  unsigned int	lw, lh;
  unsigned char *lb;

  char		*letter;

  char		*left;
  short		is_menu;
  char		*right;
  char		*sub;

  Pixmap	map;
  Pixmap	down;
  Window	xwin;

} button_t;

#define BUTTON_A	0
#define BUTTON_B	1
#define BUTTON_C	2
#define BUTTON_D	3
#define BUTTON_E	4
#define BUTTON_F	5

#define BUTTON_MTH	6
#define BUTTON_PRG	7
#define BUTTON_CST	8
#define BUTTON_VAR	9
#define BUTTON_UP	10
#define BUTTON_NXT	11

#define BUTTON_COLON	12
#define BUTTON_STO	13
#define BUTTON_EVAL	14
#define BUTTON_LEFT	15
#define BUTTON_DOWN	16
#define BUTTON_RIGHT	17

#define BUTTON_SIN	18
#define BUTTON_COS	19
#define BUTTON_TAN	20
#define BUTTON_SQRT	21
#define BUTTON_POWER	22
#define BUTTON_INV	23

#define BUTTON_ENTER	24
#define BUTTON_NEG	25
#define BUTTON_EEX	26
#define BUTTON_DEL	27
#define BUTTON_BS	28

#define BUTTON_ALPHA	29
#define BUTTON_7	30
#define BUTTON_8	31
#define BUTTON_9	32
#define BUTTON_DIV	33

#define BUTTON_SHL	34
#define BUTTON_4	35
#define BUTTON_5	36
#define BUTTON_6	37
#define BUTTON_MUL	38

#define BUTTON_SHR	39
#define BUTTON_1	40
#define BUTTON_2	41
#define BUTTON_3	42
#define BUTTON_MINUS	43

#define BUTTON_ON	44
#define BUTTON_0	45
#define BUTTON_PERIOD	46
#define BUTTON_SPC	47
#define BUTTON_PLUS	48

#define LAST_BUTTON	48

/*
 * Menu & Debugger Buttons
 */

#define MBUTTON_MENUSTART  0
#define MBUTTON_GOC        0
#define MBUTTON_GOR        1
#define MBUTTON_SPB        2
#define MBUTTON_SPQ        3
#define MBUTTON_SPE        4

#define MBUTTON_DISA       5
#define MBUTTON_DISR       6
#define MBUTTON_DISO       7
#define MBUTTON_LRAM       8
#define MBUTTON_LREG       9
#define MBUTTON_LSTK      10

#define MBUTTON_FIND      11
#define MBUTTON_SEND      12
#define MBUTTON_RECV      13

#define MBUTTON_MENUDONE  13 

#define MBUTTON_REGSTART  15
#define MBUTTON_REGPC     15
#define MBUTTON_REGA      16
#define MBUTTON_REGB      17
#define MBUTTON_REGC      18
#define MBUTTON_REGD      19
#define MBUTTON_REGR0     20
#define MBUTTON_REGR1     21
#define MBUTTON_REGR2     22
#define MBUTTON_REGR3     23
#define MBUTTON_REGR4     24
#define MBUTTON_REGD0     25
#define MBUTTON_REGD1     26
#define MBUTTON_REGIN     27
#define MBUTTON_REGOUT    28
#define MBUTTON_REGCARY   29
#define MBUTTON_REGST     30
#define MBUTTON_REGHST    31

#define MBUTTON_REGDONE   31

#define MBUTTON_STSTART   33
#define MBUTTON_STADDR    33
#define MBUTTON_STTYPE    34
#define MBUTTON_STMORE    35
#define MBUTTON_STLESS    36
#define MBUTTON_STDONE    36

#define MBUTTON_ASMSTART  38
#define MBUTTON_ASMGOC    38
#define MBUTTON_ASMGF     39
#define MBUTTON_ASMGR     40
#define MBUTTON_ASMGS     41
#define MBUTTON_ASMGO     42
#define MBUTTON_ASMGI     43

#define MBUTTON_ASMTE     44
#define MBUTTON_ASMTQ     45
#define MBUTTON_ASMTS     46
#define MBUTTON_ASMQT     47

#define MBUTTON_BADD      48 
#define MBUTTON_BRAG      49
#define MBUTTON_BREG      50
#define MBUTTON_BINT      51
#define MBUTTON_BRPL      52
#define MBUTTON_BCLR      53

#define MBUTTON_ASMDONE   53

button_t *buttons;

button_t buttons_menu[] = {
  { "GoCont"  ,  0, 0, 0x02,   0,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "CONT", 1, 0, 0, 0 },
  { "GoReset" ,  0, 0, 0x03,  50,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "RESET", 1, 0, 0, 0 },
  { "StopBreak", 0, 0, 0x04, 100,   0, 36, 26, WHITE, "STOP", 0, 0, 0, 0, 0, "BREAK", 1, 0, 0, 0},
  { "StopQuit",  0, 0, 0x05, 200,   0, 36, 26, WHITE, "STOP", 0, 0, 0, 0, 0, "QUIT", 1, 0, 0, 0 },
  { "StopExit",  0, 0, 0x06, 250,   0, 36, 26, WHITE, "STOP", 0, 0, 0, 0, 0, "EXIT", 1, 0, 0, 0 },

  { "DisAssembly",  0, 0, 0x0D,   0,  50, 36, 26, WHITE, "DIS",  0, 0, 0, 0, 0, "ASSEMBL", 1, 0, 0, 0 },
  { "DisRPL",       0, 0, 0x0E,  50,  50, 36, 26, WHITE, "DIS",  0, 0, 0, 0, 0, "RPL", 1, 0, 0, 0 },
  { "LookObject",   0, 0, 0x0F, 100,  50, 36, 26, WHITE, "LOOK", 0, 0, 0, 0, 0, "OBJECT", 1, 0, 0, 0 }, 
  { "LookRAM",      0, 0, 0x10, 150,  50, 36, 26, WHITE, "LOOK", 0, 0, 0, 0, 0, "RAM", 1, 0, 0, 0 },
  { "LookREG",      0, 0, 0x11, 200,  50, 36, 26, WHITE, "LOOK", 0, 0, 0, 0, 0, "REGISTER", 1, 0, 0, 0 },
  { "LookStack",    0, 0, 0x12, 250,  50, 36, 26, WHITE, "LOOK", 0, 0, 0, 0, 0, "STACK", 1, 0, 0, 0 },

  { "8th",  0, 0, 0x08,   0,  100, 36, 26, WHITE, 0, 0, menu_label_width, menu_label_height, menu_label_bits, 0, "FIND", 1, 0, 0, 0 },
  { "12th", 0, 0, 0x0c,  50,  100, 36, 26, WHITE, 0, 0, menu_label_width, menu_label_height, menu_label_bits, 0, "SEND", 1, 0, 0, 0 },
  { "13th", 0, 0, 0x0d, 100,  100, 36, 26, WHITE, 0, 0, menu_label_width, menu_label_height, menu_label_bits, 0, "RECEIVE", 1, 0, 0, 0 },

  { 0 },

  { "REG PC",    0, 0, 0,   0,   0, 36, 26, WHITE, "PC", 0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG A",     0, 0, 0,  50,   0, 36, 26, WHITE, "A",  0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG B",     0, 0, 0, 100,   0, 36, 26, WHITE, "B",  0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG C",     0, 0, 0, 150,   0, 36, 26, WHITE, "C",  0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG D",     0, 0, 0, 200,   0, 36, 26, WHITE, "D",  0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG R0",    0, 0, 0, 250,   0, 36, 26, WHITE, "R0", 0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG R1",    0, 0, 0,   0,  50, 36, 26, WHITE, "R1", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG R2",    0, 0, 0,  50,  50, 36, 26, WHITE, "R2", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG R3",    0, 0, 0, 100,  50, 36, 26, WHITE, "R3", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG R4",    0, 0, 0, 150,  50, 36, 26, WHITE, "R4", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG D0",    0, 0, 0, 200,  50, 36, 26, WHITE, "D0", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG D1",    0, 0, 0, 250,  50, 36, 26, WHITE, "D1", 0, 0, 0, 0, 0, 
     "SHOW", 0, "SET", 0, 0 },
  { "REG IN",    0, 0, 0,   0, 100, 36, 26, WHITE, "IN",  0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG OUT",   0, 0, 0,  50, 100, 36, 26, WHITE, "OUT", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG Carry", 0, 0, 0, 100, 100, 36, 26, WHITE, "CAR", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG ST",    0, 0, 0, 150, 100, 36, 26, WHITE, "ST",  0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },
  { "REG HST",   0, 0, 0, 200, 100, 36, 26, WHITE, "HST", 0, 0, 0, 0, 0,
     "SHOW", 0, "SET", 0, 0 },

  { 0 },

  { "StAddr",  0, 0, 0x01,   0,   0, 36, 26, WHITE, "ADDR", 0, 0, 0, 0,
       0, "FINISH", 1, 0, 0, 0 },
  { "StType"  ,  0, 0, 0x01,  50,   0, 36, 26, WHITE, "TYPE", 0, 0, 0, 0,
       0, "CONT", 1, 0, 0, 0 },
  { "StMore" ,  0, 0, 0x00, 100,   0, 36, 26, WHITE, "MORE", 0, 0, 0, 0,
       0, "RESET", 1, 0, 0, 0 },
  { "StLess", 0, 0, 0x00, 150,   0, 36, 26, WHITE, "LESS", 0, 0, 0, 0,
       0, "BREAK", 1, 0, 0, 0},

  { 0 },

  { "GoCont",   0, 0, 0x01,   0,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "CONT",   1, 0, 0, 0 },
  { "GoFinish", 0, 0, 0x02,  50,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "FINISH", 1, 0, 0, 0 },
  { "GoReset" , 0, 0, 0x03, 100,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "RESET",  1, 0, 0, 0 },
  { "GoStep",   0, 0,    4, 150,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "STEP",   1, 0, 0, 0 },
  { "GoOver",   0, 0,    5, 200,   0, 36, 26, WHITE, "GO", 0, 0, 0, 0, 0, "OVER",   1, 0, 0, 0 },
  { "GoIn",     0, 0,    6, 250,   0, 36, 26, WHITE, "GO",  0, 0, 0, 0, 0,"aIN",   1, 0, 0, 0 },

  { "TermExit", 0, 0, 0x01, 300  ,  0, 36, 26, WHITE, "TERM", 0, 0, 0, 0, 0, "EXIT",   1, 0, 0, 0 },
  { "TermQuit", 0, 0, 0x01, 350,  0, 36, 26, WHITE, "TERM", 0, 0, 0, 0, 0, "QUIT",   1, 0, 0, 0 },
  { "SaveTrace",0, 0, 0x01, 100,  50, 36, 26, WHITE, "SAVE", 0, 0, 0, 0, 0, "TRACE",   1, 0, 0, 0 },
  { "QuitTrace",0, 0, 0x01, 150,  50, 36, 26, WHITE, "STOP", 0, 0, 0, 0, 0, "TRACE",   1, 0, 0, 0 },

  { "BreakAddress",     0, 0, 0x07,   0,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "ADDRESS", 1, 0, 0, 0 },
  { "BreakRange",       0, 0, 0x08,  50,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "RANGE", 1, 0, 0, 0 },
  { "BreakRegister",    0, 0, 0x09, 100,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "REGISTER", 1, 0, 0, 0 },
  { "BreakInstruction", 0, 0, 0x0A, 150,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "INSTRUCT", 1, 0, 0, 0 },
  { "BreakRPL",         0, 0, 0x0B, 200,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "RPL", 1, 0, 0, 0 },
  { "BreakClear",       0, 0, 0x0C, 250,100, 36, 26, WHITE, "BRK", 0, 0, 0, 0, 0, "CLEAR", 1, 0, 0, 0 },

  { 0 }
};
 
button_t buttons_sx[] = {
  { "A", 0, 0, 0x14,  0, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "A", 0, 0, 0, 0, 0 },
  { "B", 0, 0, 0x84,  50, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "B", 0, 0, 0, 0, 0 },
  { "C", 0, 0, 0x83, 100, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "C", 0, 0, 0, 0, 0 },
  { "D", 0, 0, 0x82, 150, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "D", 0, 0, 0, 0, 0 },
  { "E", 0, 0, 0x81, 200, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "E", 0, 0, 0, 0, 0 },
  { "F", 0, 0, 0x80, 250, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "F", 0, 0, 0, 0, 0 },

  { "MTH", 0, 0, 0x24,  0, 50, 36, 26, WHITE, "MTH", 0, 0, 0, 0,
    "G", "PRINT", 1, 0, 0, 0 },
  { "PRG", 0, 0, 0x74,  50, 50, 36, 26, WHITE, "PRG", 0, 0, 0, 0,
    "H", "I/O", 1, 0, 0, 0 },
  { "CST", 0, 0, 0x73, 100, 50, 36, 26, WHITE, "CST", 0, 0, 0, 0,
    "I", "MODES", 1, 0, 0, 0 },
  { "VAR", 0, 0, 0x72, 150, 50, 36, 26, WHITE, "VAR", 0, 0, 0, 0,
    "J", "MEMORY", 1, 0, 0, 0 },
  { "UP", 0, 0, 0x71, 200, 50, 36, 26, WHITE,
     0, 0, up_width, up_height, up_bits,
    "K", "LIBRARY", 1, 0, 0, 0 },
  { "NXT", 0, 0, 0x70, 250, 50, 36, 26, WHITE, "NXT", 0, 0, 0, 0,
    "L", "PREV", 0, 0, 0, 0 },

  { "COLON", 0, 0, 0x04,  0, 100, 36, 26, WHITE,
     0, 0, colon_width, colon_height, colon_bits,
    "M", "UP", 0, "HOME", 0, 0 },
  { "STO", 0, 0, 0x64,  50, 100, 36, 26, WHITE, "STO", 0, 0, 0, 0,
    "N", "DEF", 0, "RCL", 0, 0 },
  { "EVAL", 0, 0, 0x63, 100, 100, 36, 26, WHITE, "EVAL", 0, 0, 0, 0,
    "O", "aQ", 0, "aNUM", 0, 0 },
  { "LEFT", 0, 0, 0x62, 150, 100, 36, 26, WHITE,
     0, 0, left_width, left_height, left_bits,
    "P", "GRAPH", 0, 0, 0, 0 },
  { "DOWN", 0, 0, 0x61, 200, 100, 36, 26, WHITE,
     0, 0, down_width, down_height, down_bits,
    "Q", "REVIEW", 0, 0, 0, 0 },
  { "RIGHT", 0, 0, 0x60, 250, 100, 36, 26, WHITE,
     0, 0, right_width, right_height, right_bits,
    "R", "SWAP", 0, 0, 0, 0 },

  { "SIN", 0, 0, 0x34,  0, 150, 36, 26, WHITE, "SIN", 0, 0, 0, 0,
    "S", "ASIN", 0, "b", 0, 0 },
  { "COS", 0, 0, 0x54,  50, 150, 36, 26, WHITE, "COS", 0, 0, 0, 0,
    "T", "ACOS", 0, "c", 0, 0 },
  { "TAN", 0, 0, 0x53,  100, 150, 36, 26, WHITE, "TAN", 0, 0, 0, 0,
    "U", "ATAN", 0, "d", 0, 0 },
  { "SQRT", 0, 0, 0x52,  150, 150, 36, 26, WHITE,
     0, 0, sqrt_width, sqrt_height, sqrt_bits,
    "V", "e", 0, "f", 0, 0 },
  { "POWER", 0, 0, 0x51,  200, 150, 36, 26, WHITE,
     0, 0, power_width, power_height, power_bits,
    "W", "g", 0, "LOG", 0, 0 },
  { "INV", 0, 0, 0x50,  250, 150, 36, 26, WHITE,
     0, 0, inv_width, inv_height, inv_bits,
    "X", "h", 0, "LN", 0, 0 },

  { "ENTER", 0, 0, 0x44, 0, 200, 86, 26, WHITE, "ENTER", 2, 0, 0, 0,
     0, "EQUATION", 0, "MATRIX", 0, 0 },
  { "NEG", 0, 0, 0x43, 100, 200, 36, 26, WHITE,
     0, 0, neg_width, neg_height, neg_bits,
    "Y", "EDIT", 0, "VISIT", 0, 0 },
  { "EEX", 0, 0, 0x42, 150, 200, 36, 26, WHITE, "EEX", 0, 0, 0, 0,
    "Z", "2D", 0, "3D", 0, 0 },
  { "DEL", 0, 0, 0x41, 200, 200, 36, 26, WHITE, "DEL", 0, 0, 0, 0,
     0, "PURGE", 0, 0, 0, 0 },
  { "BS", 0, 0, 0x40, 250, 200, 36, 26, WHITE,
     0, 0, bs_width, bs_height, bs_bits,
     0, "DROP", 0, "CLR", 0, 0 },

  { "ALPHA", 0, 0, 0x35, 0, 250, 36, 26, WHITE,
     0, 0, alpha_width, alpha_height, alpha_bits,
     0, "USR", 0, "ENTRY", 0, 0 },
  { "7", 0, 0, 0x33, 60, 250, 46, 26, WHITE, "7", 1, 0, 0, 0,
     0, "SOLVE", 1, 0, 0, 0 },
  { "8", 0, 0, 0x32, 120, 250, 46, 26, WHITE, "8", 1, 0, 0, 0,
     0, "PLOT", 1, 0, 0, 0 },
  { "9", 0, 0, 0x31, 180, 250, 46, 26, WHITE, "9", 1, 0, 0, 0,
     0, "ALGEBRA", 1, 0, 0, 0 },
  { "DIV", 0, 0, 0x30, 240, 250, 46, 26, WHITE,
     0, 0, div_width, div_height, div_bits,
     0, "( )", 0, "#", 0, 0 },

  { "SHL", 0, 0, 0x25, 0, 300, 36, 26, LEFT,
     0, 0, shl_width, shl_height, shl_bits,
     0, 0, 0, 0, 0, 0 },
  { "4", 0, 0, 0x23, 60, 300, 46, 26, WHITE, "4", 1, 0, 0, 0,
     0, "TIME", 1, 0, 0, 0 },
  { "5", 0, 0, 0x22, 120, 300, 46, 26, WHITE, "5", 1, 0, 0, 0,
     0, "STAT", 1, 0, 0, 0 },
  { "6", 0, 0, 0x21, 180, 300, 46, 26, WHITE, "6", 1, 0, 0, 0,
     0, "UNITS", 1, 0, 0, 0 },
  { "MUL", 0, 0, 0x20, 240, 300, 46, 26, WHITE,
     0, 0, mul_width, mul_height, mul_bits,
     0, "[ ]", 0, "_", 0, 0 },

  { "SHR", 0, 0, 0x15, 0, 350, 36, 26, RIGHT,
     0, 0, shr_width, shr_height, shr_bits,
     0, 0, 0, 0, 0, 0 },
  { "1", 0, 0, 0x13, 60, 350, 46, 26, WHITE, "1", 1, 0, 0, 0,
     0, "RAD", 0, "POLAR", 0, 0 },
  { "2", 0, 0, 0x12, 120, 350, 46, 26, WHITE, "2", 1, 0, 0, 0,
     0, "STACK", 0, "ARG", 0, 0 },
  { "3", 0, 0, 0x11, 180, 350, 46, 26, WHITE, "3", 1, 0, 0, 0,
     0, "CMD", 0, "MENU", 0, 0 },
  { "MINUS", 0, 0, 0x10, 240, 350, 46, 26, WHITE,
     0, 0, minus_width, minus_height, minus_bits,
     0, "i", 0, "j", 0, 0 },

  { "ON", 0, 0, 0x8000, 0, 400, 36, 26, WHITE, "ON", 0, 0, 0, 0,
     0, "CONT", 0, "OFF", "ATTN", 0 },
  { "0", 0, 0, 0x03, 60, 400, 46, 26, WHITE, "0", 1, 0, 0, 0,
     0, "= ", 0, " a", 0, 0 },
  { "PERIOD", 0, 0, 0x02, 120, 400, 46, 26, WHITE, ".", 1, 0, 0, 0,
     0, ", ", 0, " k", 0, 0 },
  { "SPC", 0, 0, 0x01, 180, 400, 46, 26, WHITE, "SPC", 0, 0, 0, 0,
     0, "l ", 0, " m", 0, 0 },
  { "PLUS", 0, 0, 0x00, 240, 400, 46, 26, WHITE,
     0, 0, plus_width, plus_height, plus_bits,
     0, "{ }", 0, ": :", 0, 0 },

  { 0 }
};

button_t buttons_gx[] = {
  { "A", 0, 0, 0x14,  0, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "A", 0, 0, 0, 0, 0 },
  { "B", 0, 0, 0x84,  50, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "B", 0, 0, 0, 0, 0 },
  { "C", 0, 0, 0x83, 100, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "C", 0, 0, 0, 0, 0 },
  { "D", 0, 0, 0x82, 150, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "D", 0, 0, 0, 0, 0 },
  { "E", 0, 0, 0x81, 200, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "E", 0, 0, 0, 0, 0 },
  { "F", 0, 0, 0x80, 250, 0, 36, 23, WHITE,
     0, 0, menu_label_width, menu_label_height, menu_label_bits,
    "F", 0, 0, 0, 0, 0 },

  { "MTH", 0, 0, 0x24,  0, 50, 36, 26, WHITE, "MTH", 0, 0, 0, 0,
    "G", "RAD", 0, "POLAR", 0, 0 },
  { "PRG", 0, 0, 0x74,  50, 50, 36, 26, WHITE, "PRG", 0, 0, 0, 0,
    "H", 0, 0, "CHARS", 0, 0 },
  { "CST", 0, 0, 0x73, 100, 50, 36, 26, WHITE, "CST", 0, 0, 0, 0,
    "I", 0, 0, "MODES", 0, 0 },
  { "VAR", 0, 0, 0x72, 150, 50, 36, 26, WHITE, "VAR", 0, 0, 0, 0,
    "J", 0, 0, "MEMORY", 0, 0 },
  { "UP", 0, 0, 0x71, 200, 50, 36, 26, WHITE,
     0, 0, up_width, up_height, up_bits,
    "K", 0, 0, "STACK", 0, 0 },
  { "NXT", 0, 0, 0x70, 250, 50, 36, 26, WHITE, "NXT", 0, 0, 0, 0,
    "L", "PREV", 0, "MENU", 0, 0 },

  { "COLON", 0, 0, 0x04,  0, 100, 36, 26, WHITE,
     0, 0, colon_width, colon_height, colon_bits,
    "M", "UP", 0, "HOME", 0, 0 },
  { "STO", 0, 0, 0x64,  50, 100, 36, 26, WHITE, "STO", 0, 0, 0, 0,
    "N", "DEF", 0, "RCL", 0, 0 },
  { "EVAL", 0, 0, 0x63, 100, 100, 36, 26, WHITE, "EVAL", 0, 0, 0, 0,
    "O", "aNUM", 0, "UNDO", 0, 0 },
  { "LEFT", 0, 0, 0x62, 150, 100, 36, 26, WHITE,
     0, 0, left_width, left_height, left_bits,
    "P", "PICTURE", 0, 0, 0, 0 },
  { "DOWN", 0, 0, 0x61, 200, 100, 36, 26, WHITE,
     0, 0, down_width, down_height, down_bits,
    "Q", "VIEW", 0, 0, 0, 0 },
  { "RIGHT", 0, 0, 0x60, 250, 100, 36, 26, WHITE,
     0, 0, right_width, right_height, right_bits,
    "R", "SWAP", 0, 0, 0, 0 },

  { "SIN", 0, 0, 0x34,  0, 150, 36, 26, WHITE, "SIN", 0, 0, 0, 0,
    "S", "ASIN", 0, "b", 0, 0 },
  { "COS", 0, 0, 0x54,  50, 150, 36, 26, WHITE, "COS", 0, 0, 0, 0,
    "T", "ACOS", 0, "c", 0, 0 },
  { "TAN", 0, 0, 0x53,  100, 150, 36, 26, WHITE, "TAN", 0, 0, 0, 0,
    "U", "ATAN", 0, "d", 0, 0 },
  { "SQRT", 0, 0, 0x52,  150, 150, 36, 26, WHITE,
     0, 0, sqrt_width, sqrt_height, sqrt_bits,
    "V", "n", 0, "o", 0, 0 },
  { "POWER", 0, 0, 0x51,  200, 150, 36, 26, WHITE,
     0, 0, power_width, power_height, power_bits,
    "W", "p", 0, "LOG", 0, 0 },
  { "INV", 0, 0, 0x50,  250, 150, 36, 26, WHITE,
     0, 0, inv_width, inv_height, inv_bits,
    "X", "q", 0, "LN", 0, 0 },

  { "ENTER", 0, 0, 0x44, 0, 200, 86, 26, WHITE, "ENTER", 2, 0, 0, 0,
     0, "EQUATION", 0, "MATRIX", 0, 0 },
  { "NEG", 0, 0, 0x43, 100, 200, 36, 26, WHITE,
     0, 0, neg_width, neg_height, neg_bits,
    "Y", "EDIT", 0, "CMD", 0, 0 },
  { "EEX", 0, 0, 0x42, 150, 200, 36, 26, WHITE, "EEX", 0, 0, 0, 0,
    "Z", "PURG", 0, "ARG", 0, 0 },
  { "DEL", 0, 0, 0x41, 200, 200, 36, 26, WHITE, "DEL", 0, 0, 0, 0,
     0, "CLEAR", 0, 0, 0, 0 },
  { "BS", 0, 0, 0x40, 250, 200, 36, 26, WHITE,
     0, 0, bs_width, bs_height, bs_bits,
     0, "DROP", 0, 0, 0, 0 },

  { "ALPHA", 0, 0, 0x35, 0, 250, 36, 26, WHITE,
     0, 0, alpha_width, alpha_height, alpha_bits,
     0, "USER", 0, "ENTRY", 0, 0 },
  { "7", 0, 0, 0x33, 60, 250, 46, 26, WHITE, "7", 1, 0, 0, 0,
     0, 0, 1, "SOLVE", 0, 0 },
  { "8", 0, 0, 0x32, 120, 250, 46, 26, WHITE, "8", 1, 0, 0, 0,
     0, 0, 1, "PLOT", 0, 0 },
  { "9", 0, 0, 0x31, 180, 250, 46, 26, WHITE, "9", 1, 0, 0, 0,
     0, 0, 1, "SYMBOLIC", 0, 0 },
  { "DIV", 0, 0, 0x30, 240, 250, 46, 26, WHITE,
     0, 0, div_width, div_height, div_bits,
     0, "r ", 0, "s", 0, 0 },

  { "SHL", 0, 0, 0x25, 0, 300, 36, 26, LEFT,
     0, 0, shl_width, shl_height, shl_bits,
     0, 0, 0, 0, 0, 0 },
  { "4", 0, 0, 0x23, 60, 300, 46, 26, WHITE, "4", 1, 0, 0, 0,
     0, 0, 1, "TIME", 0, 0 },
  { "5", 0, 0, 0x22, 120, 300, 46, 26, WHITE, "5", 1, 0, 0, 0,
     0, 0, 1, "STAT", 0, 0 },
  { "6", 0, 0, 0x21, 180, 300, 46, 26, WHITE, "6", 1, 0, 0, 0,
     0, 0, 1, "UNITS", 0, 0 },
  { "MUL", 0, 0, 0x20, 240, 300, 46, 26, WHITE,
     0, 0, mul_width, mul_height, mul_bits,
     0, "t ", 0, "u", 0, 0 },

  { "SHR", 0, 0, 0x15, 0, 350, 36, 26, RIGHT,
     0, 0, shr_width, shr_height, shr_bits,
     0, 0, 1, " ", 0, 0 },
  { "1", 0, 0, 0x13, 60, 350, 46, 26, WHITE, "1", 1, 0, 0, 0,
     0, 0, 1, "I/O", 0, 0 },
  { "2", 0, 0, 0x12, 120, 350, 46, 26, WHITE, "2", 1, 0, 0, 0,
     0, 0, 1, "LIBRARY", 0, 0 },
  { "3", 0, 0, 0x11, 180, 350, 46, 26, WHITE, "3", 1, 0, 0, 0,
     0, 0, 1, "EQ LIB", 0, 0 },
  { "MINUS", 0, 0, 0x10, 240, 350, 46, 26, WHITE,
     0, 0, minus_width, minus_height, minus_bits,
     0, "v ", 0, "w", 0, 0 },

  { "ON", 0, 0, 0x8000, 0, 400, 36, 26, WHITE, "ON", 0, 0, 0, 0,
     0, "CONT", 0, "OFF", "CANCEL", 0 },
  { "0", 0, 0, 0x03, 60, 400, 46, 26, WHITE, "0", 1, 0, 0, 0,
     0, "\004 ", 0, "\003", 0, 0 },
  { "PERIOD", 0, 0, 0x02, 120, 400, 46, 26, WHITE, ".", 1, 0, 0, 0,
     0, "\002 ", 0, "\001", 0, 0 },
  { "SPC", 0, 0, 0x01, 180, 400, 46, 26, WHITE, "SPC", 0, 0, 0, 0,
     0, "\005 ", 0, "z", 0, 0 },
  { "PLUS", 0, 0, 0x00, 240, 400, 46, 26, WHITE,
     0, 0, plus_width, plus_height, plus_bits,
     0, "x ", 0, "y", 0, 0 },

  { 0 }
};

typedef struct icon_t {
  unsigned int   w;
  unsigned int   h;
  int            c;
  unsigned char *bits;
} icon_map_t;

#define ICON_MAP  0
#define ON_MAP    1
#define DISP_MAP  2
#define FIRST_MAP 3
#define LAST_MAP  9

icon_map_t *icon_maps;

icon_map_t icon_maps_sx[] = {
  { hp48_icon_width, hp48_icon_height, BLACK, hp48_icon_bits },
  { hp48_on_width, hp48_on_height, PIXEL, hp48_on_bits },
  { hp48_disp_width, hp48_disp_height, LCD, hp48_disp_bits },
  { hp48_top_width, hp48_top_height, DISP_PAD, hp48_top_bits },
  { hp48_bottom_width, hp48_bottom_height, PAD, hp48_bottom_bits },
  { hp48_logo_width, hp48_logo_height, LOGO, hp48_logo_bits },
  { hp48_text_width, hp48_text_height, LABEL, hp48_text_bits },
  { hp48_keys_width, hp48_keys_height, BLACK, hp48_keys_bits }, 
  { hp48_orange_width, hp48_orange_height, LEFT, hp48_orange_bits },
  { hp48_blue_width, hp48_blue_height, RIGHT, hp48_blue_bits }
};

icon_map_t icon_maps_gx[] = {
  { hp48_icon_width, hp48_icon_height, BLACK, hp48_icon_bits },
  { hp48_on_width, hp48_on_height, PIXEL, hp48_on_bits },
  { hp48_disp_width, hp48_disp_height, LCD, hp48_disp_bits },
  { hp48_top_gx_width, hp48_top_gx_height, DISP_PAD, hp48_top_gx_bits },
  { hp48_bottom_width, hp48_bottom_height, PAD, hp48_bottom_bits },
  { hp48_logo_gx_width, hp48_logo_gx_height, LOGO, hp48_logo_gx_bits },
  { hp48_text_gx_width, hp48_text_gx_height, LABEL, hp48_text_gx_bits },
  { hp48_keys_width, hp48_keys_height, BLACK, hp48_keys_bits }, 
  { hp48_orange_width, hp48_orange_height, LEFT, hp48_orange_bits },
  { hp48_green_gx_width, hp48_green_gx_height, RIGHT, hp48_green_gx_bits }
};

int
#ifdef __FunctionProto__
AllocColors(void)
#else
AllocColors()
#endif
{
  int c, error, dyn;
  int r_shift = 0, g_shift = 0, b_shift = 0;
  XSetWindowAttributes xswa;

  error = -1;
  dyn = dynamic_color;

  if (direct_color)
    {
      while (!(visual->red_mask & (1 << r_shift)))
        r_shift++;
      while (visual->red_mask & (1 << r_shift))
        r_shift++;
      r_shift = 16 - r_shift;
      while (!(visual->green_mask & (1 << g_shift)))
        g_shift++;
      while ((visual->green_mask & (1 << g_shift)))
        g_shift++;
      g_shift = 16 - g_shift;
      while (!(visual->blue_mask & (1 << b_shift)))
        b_shift++;
      while ((visual->blue_mask & (1 << b_shift)))
        b_shift++;
      b_shift = 16 - b_shift;
    }

  for (c = WHITE; c <= BLACK; c++) {
    switch (color_mode)
    {
      case COLOR_MODE_MONO:
        colors[c].xcolor.red = colors[c].mono_rgb << 8;
        colors[c].xcolor.green = colors[c].mono_rgb << 8;
        colors[c].xcolor.blue = colors[c].mono_rgb << 8;
        break;
      case COLOR_MODE_GRAY:
        colors[c].xcolor.red = colors[c].gray_rgb << 8;
        colors[c].xcolor.green = colors[c].gray_rgb << 8;
        colors[c].xcolor.blue = colors[c].gray_rgb << 8;
        break;
      default:
        colors[c].xcolor.red = colors[c].r << 8;
        colors[c].xcolor.green = colors[c].g << 8;
        colors[c].xcolor.blue = colors[c].b << 8;
        break;
    }
    if (direct_color)
      {
        colors[c].xcolor.pixel =
                   ((colors[c].xcolor.red >> r_shift) & visual->red_mask) |
                   ((colors[c].xcolor.green >> g_shift) & visual->green_mask) |
                   ((colors[c].xcolor.blue >> b_shift) & visual->blue_mask);
        XStoreColor(dpy, cmap, &colors[c].xcolor);
      }
    else
      {
        if (dynamic_color && c == PIXEL)
          {
            if (XAllocColorCells(dpy, cmap, True, (unsigned long *)0, 0,
                                 &colors[c].xcolor.pixel, 1) == 0)
              {
                dyn = 0;
                if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
                  {
                    if (!quiet)
                      fprintf(stderr, "%s: XAllocColor failed.\n", progname);
                    error = c;
                    break;
                  }
              }
            else if (colors[c].xcolor.pixel >= visual->map_entries)
	      {
                dyn = 0;
                if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
                  {
                    if (!quiet)
                      fprintf(stderr, "%s: XAllocColor failed.\n", progname);
                    error = c;
                    break;
                  }
              }
            else
              {
                XStoreColor(dpy, cmap, &colors[c].xcolor);
              }
          }
        else {
          if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
            {
              if (!quiet)
                fprintf(stderr, "%s: XAllocColor failed.\n", progname);
              error = c;
              break;
            }
        }
    }
  }

  /*
   * Can't be reached when visual->class == DirectColor
   */

  if (error != -1)
    {
      if (!quiet)
        fprintf(stderr, "%s: Using own Colormap.\n", progname);
      /*
       * free colors so far allocated
       */
      for (c = WHITE; c < error; c++)
        {
          XFreeColors(dpy, cmap, &colors[c].xcolor.pixel, 1, 0);
        }

      /*
       * Create my own Colormap
       */
      cmap = XCreateColormap(dpy, mainW, visual, AllocNone);
      if (cmap == (Colormap)0)
        {
          sprintf(errbuf, "can\'t alloc Colormap.\n");
          fatal_exit();
        }
      xswa.colormap = cmap;
      XChangeWindowAttributes(dpy, mainW, CWColormap, &xswa);
      if (iconW)
        XChangeWindowAttributes(dpy, iconW, CWColormap, &xswa);

      /*
       * Try to allocate colors again
       */
      dyn = dynamic_color;
      for (c = WHITE; c <= BLACK; c++) {
        switch (color_mode)
        {
          case COLOR_MODE_MONO:
            colors[c].xcolor.red = colors[c].mono_rgb << 8;
            colors[c].xcolor.green = colors[c].mono_rgb << 8;
            colors[c].xcolor.blue = colors[c].mono_rgb << 8;
            break;
          case COLOR_MODE_GRAY:
            colors[c].xcolor.red = colors[c].gray_rgb << 8;
            colors[c].xcolor.green = colors[c].gray_rgb << 8;
            colors[c].xcolor.blue = colors[c].gray_rgb << 8;
            break;
          default:
            colors[c].xcolor.red = colors[c].r << 8;
            colors[c].xcolor.green = colors[c].g << 8;
            colors[c].xcolor.blue = colors[c].b << 8;
            break;
        }
        if (dynamic_color && c == PIXEL) {
          if (XAllocColorCells(dpy, cmap, True, (unsigned long *)0, 0,
                               &colors[c].xcolor.pixel, 1) == 0)
            {
              dyn = 0;
              if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
                {
                  sprintf(errbuf, "can\'t alloc Color.\n");
                  fatal_exit();
                }
            }
          else if (colors[c].xcolor.pixel >= visual->map_entries)
	    {
              dyn = 0;
              if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
                {
                  sprintf(errbuf, "can\'t alloc Color.\n");
                  fatal_exit();
                }
            }
          else
            {
              XStoreColor(dpy, cmap, &colors[c].xcolor);
            }
        } else {
          if (XAllocColor(dpy, cmap, &colors[c].xcolor) == 0)
            {
              sprintf(errbuf, "can\'t alloc Color.\n");
              fatal_exit();
            }
        }
      }
    }

  dynamic_color = dyn;
  return 0;
}

void
#ifdef __FunctionProto__
adjust_contrast(int contrast)
#else
adjust_contrast(contrast)
int contrast;
#endif
{
  int  gray = 0;
  int  r = 0, g = 0, b = 0;
  unsigned long old;

  if (contrast < 0x3) contrast = 0x3;
  if (contrast > 0x13) contrast = 0x13;

  old = colors[PIXEL].xcolor.pixel;
  switch (color_mode)
  {
    case COLOR_MODE_MONO:
      return;
    case COLOR_MODE_GRAY:
      gray = (0x13 - contrast) * (colors[LCD].gray_rgb / 0x10);
      colors[PIXEL].xcolor.red = gray << 8;
      colors[PIXEL].xcolor.green = gray << 8;
      colors[PIXEL].xcolor.blue = gray << 8;
      break;
    default:
      r = (0x13 - contrast) * (colors[LCD].r / 0x10);
      g = (0x13 - contrast) * (colors[LCD].g / 0x10);
      b = 128 - ((0x13 - contrast) * ((128 - colors[LCD].b) / 0x10));
      colors[PIXEL].xcolor.red = r << 8;
      colors[PIXEL].xcolor.green = g << 8;
      colors[PIXEL].xcolor.blue = b << 8;
      break;
  }
  if (direct_color)
    {
      colors[PIXEL].gray_rgb = gray;
      colors[PIXEL].r = r;
      colors[PIXEL].g = g;
      colors[PIXEL].b = b;
      AllocColors();
      XSetForeground(dpy, disp.gc, COLOR(PIXEL));
#ifdef HAVE_XSHM
      disp.display_update = UPDATE_DISP | UPDATE_MENU;
      refresh_display();
#else
      redraw_display();
#endif
      redraw_annunc();
      last_icon_state = -1;
      refresh_icon();
    }
  else if (dynamic_color)
    {
      XStoreColor(dpy, cmap, &colors[PIXEL].xcolor);
    }
  else
    {
      if (XAllocColor(dpy, cmap, &colors[PIXEL].xcolor) == 0)
        {
          colors[PIXEL].xcolor.pixel = old;
          if (!quiet)
            fprintf(stderr, "%s: warning: can\'t alloc new pixel color.\n",
                    progname);
        }
      else
        {
          XFreeColors(dpy, cmap, &old, 1, 0);
          XSetForeground(dpy, disp.gc, COLOR(PIXEL));
#ifdef HAVE_XSHM
          disp.display_update = UPDATE_DISP | UPDATE_MENU;
          refresh_display();
#else
          redraw_display();
#endif
          redraw_annunc();
          last_icon_state = -1;
          refresh_icon();
        }
    }
}

int
#ifdef __FunctionProto__
merge_app_defaults(char *path, XrmDatabase *db)
#else
merge_app_defaults(path, db)
char        *path;
XrmDatabase *db;
#endif
{
  char        file[1024];
  XrmDatabase tmp;

  if (path == (char *)0)
    return 0;

  sprintf(file, "%s/%s", path, res_class);

  tmp = XrmGetFileDatabase(file);
  if (tmp == (XrmDatabase)0)
    return 0;

  XrmMergeDatabases(tmp, db);

  return 1;
}

int
#ifdef __FunctionProto__
InitDisplay(int argc, char **argv)
#else
InitDisplay(argc, argv)
int    argc;
char **argv;
#endif
{
  XrmDatabase    cmd = NULL, tmp = NULL;
  char          *res, *s;
  char           buf[1024], home[1024];
  int            def, i;
  struct passwd *pwd;
#ifdef SYSV
  struct utsname uts;
#else
  char           hostname[128];
#endif

  /*
   * Parse the command line
   */
  XrmInitialize();
  XrmParseCommand(&cmd, options, sizeof(options)/sizeof(*options),
                  progname, &argc, argv);

  if ((argc == 2) && !strcmp(argv[1], "-help"))
    usage();
  else if (argc > 1)
    {
      fprintf(stderr, "%s: unknown option %s or missing argument\n",
              progname, argv[1]);
      usage();
    }

  res_name = progname;
  res_class = strdup(res_name);
  *res_class = islower(*res_class) ? _toupper(*res_class) : *res_class;

  /*
   * look for argument -name
   */
  res = get_string_resource_from_db(cmd, "name", "Name");
  if (res)
    {
      if (!(res_name = strdup(res)))
        {
          sprintf(errbuf, "out of memory in InitDisplay()\n");
          fatal_exit();
        }

      for (s = res_name; *s; s++)
        *s = isupper(*s) ? _tolower(*s) : *s;

      free(res_class);
      res_class = strdup(res_name);
      *res_class = islower(*res_class) ? _toupper(*res_class) : *res_class;

      argc = saved_argc;
      argv = (char **)malloc((argc + 1) * sizeof(char *));
      if (argv == (char **)0)
        {
          sprintf(errbuf, "out of memory in InitDisplay()\n");
          fatal_exit();
        }
      argv[argc] = (char *)0;
      for (i = 0; i < argc; i++)
        argv[i] = saved_argv[i];

      XrmParseCommand(&cmd, options, sizeof(options)/sizeof(*options),
                      res_name, &argc, argv);
    }

  /*
   * Open the display
   */
  res = get_string_resource_from_db(cmd, "display", "Display");

  dpy = XOpenDisplay(res);
  if (dpy == (Display *)0)
    {
      if (res)
        {
          if (!quiet)
            fprintf(stderr, "%s: can\'t open display %s\n", progname, res);
        }
      else
        {
          if (!quiet)
            fprintf(stderr, "%s: can\'t open display\n", progname);
        }
      return -1;
    }

  /*
   * Load all those Resources.
   *
   * 1. Hardcoded Defaults
   *
   * 2. /usr/lib/X11/app-defaults/X48
   *
   * 3. Values in $XUSERFILESEARCHPATH/X48 or, if not set,
   *    $XAPPLRESDIR/X48
   *
   * 4. Values from XResourceManagerString() or, if empty,
   *    ~/.Xdefaults
   *
   * 5. Values in $XENVIRONMENT or, if not set,
   *    ~/.Xdefaults-hostname
   *
   * 6. Command line arguments
   */

  /* 1.  Hardcoded Defaults */

  for (def = 0; defaults[def]; def++)
    {
      if ((tmp = XrmGetStringDatabase(defaults[def])))
        XrmMergeDatabases(tmp, &rdb);
    }

  /* 2. /usr/lib/X11/app-defaults/X48 */

  merge_app_defaults("/usr/lib/X11/app-defaults", &rdb);

  /* 3. Values in $XUSERFILESEARCHPATH/X48, or $XAPPLRESDIR/X48 */

  if (!merge_app_defaults(getenv("XUSERFILESEARCHPATH"), &rdb))
    merge_app_defaults(getenv("XAPPLRESDIR"), &rdb);

  /* 4. Values from XResourceManagerString() or ~/.Xdefaults */

  res = XResourceManagerString(dpy);
  if (res)
    {
      if ((tmp = XrmGetStringDatabase(res)))
        XrmMergeDatabases(tmp, &rdb);
    }
  else
    {
      res = getenv("HOME");
      if (res)
        strcpy(home, res);
      else
        {
          pwd = getpwuid(getuid());
          if (pwd)
            strcpy(home, pwd->pw_dir);
        }
      sprintf(buf, "%s/.Xdefaults", home);
      if ((tmp = XrmGetFileDatabase(buf)))
        XrmMergeDatabases(tmp, &rdb);
    }

  /* 5. Values in $XENVIRONMENT or ~/.Xdefaults-hostname */

  res = getenv("XENVIRONMENT");
  if (res)
    {
      if ((tmp = XrmGetFileDatabase(res)))
        XrmMergeDatabases(tmp, &rdb);
    }
  else
    {
      res = getenv("HOME");
      if (res)
        strcpy(home, res);
      else
        {
          pwd = getpwuid(getuid());
          if (pwd)
            strcpy(home, pwd->pw_dir);
        }
      tmp = (XrmDatabase)0;
#ifdef SYSV
      if (uname(&uts) >= 0)
        {
          sprintf(buf, "%s/.Xdefaults-%s", home, uts.nodename);
          tmp = XrmGetFileDatabase(buf);
        }
#else
      if (gethostname(hostname, 128) >= 0)
        {
          sprintf(buf, "%s/.Xdefaults-%s", home, hostname);
          tmp = XrmGetFileDatabase(buf);
        }
#endif
      if (tmp)
        XrmMergeDatabases(tmp, &rdb);
    }

  /* 6. Command line arguments */

  if (cmd)
    XrmMergeDatabases(cmd, &rdb);

  get_resources();

  /*
   * Get the default screen
   */
  screen = DefaultScreen(dpy);

  /*
   * Does the Xserver do backing-store?
   */
  does_backing_store = XDoesBackingStore(XScreenOfDisplay(dpy, screen));
#ifdef DEBUG_BACKING_STORE
  fprintf(stderr, "XServer does%sBackingStore\n",
          does_backing_store ? " " : " not do ");
#endif

#ifdef HAVE_XSHM
  /*
   * Try to use XShm-Extension
   */
  shm_flag = useXShm;

  if (!XShmQueryExtension(dpy)) {
    shm_flag = 0;
    if (!quiet)
      fprintf(stderr, "%s: Xserver does not support XShm extension.\n",
              progname);
  }
#else
  if (useXShm)
    {
      if (!quiet)
        fprintf(stderr, "%s: not compiled to use XShm extension.\n",
                progname);
    }
#endif

  return 0;
}

int
#ifdef __FunctionProto__
SmallTextWidth(const char *string, unsigned int length)
#else
SmallTextWidth(string, length)
const char *string;
unsigned int length;
#endif
{
  int i, w;

  w = 0;
  for (i = 0; i < length; i++) {
    if (small_font[(int)string[i]].h != 0) {
      w += small_font[(int)string[i]].w + 1;
    } else {
      if (!quiet)
        fprintf(stderr, "Unknown small letter 0x00%x\n", (int)string[i]);
      w += 5;
    }
  }
  return w;
}

int
#ifdef __FunctionProto__
DrawSmallString(Display *the_dpy, Drawable d, GC the_gc,
                int x, int y, const char *string, unsigned int length)
#else
DrawSmallString(the_dpy, d, the_gc, x, y, string, length)
Display *the_dpy;
Drawable d;
GC the_gc;
int x;
int y;
const char *string;
unsigned int length;
#endif
{
  int i;
  Pixmap pix;

  for (i = 0; i < length; i++) {
    if (small_font[(int)string[i]].h != 0) {
      pix = XCreateBitmapFromData(the_dpy, d,
                (char *)small_font[(int)string[i]].bits,
		small_font[(int)string[i]].w, small_font[(int)string[i]].h);
      XCopyPlane(the_dpy, pix, d, the_gc, 0, 0, small_font[(int)string[i]].w,
                 small_font[(int)string[i]].h, x,
	         (int)(y - small_font[(int)string[i]].h), 1);
      XFreePixmap(the_dpy, pix);
    }
    x += SmallTextWidth(&string[i], 1);
  }
  return 0;
}

int
#ifdef __FunctionProto__
CreateButtons(int first_button, int last_button, Window parent)
#else
CreateButtons(first_button, last_button, parent)
  int first_button;
  int last_button;
  Window parent;
#endif
{
  int i, x, y;
  XSetWindowAttributes xswa;
  XFontStruct *finfo, *f_small, *f_med, *f_big;
  XGCValues val;
  unsigned long gc_mask;
  Pixmap pix;
  XCharStruct xchar;
  int dir, fa, fd;
  unsigned long pixel;

  f_small = get_font_resource(dpy, "smallLabelFont", "SmallLabelFont");
  f_med = get_font_resource(dpy, "mediumLabelFont", "mediumLabelFont");
  f_big = get_font_resource(dpy, "largeLabelFont", "LargeLabelFont");

  for (i = first_button; i <= last_button; i++) {

    if (i < BUTTON_MTH && ( buttons == buttons_sx || buttons == buttons_gx ))
      pixel = COLOR(DISP_PAD);
    else
      {
        if (opt_gx && buttons[i].is_menu )
          pixel = COLOR(UNDERLAY);
        else
          pixel = COLOR(PAD);
      }

    /*
     * create the buttons subwindows
     */
    if (buttons == buttons_sx || buttons == buttons_gx)
      buttons[i].xwin = XCreateSimpleWindow(dpy, parent,
			KEYBOARD_OFFSET_X + buttons[i].x,
			KEYBOARD_OFFSET_Y + buttons[i].y,
			buttons[i].w, buttons[i].h, 0,
			COLOR(BLACK), pixel);
    else
      buttons[i].xwin = XCreateSimpleWindow(dpy, parent,
                        KEYBOARD_OFFSET_X + buttons[i].x,
                        MENUOFFSET_Y + buttons[i].y,
                        buttons[i].w, buttons[i].h, 0,
                        COLOR(BLACK), pixel);

    xswa.event_mask = LeaveWindowMask | ExposureMask | StructureNotifyMask;
    xswa.backing_store = Always;

    XChangeWindowAttributes(dpy, buttons[i].xwin,
                            CWEventMask|CWBackingStore, &xswa);

    /*
     * draw the released button
     */
    buttons[i].map = XCreatePixmap(dpy, buttons[i].xwin, buttons[i].w,
				buttons[i].h, depth);

    XSetForeground(dpy, gc, pixel);
    XFillRectangle(dpy, buttons[i].map, gc, 0, 0, buttons[i].w,
                   buttons[i].h);

    XSetForeground(dpy, gc, COLOR(BUTTON));
    XFillRectangle(dpy, buttons[i].map, gc, 1, 1, buttons[i].w - 2,
                   buttons[i].h - 2);

    if (buttons[i].label != (char *)0) {

      /*
       * set font size in gc
       */
      switch (buttons[i].font_size) {
        case 0:
          finfo = f_small;
          break;
        case 1:
          finfo = f_big;
          break;
        case 2:
          finfo = f_med;
          break;
        default:
          finfo = f_small;
          break;
      }
      val.font = finfo->fid;
      gc_mask = GCFont;
      XChangeGC(dpy, gc, gc_mask, &val);

      /*
       * draw string centered in button
       */
      XSetBackground(dpy, gc, COLOR(BUTTON));
      XSetForeground(dpy, gc, COLOR(buttons[i].lc));

      XTextExtents(finfo, buttons[i].label, (int)strlen(buttons[i].label),
		   &dir, &fa, &fd, &xchar);
      x = (buttons[i].w - xchar.width) / 2;
      y = (1 + buttons[i].h -
          (xchar.ascent + xchar.descent)) / 2 + xchar.ascent + 1;
      XDrawImageString(dpy, buttons[i].map, gc, x, y,
                       buttons[i].label, (int)strlen(buttons[i].label));

      XSetBackground(dpy, gc, COLOR(BLACK));

    } else if (buttons[i].lw != 0) {

      /*
       * draw pixmap centered in button
       */
      XSetBackground(dpy, gc, COLOR(BUTTON));
      XSetForeground(dpy, gc, COLOR(buttons[i].lc));

      pix = XCreateBitmapFromData(dpy, buttons[i].xwin, (char *)buttons[i].lb,
				  buttons[i].lw, buttons[i].lh);

      x = (1 + buttons[i].w - buttons[i].lw) / 2;
      y = (1 + buttons[i].h - buttons[i].lh) / 2 + 1;

      XCopyPlane(dpy, pix, buttons[i].map, gc, 0, 0, buttons[i].lw,
		 buttons[i].lh, x, y, 1);

      XFreePixmap(dpy, pix);

      XSetBackground(dpy, gc, COLOR(BLACK));

    }

    /*
     * draw edge of button
     */
    XSetForeground(dpy, gc, COLOR(BUT_TOP));

    XDrawLine(dpy, buttons[i].map, gc, 1, (int)(buttons[i].h - 2), 1, 1);
    XDrawLine(dpy, buttons[i].map, gc, 2, (int)(buttons[i].h - 3), 2, 2);
    XDrawLine(dpy, buttons[i].map, gc, 3, (int)(buttons[i].h - 4), 3, 3);

    XDrawLine(dpy, buttons[i].map, gc, 1, 1, (int)(buttons[i].w - 2), 1);
    XDrawLine(dpy, buttons[i].map, gc, 2, 2, (int)(buttons[i].w - 3), 2);
    XDrawLine(dpy, buttons[i].map, gc, 3, 3, (int)(buttons[i].w - 4), 3);
    XDrawLine(dpy, buttons[i].map, gc, 4, 4, (int)(buttons[i].w - 5), 4);

    XDrawPoint(dpy, buttons[i].map, gc, 4, 5);

    XSetForeground(dpy, gc, COLOR(BUT_BOT));

    XDrawLine(dpy, buttons[i].map, gc, 3, (int)(buttons[i].h - 2),
              (int)(buttons[i].w - 2), (int)(buttons[i].h - 2));
    XDrawLine(dpy, buttons[i].map, gc, 4, (int)(buttons[i].h - 3),
              (int)(buttons[i].w - 3), (int)(buttons[i].h - 3));

    XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2),
              (int)(buttons[i].h - 2), (int)(buttons[i].w - 2), 3);
    XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 3),
              (int)(buttons[i].h - 3), (int)(buttons[i].w - 3), 4);
    XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 4),
              (int)(buttons[i].h - 4), (int)(buttons[i].w - 4), 5);

    XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 5),
               (int)(buttons[i].h - 4));

    /*
     * draw frame around button
     */
    XSetForeground(dpy, gc, COLOR(FRAME));

    XDrawLine(dpy, buttons[i].map, gc, 0, (int)(buttons[i].h - 3), 0, 2);
    XDrawLine(dpy, buttons[i].map, gc, 2, 0, (int)(buttons[i].w - 3), 0);
    XDrawLine(dpy, buttons[i].map, gc, 2, (int)(buttons[i].h - 1),
              (int)(buttons[i].w - 3), (int)(buttons[i].h - 1));
    XDrawLine(dpy, buttons[i].map, gc, (int)(buttons[i].w - 1),
              (int)(buttons[i].h - 3), (int)(buttons[i].w - 1), 2);

    if (i == BUTTON_ON)
      {
        XDrawLine(dpy, buttons[i].map, gc, 1, 1, (int)(buttons[i].w - 2), 1);
        XDrawPoint(dpy, buttons[i].map, gc, 1, 2);
        XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), 2);
      }
    else
      {
        XDrawPoint(dpy, buttons[i].map, gc, 1, 1);
        XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2), 1);
      }
    XDrawPoint(dpy, buttons[i].map, gc, 1, (int)(buttons[i].h - 2));
    XDrawPoint(dpy, buttons[i].map, gc, (int)(buttons[i].w - 2),
               (int)(buttons[i].h - 2));

    /*
     * draw the depressed button
     */
    buttons[i].down = XCreatePixmap(dpy, buttons[i].xwin, buttons[i].w,
				    buttons[i].h, depth);

    XSetForeground(dpy, gc, pixel);
    XFillRectangle(dpy, buttons[i].down, gc, 0, 0, buttons[i].w,
                   buttons[i].h);

    XSetForeground(dpy, gc, COLOR(BUTTON));
    XFillRectangle(dpy, buttons[i].down, gc, 1, 1, buttons[i].w - 2,
                   buttons[i].h - 2);

    if (buttons[i].label != (char *)0) {

      /*
       * set small or big font in gc
       */
      switch (buttons[i].font_size) {
        case 0:
          finfo = f_small;
          break;
        case 1:
          finfo = f_big;
          break;
        case 2:
          finfo = f_med;
          break;
        default:
          finfo = f_small;
          break;
      }
      val.font = finfo->fid;
      gc_mask = GCFont;
      XChangeGC(dpy, gc, gc_mask, &val);

      /*
       * draw string centered in button
       */
      XSetBackground(dpy, gc, COLOR(BUTTON));
      XSetForeground(dpy, gc, COLOR(buttons[i].lc));

      XTextExtents(finfo, buttons[i].label, (int)strlen(buttons[i].label),
		   &dir, &fa, &fd, &xchar);
      x = (buttons[i].w - xchar.width) / 2;
      y = (1 + buttons[i].h -
          (xchar.ascent + xchar.descent)) / 2 + xchar.ascent;
      XDrawImageString(dpy, buttons[i].down, gc, x, y,
                       buttons[i].label, (int)strlen(buttons[i].label));

      XSetBackground(dpy, gc, COLOR(BLACK));

    } else {

      /*
       * draw pixmap centered in button
       */
      XSetBackground(dpy, gc, COLOR(BUTTON));
      XSetForeground(dpy, gc, COLOR(buttons[i].lc));

      pix = XCreateBitmapFromData(dpy, buttons[i].xwin, (char *)buttons[i].lb,
				  buttons[i].lw, buttons[i].lh);

      x = (1 + buttons[i].w - buttons[i].lw) / 2;
      y = (1 + buttons[i].h - buttons[i].lh) / 2;

      XCopyPlane(dpy, pix, buttons[i].down, gc, 0, 0, buttons[i].lw,
		 buttons[i].lh, x, y, 1);

      XFreePixmap(dpy, pix);

      XSetBackground(dpy, gc, COLOR(BLACK));

    }

    /*
     * draw edge of button
     */
    XSetForeground(dpy, gc, COLOR(BUT_TOP));

    XDrawLine(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 4), 2, 2);
    XDrawLine(dpy, buttons[i].down, gc, 3, (int)(buttons[i].h - 5), 3, 3);

    XDrawLine(dpy, buttons[i].down, gc, 2, 2, (int)(buttons[i].w - 4), 2);
    XDrawLine(dpy, buttons[i].down, gc, 3, 3, (int)(buttons[i].w - 5), 3);

    XDrawPoint(dpy, buttons[i].down, gc, 4, 4);

    XSetForeground(dpy, gc, COLOR(BUT_BOT));

    XDrawLine(dpy, buttons[i].down, gc, 3, (int)(buttons[i].h - 3),
              (int)(buttons[i].w - 3), (int)(buttons[i].h - 3));
    XDrawLine(dpy, buttons[i].down, gc, 4, (int)(buttons[i].h - 4),
              (int)(buttons[i].w - 4), (int)(buttons[i].h - 4));

    XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3),
              (int)(buttons[i].h - 3), (int)(buttons[i].w - 3), 3);
    XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 4),
              (int)(buttons[i].h - 4), (int)(buttons[i].w - 4), 4);

    XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 5),
               (int)(buttons[i].h - 5));

    /*
     * draw frame around button
     */
    XSetForeground(dpy, gc, COLOR(FRAME));

    XDrawLine(dpy, buttons[i].down, gc, 0, (int)(buttons[i].h - 3), 0, 2);
    XDrawLine(dpy, buttons[i].down, gc, 2, 0, (int)(buttons[i].w - 3), 0);
    XDrawLine(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 1),
              (int)(buttons[i].w - 3), (int)(buttons[i].h - 1));
    XDrawLine(dpy, buttons[i].down, gc, (int)(buttons[i].w - 1),
              (int)(buttons[i].h - 3), (int)(buttons[i].w - 1), 2);

    if (i == BUTTON_ON)
      {
        XDrawLine(dpy, buttons[i].down, gc, 1, 1, (int)(buttons[i].w - 2), 1);
        XDrawPoint(dpy, buttons[i].down, gc, 1, 2);
        XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2), 2);
      }
    else
      {
        XDrawPoint(dpy, buttons[i].down, gc, 1, 1);
        XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2), 1);
      }
    XDrawPoint(dpy, buttons[i].down, gc, 1, (int)(buttons[i].h - 2));
    XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 2),
               (int)(buttons[i].h - 2));

    if (i == BUTTON_ON)
      {
        XDrawRectangle(dpy, buttons[i].down, gc, 1, 2, buttons[i].w - 3,
                       buttons[i].h - 4);
        XDrawPoint(dpy, buttons[i].down, gc, 2, 3);
        XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), 3);
      }
    else
      {
        XDrawRectangle(dpy, buttons[i].down, gc, 1, 1, buttons[i].w - 3,
                       buttons[i].h - 3);
        XDrawPoint(dpy, buttons[i].down, gc, 2, 2);
        XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3), 2);
      }
    XDrawPoint(dpy, buttons[i].down, gc, 2, (int)(buttons[i].h - 3));
    XDrawPoint(dpy, buttons[i].down, gc, (int)(buttons[i].w - 3),
               (int)(buttons[i].h - 3));

  }

  XFreeFont(dpy, f_big);
  XFreeFont(dpy, f_med);
  XFreeFont(dpy, f_small);

  return 0;
}

int
#ifdef __FunctionProto__
DrawButtons(int first, int last, struct button_t *but)
#else
DrawButtons(first, last, but)
  int first;
  int last;
  struct button_t *but;
#endif
{
  int i;

  for (i = first; i <= last; i++) {
    if (but[i].pressed) {
      XCopyArea(dpy, but[i].down, but[i].xwin, gc, 0, 0, but[i].w,
                but[i].h, 0, 0);
    } else {
      XCopyArea(dpy, but[i].map, but[i].xwin, gc, 0, 0, but[i].w,
                but[i].h, 0, 0);
    }
  }
  return 0;
}

int
#ifdef __FunctionProto__
DrawButton(int i, struct button_t *but)
#else
DrawButton(i, but)
  int i;
  struct button_t *but;
#endif
{
  if (but[i].pressed) {
    XCopyArea(dpy, but[i].down, but[i].xwin, gc, 0, 0, but[i].w,
              but[i].h, 0, 0);
  } else {
    XCopyArea(dpy, but[i].map, but[i].xwin, gc, 0, 0, but[i].w,
              but[i].h, 0, 0);
  }
  return 0;
}

int
#ifdef __FunctionProto__
CreateKeypad(unsigned int w, unsigned int h, Window parent, 
                                struct keypad_t *pad, int first, int last)
#else
CreateKeypad(w, h, parent, pad, first, last)
unsigned int w;
unsigned int h;
Window parent;
struct keypad_t *pad;
int first;
int last;
#endif
{
  int i, x, y;
  int wl, wr, ws;
  Pixmap pix;
  unsigned long pixel=0;
  unsigned int  pw, ph;
  unsigned int  display_offset_x=0, display_offset_y=0, display_height=0;
  unsigned int  display_width=0;
  int cut;

  /*
   * draw the nice labels around the buttons
   */
  pad->width = w;
  pad->height = h;

  pad->pixmap = XCreatePixmap(dpy, parent, w, h, depth);

  XSetBackground(dpy, gc, COLOR(PAD));
  XSetForeground(dpy, gc, COLOR(PAD));

  XFillRectangle(dpy, pad->pixmap, gc, 0, 0, w, h);

  XSetBackground(dpy, gc, COLOR(DISP_PAD));
  XSetForeground(dpy, gc, COLOR(DISP_PAD));

  if (parent == mainW)
    cut = KEYBOARD_OFFSET_Y + buttons[BUTTON_MTH].y - 19;
  else
    cut = MENUOFFSET_Y +  buttons[1].y - 19;

  XFillRectangle(dpy, pad->pixmap, gc, 0, 0, w, (unsigned int)cut);

  /*
   * draw the character labels
   */
  for (i = first; i <= last; i++) {

    if (i < BUTTON_MTH && parent == mainW )
      pixel = COLOR(DISP_PAD);
    else
      pixel = COLOR(PAD);

    if (buttons[i].letter != (char *)0) {

      XSetBackground(dpy, gc, pixel);
      XSetForeground(dpy, gc, COLOR(WHITE));

      if (opt_gx)
        {
          x = KEYBOARD_OFFSET_X + buttons[i].x + buttons[i].w + 3;
          y = KEYBOARD_OFFSET_Y + buttons[i].y + buttons[i].h + 1;
        }
      else
        {
          x = KEYBOARD_OFFSET_X + buttons[i].x + buttons[i].w -
              SmallTextWidth(buttons[i].letter, 1) / 2 + 5;
          y = KEYBOARD_OFFSET_Y + buttons[i].y + buttons[i].h - 2;
        }
      if(parent != mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }

      DrawSmallString(dpy, pad->pixmap, gc, x, y,
                      buttons[i].letter, 1);
    }
  }

  /*
   * draw the bottom labels
   */
  for (i = first; i <= last; i++) {

    if (buttons[i].sub != (char *)0) {

      XSetBackground(dpy, gc, pixel);
      XSetForeground(dpy, gc, COLOR(WHITE));

      x = KEYBOARD_OFFSET_X + buttons[i].x + (1 + buttons[i].w -
          SmallTextWidth(buttons[i].sub, strlen(buttons[i].sub))) / 2;
      y = KEYBOARD_OFFSET_Y + buttons[i].y + buttons[i].h + small_ascent + 2;

      if(parent != mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }

      DrawSmallString(dpy, pad->pixmap, gc, x, y,
                      buttons[i].sub, strlen(buttons[i].sub));
    }
  }

  /*
   * draw the left labels
   */
  for (i = first; i <= last; i++) {

    if (buttons[i].left != (char *)0) {

      if (buttons[i].is_menu) {

        /*
         * draw the dark shade under the label
         */
        if (opt_gx)
          {
            pw = 58;
            ph = 48;
          }
        else
          {
            pw = 44;
            ph = 9;
          }

	pix = XCreatePixmap(dpy, pad->pixmap, pw, ph, depth);

        XSetForeground(dpy, gc, COLOR(UNDERLAY));

	XFillRectangle(dpy, pix, gc, 0, 0, pw, ph);

        XSetBackground(dpy, gc, COLOR(UNDERLAY));
	XSetForeground(dpy, gc, COLOR(LEFT));

	x = (pw + 1 - SmallTextWidth(buttons[i].left,
                                 strlen(buttons[i].left))) / 2;
        if (opt_gx)
          y = 14;
        else
          y = 8;

        DrawSmallString(dpy, pix, gc, x, y,
                        buttons[i].left, strlen(buttons[i].left));

        XSetForeground(dpy, gc, pixel);

        if (!opt_gx)
          {
	    XDrawPoint(dpy, pix, gc, 0, 0); 
	    XDrawPoint(dpy, pix, gc, 0, ph - 1); 
	    XDrawPoint(dpy, pix, gc, pw - 1, 0); 
	    XDrawPoint(dpy, pix, gc, pw - 1, ph - 1); 
          }

        if (opt_gx)
          {
            x = KEYBOARD_OFFSET_X + buttons[i].x - 6;
            y = KEYBOARD_OFFSET_Y + buttons[i].y
                - small_ascent - small_descent - 6;
          }
        else
          {
            x = KEYBOARD_OFFSET_X + buttons[i].x + (buttons[i].w - pw) / 2;
            y = KEYBOARD_OFFSET_Y + buttons[i].y
                - small_ascent - small_descent;
          }
      if(parent != mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }

        XCopyArea(dpy, pix, pad->pixmap, gc, 0, 0, pw, ph, x, y);

	XFreePixmap(dpy, pix);

      } else {

        XSetBackground(dpy, gc, pixel);
        XSetForeground(dpy, gc, COLOR(LEFT));

        if (buttons[i].right == (char *)0) {	/* centered label */

          x = KEYBOARD_OFFSET_X + buttons[i].x + (1 + buttons[i].w -
              SmallTextWidth(buttons[i].left,
                             strlen(buttons[i].left))) / 2;

        } else {					/* label to the left */

	  wl = SmallTextWidth(buttons[i].left, strlen(buttons[i].left));
	  wr = SmallTextWidth(buttons[i].right, strlen(buttons[i].right));
	  ws = SmallTextWidth(" ", 1);

          x = KEYBOARD_OFFSET_X + buttons[i].x + (1 + buttons[i].w -
              (wl + wr + ws)) / 2;

        }

        y = KEYBOARD_OFFSET_Y + buttons[i].y - small_descent;
      if(parent != mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }


        DrawSmallString(dpy, pad->pixmap, gc, x, y,
                        buttons[i].left, strlen(buttons[i].left));
      }
    }
  }

  /*
   * draw the right labels
   */
  for (i = first; i <= last; i++) {

    if (i < BUTTON_MTH)
      pixel = COLOR(DISP_PAD);
    else
      pixel = COLOR(PAD);

    if (buttons[i].right != (char *)0) {

      if (buttons[i].is_menu) {

        /*
         * draw the dark shade under the label
         */
        if (opt_gx)
          {
            pw = 58;
            ph = 48;
          }
        else
          {
            pw = 44;
            ph = 9;
          }

        pix = XCreatePixmap(dpy, pad->pixmap, pw, ph, depth);

        XSetForeground(dpy, gc, COLOR(UNDERLAY));

	XFillRectangle(dpy, pix, gc, 0, 0, pw, ph);

        XSetBackground(dpy, gc, COLOR(UNDERLAY));
	XSetForeground(dpy, gc, COLOR(RIGHT));

	x = (pw + 1 - SmallTextWidth(buttons[i].right,
                                 strlen(buttons[i].right))) / 2;
        if (opt_gx)
          y = 14;
        else
          y = 8;

        DrawSmallString(dpy, pix, gc, x, y,
                        buttons[i].right, strlen(buttons[i].right));

        XSetForeground(dpy, gc, pixel);

        if (!opt_gx)
          {
	    XDrawPoint(dpy, pix, gc, 0, 0); 
	    XDrawPoint(dpy, pix, gc, 0, ph - 1); 
	    XDrawPoint(dpy, pix, gc, pw - 1, 0); 
	    XDrawPoint(dpy, pix, gc, pw - 1, ph - 1); 
          }

        if (opt_gx)
          {
            x = KEYBOARD_OFFSET_X + buttons[i].x - 6;
            y = KEYBOARD_OFFSET_Y + buttons[i].y
                - small_ascent - small_descent - 6;
          }
        else
          {
            x = KEYBOARD_OFFSET_X + buttons[i].x + (buttons[i].w - pw) / 2;
            y = KEYBOARD_OFFSET_Y + buttons[i].y
                - small_ascent - small_descent;
          }
      if(parent !=mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }


        XCopyArea(dpy, pix, pad->pixmap, gc, 0, 0, pw, ph, x, y);

	XFreePixmap(dpy, pix);

      } else {

        XSetBackground(dpy, gc, pixel);
        XSetForeground(dpy, gc, COLOR(RIGHT));

        if (buttons[i].left == (char *)0) {	/* centered label */

          x = KEYBOARD_OFFSET_X + buttons[i].x + (1 + buttons[i].w -
              SmallTextWidth(buttons[i].right,
                             strlen(buttons[i].right))) / 2;

        } else {				/* label to the right */

	  wl = SmallTextWidth(buttons[i].left, strlen(buttons[i].left));
	  wr = SmallTextWidth(buttons[i].right, strlen(buttons[i].right));
	  ws = SmallTextWidth(" ", 1);

          x = KEYBOARD_OFFSET_X + buttons[i].x + (1 + buttons[i].w -
              (wl + wr + ws)) / 2 + wl + ws;

        }

        y = KEYBOARD_OFFSET_Y + buttons[i].y - small_descent;
      if(parent != mainW)
        {
          y -= KEYBOARD_OFFSET_Y;
          y += MENUOFFSET_Y;
        }


        DrawSmallString(dpy, pad->pixmap, gc, x, y,
                        buttons[i].right, strlen(buttons[i].right));
      }
    }
  }

  /*
   * insert the HP Logo
   */

  XSetBackground(dpy, gc, COLOR(LOGO_BACK));
  XSetForeground(dpy, gc, COLOR(LOGO));

  pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)hp_bits,
                              hp_width, hp_height);

  if (opt_gx)
    x = SIDE_SKIP - 6;
  else
    x = SIDE_SKIP ;

  XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, hp_width, hp_height,
             x, 10, 1);

  XFreePixmap(dpy, pix);

  if (!opt_gx)
    {
      XSetForeground(dpy, gc, COLOR(FRAME));

      XDrawLine(dpy, pad->pixmap, gc, (int)SIDE_SKIP, 9,
                (int)(SIDE_SKIP + hp_width - 1), 9);
      XDrawLine(dpy, pad->pixmap, gc, (int)(SIDE_SKIP - 1), 10,
                (int)(SIDE_SKIP - 1), 10 + hp_height - 1);
      XDrawLine(dpy, pad->pixmap, gc, (int)SIDE_SKIP, 10 + hp_height,
                (int)(SIDE_SKIP + hp_width - 1), 10 + hp_height);
      XDrawLine(dpy, pad->pixmap, gc, (int)(SIDE_SKIP + hp_width), 10,
                (int)(SIDE_SKIP + hp_width), 10 + hp_height - 1);
    }

  /*
   * write the name of it
   */
  XSetBackground(dpy, gc, COLOR(DISP_PAD));
  XSetForeground(dpy, gc, COLOR(LABEL));

  if (opt_gx)
    {
      x = SIDE_SKIP + DISPLAY_WIDTH - gx_128K_ram_width
          + gx_128K_ram_x_hot + 2;
      y = 10 + gx_128K_ram_y_hot;
      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)gx_128K_ram_bits,
                                  gx_128K_ram_width, gx_128K_ram_height);
      XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, gx_128K_ram_width,
                 gx_128K_ram_height, x, y, 1);
      XFreePixmap(dpy, pix);

      XSetForeground(dpy, gc, COLOR(LOGO));
      x = SIDE_SKIP + hp_width;
      y = hp_height + 8 - hp48gx_height;
      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)hp48gx_bits,
                                  hp48gx_width, hp48gx_height);
      XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, hp48gx_width,
                 hp48gx_height, x, y, 1);
      XFreePixmap(dpy, pix);

      XSetFillStyle(dpy, gc, FillStippled);
      x = SIDE_SKIP + DISPLAY_WIDTH - gx_128K_ram_width
          + gx_silver_x_hot + 2;
      y = 10 + gx_silver_y_hot;
      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)gx_silver_bits,
                                  gx_silver_width, gx_silver_height);
      XSetStipple(dpy, gc, pix);
      XSetTSOrigin(dpy, gc, x, y);
      XFillRectangle(dpy, pad->pixmap, gc, x, y, gx_silver_width,
                     gx_silver_height);
      XFreePixmap(dpy, pix);

      XSetForeground(dpy, gc, COLOR(RIGHT));
      x = SIDE_SKIP + DISPLAY_WIDTH - gx_128K_ram_width
          + gx_green_x_hot + 2;
      y = 10 + gx_green_y_hot;
      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)gx_green_bits,
                                  gx_green_width, gx_green_height);
      XSetStipple(dpy, gc, pix);
      XSetTSOrigin(dpy, gc, x, y);
      XFillRectangle(dpy, pad->pixmap, gc, x, y, gx_green_width,
                     gx_green_height);
      XFreePixmap(dpy, pix);

      XSetTSOrigin(dpy, gc, 0, 0);
      XSetFillStyle(dpy, gc, FillSolid);
    }
  else
    {
      x = SIDE_SKIP;
      y = TOP_SKIP - DISP_FRAME - hp48sx_height - 3;

      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)hp48sx_bits,
                                  hp48sx_width, hp48sx_height);

      XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, hp48sx_width,
                 hp48sx_height, x, y, 1);

      XFreePixmap(dpy, pix);

      x = SIDE_SKIP + DISPLAY_WIDTH - 1 - science_width;
      y = TOP_SKIP - DISP_FRAME - science_height - 4;

      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)science_bits,
                                  science_width, science_height);

      XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, science_width,
                 science_height, x, y, 1);
    }

  if (parent == menuWin )
    return 0;

  /*
   * draw the frame around the display
   */

  if(parent == mainW ) {
    display_offset_x = DISPLAY_OFFSET_X;
    display_offset_y = DISPLAY_OFFSET_Y;
    display_height = DISPLAY_HEIGHT;
    display_width  = DISPLAY_WIDTH;
  }
  if(parent == regWin || parent == stackWin || parent == asmWin ){
    display_offset_x = SIDE_SKIP;
    display_offset_y = 225;
    display_height = REG_DISPLAY_Y; 
    display_width = w - (2*SIDE_SKIP);
  }

  XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP));

  for (i = 0; i < DISP_FRAME; i++) {
    XDrawLine(dpy, pad->pixmap, gc,
              (int)(display_offset_x - i),
              (int)(display_offset_y + display_height + 2 * i),
              (int)(display_offset_x + display_width + i),
              (int)(display_offset_y + display_height + 2 * i));
    XDrawLine(dpy, pad->pixmap, gc,
              (int)(display_offset_x - i),
              (int)(display_offset_y + display_height + 2 * i + 1),
              (int)(display_offset_x + display_width + i),
              (int)(display_offset_y + display_height + 2 * i + 1));
    XDrawLine(dpy, pad->pixmap, gc,
              (int)(display_offset_x + display_width + i),
              (int)(display_offset_y - i),
              (int)(display_offset_x + display_width + i),
              (int)(display_offset_y + display_height + 2 * i));
  }

  XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT));

  for (i = 0; i < DISP_FRAME; i++) {
    XDrawLine(dpy, pad->pixmap, gc,
              (int)(display_offset_x - i - 1),
              (int)(display_offset_y - i - 1),
              (int)(display_offset_x + display_width + i - 1),
              (int)(display_offset_y - i - 1));
    XDrawLine(dpy, pad->pixmap, gc,
              (int)(display_offset_x - i - 1),
              (int)(display_offset_y - i - 1),
              (int)(display_offset_x - i - 1),
              (int)(display_offset_y + display_height + 2 * i - 1));
  }
  /*
   * round off corners
   */
  XSetForeground(dpy, gc, COLOR(DISP_PAD));

  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y - DISP_FRAME),
            (int)(display_offset_x - DISP_FRAME + 3),
            (int)(display_offset_y - DISP_FRAME));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y - DISP_FRAME),
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y - DISP_FRAME + 3));
  XDrawPoint(dpy, pad->pixmap, gc,
             (int)(display_offset_x - DISP_FRAME + 1),
             (int)(display_offset_y - DISP_FRAME + 1));

  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + display_width + DISP_FRAME - 4),
            (int)(display_offset_y - DISP_FRAME),
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y - DISP_FRAME));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y - DISP_FRAME),
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y - DISP_FRAME + 3));
  XDrawPoint(dpy, pad->pixmap, gc,
             (int)(display_offset_x + display_width + DISP_FRAME - 2),
             (int)(display_offset_y - DISP_FRAME + 1));

  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 4),
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x - DISP_FRAME),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1),
            (int)(display_offset_x - DISP_FRAME + 3),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1));
  XDrawPoint(dpy, pad->pixmap, gc,
             (int)(display_offset_x - DISP_FRAME + 1),
             (int)(display_offset_y + display_height + 2 * DISP_FRAME - 2));

  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 4),
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + display_width + DISP_FRAME - 4),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1),
            (int)(display_offset_x + display_width + DISP_FRAME - 1),
            (int)(display_offset_y + display_height + 2 * DISP_FRAME - 1));
  XDrawPoint(dpy, pad->pixmap, gc,
             (int)(display_offset_x + display_width + DISP_FRAME - 2),
             (int)(display_offset_y + display_height + 2 * DISP_FRAME - 2));

  /*
   * simulate rounded lcd corners
   */
  XSetForeground(dpy, gc, COLOR(LCD));

  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x - 1),
            (int)(display_offset_y + 1),
            (int)(display_offset_x - 1),
            (int)(display_offset_y + display_height - 2));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + 1),
            (int)(display_offset_y - 1),
            (int)(display_offset_x + display_width - 2),
            (int)(display_offset_y - 1)); 
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + 1),
            (int)(display_offset_y + display_height),
            (int)(display_offset_x + display_width - 2),
            (int)(display_offset_y + display_height));
  XDrawLine(dpy, pad->pixmap, gc,
            (int)(display_offset_x + display_width),
            (int)(display_offset_y + 1),
            (int)(display_offset_x + display_width),
            (int)(display_offset_y + display_height - 2));
  XFillRectangle(dpy, pad->pixmap, gc, 
               display_offset_x,
               display_offset_y,
               display_width,
               display_height );


   if(parent != mainW)
     {
       return 0;
     }

  /*
   * at last draw the v--- LAST ---v thing
   */

  if (!opt_gx)
    {
      XSetBackground(dpy, gc, COLOR(PAD));
      XSetForeground(dpy, gc, COLOR(WHITE));

      pix = XCreateBitmapFromData(dpy, pad->pixmap, (char *)last_bits,
			          last_width, last_height);

      x = KEYBOARD_OFFSET_X + buttons[BUTTON_1].x + buttons[BUTTON_1].w +
          (buttons[BUTTON_2].x - buttons[BUTTON_1].x - buttons[BUTTON_1].w) / 2;
      y = KEYBOARD_OFFSET_Y + buttons[BUTTON_5].y + buttons[BUTTON_5].h + 2;

      XCopyPlane(dpy, pix, pad->pixmap, gc, 0, 0, last_width, last_height,
	         x, y, 1);

      XFreePixmap(dpy, pix);
    }

  /*
   * lower the whole thing
   */
  XSetForeground(dpy, gc, COLOR(PAD_TOP));

  /* bottom lines */
  XDrawLine(dpy, pad->pixmap, gc, 1, (int)(pad->height - 1),
	    (int)(pad->width - 1), (int)(pad->height - 1));
  XDrawLine(dpy, pad->pixmap, gc, 2, (int)(pad->height - 2),
	    (int)(pad->width - 2), (int)(pad->height - 2));

  /* right lines */
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 1),
	    (int)(pad->height - 1), (int)(pad->width - 1), cut);
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 2),
	    (int)(pad->height - 2), (int)(pad->width - 2), cut);

  XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP));

  /* right lines */
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 1),
	    cut - 1, (int)(pad->width - 1), 1);
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 2),
	    cut - 1, (int)(pad->width - 2), 2);

  XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT));

  /* top lines */
  XDrawLine(dpy, pad->pixmap, gc, 0, 0, (int)(pad->width - 2), 0);
  XDrawLine(dpy, pad->pixmap, gc, 1, 1, (int)(pad->width - 3), 1);

  /* left lines */
  XDrawLine(dpy, pad->pixmap, gc, 0, cut - 1, 0, 0);
  XDrawLine(dpy, pad->pixmap, gc, 1, cut - 1, 1, 1);

  XSetForeground(dpy, gc, COLOR(PAD_BOT));

  /* left lines */
  XDrawLine(dpy, pad->pixmap, gc, 0, (int)(pad->height - 2), 0, cut);
  XDrawLine(dpy, pad->pixmap, gc, 1, (int)(pad->height - 3), 1, cut);

  /*
   * lower the menu buttons
   */
  XSetForeground(dpy, gc, COLOR(PAD_TOP));

  /* bottom lines */
  XDrawLine(dpy, pad->pixmap, gc, 3, (int)(pad->height - 3),
	    (int)(pad->width - 3), (int)(pad->height - 3));
  XDrawLine(dpy, pad->pixmap, gc, 4, (int)(pad->height - 4),
	    (int)(pad->width - 4), (int)(pad->height - 4));

  /* right lines */
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 3),
	    (int)(pad->height - 3), (int)(pad->width - 3), cut);
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 4),
	    (int)(pad->height - 4), (int)(pad->width - 4), cut);

  XSetForeground(dpy, gc, COLOR(DISP_PAD_TOP));

  /* right lines */
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 3),
	    cut - 1, (int)(pad->width - 3), KEYBOARD_OFFSET_Y - 24);
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 4),
	    cut - 1, (int)(pad->width - 4), KEYBOARD_OFFSET_Y - 23);

  XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT));

  /* top lines */
  XDrawLine(dpy, pad->pixmap, gc, 2, KEYBOARD_OFFSET_Y - 25,
            (int)(pad->width - 4), KEYBOARD_OFFSET_Y - 25);
  XDrawLine(dpy, pad->pixmap, gc, 3, KEYBOARD_OFFSET_Y - 24,
            (int)(pad->width - 5), KEYBOARD_OFFSET_Y - 24);

  /* left lines */
  XDrawLine(dpy, pad->pixmap, gc, 2, cut - 1, 2, KEYBOARD_OFFSET_Y - 24);
  XDrawLine(dpy, pad->pixmap, gc, 3, cut - 1, 3, KEYBOARD_OFFSET_Y - 23);

  XSetForeground(dpy, gc, COLOR(PAD_BOT));

  /* left lines */
  XDrawLine(dpy, pad->pixmap, gc, 2, (int)(pad->height - 4), 2, cut);
  XDrawLine(dpy, pad->pixmap, gc, 3, (int)(pad->height - 5), 3, cut);

  /*
   * lower the keyboard
   */
  XSetForeground(dpy, gc, COLOR(PAD_TOP));

  /* bottom lines */
  XDrawLine(dpy, pad->pixmap, gc, 5, (int)(pad->height - 5),
	    (int)(pad->width - 3), (int)(pad->height - 5));
  XDrawLine(dpy, pad->pixmap, gc, 6, (int)(pad->height - 6),
	    (int)(pad->width - 4), (int)(pad->height - 6));

  /* right lines */
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 5),
	    (int)(pad->height - 5), (int)(pad->width - 5), cut + 1);
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 6),
	    (int)(pad->height - 6), (int)(pad->width - 6), cut + 2);

  XSetForeground(dpy, gc, COLOR(DISP_PAD_BOT));

  /* top lines */
  XDrawLine(dpy, pad->pixmap, gc, 4, cut,
            (int)(pad->width - 6), cut);
  XDrawLine(dpy, pad->pixmap, gc, 5, cut + 1,
            (int)(pad->width - 7), cut + 1);

  XSetForeground(dpy, gc, COLOR(PAD_BOT));

  /* left lines */
  XDrawLine(dpy, pad->pixmap, gc, 4, (int)(pad->height - 6), 4, cut + 1);
  XDrawLine(dpy, pad->pixmap, gc, 5, (int)(pad->height - 7), 5, cut + 2);

  /*
   * round off the bottom edge
   */
  XSetForeground(dpy, gc, COLOR(PAD_TOP));

  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 7),
            (int)(pad->height - 7), (int)(pad->width - 7),
            (int)(pad->height - 14));
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 8),
            (int)(pad->height - 8), (int)(pad->width - 8),
            (int)(pad->height - 11));
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 7),
            (int)(pad->height - 7), (int)(pad->width - 14),
            (int)(pad->height - 7));
  XDrawLine(dpy, pad->pixmap, gc, (int)(pad->width - 7),
            (int)(pad->height - 8), (int)(pad->width - 11),
            (int)(pad->height - 8));
  XDrawPoint(dpy, pad->pixmap, gc,
             (int)(pad->width - 9), (int)(pad->height - 9));

  XDrawLine(dpy, pad->pixmap, gc, 7, (int)(pad->height - 7), 13,
            (int)(pad->height - 7));
  XDrawLine(dpy, pad->pixmap, gc, 8, (int)(pad->height - 8), 10,
            (int)(pad->height - 8));
  XSetForeground(dpy, gc, COLOR(PAD_BOT));
  XDrawLine(dpy, pad->pixmap, gc, 6, (int)(pad->height - 8), 6,
            (int)(pad->height - 14));
  XDrawLine(dpy, pad->pixmap, gc, 7, (int)(pad->height - 9), 7,
            (int)(pad->height - 11));



  /*
   * that's it. Ooph.
   */
  return 0;
}

int
#ifdef __FunctionProto__
DrawKeypad(struct keypad_t src, Drawable dest)
#else
DrawKeypad(src, dest)
  Drawable src;
  Drawable dest;
#endif
{
  XCopyArea(dpy, src.pixmap, dest, gc, 0, 0, src.width,
            src.height, 0, 0);
  return 0;
}

int
#ifdef __FunctionProto__
CreateIcon(void)
#else
CreateIcon()
#endif
{
  XSetWindowAttributes xswa;
  XWindowAttributes    xwa;
  Pixmap               tmp_pix;
  int                  p;

  XGetWindowAttributes(dpy, iconW, &xwa);
  xswa.event_mask = xwa.your_event_mask | ExposureMask;
  xswa.backing_store = Always;
  XChangeWindowAttributes(dpy, iconW, CWEventMask|CWBackingStore, &xswa);

  icon_pix = XCreatePixmap(dpy, iconW, hp48_icon_width,
                           hp48_icon_height, depth);

  /*
   * draw the icon pixmap
   */
  if (icon_color_mode == COLOR_MODE_MONO)
    {
      tmp_pix = XCreateBitmapFromData(dpy, iconW,
				      (char *)icon_maps[ICON_MAP].bits,
		                      icon_maps[ICON_MAP].w,
                                      icon_maps[ICON_MAP].h);
      XSetForeground(dpy, gc, COLOR(BLACK));
      XSetBackground(dpy, gc, COLOR(WHITE));
      XCopyPlane(dpy, tmp_pix, icon_pix, gc, 0, 0,
                 icon_maps[ICON_MAP].w, icon_maps[ICON_MAP].h, 0, 0, 1);
      XFreePixmap(dpy, tmp_pix);
    }
  else
    {
      XSetFillStyle(dpy, gc, FillStippled);
      for (p = FIRST_MAP; p <= LAST_MAP; p++)
        {
          tmp_pix = XCreateBitmapFromData(dpy, iconW,
					  (char *)icon_maps[p].bits,
		                          icon_maps[p].w,
                                          icon_maps[p].h);
          XSetStipple(dpy, gc, tmp_pix);
          XSetForeground(dpy, gc, COLOR(icon_maps[p].c));
          XFillRectangle(dpy, icon_pix, gc, 0, 0,
                         icon_maps[p].w, icon_maps[p].h);
          XFreePixmap(dpy, tmp_pix);
        }
      XSetFillStyle(dpy, gc, FillSolid);

      /*
       * draw frame around icon
       */
      XSetForeground(dpy, gc, COLOR(BLACK));
      XDrawRectangle(dpy, icon_pix, gc, 0, 0, icon_maps[ICON_MAP].w - 1,
                     icon_maps[ICON_MAP].h - 1);

    }

  /*
   * draw the display
   */
  XSetFillStyle(dpy, gc, FillStippled);
  icon_disp_pix = XCreateBitmapFromData(dpy, iconW,
					(char *)icon_maps[DISP_MAP].bits,
                                  	icon_maps[DISP_MAP].w,
                                  	icon_maps[DISP_MAP].h);
  XSetStipple(dpy, gc, icon_disp_pix);
  if (icon_color_mode == COLOR_MODE_MONO)
    XSetForeground(dpy, gc, COLOR(WHITE));
  else
    XSetForeground(dpy, gc, COLOR(icon_maps[DISP_MAP].c));
  XFillRectangle(dpy, icon_pix, gc, 0, 0,
                 icon_maps[DISP_MAP].w, icon_maps[DISP_MAP].h);

  /*
   * draw the 'x48' string
   */
  icon_text_pix = XCreateBitmapFromData(dpy, iconW,
					(char *)icon_maps[ON_MAP].bits,
                                  	icon_maps[ON_MAP].w,
                                  	icon_maps[ON_MAP].h);
  XSetStipple(dpy, gc, icon_text_pix);
  if (icon_color_mode == COLOR_MODE_MONO)
    XSetForeground(dpy, gc, COLOR(BLACK));
  else
    XSetForeground(dpy, gc, COLOR(icon_maps[ON_MAP].c));
  XFillRectangle(dpy, icon_pix, gc, 0, 0,
                 icon_maps[ON_MAP].w, icon_maps[ON_MAP].h);
  XSetFillStyle(dpy, gc, FillSolid);

  return 0;
}

void
#ifdef __FunctionProto__
refresh_icon(void)
#else
refresh_icon()
#endif
{
  int icon_state;

  icon_state = ((display.on && !((ANN_IO & display.annunc) == ANN_IO))
               || (display.on && !((ANN_IO & display.annunc) == ANN_IO)));

  if (icon_state == last_icon_state)
    return;
  last_icon_state = icon_state;
  XSetFillStyle(dpy, gc, FillStippled);
  if (icon_state)
    {
      /*
       * draw the 'x48' string
       */ 
      XSetStipple(dpy, gc, icon_text_pix);
      if (icon_color_mode == COLOR_MODE_MONO)
        XSetForeground(dpy, gc, COLOR(BLACK));
      else
        XSetForeground(dpy, gc, COLOR(icon_maps[ON_MAP].c));
      XFillRectangle(dpy, icon_pix, gc, 0, 0,
                     icon_maps[ON_MAP].w, icon_maps[ON_MAP].h);
    }
  else
    {
      /*
       * clear the display
       */
      XSetFillStyle(dpy, gc, FillStippled);
      XSetStipple(dpy, gc, icon_disp_pix);
      if (icon_color_mode == COLOR_MODE_MONO)
        XSetForeground(dpy, gc, COLOR(WHITE));
      else
        XSetForeground(dpy, gc, COLOR(icon_maps[DISP_MAP].c));
      XFillRectangle(dpy, icon_pix, gc, 0, 0,
                     icon_maps[DISP_MAP].w, icon_maps[DISP_MAP].h);
    }
  XSetFillStyle(dpy, gc, FillSolid);
  XCopyArea(dpy, icon_pix, iconW, gc, 0, 0,
            hp48_icon_width, hp48_icon_height, 0, 0);
}

int
#ifdef __FunctionProto__
DrawIcon(void)
#else
DrawIcon()
#endif
{
  XCopyArea(dpy, icon_pix, iconW, gc, 0, 0,
            hp48_icon_width, hp48_icon_height, 0, 0);
  return 0;
}

#ifdef HAVE_XSHM
int
#ifdef __FunctionProto__
handle_xerror(Display *the_dpy, XErrorEvent *eev)
#else
handle_xerror(the_dpy, eev)
Display *the_dpy;
XErrorEvent *eev;
#endif
{
  xerror_flag = 1;
  return 0;
}
#endif

int
#ifdef __FunctionProto__
CreateDispWindow(void)
#else
CreateDispWindow()
#endif
{
  XSetWindowAttributes xswa;
  XGCValues val;
  unsigned long gc_mask;
  static XRectangle rect;

  /*
   * create the display subwindow
   */
  disp.w = DISPLAY_WIDTH;
  disp.h = DISPLAY_HEIGHT;

  disp.win = XCreateSimpleWindow(dpy, mainW,
			(int)DISPLAY_OFFSET_X, (int)DISPLAY_OFFSET_Y,
			disp.w, disp.h, 0,
			COLOR(BLACK), COLOR(LCD));

  disp.mapped = 1;

  xswa.event_mask = ExposureMask | StructureNotifyMask;
  xswa.backing_store = Always;

  XChangeWindowAttributes(dpy, disp.win, CWEventMask|CWBackingStore, &xswa);

  /*
   * set up the gc
   */
  val.foreground = COLOR(LCD);
  val.background = COLOR(LCD);
  val.function = GXcopy;
  gc_mask = GCForeground | GCBackground | GCFunction;
  disp.gc = XCreateGC(dpy, mainW, gc_mask, &val);

  XSetForeground(dpy, disp.gc, COLOR(PIXEL));

#ifdef HAVE_XSHM

  disp.display_update = UPDATE_DISP | UPDATE_MENU;

  xerror_flag = 0;
  XSetErrorHandler(handle_xerror);
  XFlush(dpy);

  disp.disp_image = NULL;
  disp.menu_image = NULL;
  if (shm_flag) {

    /*
     * create XShmImage for DISP
     */
    disp.disp_image = XShmCreateImage(dpy, None, 1, XYBitmap, NULL,
                                      &disp.disp_info, 288, 128);
    if (disp.disp_image == NULL) {
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in CreateImage(DISP), disabling.\n",
                progname);
      goto shm_error;
    }

    /*
     * get ID of shared memory block for DISP
     */
    disp.disp_info.shmid = shmget(IPC_PRIVATE,
            (disp.disp_image->bytes_per_line * disp.disp_image->height),
            IPC_CREAT | 0777);
    if (disp.disp_info.shmid < 0) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in shmget(DISP), disabling.\n",
                progname);
      goto shm_error;
    }

    /*
     * get address of shared memory block for DISP
     */
    disp.disp_info.shmaddr = (char *)shmat(disp.disp_info.shmid, 0, 0);
    if (disp.disp_info.shmaddr == ((char *)-1)) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in shmat(DISP), disabling.\n",
                progname);
      goto shm_error;
    }
    disp.disp_image->data = disp.disp_info.shmaddr;
    disp.disp_info.readOnly = False;
    XShmAttach(dpy, &disp.disp_info);

    /*
     * create XShmImage for MENU
     */
    disp.menu_image = XShmCreateImage(dpy, None, 1, XYBitmap, NULL,
                                      &disp.menu_info, 272, 128);
    if (disp.menu_image == NULL) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in CreateImage(MENU), disabling.\n",
                progname);
      goto shm_error;
    }

    /*
     * get ID of shared memory block for MENU
     */
    disp.menu_info.shmid = shmget(IPC_PRIVATE,
            (disp.menu_image->bytes_per_line * disp.menu_image->height),
            IPC_CREAT | 0777);
    if (disp.menu_info.shmid < 0) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      XDestroyImage(disp.menu_image);
      disp.menu_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in shmget(MENU), disabling.\n",
                progname);
      goto shm_error;
    }

    /*
     * get address of shared memory block for MENU
     */
    disp.menu_info.shmaddr = (char *)shmat(disp.menu_info.shmid, 0, 0);
    if (disp.menu_info.shmaddr == ((char *)-1)) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      XDestroyImage(disp.menu_image);
      disp.menu_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in shmat(MENU), disabling.\n",
                progname);
      goto shm_error;
    }
    disp.menu_image->data = disp.menu_info.shmaddr;
    disp.menu_info.readOnly = False;
    XShmAttach(dpy, &disp.menu_info);

    XFlush(dpy);
    XSync(dpy, 0);
    sleep(1);

    if (xerror_flag) {
      XDestroyImage(disp.disp_image);
      disp.disp_image = NULL;
      XDestroyImage(disp.menu_image);
      disp.menu_image = NULL;
      shm_flag = 0;
      if (!quiet)
        fprintf(stderr, "%s: XShm error in shmget(MENU), disabling.\n",
                progname);
      goto shm_error;
    } else {
      shmctl(disp.disp_info.shmid, IPC_RMID, 0);
      shmctl(disp.menu_info.shmid, IPC_RMID, 0);
    }

    memset(disp.disp_image->data, 0,
           (size_t)(disp.disp_image->bytes_per_line * disp.disp_image->height));
    memset(disp.menu_image->data, 0,
           (size_t)(disp.menu_image->bytes_per_line * disp.menu_image->height));

    if (verbose)
      printf("%s: using XShm extension.\n", progname);

    CompletionType = XShmGetEventBase(dpy) + ShmCompletion;
  }
  shm_error:

  XSetErrorHandler(NULL);
  XFlush(dpy);

  if (!shm_flag) {
#endif
    rect.x = 5;
    rect.y = 0;
    rect.width = 262;
    rect.height = disp.h;
    XSetClipRectangles(dpy, disp.gc, 0, 0, &rect, 1, Unsorted);
#ifdef HAVE_XSHM
  }
#endif

  return 0;
}

int
#ifdef __FunctionProto__
CreateWindows(int argc, char **argv)
#else
CreateWindows(argc, argv)
int    argc;
char **argv;
#endif
{
  XSizeHints	hint, ih, mhint;
  XWMHints	wmh;
  XClassHint	clh;
  unsigned int	class;
  XGCValues	val, vals;
  unsigned long gc_mask;
  unsigned int	mask;
  XSetWindowAttributes xswa, stwa;
  XTextProperty	wname, iname;
  Atom		protocols[2];
  char		*name, *user_geom, def_geom[40];
  int		info, x, y, w, h;
  unsigned int	width, height, regheight;

  regheight = REGSIZE_Y;

  if (opt_gx)
    {
      buttons = buttons_gx;
      colors = colors_gx;
      icon_maps = icon_maps_gx;
    }
  else
    {
      buttons = buttons_sx;
      colors = colors_sx;
      icon_maps = icon_maps_sx;
    }

  class = InputOutput;
  visual = get_visual_resource(dpy, "visual", "Visual", &depth);
  if (visual != DefaultVisual(dpy, screen))
    {
      if (visual->class == DirectColor)
        cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocAll);
      else
        cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocNone);
    }
  else
    cmap = DefaultColormap(dpy, screen);

  direct_color = 0;
  switch (visual->class)
  {
    case DirectColor:
      direct_color = 1;
    case GrayScale:
    case PseudoColor:
      dynamic_color = 1;
      break;
    case StaticGray:
    case StaticColor:
    case TrueColor:
    default:
      dynamic_color = 0;
      break;
  }

  if ((visual->class == StaticGray) || (visual->class == GrayScale))
    color_mode = COLOR_MODE_GRAY;
  else
    color_mode = COLOR_MODE_COLOR;
  if (get_boolean_resource("gray", "Gray"))
    color_mode = COLOR_MODE_GRAY;

  if (get_boolean_resource("mono", "Mono"))
    color_mode = COLOR_MODE_MONO;
  if (depth == 1)
    color_mode = COLOR_MODE_MONO;

  icon_color_mode = color_mode;
  if (get_boolean_resource("monoIcon", "Mono"))
    icon_color_mode = COLOR_MODE_MONO;


  clh.res_name = res_name;
  clh.res_class = res_class;
  if(!XStringListToTextProperty(&progname, 1, &iname))
    return -1;

  if ((name = get_string_resource("title", "Title")) == (char *)0)
    {
      name = (char *)malloc(128);
      if (name == (char *)0) {
        sprintf(errbuf, "malloc failed.\n");
        fatal_exit();
      }
      sprintf(name, "%s-%d.%d.%d", progname, saturn.version[0],
              saturn.version[1], saturn.version[2]);
    }

  if(!XStringListToTextProperty(&name, 1, &wname))
    return -1;

  /*
   * Set some Window Attributes
   */
  xswa.colormap = cmap;
  stwa.colormap = cmap;
  mask = CWColormap;

  /*
   * create the window
   */
  width = KEYBOARD_WIDTH + 2 * SIDE_SKIP;
  height = DISPLAY_OFFSET_Y + DISPLAY_HEIGHT + DISP_KBD_SKIP +
           KEYBOARD_HEIGHT + BOTTOM_SKIP;

  mainW = XCreateWindow(dpy, RootWindow(dpy, screen),
                        0, 0, width, height,
                        0, (int)depth, class,
                        visual, mask, &xswa);

  menuWin = XCreateWindow( dpy, RootWindow(dpy, screen),
                        0, 0, width, width,
                        0, (int)depth, class,
                        visual, 0, &stwa);

  regWin = XCreateWindow( dpy, RootWindow(dpy, screen),
                        0, 0, width, regheight,
                        0, (int)depth, class,
                        visual, 0, &stwa);
  stackWin = XCreateWindow( dpy, RootWindow(dpy, screen),
                        0, 0, width, regheight,
                        0, (int)depth, class,
                        visual, 0, &stwa);
  asmWin = XCreateWindow( dpy, RootWindow(dpy, screen),
                        0, 0, 650, regheight,
                        0, (int)depth, class,
                        visual, 0, &stwa);

  if (mainW == 0 || menuWin == 0 || regWin == 0 || stackWin == 0 || asmWin == 0)
    return -1;

  /*
   * allocate my colors
   */
  AllocColors();

  /*
   * parse -geometry ...
   */
  mhint.x = mhint.y = hint.x = hint.y = 0;
  hint.min_width = hint.max_width = hint.base_width = hint.width = width;
  hint.min_height = hint.max_height = hint.base_height = hint.height = height;
  mhint.min_width = mhint.max_width = mhint.base_width = mhint.width = width;
  mhint.min_height = mhint.max_height =  mhint.base_height = mhint.height = width;

  hint.win_gravity = NorthWestGravity;
  hint.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity;
  mhint.win_gravity = NorthWestGravity;
  mhint.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity;


  sprintf(def_geom, "%ux%u", width, height);
  user_geom = get_string_resource("geometry", "Geometry");

  info = XWMGeometry(dpy, screen, user_geom, def_geom, 0, &hint,
                     &x, &y, &w, &h, &hint.win_gravity);

  if (info & (XValue | YValue))
    {
      if (info & XValue)
        hint.x = x;
      if (info & YValue)
        hint.y = y;
      hint.flags |= USPosition;
    }

  /*
   * check if we start iconic
   */
  if (get_boolean_resource("iconic", "Iconic"))
    wmh.initial_state = IconicState;
  else
    wmh.initial_state = NormalState;
  wmh.input = True;
  wmh.flags = StateHint | InputHint;

  /*
   * Set some more Window Attributes
   */
  xswa.background_pixel = COLOR(PAD);
  xswa.border_pixel = COLOR(BLACK);
  xswa.backing_store = Always;
  xswa.win_gravity = hint.win_gravity;
  xswa.bit_gravity = NorthWestGravity;
  xswa.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
                    ButtonReleaseMask | ExposureMask | KeymapStateMask |
                    EnterWindowMask | StructureNotifyMask;
  mask = CWBackPixel | CWBorderPixel | CWBackingStore | CWEventMask |
         CWBitGravity | CWWinGravity;
  XChangeWindowAttributes(dpy, mainW, mask, &xswa);
  XMoveWindow(dpy, mainW, hint.x, hint.y);

  stwa.background_pixel = COLOR(PAD);
  stwa.border_pixel = COLOR(BLACK);
  stwa.backing_store = Always; 
  stwa.win_gravity = mhint.win_gravity;
  stwa.bit_gravity = NorthWestGravity; 
  stwa.event_mask = GCForeground | GCLineWidth | GCBackground; /* GCFont */
  XChangeWindowAttributes(dpy, menuWin, mask, &stwa); 
  XMoveWindow(dpy, menuWin, hint.x + 100 , hint.y);
  XChangeWindowAttributes(dpy, regWin, mask, &stwa);
  XMoveWindow(dpy, regWin, hint.x + 100 , hint.y);
  XChangeWindowAttributes(dpy, stackWin, mask, &stwa);
  XMoveWindow(dpy, stackWin, hint.x + 100 , hint.y);
  XChangeWindowAttributes(dpy, asmWin, mask, &stwa);
  XMoveWindow(dpy, asmWin, hint.x + 100 , hint.y);



  /*
   * create the icon
   */
  xswa.colormap = cmap;
  mask = CWColormap;
  iconW = XCreateWindow(dpy, RootWindow(dpy, screen),
                        0, 0, hp48_icon_width, hp48_icon_height,
                        0, (int)depth, class,
                        visual, mask, &xswa);

  if (iconW == 0)
    return -1;

  wmh.icon_window = iconW;
  wmh.window_group = mainW;
  wmh.flags |= (IconWindowHint | WindowGroupHint);

  /*
   * set icon position if requested
   */
  ih.x = ih.y = 0;
  ih.min_width = ih.max_width = ih.base_width = ih.width = hp48_icon_width;
  ih.min_height = ih.max_height = ih.base_height = ih.height = hp48_icon_height;
  ih.win_gravity = NorthWestGravity;
  ih.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity;

  user_geom = get_string_resource("iconGeom", "IconGeom");
  info = XWMGeometry(dpy, screen, user_geom, (char *)0, 0, &ih,
                     &x, &y, &w, &h, &ih.win_gravity);

  if ((info & XValue) && (info & YValue))
    {
      wmh.icon_x = x;
      wmh.icon_y = y;
      wmh.flags |= IconPositionHint;
    }

  /*
   * set some more attributes of icon window
   */
  xswa.background_pixel = COLOR(BLACK);
  xswa.border_pixel = COLOR(BLACK);
  xswa.backing_store = NotUseful;
  xswa.win_gravity = ih.win_gravity;
  xswa.bit_gravity = NorthWestGravity;
  mask = CWBackPixel | CWBorderPixel | CWBackingStore | CWBitGravity |
         CWWinGravity;
  XChangeWindowAttributes(dpy, iconW, mask, &xswa);


  /*
   * tell window manager all the stuff we dug out
   */
  XSetWMProperties(dpy, mainW, &wname, &iname, argv, argc, &hint, &wmh, &clh);

  sprintf(name, "%s-%d.%d.%d Menu", progname, saturn.version[0],
              saturn.version[1], saturn.version[2]);
  XStringListToTextProperty(&name, 1, &wname);
  XSetWMProperties(dpy, menuWin, &wname, &iname, argv, argc, 
                                                     &mhint, &wmh, &clh);
mhint.min_height = mhint.max_height =  mhint.base_height = mhint.height = regheight;
  sprintf(name, "%s-%d.%d.%d Registers", progname, saturn.version[0],
              saturn.version[1], saturn.version[2]);
  XStringListToTextProperty(&name, 1, &wname);
  XSetWMProperties(dpy, regWin, &wname, &iname, argv, argc,
                                                     &mhint, &wmh, &clh);
  sprintf(name, "%s-%d.%d.%d Stack", progname, saturn.version[0],
              saturn.version[1], saturn.version[2]);
  XStringListToTextProperty(&name, 1, &wname);
  XSetWMProperties(dpy, stackWin, &wname, &iname, argv, argc,
                                                     &mhint, &wmh, &clh);

  mhint.min_width = mhint.max_width = mhint.base_width = mhint.width = 2*width;
  sprintf(def_geom, "%ux%u", 2*width, height);
  user_geom = get_string_resource("geometry", "Geometry");

  sprintf(name, "%s-%d.%d.%d Assembly", progname, saturn.version[0],
              saturn.version[1], saturn.version[2]);
  XStringListToTextProperty(&name, 1, &wname);
  XSetWMProperties(dpy, asmWin, &wname, &iname, argv, argc,
                                                     &mhint, &wmh, &clh);


  /*
   * turn on WM_DELETE_WINDOW
   */
  wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
  wm_save_yourself = XInternAtom(dpy, "WM_SAVE_YOURSELF", 0);
  wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", 0);
  protocols[0] = wm_delete_window;
  protocols[1] = wm_save_yourself;
  XSetWMProtocols(dpy, mainW, protocols, 2);

  /*
   * turn off icon name for olwm, olvwm
   */
  ol_decor_icon_name = XInternAtom(dpy, "_OL_DECOR_ICON_NAME", 0);
  ol_decor_del = XInternAtom(dpy, "_OL_DECOR_DEL", 0);
  atom_type = XInternAtom(dpy, "ATOM", 0);
  XChangeProperty(dpy, mainW, ol_decor_del, atom_type, 32, PropModeReplace,
                  (unsigned char *)&ol_decor_icon_name, 1);

  /*
   * set up the GC's
   */
  vals.background = COLOR(LCD);
  vals.foreground = COLOR(BLACK);
  vals.function = GXcopy;
  DispFont = get_font_resource(dpy,  "smallLabelFont", "SmallLabelFont");
  vals.font = DispFont->fid;
  font_height = DispFont->ascent + DispFont->descent;
  gc_mask = GCForeground | GCBackground | GCFunction | GCFont ;
  gc_stack = XCreateGC(dpy, menuWin, gc_mask, &vals);

  vals.background = COLOR(BLACK);
  vals.foreground = COLOR(LCD);
  gc_stack_erase = XCreateGC(dpy, menuWin, gc_mask, &vals);

  val.foreground = COLOR(WHITE);
  val.background = COLOR(BLACK);
  val.function = GXcopy;
  gc_mask = GCForeground | GCBackground | GCFunction;
  gc = XCreateGC(dpy, mainW, gc_mask, &val);

  /* XFreeFont(dpy, f_med); */

  /*
   * create the icon pixmap
   */
  CreateIcon();

  /*
   * create the display
   */
  CreateDispWindow();

  /*
   * create the buttons
   */
  CreateButtons(BUTTON_A, LAST_BUTTON, mainW);

  /*
   * create the keypad
   */
  CreateKeypad(width, height, mainW, &keypad, BUTTON_A, LAST_BUTTON);
  /*
   * map the window
   */
  XMapWindow(dpy, mainW);
  XMapSubwindows(dpy, mainW);

  DrawKeypad( keypad, mainW);
  DrawButtons(BUTTON_A, LAST_BUTTON, buttons);

  DrawIcon();

  buttons = buttons_menu; 

  CreateButtons(MBUTTON_MENUSTART, MBUTTON_MENUDONE, menuWin); 
  CreateKeypad(width, width, menuWin, &menupad, MBUTTON_MENUSTART, MBUTTON_MENUDONE); 
  DrawKeypad (menupad, menuWin);
  DrawButtons(MBUTTON_MENUSTART, MBUTTON_MENUDONE, buttons_menu);

  CreateButtons(MBUTTON_REGSTART, MBUTTON_REGDONE, regWin);
  CreateKeypad(width, regheight, regWin, &regpad, MBUTTON_REGSTART, MBUTTON_REGDONE);
  DrawKeypad (regpad, regWin);
  DrawButtons(MBUTTON_REGSTART, MBUTTON_REGDONE, buttons_menu);

  CreateButtons(MBUTTON_STSTART, MBUTTON_STDONE, stackWin);
  CreateKeypad(width, regheight, stackWin, &stackpad, MBUTTON_STSTART, MBUTTON_STDONE);
  DrawKeypad (stackpad, stackWin);
  DrawButtons(MBUTTON_STSTART, MBUTTON_STDONE, buttons_menu);

  CreateButtons(MBUTTON_ASMSTART, MBUTTON_ASMDONE, asmWin);
  CreateKeypad(2*width, regheight, asmWin, &asmpad, MBUTTON_ASMSTART, MBUTTON_ASMDONE);
  DrawKeypad (asmpad, asmWin);
  DrawButtons(MBUTTON_ASMSTART, MBUTTON_ASMDONE, buttons_menu);

  if (opt_gx)
	  buttons = buttons_gx;
  else
	  buttons = buttons_sx;

#ifdef HAVE_XSHM
  if (shm_flag) {
    XSetForeground(dpy, disp.gc, COLOR(PIXEL));
    XFillRectangle(dpy, disp.win, disp.gc, 5, 20, 262, 128);
  }
#endif

  return 0;
}

void
#ifdef __FunctionProto__
ShowConnections(char *wire, char *ir)
#else
ShowConnections(wire, ir)
char *wire;
char *ir;
#endif
{
  int           x, y, w, h;
  int           conn_top;
  XFontStruct  *finfo;
  char          name[128];
  XGCValues     val;
  unsigned long gc_mask;
  XCharStruct   xchar;
  int           dir, fa, fd;
  Pixmap        pix;

  finfo = get_font_resource(dpy, "connectionFont", "ConnectionFont");
  val.font = finfo->fid;
  gc_mask = GCFont;
  XChangeGC(dpy, gc, gc_mask, &val);

  conn_top = DISPLAY_OFFSET_Y + DISPLAY_HEIGHT + 18;

  XTextExtents(finfo, "TEST", (int)strlen("TEST"), &dir, &fa, &fd, &xchar);
  w = DISPLAY_WIDTH;
  h = fa + fd;

  pix = XCreatePixmap(dpy, keypad.pixmap, w, h, depth);
  XSetForeground(dpy, gc, COLOR(DISP_PAD));
  XFillRectangle(dpy, pix, gc, 0, 0, w, h);

  XSetBackground(dpy, gc, COLOR(DISP_PAD));
  XSetForeground(dpy, gc, COLOR(LABEL));

  sprintf(name, "wire: %s", wire ? wire : "none");
  XTextExtents(finfo, name, (int)strlen(name), &dir, &fa, &fd, &xchar);
  x = 0;
  y = fa;
  XDrawImageString(dpy, pix, gc, x, y, name, (int)strlen(name));

  sprintf(name, "IR: %s", ir ? ir : "none");
  XTextExtents(finfo, name, (int)strlen(name), &dir, &fa, &fd, &xchar);
  x = w - xchar.width - 1;
  y = fa;
  XDrawImageString(dpy, pix, gc, x, y, name, (int)strlen(name));

  x = DISPLAY_OFFSET_X;
  y = conn_top;
  XCopyArea(dpy, pix, keypad.pixmap, gc, 0, 0, w, h, x, y);

  DrawKeypad( keypad, mainW);

  XFreePixmap(dpy, pix);
  XFreeFont(dpy, finfo);
}

int
#ifdef __FunctionProto__
button_released(int b, XEvent *xev)
#else
button_released(b, xev)
int b;
XEvent *xev;
#endif
{
  int code;
  int i, r, c;
  int all_up;

  code = buttons[b].code;
  all_up = 1;
  for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
    if (buttons[i].pressed) {
      if (buttons[i].key_down) {
        all_up = 0;
      } else {
        buttons[i].pressed = 0;
        DrawButton(i,buttons);
        if (code == 0x8000) {
          for (i = 0; i < 9; i++)
            saturn.keybuf.rows[i] &= ~0x8000;
        } else {
          r = code >> 4;
          c = 1 << (code & 0xf);
          saturn.keybuf.rows[r] &= ~c;
        }
      }
    }
  }
  if (all_up)
    memset(&saturn.keybuf, 0, sizeof(saturn.keybuf));
#ifdef DEBUG_BUTTONS
  printf("Button released %d (%s)\n",
          buttons[b].code, buttons[b].name);
#endif
  return 0;
}

int
#ifdef __FunctionProto__
button_pressed(int b, XEvent *xev)
#else
button_pressed(b, xev)
int     b;
XEvent *xev;
#endif
{
  int code;
  int i, r, c;

  code = buttons[b].code;
  buttons[b].pressed = 1;
  if (code == 0x8000) {
    for (i = 0; i < 9; i++)
      saturn.keybuf.rows[i] |= 0x8000;
    do_kbd_int();
  } else {
    r = code >> 4;
    c = 1 << (code & 0xf);
    if ((saturn.keybuf.rows[r] & c) == 0) {
      if (saturn.kbd_ien) {
        do_kbd_int();
      }
      saturn.keybuf.rows[r] |= c;
    }
  }

#ifdef DEBUG_BUTTONS
  printf( "Button pressed  %d (%s)\n",
          buttons[b].code, buttons[b].name);
#endif

  return 0;
}

int
#ifdef __FunctionProto__
key_event(int b, XEvent *xev)
#else
key_event(b, xev)
int b;
XEvent *xev;
#endif
{
  int code;
  int i, r, c;
  int all_up;

  code = buttons[b].code;
  if (xev->type == KeyPress) {
    buttons[b].key_down = 1;
    buttons[b].pressed = 1;
    DrawButton(b, buttons);
    if (code == 0x8000) {
      for (i = 0; i < 9; i++)
        saturn.keybuf.rows[i] |= 0x8000;
      do_kbd_int();
    } else {
      r = code >> 4;
      c = 1 << (code & 0xf);
      if ((saturn.keybuf.rows[r] & c) == 0) {
        if (saturn.kbd_ien) {
          do_kbd_int();
        }
        saturn.keybuf.rows[r] |= c; 
      }
    }
#ifdef DEBUG_BUTTONS
    printf("Button pressed  %d (%s)\n",
            buttons[b].code, buttons[b].name);
#endif
  } else {
    buttons[b].key_down = 0;
    all_up = 1;
    for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
      if (buttons[i].pressed) {
        if (buttons[i].key_down) {
          all_up = 0;
        } else {
          buttons[i].pressed = 0;
          DrawButton(i,buttons);
          if (code == 0x8000) {
            for (i = 0; i < 9; i++)
              saturn.keybuf.rows[i] &= ~0x8000;
          } else {
            r = code >> 4;
            c = 1 << (code & 0xf);
            saturn.keybuf.rows[r] &= ~c;
          }
        }
      }
    }
    if (all_up)
      memset(&saturn.keybuf, 0, sizeof(saturn.keybuf));
#ifdef DEBUG_BUTTONS
    printf( "Button released %d (%s)\n",
            buttons[b].code, buttons[b].name);
#endif
  }
  return 0;
}

#ifdef HAVE_XSHM
void
#ifdef __FunctionProto__
refresh_display(void)
#else
refresh_display()
#endif
{
  if (shm_flag) { 
    if (disp.display_update & UPDATE_DISP) {
#ifdef XSHM_WAIT_FOR_SEND_EVENT
      XShmPutImage(dpy, disp.win, disp.gc, disp.disp_image, disp.offset, 0,
                   5, 20, 262, (unsigned int)(disp.lines + 2), 1);
      while(1) {
        XEvent xev;
        XNextEvent(dpy, &xev);
        if(xev.type == CompletionType)
          break;
      }
#else
      XShmPutImage(dpy, disp.win, disp.gc, disp.disp_image, disp.offset, 0,
                   5, 20, 262, (unsigned int)(disp.lines + 2), 0);
#endif
    }
    if ((disp.lines < 126) && (disp.display_update & UPDATE_MENU)) {
#ifdef XSHM_WAIT_FOR_SEND_EVENT
      XShmPutImage(dpy, disp.win, disp.gc, disp.menu_image,
                   0, 0, 5, (int)(disp.lines + 22),
                   262, (unsigned int)(126 - disp.lines), 1);
      while(1) {
        XEvent xev;
        XNextEvent(dpy, &xev);
        if(xev.type == CompletionType)
          break;
      }
#else
      XShmPutImage(dpy, disp.win, disp.gc, disp.menu_image,
                   0, 0, 5, (int)(disp.lines + 22),
                   262, (unsigned int)(126 - disp.lines), 0);
#endif
    }
    disp.display_update = 0;
  }
}
#endif

void
#ifdef __FunctionProto__
DrawDisp(void)
#else
DrawDisp()
#endif
{

#ifdef HAVE_XSHM
  if (shm_flag) { 
    XShmPutImage(dpy, disp.win, disp.gc, disp.disp_image, disp.offset, 0,
                 5, 20, 262, (unsigned int)(disp.lines + 2), 0);
    if (display.lines < 63) {
      XShmPutImage(dpy, disp.win, disp.gc, disp.menu_image,
                   0, disp.lines - 110, 5, 22 + disp.lines,
                   262, (unsigned int)(126 - disp.lines), 0);
    }
    disp.display_update = 0;
  } else {
#endif
    redraw_display();
#ifdef HAVE_XSHM
  }
#endif
  redraw_annunc();
}

void
#ifdef __FunctionProto__
get_geometry_string(Window win, char *s, int allow_off_screen)
#else
get_geometry_string(win, s, allow_off_screen)
Window  win;
char   *s;
int     allow_off_screen;
#endif
{
  XWindowAttributes    xwa;
  Window               root, parent, window;
  Window              *children = (Window *)0;
  unsigned int         rw, rh, rbw, rd;
  unsigned int         w, h, bw, d;
  unsigned int         nc;
  int                  rx, ry, x, y;
  int                  x_pos, x_neg, x_s, y_pos, y_neg, y_s;

  window = win;
  nc = 0;
  XQueryTree(dpy, window, &root, &parent, &children, &nc);
  XFree((char *)children);
  while (parent != root)
    {
      window = parent;
      nc = 0;
      XQueryTree(dpy, window, &root, &parent, &children, &nc);
      XFree((char *)children);
    }
  XGetGeometry(dpy, window, &root, &x, &y, &w, &h, &bw, &d);
  XGetGeometry(dpy, root, &root, &rx, &ry, &rw, &rh, &rbw, &rd);

  x_s = 1;
  x_pos = x;
  x_neg = rw - (x + w);
  if (abs(x_pos) > abs(x_neg))
    {
      x = x_neg;
      x_s = -1;
    }
  y_s = 1;
  y_pos = y;
  y_neg = rh - (y + h);
  if (abs(y_pos) > abs(y_neg))
    {
      y = y_neg;
      y_s = -1;
    }

  if (!allow_off_screen)
    {
      if (x < 0) x = 0;
      if (y < 0) y = 0;
    }

  XGetWindowAttributes(dpy, win, &xwa);
  sprintf(s, "%ux%u%s%d%s%d", xwa.width, xwa.height,
          (x_s > 0) ? "+" : "-", x, (y_s > 0) ? "+" : "-", y); 
}

int
#ifdef __FunctionProto__
update_regs(void)
#else
update_regs()
#endif
{

  int     line = 1, height, clear_from, i, val, offset, coffset;
  word_20	addr, naddr;
  int     indent;
  unsigned int  win_width ;
  char	        instr[100], buf[100];

  height = font_height;
  indent = SIDE_SKIP ;
  line = 1;
  offset = 225;
  coffset = offset + DispFont->descent;
  win_width = KEYBOARD_WIDTH;
  XSetForeground(dpy, gc_stack, COLOR(BLACK));
  XSetBackground(dpy, gc_stack, COLOR(LCD));


  if (buttons_menu[MBUTTON_REGPC].code) {
    naddr = disassemble (saturn.PC, buf, DIS_INSTR);
    addr = read_nibbles(saturn.PC, naddr - saturn.PC);
    sprintf (instr, "   PC: %.5lX  OPCODE: %lX", saturn.PC, addr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr) );
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase, 
                     clear_from, (line-1)*height + coffset, 
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGA].code) {
    dump_reg ("    A: ", 16, saturn.A, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,                    
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGB].code) {
    dump_reg ("    B: ", 16, saturn.B, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,                    
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGC].code) {
    dump_reg ("    C: ", 16, saturn.C, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,                    
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGD].code) {
    dump_reg ("    D: ", 16, saturn.D, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,                    
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGR0].code) {
    dump_reg ("   R0: ", 16, saturn.R0, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGR1].code) {
    dump_reg ("   R1: ", 16, saturn.R1, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGR2].code) {
    dump_reg ("   R2: ", 16, saturn.R2, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGR3].code) {
    dump_reg ("   R3: ", 16, saturn.R3, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGR4].code) {
    dump_reg ("   R4: ", 16, saturn.R4, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                    indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }
 
  if (buttons_menu[MBUTTON_REGD0].code) {
    sprintf (instr, "   D0: %.5lX ->", saturn.D0);
    for (i = 0; i < 20; i += 5)
      {
        val = strlen(instr);
        sprintf (&instr[val], " %.5lX", read_nibbles (saturn.D0 + i, 5));
      }
    XDrawImageString( dpy, regWin, gc_stack,
                   indent, line*height + offset, instr, strlen(instr) );
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGD1].code) {
    sprintf (instr, "   D1: %.5lX ->", saturn.D1);
    for (i = 0; i < 20; i += 5)
      {
        val = strlen(instr);
        sprintf (&instr[val], " %.5lX", read_nibbles (saturn.D1 + i, 5));
      }
    XDrawImageString( dpy, regWin, gc_stack,
                   indent, line*height + offset, instr, strlen(instr) );
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGIN].code) {
    dump_reg ("   IN: ", 4, saturn.IN, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGOUT].code) {
    dump_reg ("  OUT: ", 3, saturn.OUT, instr);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGCARY].code) {
    sprintf(instr, "CARRY: %.1d",saturn.CARRY);
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr));
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGST].code) {
    val = 0;
    for (i = NR_PSTAT - 1; i >= 0; i--) {
      val <<= 1;
      val |= saturn.PSTAT[i] ? 1 : 0;
    }
    sprintf (instr,"   ST: %.4X ( ", val);
    for (i = NR_PSTAT - 1; i >= 0; i--) {
      val = strlen(instr);
      if (saturn.PSTAT[i])
          sprintf (&instr[val], "%.1X", i);
      else
          sprintf (&instr[val], "-");
      if ((float)i/4 == i/4)
         sprintf (&instr[val+1], " ");
    }
    val = strlen(instr);
    sprintf(&instr[val], ")" );
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr) );
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (buttons_menu[MBUTTON_REGHST].code) {
    val = 0;
    if (saturn.XM != 0)
      val |= 1;
    if (saturn.SB != 0)
      val |= 2;
    if (saturn.SR != 0)
      val |= 3;
    if (saturn.MP != 0)
      val |= 4;
    sprintf (instr, "  HST: %.1X    (%s%s%s%s)", val,
          saturn.MP ? "MP " : "-- ", saturn.SR ? "SR " : "-- ",
          saturn.SB ? "SB " : "-- ", saturn.XM ? "XM" : "--");
    XDrawImageString( dpy, regWin, gc_stack,
                     indent, line*height + offset, instr, strlen(instr) );
    clear_from = XTextWidth(DispFont, instr, strlen(instr)) + indent;
    XFillRectangle (dpy, regWin, gc_stack_erase,
                     clear_from, (line-1)*height + coffset,
                     win_width - clear_from + indent, height);
    line++;
  }

  if (line != 18) {
    XSetForeground(dpy, gc_stack, COLOR(LCD));
    line--;
    XFillRectangle(dpy, regWin, gc_stack, 
           indent, line*height + coffset,
           win_width, height);
  }

  return 1;
}

int
#ifdef __FunctionProto__
update_instr(void )
#else
update_instr()
#endif
{
  word_20 addr, naddr, opcode;
  char    buf [100], instr[100];
  int     i, height, clear_from;
  int     indent, pos, coffset, offset, win_width, win_height;
  int  line = 0, j , k;

  height = font_height;
  indent = SIDE_SKIP ;
  offset = REG_DISPLAY_Y;
  coffset = DispFont->descent;
  win_width = 2*KEYBOARD_WIDTH + 2*SIDE_SKIP;
  win_height = REGSIZE_Y ; 
  XSetForeground(dpy, gc_stack, COLOR(BLACK));
  XSetBackground(dpy, gc_stack, COLOR(LCD));

  /* List out the last 5 instructions */

  pos = saturn.old_index-5;
  if (pos < 0 )
    pos+=50;
  for (i = 0 ; i <= 5 ; i++)
    {
      naddr = disassemble (saturn.old_PC[pos], instr, DIS_INSTR);
      opcode =  read_nibbles(saturn.old_PC[pos], naddr - saturn.old_PC[pos]);
      instr[24] = 0;
      sprintf (buf, "%.5lX <%lX>       ", saturn.old_PC[pos], opcode);
      sprintf (&buf[15],"%s", instr);
      XDrawImageString( dpy, asmWin, gc_stack,
                    indent, line*height + offset, buf, strlen(buf));
      clear_from = XTextWidth(DispFont, buf, strlen(buf)) + indent;
      XFillRectangle (dpy, asmWin, gc_stack_erase,
                     clear_from, offset + (line-1)*height + coffset,
                     win_width - clear_from + indent, height);

      line++;
      if(pos ==MAX_TRACE)
        pos = -1;
      pos++;
    }

 /* List the current instruction */

  addr = disassemble (saturn.PC, instr, DIS_ALL);
  opcode =  read_nibbles(saturn.PC, addr - saturn.PC);
  sprintf (buf, "%.5lX <%lX>       ", saturn.PC, opcode );
  sprintf (&buf[16],"%s", instr);

  XFillRectangle (dpy, asmWin, gc_stack,
                     indent, offset + (line-1)*height + coffset,
                     win_width , height);

  XDrawImageString( dpy, asmWin, gc_stack_erase,
                 indent, line*height + offset, buf, strlen(buf));
  line++;

 /* List the next 5 instructions */

  for (i = 5 ; i >= 1 ; i--)
    {
       naddr = disassemble (addr, instr, DIS_INSTR);
       opcode =  read_nibbles(addr, naddr - addr);
       if (strlen(instr) > 20)
         instr[24] = 0;
       sprintf (buf, "%.5lX <%lX>        ", addr, opcode);
       sprintf (&buf[16],"%s", instr);

       addr = naddr;
       XDrawImageString( dpy, menuWin, gc_stack,
                    indent, line*height+offset, buf, strlen(buf) );
      XDrawImageString( dpy, asmWin, gc_stack,
                    indent, line*height + offset, buf, strlen(buf));
      clear_from = XTextWidth(DispFont, buf, strlen(buf)) + indent;
      XFillRectangle (dpy, asmWin, gc_stack_erase,
                     clear_from, offset + (line-1)*height + coffset,
                     win_width - clear_from + indent, height);

       line++;

    }

  /* dump the return stack on the botton */
  line ++;
  j = 0;
  k = line;
  for (i = 0; i < 8 ; i++) {
    sprintf (buf, "RST%d:  ", i); 
    if (i <= saturn.rstkp )
      sprintf (&buf[6], "%.5lX", saturn.rstk[saturn.rstkp-i]);
    else
      sprintf (&buf[6], "-----");
    XDrawImageString( dpy, asmWin, gc_stack,
            indent + j, line*height+offset, buf, strlen(buf) );
    line++;
    if (line - k == 3) {
      line = k;
      j += 100;
    }

  }

 
  return 1;
}

int
#ifdef __FunctionProto__
update_stack(struct se *stack, int n )
#else
update_stack(stack, n)
  struct se *stack;
  int       n;
#endif
{
  int     i=n, offset, coffset , str, j, k, l, start=0;
  word_20 len;
  char    buf[65536], buf1[100], buf2[100];
  int     clear_from;
  int     indent, height;
  unsigned int  win_width, win_height;
  struct se  *stk;

  stk = stack;
  height = font_height;
  indent = SIDE_SKIP ;
  offset = REG_DISPLAY_Y;
  coffset = DispFont->descent;
  win_width = KEYBOARD_WIDTH;
  win_height = REGSIZE_Y ; 
  XSetForeground(dpy, gc_stack, COLOR(BLACK));
  XSetBackground(dpy, gc_stack, COLOR(LCD));

  str = 24;
  if ( !buttons_menu[MBUTTON_STADDR].code )
    str += 9;
  if ( !buttons_menu[MBUTTON_STTYPE].code)
    str +=16;
  i = 15;
  for (k = 0; k < n; k++)
    {
      stack = stk;
      for (j = 1; j < n- k; j++)
        stack = stack->se_next ;

      decode_rpl_obj(stack->se_p, &len, buf);
      if (strlen(buf) > str+3) {
        strncpy(buf1, buf, str+3);
        sprintf(&buf1[str], "...");
        buf1[str+3] = '\0';
       if ( buttons_menu[MBUTTON_STMORE].code <= (strlen(buf) - str )/33 +1) 
         i -= buttons_menu[MBUTTON_STMORE].code ;
       else
         i -= (strlen(buf) - str )/33 +1;
       start = i;
       }
       else
         strcpy(buf1, buf);

      if ( i >= 0) {
        if (buttons_menu[MBUTTON_STADDR].code &&
                                            buttons_menu[MBUTTON_STTYPE].code)
           sprintf(&buf2[0], "%2d: %.5lX -> %s", stack->se_n, stack->se_p, buf1);
        if ( !buttons_menu[MBUTTON_STADDR].code && 
                 buttons_menu[MBUTTON_STTYPE].code)
           sprintf(&buf2[0], "%2d: %s", stack->se_n, buf1);
        if ( !buttons_menu[MBUTTON_STADDR].code &&
              !buttons_menu[MBUTTON_STTYPE].code)
           sprintf(&buf2[0], "%2d: %s", stack->se_n, &buf1[16]);
        if (buttons_menu[MBUTTON_STADDR].code &&
             !buttons_menu[MBUTTON_STTYPE].code)
           sprintf(&buf2[0], "%2d: %.5lX -> %s", stack->se_n, 
                                                      stack->se_p, &buf1[16]);

        XDrawImageString( dpy, stackWin, gc_stack,
                        indent , offset  + (i*height), buf2, strlen(buf2));

        clear_from = XTextWidth(DispFont, buf2, strlen(buf2)) ;
        XFillRectangle (dpy, stackWin, gc_stack_erase,
             indent + clear_from, offset +  ((i-1)*height) +coffset ,
             win_width - clear_from, height);


        if (strlen(buf)>str && buttons_menu[MBUTTON_STMORE].code) 
          {
            l = 0;
            for(j=0; j < buttons_menu[MBUTTON_STMORE].code; j++) {
              i++;
              strncpy(buf1,&buf[str + j*33],60);
              if (strlen(buf1) > 36) {
                  sprintf(&buf1[33], "...");
                  buf1[36] = '\0';
               }
               else
                 l = 1;

              if (strlen(buf1) ) {
                sprintf(&buf2[0], "    %s", buf1);
                XDrawImageString( dpy, stackWin, gc_stack,
                      indent , offset + (i*height), buf2, strlen(buf2));

                clear_from = XTextWidth(DispFont, buf2, strlen(buf2)) ;
                XFillRectangle (dpy, stackWin, gc_stack_erase,
                    indent + clear_from, offset + ((i-1)*height) +coffset,
                    win_width - clear_from, height);
              } 
              if (l)
                break;
            }
            i = start ; 
          }
        i--;
        start = i;
      }
      stack = stack->se_next;
    } 

  if ( i >= 0)
    XFillRectangle (dpy, stackWin, gc_stack_erase,
                    indent , offset-height,
                    win_width , (i+1) * height + coffset);

  return 1;
}


void
#ifdef __FunctionProto__
save_command_line(void)
#else
save_command_line()
#endif
{
  XWindowAttributes    xwa;
  int                  wm_argc, ac;
  char 		     **wm_argv, geom[128], icon_geom[128];

  ac = wm_argc = 0;

  wm_argv = (char **)malloc((saved_argc + 5) * sizeof(char *));
  if (wm_argv == (char **)0)
    {
      if (!quiet)
        fprintf(stderr, "%s: warning: malloc failed in wm_save_yourself.\n",
                progname);
      XSetCommand(dpy, mainW, saved_argv, saved_argc);
      return;
    }

  while (saved_argv[ac])
    {
      if (!strcmp(saved_argv[ac], "-geometry"))
        {
          ac += 2;
          continue;
        }
      if (!strcmp(saved_argv[ac], "-iconGeom"))
        {
          ac += 2;
          continue;
        }
      if (!strcmp(saved_argv[ac], "-iconic"))
        {
          ac++;
          continue;
        }
      wm_argv[wm_argc++] = saved_argv[ac++];
    }

  wm_argv[wm_argc++] = "-geometry";
  get_geometry_string(mainW, geom, 1);
  wm_argv[wm_argc++] = geom;

  wm_argv[wm_argc++] = "-iconGeom";
  get_geometry_string(iconW, icon_geom, 0);
  wm_argv[wm_argc++] = icon_geom;

  XGetWindowAttributes(dpy, mainW, &xwa);
  if (xwa.map_state == IsUnmapped)
    {
      wm_argv[wm_argc++] = "-iconic";
    }
  wm_argv[wm_argc] = (char *)0;

  XSetCommand(dpy, mainW, wm_argv, wm_argc);
}

void
#ifdef __FunctionProto__
exit_x48(int tell_x11)
#else
exit_x48(tell_x11)
int tell_x11;
#endif
{
  exit_emulator();
  if (tell_x11)
    XCloseDisplay(dpy);
  exit (0);
}

int
#ifdef __FunctionProto__
decode_key(XEvent *xev, KeySym sym, char *buf, int buflen)
#else
decode_key(xev, sym, buf, buflen)
XEvent *xev;
KeySym  sym;
char   *buf;
int     buflen;
#endif
{
  int wake;

  wake = 0;
  if (buflen == 1)
    switch (buf[0]) {
      case '0':
        sym = XK_0;
        break;
      case '1':
        sym = XK_1;
        break;
      case '2':
        sym = XK_2;
        break;
      case '3':
        sym = XK_3;
        break;
      case '4':
        sym = XK_4;
        break;
      case '5':
        sym = XK_5;
        break;
      case '6':
        sym = XK_6;
        break;
      case '7':
        sym = XK_7;
        break;
      case '8':
        sym = XK_8;
        break;
      case '9':
        sym = XK_9;
        break;
      default:
        break;
    }

  switch ((int)sym) {
    case XK_KP_0:
    case XK_0:
      key_event(BUTTON_0, xev);
      wake = 1;
      break;
    case XK_KP_1:
    case XK_1:
      key_event(BUTTON_1, xev);
      wake = 1;
      break;
    case XK_KP_2:
    case XK_2:
      key_event(BUTTON_2, xev);
      wake = 1;
      break;
    case XK_KP_3:
    case XK_3:
      key_event(BUTTON_3, xev);
      wake = 1;
      break;
    case XK_KP_4:
    case XK_4:
      key_event(BUTTON_4, xev);
      wake = 1;
      break;
    case XK_KP_5:
    case XK_5:
      key_event(BUTTON_5, xev);
      wake = 1;
      break;
    case XK_KP_6:
    case XK_6:
      key_event(BUTTON_6, xev);
      wake = 1;
      break;
    case XK_KP_7:
    case XK_7:
      key_event(BUTTON_7, xev);
      wake = 1;
    break;
    case XK_KP_8:
    case XK_8:
      key_event(BUTTON_8, xev);
      wake = 1;
      break;
    case XK_KP_9:
    case XK_9:
      key_event(BUTTON_9, xev);
      wake = 1;
      break;
    case XK_KP_Add:
    case XK_plus:
      key_event(BUTTON_PLUS, xev);
      wake = 1;
      break;
    case XK_KP_Subtract:
    case XK_minus:
      key_event(BUTTON_MINUS, xev);
      wake = 1;
      break;
#ifdef XK_F25
    case XK_F25:
#endif
    case XK_KP_Divide:
    case XK_slash:
      key_event(BUTTON_DIV, xev);
      wake = 1;
      break;
#ifdef XK_F26
    case XK_F26:
#endif
    case XK_KP_Multiply:
    case XK_asterisk:
      key_event(BUTTON_MUL, xev);
      wake = 1;
      break;
    case XK_KP_Enter:
    case XK_Return:
      key_event(BUTTON_ENTER, xev);
      wake = 1;
      break;
    case XK_KP_Decimal:
    case XK_period:
      key_event(BUTTON_PERIOD, xev);
      wake = 1;
      break;
    case XK_space:
      key_event(BUTTON_SPC, xev);
      wake = 1;
      break;
    case XK_Delete:
      key_event(BUTTON_DEL, xev);
      wake = 1;
      break;
    case XK_BackSpace:
      key_event(BUTTON_BS, xev);
      wake = 1;
      break;
    case XK_Escape:
      key_event(BUTTON_ON, xev);
      wake = 1;
      break;
    case XK_Shift_L:
      key_event(BUTTON_SHL, xev);
      wake = 1;
      break;
    case XK_Shift_R:
      key_event(BUTTON_SHR, xev);
      wake = 1;
      break;
    case XK_Alt_L:
    case XK_Alt_R:
      key_event(BUTTON_ALPHA, xev);
      wake = 1;
      break;
    case XK_a:
    case XK_F1:
      key_event(BUTTON_A, xev);
      wake = 1;
      break;
    case XK_b:
    case XK_F2:
      key_event(BUTTON_B, xev);
      wake = 1;
      break;
    case XK_c:
    case XK_F3:
      key_event(BUTTON_C, xev);
      wake = 1;
      break;
    case XK_d:
    case XK_F4:
      key_event(BUTTON_D, xev);
      wake = 1;
      break;
    case XK_e:
    case XK_F5:
      key_event(BUTTON_E, xev);
      wake = 1;
      break;
    case XK_f:
    case XK_F6:
      key_event(BUTTON_F, xev);
      wake = 1;
      break;
    case XK_g:
      key_event(BUTTON_MTH, xev);
      wake = 1;
      break;
    case XK_h:
      key_event(BUTTON_PRG, xev);
      wake = 1;
      break;
    case XK_i:
      key_event(BUTTON_CST, xev);
      wake = 1;
      break;
    case XK_j:
      key_event(BUTTON_VAR, xev);
      wake = 1;
      break;
    case XK_k:
    case XK_Up:
      key_event(BUTTON_UP, xev);
      wake = 1;
      break;
    case XK_l:
      key_event(BUTTON_NXT, xev);
      wake = 1;
      break;
    case XK_m:
      key_event(BUTTON_COLON, xev);
      wake = 1;
      break;
    case XK_n:
      key_event(BUTTON_STO, xev);
      wake = 1;
      break;
    case XK_o:
      key_event(BUTTON_EVAL, xev);
      wake = 1;
      break;
    case XK_p:
    case XK_Left:
      key_event(BUTTON_LEFT, xev);
      wake = 1;
      break;
    case XK_q:
    case XK_Down:
      key_event(BUTTON_DOWN, xev);
      wake = 1;
      break;
    case XK_r:
    case XK_Right:
      key_event(BUTTON_RIGHT, xev);
      wake = 1;
      break;
    case XK_s:
      key_event(BUTTON_SIN, xev);
      wake = 1;
      break;
    case XK_t:
      key_event(BUTTON_COS, xev);
      wake = 1;
      break;
    case XK_u:
      key_event(BUTTON_TAN, xev);
      wake = 1;
      break;
    case XK_v:
      key_event(BUTTON_SQRT, xev);
      wake = 1;
      break;
    case XK_w:
      key_event(BUTTON_POWER, xev);
      wake = 1;
      break;
    case XK_x:
      key_event(BUTTON_INV, xev);
      wake = 1;
      break;
    case XK_y:
      key_event(BUTTON_NEG, xev);
      wake = 1;
      break;
    case XK_z:
      key_event(BUTTON_EEX, xev);
      wake = 1;
      break;
    default:
      break;
  }
  return wake;
}

void
#ifdef __FunctionProto__
PopUpMenu(void)
#else
PopUPMenu()
#endif
{
  if (!Menu)
    {
      Menu = 1;
      XMapWindow(dpy, menuWin );
      XMapSubwindows(dpy, menuWin);

    }
  else 
    {
       Menu = 0;
       XUnmapSubwindows(dpy, menuWin);
       XUnmapWindow(dpy, menuWin);
    }
}

int
#ifdef __FunctionProto__
StackMenu(int i)
#else
StackMenu(i)
  int i;
#endif
{ 
  switch (i) {
    case (MBUTTON_STMORE):
      buttons_menu[MBUTTON_STMORE].code++;
      break;
    case ( MBUTTON_STLESS):
      if (buttons_menu[MBUTTON_STMORE].code > 0)
        buttons_menu[MBUTTON_STMORE].code--;
      break;
    default:
      if (buttons_menu[i].code)
        buttons_menu[i].code = 0;
      else
        buttons_menu[i].code = 1;
      break;
  }

  update_gui();
  return 0;
}


int
#ifdef __FunctionProto__
RegMenu(int i)
#else
RegMenu(i)
  int i;
#endif
{
  if (buttons_menu[i].code)
    buttons_menu[i].code = 0;
  else
    buttons_menu[i].code = 1;

  update_regs();
  return 0;
}

int
#ifdef __FunctionProto__
MainMenu(int i)
#else
MainMenu(i)
  int i;
#endif
{
  switch (i) {
    case MBUTTON_GOC:
      continue_flag = 1;
      break;
    case MBUTTON_GOR:
      break;
    case MBUTTON_SPB:
      continue_flag = 0;
      break;
    case MBUTTON_SPQ:
      break;
    case MBUTTON_SPE:
        XCloseDisplay(dpy);
        exit (0);
      break;
    case MBUTTON_BADD:
      break;
    case MBUTTON_BRAG:
      break;
    case MBUTTON_BREG:
      break;
    case MBUTTON_BINT:
      break;
    case MBUTTON_BRPL:
      break;
    case MBUTTON_BCLR:
      break;
    case MBUTTON_DISA:
      if (!Disassembly) {
        Disassembly = 1;
        XMapWindow(dpy, asmWin);
        XMapSubwindows(dpy, asmWin);
        update_instr();
      }
      else {
        Disassembly = 0;
        XUnmapSubwindows(dpy, asmWin);
        XUnmapWindow(dpy, asmWin);
      }
      
      break;
    case MBUTTON_LREG:
      if (!Register)
        {
          Register = 1;
          XMapWindow(dpy, regWin );
          XMapSubwindows(dpy, regWin);
        }
      else
        {
           Register = 0;
           XUnmapSubwindows(dpy, regWin);
           XUnmapWindow(dpy, regWin);
        }
      break;
    case MBUTTON_LSTK:
      if(!Stack)
        {
          Stack = 1;
          XMapWindow(dpy, stackWin );
          XMapSubwindows(dpy, stackWin);
          update_gui();
        }
      else
        {
           Stack = 0;
           XUnmapSubwindows(dpy, stackWin);
           XUnmapWindow(dpy, stackWin);

        }
      break;

  }
  return 0;
}

int
#ifdef __FunctionProto__
GetEvent(void)
#else
GetEvent()
#endif
{
  XEvent               xev;
  XClientMessageEvent *cm;
  int                  i=0, wake, bufs = 2;
  char                 buf[2];
  KeySym               sym;
  int                  button_expose;
  static int           button_leave = -1;
  static int           release_pending = 0;
  static XKeyEvent     release_event;
  static Time          last_release_time = 0;

  wake = 0;

  if (release_pending)
    {
      i = XLookupString(&release_event, buf, bufs, &sym, NULL);
      wake = decode_key((XEvent *)&release_event, sym, buf, i);
      release_pending = 0;
    }

  while (XPending(dpy) > 0) {

    XNextEvent(dpy, &xev);

    switch ((int)xev.type) {

      case KeyPress:

        release_pending = 0;
        if (xev.xkey.time == last_release_time)
          break;

        i = XLookupString(&xev.xkey, buf, bufs, &sym, NULL);
        wake = decode_key(&xev, sym, buf, i);
        break;

      case KeyRelease:

        release_pending = 1;
        last_release_time = xev.xkey.time;
        memcpy(&release_event, &xev, sizeof(XKeyEvent));
        break;

      case NoExpose:

	break;

      case Expose:

        button_expose = 0;
        for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
          if (xev.xexpose.window == buttons[i].xwin) {
            DrawButton(i,buttons);
            button_expose = 1;
            break;
          }
        }
        if (!button_expose) {
          if (xev.xexpose.window == disp.win) {
            DrawDisp();
            button_expose = 1;
          }
        }
        if (!button_expose) {
          if (xev.xexpose.window == iconW) {
            DrawIcon();
            button_expose = 1;
          }
        }
        if (!button_expose) {
          DrawKeypad( keypad, mainW);
          DrawKeypad (menupad, menuWin);
        }
        
	break;

      case UnmapNotify:
        if(xev.xunmap.window == mainW)
          disp.mapped = 0;
        break;

      case MapNotify:
        if(xev.xmap.window == mainW)
          disp.mapped = 1;
        update_display();
        redraw_annunc();
        break;

      case ButtonPress:

        if (xev.xbutton.button == Button1 || xev.xbutton.button == Button2) {
	  for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
	    if (xev.xbutton.subwindow == buttons[i].xwin) {
              buttons[i].key_down = 1;
	      button_pressed(i, &xev);
              wake = 1;
              DrawButton(i,buttons);
              break;
            }
	  }
          for (i = MBUTTON_MENUSTART; i <= MBUTTON_MENUDONE; i++) {
            if (xev.xbutton.subwindow == buttons_menu[i].xwin) {
              buttons_menu[i].key_down = 1;
              buttons_menu[i].pressed = 1;
              wake = 1;
              DrawButton(i,buttons_menu);
              MainMenu(i);
              break;
            }
          }
          for (i = MBUTTON_REGSTART; i <= MBUTTON_REGDONE; i++) {
            if (xev.xbutton.subwindow == buttons_menu[i].xwin) {
              buttons_menu[i].key_down = 1;
              buttons_menu[i].pressed = 1;
              wake = 1;
              DrawButton(i,buttons_menu);
              RegMenu(i);
              break;
            }
          }
          for (i = MBUTTON_STSTART; i <= MBUTTON_STDONE; i++) {
            if (xev.xbutton.subwindow == buttons_menu[i].xwin) {
              buttons_menu[i].key_down = 1;
              buttons_menu[i].pressed = 1;
              wake = 1;
              DrawButton(i,buttons_menu);
              StackMenu(i);
              break;
            }
          }

        }

        if (opt_gx)
            i = SIDE_SKIP - 6;
        else
            i = SIDE_SKIP;
        if ( xev.xbutton.x > i  && xev.xbutton.x < i + hp_width &&
               xev.xbutton.y > 10 && xev.xbutton.y < 10 + hp_height)
          {
            if (xev.xbutton.window == mainW)
              PopUpMenu(); 
          }
        
	break;

      case ButtonRelease:

	for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
	  if (xev.xbutton.subwindow == buttons[i].xwin) {
            buttons[i].key_down = 0;
            if (xev.xbutton.button == Button1) {
	      button_released(i, &xev);
              wake = 1;
              DrawButton(i, buttons);
              break;
            }
	  }
        }
        for (i = MBUTTON_MENUSTART; i <= MBUTTON_MENUDONE; i++) {
          if (xev.xbutton.subwindow == buttons_menu[i].xwin) {
            buttons_menu[i].key_down = 0;
            if (xev.xbutton.button == Button1) {
              wake = 1;
              buttons_menu[i].pressed = 0;

              DrawButton(i, buttons_menu);
              break;
            }
          }
        }
        for (i = MBUTTON_REGSTART; i <= MBUTTON_REGDONE; i++) {
          if (xev.xbutton.subwindow == buttons_menu[i].xwin) {
            buttons_menu[i].key_down = 0;
            if (xev.xbutton.button == Button1) {
              wake = 1;
              buttons_menu[i].pressed = 0;

              DrawButton(i, buttons_menu);
              break;
            }
          }

        }

	break;

      case MappingNotify:

	switch (xev.xmapping.request) 
	{
	  case MappingModifier:
	  case MappingKeyboard:
	    XRefreshKeyboardMapping(&xev.xmapping);
	    break;
	  case MappingPointer:
          default:
	    break;
        }
        break;

      case EnterNotify:

        if ((xev.xcrossing.state & Button1Mask) != 0) {
          if (xev.xcrossing.mode == NotifyNormal) {
	    if (button_leave >= 0) {
              buttons[button_leave].key_down = 0;
              button_released(button_leave, &xev);
              wake = 1;
              DrawButton(button_leave,buttons);
	      button_leave = -1;
            }
          }
        }
        break;

      case LeaveNotify:

        if ((xev.xcrossing.state & Button1Mask) != 0) {
          for (i = BUTTON_A; i <= LAST_BUTTON; i++) {
	    if (xev.xcrossing.window == buttons[i].xwin) {
	      button_leave = i;
              break;
            }
          }
	}
        break;

      case ClientMessage:

        cm = (XClientMessageEvent *)&xev;

        if (cm->message_type == wm_protocols)
          {
            if (cm->data.l[0] == wm_delete_window)
              {
                /*
                 * Quit selected from window managers menu
                 */
		exit_x48(1);
              }

            if (cm->data.l[0] == wm_save_yourself)
              {
		save_command_line();
              }
	  }
        break;

      default:

#ifdef DEBUG_XEVENT
        printf("Event: %d\n", xev.type);
#endif
        break;

    }
  }
  return wake;
}


