File:  [UNIX Amiga Emulator] / uae / xwin.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:38:02 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, BSchmidt
CVS tags: uae060, HEAD
uae-0.6.0

 /* 
  * UAE - The Un*x Amiga Emulator
  * 
  * X interface
  * 
  * Copyright 1995, 1996 Bernd Schmidt
  * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
  */

#include "sysconfig.h"
#include "sysdeps.h"

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

#ifndef DONT_WANT_SHM
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif

#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "xwin.h"
#include "keyboard.h"
#include "keybuf.h"
#include "gui.h"

static Display *display;
static int screen;
static Window rootwin, mywin;

static GC whitegc,blackgc;
static XColor black,white;
static Colormap cmap;

static XImage *img;
static Visual *vis;
static XVisualInfo visualInfo;
static int bitdepth;
#ifndef DONT_WANT_SHM
static XShmSegmentInfo shminfo;
#endif
static Cursor blankCursor, xhairCursor;
static int cursorOn;

xcolnr xcolors[4096];

 /* Keyboard and mouse */

static int keystate[256];

int buttonstate[3];
int lastmx, lastmy;
int newmousecounters;

static int inwindow;
const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
			    |ButtonReleaseMask|PointerMotionMask
			    |FocusChangeMask|EnterWindowMask
			    |ExposureMask
			    |LeaveWindowMask);

static int vsize, hsize, hpixels;
static char *oldpixbuf;

struct vidbuf_description gfxvidinfo;

void flush_line(int y)
{
    int xs = 0, xe = hsize - 1;
    int len;
    char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
    
#ifndef LOW_BANDWIDTH
    fprintf(stderr, "Bug!\n");
#endif
	
    switch(bitdepth) {
     case 24: case 32:
	{
	    int *newp = (int *)linebuf;
	    int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes);
	    while (newp[xs] == oldp[xs]) {
		if (xs == xe)
		    return;
		xs++;
	    }
	    while (newp[xe] == oldp[xe]) xe--;

	    memcpy (oldp + xs, newp + xs, 4 * (xe - xs + 1));	                   
	}
	break;
     case 16: case 12:
	{
	    short *newp = (short *)linebuf;
	    short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes);
	    while (newp[xs] == oldp[xs]) {
		if (xs == xe)
		    return;
		xs++;
	    }
	    while (newp[xe] == oldp[xe]) xe--;

	    memcpy (oldp + xs, newp + xs, 2 * (xe - xs + 1));
	}
	break;
     case 8:
	{
	    char *newp = (char *)linebuf;
	    char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes);
	    while (newp[xs] == oldp[xs]) {
		if (xs == xe)
		    return;
		xs++;
	    }
	    while (newp[xe] == oldp[xe]) xe--;

	    memcpy (oldp + xs, newp + xs, 1 * (xe - xs + 1));
	}
	break;
    }

    len = xe - xs + 1;
    
#ifdef DONT_WANT_SHM
    XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1);
#else
    XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0);
#endif
}

void flush_block (int ystart, int ystop)
{
    int len, xs;
    if (use_lores) {
	len = 320;
	xs = prev_max_diwstop - 328;
    } else {
	len = hpixels;
	xs = 0;
    }
#ifdef DONT_WANT_SHM
    XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, 
	      ystop - ystart + 1);
#else
    XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
		 ystop - ystart + 1, 0);
#endif
}

void flush_screen (int ystart, int ystop)
{
#ifndef DONT_WANT_SHM
    XSync(display, 0);
#endif
}

#ifndef DONT_WANT_SHM
static void initShm(int depth)
{
    img = XShmCreateImage(display, vis, depth,
			  ZPixmap, 0, &shminfo, hsize, vsize);
    
    shminfo.shmid = shmget(IPC_PRIVATE, vsize * img->bytes_per_line,
			   IPC_CREAT | 0777);
    shminfo.shmaddr = img->data = (char *)shmat(shminfo.shmid, 0, 0);
    shminfo.readOnly = False;
    /* let the xserver attach */
    XShmAttach(display, &shminfo);
    /* NOW ! */
    XSync(display,0);
    /* now deleting means making it temporary */
    shmctl(shminfo.shmid, IPC_RMID, 0);
    
    gfxvidinfo.bufmem = img->data;
    gfxvidinfo.rowbytes = img->bytes_per_line;
}
#endif

static __inline__ int bitsInMask(unsigned long mask)
{
    /* count bits in mask */
    int n = 0;
    while(mask) {
	n += mask&1;
	mask >>= 1;
    }
    return n;
}

static __inline__ int maskShift(unsigned long mask)
{
    /* determine how far mask is shifted */
    int n = 0;
    while(!(mask&1)) {
	n++;
	mask >>= 1;
    }
    return n;
}

static int get_color(int r, int g, int b, xcolnr *cnp)
{
    XColor col;
    char str[10];
    sprintf(str, "rgb:%x/%x/%x", r, g, b);
    XParseColor(display, cmap, str, &col);
    if (XAllocColor(display, cmap, &col)) {
	*cnp = col.pixel;
	return 1;
    }
    return 0;
}

static int init_colors(void)
{
    if (visualInfo.depth != 8 && visualInfo.depth != 12 
	&& visualInfo.depth != 16 && visualInfo.depth != 24) {
    	fprintf(stderr, "Unsupported bit depth (%d)\n", visualInfo.depth);
	return 0;
    }
    
#ifdef __cplusplus
    switch(visualInfo.c_class) 
#else
    switch(visualInfo.class) 
#endif
    {
     case TrueColor: 
	{	    
	    int red_bits = bitsInMask(visualInfo.red_mask);
	    int green_bits = bitsInMask(visualInfo.green_mask);
	    int blue_bits = bitsInMask(visualInfo.blue_mask);
	    int red_shift = maskShift(visualInfo.red_mask);
	    int green_shift = maskShift(visualInfo.green_mask);
	    int blue_shift = maskShift(visualInfo.blue_mask);
	    alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, 
			    green_shift, blue_shift);
	}
	break;

     case GrayScale:
     case PseudoColor:
	alloc_colors256(get_color);
	break;
	
     default:
#ifdef __cplusplus
	fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class);
#else
	fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class);
#endif
	return 0;
    }
    return 1;
}

int graphics_init(void)
{
    int i;
    char *display_name = 0;
    XSetWindowAttributes wattr;

    if (screen_res < 3) {
#ifdef LOW_BANDWIDTH
	fprintf(stderr, "Low resolution mode not supported with LOW_BANDWIDTH.\n");
	return 0;
#else
	fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n");
#endif
    }
    
    display = XOpenDisplay(display_name);
    if (display == 0)  {
	fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
	return 0;
    }
    screen = XDefaultScreen(display);
    rootwin = XRootWindow(display,screen);
    
    /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
    if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
    } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
    } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
    } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
	/* for our HP boxes */
    } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
    } else {
	fprintf(stderr, "Can't obtain appropriate X visual\n");
	return 0;
    }

    vis = visualInfo.visual;
    bitdepth = visualInfo.depth;

    gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
			   : bitdepth == 12 || bitdepth == 16 ? 2
			   : 1);
    vsize = dont_want_aspect ? numscrlines : 2*numscrlines;
    hsize = use_lores ? 400 : 800;
    hpixels = use_lores ? 320 : 796;
    fprintf(stderr, "Using %d bit visual\n", bitdepth);

    cmap = XCreateColormap(display, rootwin, vis, AllocNone);
    XParseColor(display, cmap, "#000000", &black);
    if (!XAllocColor(display, cmap, &black))
	fprintf(stderr, "Whoops??\n");
    XParseColor(display, cmap, "#ffffff", &white);
    if (!XAllocColor(display, cmap, &white))
	fprintf(stderr, "Whoops??\n");

    wattr.event_mask = eventmask;
    wattr.background_pixel = black.pixel;
    wattr.backing_store = Always;
    wattr.backing_planes = bitdepth;
    wattr.border_pixmap = None;
    wattr.border_pixel = black.pixel;
    wattr.colormap = cmap;

    mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0,
			  bitdepth, InputOutput, vis,
			  CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
			  |CWBackingPlanes|CWColormap,
			  &wattr);
    XMapWindow(display,mywin);
    XStoreName(display, mywin, "UAE");
    
    blankCursor = XCreatePixmapCursor(display,
				      XCreatePixmap(display, mywin, 1, 1, 1),
				      XCreatePixmap(display, mywin, 1, 1, 1), 
				      &black, &white, 0, 0);
    xhairCursor = XCreateFontCursor(display, XC_crosshair);

    whitegc = XCreateGC(display,mywin,0,0);
    blackgc = XCreateGC(display,mywin,0,0);
    
    XSetForeground(display,blackgc,black.pixel);
    XSetForeground(display,whitegc,white.pixel);

#ifdef DONT_WANT_SHM
    gfxvidinfo.rowbytes = hsize * gfxvidinfo.pixbytes;
    gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize);
    img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, gfxvidinfo.bufmem, 
		       hsize, vsize, 32, 0);
#else
    initShm (bitdepth);
#endif
#ifdef LOW_BANDWIDTH
    gfxvidinfo.maxblocklines = 0;
    oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize);
#else
    gfxvidinfo.maxblocklines = 100; /* whatever... */
#endif

    if (!init_colors())
	return 0;
    
    buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
    for(i=0; i<256; i++)
	keystate[i] = 0;
    
    lastmx = lastmy = 0; 
    newmousecounters = 0;
    inwindow = 0;
    
    if (use_xhair)
	XDefineCursor(display, mywin, xhairCursor);
    else
	XDefineCursor(display, mywin, blankCursor);
    cursorOn = 1;
    return 1;
}

void graphics_leave(void)
{
    XAutoRepeatOn(display);
}

/* Decode KeySyms. This function knows about all keys that are common 
 * between different keyboard languages. */
static int kc_decode (KeySym ks)
{
    switch (ks) {	
     case XK_B: case XK_b: return AK_B;
     case XK_C: case XK_c: return AK_C;
     case XK_D: case XK_d: return AK_D;
     case XK_E: case XK_e: return AK_E;
     case XK_F: case XK_f: return AK_F;
     case XK_G: case XK_g: return AK_G;
     case XK_H: case XK_h: return AK_H;
     case XK_I: case XK_i: return AK_I;
     case XK_J: case XK_j: return AK_J;
     case XK_K: case XK_k: return AK_K;
     case XK_L: case XK_l: return AK_L;
     case XK_N: case XK_n: return AK_N;
     case XK_O: case XK_o: return AK_O;
     case XK_P: case XK_p: return AK_P;
     case XK_R: case XK_r: return AK_R;
     case XK_S: case XK_s: return AK_S;
     case XK_T: case XK_t: return AK_T;
     case XK_U: case XK_u: return AK_U;
     case XK_V: case XK_v: return AK_V;
     case XK_W: case XK_w: return AK_W;
     case XK_X: case XK_x: return AK_X;
	
     case XK_0: return AK_0;
     case XK_1: return AK_1;
     case XK_2: return AK_2;
     case XK_3: return AK_3;
     case XK_4: return AK_4;
     case XK_5: return AK_5;
     case XK_6: return AK_6;
     case XK_7: return AK_7;
     case XK_8: return AK_8;
     case XK_9: return AK_9;
	
	/* You never know which Keysyms might be missing on some workstation
	 * This #ifdef should be enough. */
#if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
     case XK_KP_0: case XK_KP_Insert: return AK_NP0;
     case XK_KP_1: case XK_KP_End: return AK_NP1;
     case XK_KP_2: case XK_KP_Down: return AK_NP2;
     case XK_KP_3: case XK_KP_Next: return AK_NP3;
     case XK_KP_4: case XK_KP_Left: return AK_NP4;
     case XK_KP_5: case XK_KP_Begin: return AK_NP5;
     case XK_KP_6: case XK_KP_Right: return AK_NP6;
     case XK_KP_7: case XK_KP_Home: return AK_NP7;
     case XK_KP_8: case XK_KP_Up: return AK_NP8;
     case XK_KP_9: case XK_KP_Prior: return AK_NP9;
#else
     case XK_KP_0: return AK_NP0;
     case XK_KP_1: return AK_NP1;
     case XK_KP_2: return AK_NP2;
     case XK_KP_3: return AK_NP3;
     case XK_KP_4: return AK_NP4;
     case XK_KP_5: return AK_NP5;
     case XK_KP_6: return AK_NP6;
     case XK_KP_7: return AK_NP7;
     case XK_KP_8: return AK_NP8;
     case XK_KP_9: return AK_NP9;
#endif
     case XK_KP_Divide: return AK_NPDIV;
     case XK_KP_Multiply: return AK_NPMUL;
     case XK_KP_Subtract: return AK_NPSUB;
     case XK_KP_Add: return AK_NPADD;
     case XK_KP_Decimal: return AK_NPDEL;
     case XK_KP_Enter: return AK_ENT;

     case XK_F1: return AK_F1;
     case XK_F2: return AK_F2;
     case XK_F3: return AK_F3;
     case XK_F4: return AK_F4;
     case XK_F5: return AK_F5;
     case XK_F6: return AK_F6;
     case XK_F7: return AK_F7;
     case XK_F8: return AK_F8;
     case XK_F9: return AK_F9;
     case XK_F10: return AK_F10;
	    
     case XK_BackSpace: return AK_BS;
     case XK_Delete: return AK_DEL;
     case XK_Control_L: case XK_Control_R: return AK_CTRL;
     case XK_Tab: return AK_TAB;
     case XK_Alt_L: return AK_LALT;
     case XK_Alt_R: return AK_RALT;
     case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
     case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
     case XK_Return: return AK_RET;
     case XK_space: return AK_SPC;
     case XK_Shift_L: return AK_LSH;
     case XK_Shift_R: return AK_RSH;
     case XK_Escape: return AK_ESC;

     case XK_Insert: return AK_BACKSLASH;
     case XK_End: return AK_HELP;
     case XK_Caps_Lock: return AK_CAPSLOCK;
	
     case XK_Up: return AK_UP;
     case XK_Down: return AK_DN;
     case XK_Left: return AK_LF;
     case XK_Right: return AK_RT;
	
     case XK_F11: return AK_BACKSLASH;
     case XK_F12: return AK_mousestuff;
#ifdef XK_F14
     case XK_F14:
#endif
     case XK_Scroll_Lock: return AK_inhibit;

#ifdef XK_Page_Up /* These are missing occasionally */
     case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
     case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
#endif
    }
    return -1;
}

static int decode_fr(KeySym ks)
{
    switch(ks) {        /* FR specific */
     case XK_A: case XK_a: return AK_Q;
     case XK_M: case XK_m: return AK_SEMICOLON; 
     case XK_Q: case XK_q: return AK_A;	
     case XK_Y: case XK_y: return AK_Y;
     case XK_Z: case XK_z: return AK_Z;
     case XK_bracketleft: return AK_LBRACKET;
     case XK_bracketright: return AK_RBRACKET;
     case XK_comma: return AK_M;
     case XK_less: case XK_greater: return AK_LTGT;
     case XK_period: return AK_COMMA;
     case XK_parenright: return AK_MINUS;
     case XK_equal: return AK_SLASH;
     case XK_numbersign: return AK_NUMBERSIGN;
     case XK_slash: return AK_PERIOD;
     case XK_minus: return AK_EQUAL;
     case XK_backslash: return AK_BACKSLASH;
    }

    return -1;
}

static int decode_us(KeySym ks)
{
    switch(ks) {	/* US specific */	
     case XK_A: case XK_a: return AK_A;
     case XK_M: case XK_m: return AK_M;
     case XK_Q: case XK_q: return AK_Q;
     case XK_Y: case XK_y: return AK_Y;
     case XK_Z: case XK_z: return AK_Z;
     case XK_bracketleft: return AK_LBRACKET;
     case XK_bracketright: return AK_RBRACKET;
     case XK_comma: return AK_COMMA;
     case XK_period: return AK_PERIOD;
     case XK_slash: return AK_SLASH;
     case XK_semicolon: return AK_SEMICOLON;
     case XK_minus: return AK_MINUS;
     case XK_equal: return AK_EQUAL;
	/* this doesn't work: */
     case XK_quoteright: return AK_QUOTE;
     case XK_quoteleft: return AK_BACKQUOTE;
     case XK_backslash: return AK_NUMBERSIGN;
    }

    return -1;
}

static int decode_de(KeySym ks)
{
    switch(ks) {
	/* DE specific */
     case XK_A: case XK_a: return AK_A;
     case XK_M: case XK_m: return AK_M;
     case XK_Q: case XK_q: return AK_Q;
     case XK_Y: case XK_y: return AK_Z;
     case XK_Z: case XK_z: return AK_Y;
     case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
     case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
     case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
     case XK_plus: case XK_asterisk: return AK_RBRACKET;
     case XK_comma: return AK_COMMA;
     case XK_period: return AK_PERIOD;
     case XK_less: case XK_greater: return AK_LTGT;
     case XK_numbersign: return AK_NUMBERSIGN;
     case XK_ssharp: return AK_MINUS;
     case XK_apostrophe: return AK_EQUAL;
     case XK_asciicircum: return AK_BACKQUOTE;
     case XK_minus: return AK_SLASH;
    }

    return -1;
}

static int decode_se(KeySym ks)
{
    switch(ks) {
	/* SE specific */
     case XK_A: case XK_a: return AK_A;
     case XK_M: case XK_m: return AK_M;
     case XK_Q: case XK_q: return AK_Q;
     case XK_Y: case XK_y: return AK_Y;
     case XK_Z: case XK_z: return AK_Z;
     case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
     case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
     case XK_Aring: case XK_aring: return AK_LBRACKET;
     case XK_comma: return AK_COMMA;
     case XK_period: return AK_PERIOD;
     case XK_minus: return AK_SLASH;
     case XK_less: case XK_greater: return AK_LTGT;
     case XK_plus: case XK_question: return AK_EQUAL;
     case XK_at: case XK_onehalf: return AK_BACKQUOTE;
     case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
     case XK_backslash: case XK_bar: return AK_MINUS;
	
     case XK_numbersign: return AK_NUMBERSIGN;
    }

    return -1;
 }

static int decode_it(KeySym ks)
{
    switch(ks) {
	/* IT specific */
     case XK_A: case XK_a: return AK_A;
     case XK_M: case XK_m: return AK_M;
     case XK_Q: case XK_q: return AK_Q;
     case XK_Y: case XK_y: return AK_Y;
     case XK_Z: case XK_z: return AK_Z;
     case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
     case XK_Agrave: case XK_agrave: return AK_QUOTE;
     case XK_Egrave: case XK_egrave: return AK_LBRACKET;
     case XK_plus: case XK_asterisk: return AK_RBRACKET;
     case XK_comma: return AK_COMMA;
     case XK_period: return AK_PERIOD;
     case XK_less: case XK_greater: return AK_LTGT;
     case XK_backslash: case XK_bar: return AK_BACKQUOTE;               
     case XK_apostrophe: return AK_MINUS;           
     case XK_Igrave: case XK_igrave: return AK_EQUAL;
     case XK_minus: return AK_SLASH;
     case XK_numbersign: return AK_NUMBERSIGN;
    }

    return -1;
}

static int keycode2amiga(XKeyEvent *event)
{
    KeySym ks;
    int as;
    int index = 0;
    
    do {
	ks = XLookupKeysym(event, index);
	as = kc_decode (ks);
	
	if (as == -1) {	    
	    switch(keyboard_lang) {

	    case KBD_LANG_FR:
		as = decode_fr(ks);
		break;

 	    case KBD_LANG_US:
		as = decode_us(ks);
		break;
		
	     case KBD_LANG_DE:
		as = decode_de(ks);
		break;
		
	     case KBD_LANG_SE:
		as = decode_se(ks);
		break;
		
	     case KBD_LANG_IT:
		as = decode_it(ks);
		break;

	     default:
		as = -1;
		break;
	    }
	}
	if(-1 != as)
		return as;
	index++;
    } while (ks != NoSymbol);
    return -1;
}

static struct timeval lastMotionTime;

void handle_events(void)
{
    int repeat, refresh = 0;
    newmousecounters = 0;
    gui_handle_events();
    
    do {
	XEvent event;
	if (!XCheckMaskEvent(display, eventmask, &event)) break;
	repeat = 0;
	
	switch(event.type) {
	 case KeyPress: {		
	     int kc = keycode2amiga((XKeyEvent *)&event);
	     if (kc == -1) break;
	     switch (kc) {
	      case AK_mousestuff:
		 togglemouse();
		 break;

	      case AK_inhibit:
		 inhibit_frame ^= 1;
		 break;

	      default:
	     	 if (!keystate[kc]) {
		     keystate[kc] = 1;
		     record_key (kc << 1);
		 }
		 break;
	     }
	     break;
	 }
	 case KeyRelease: {	     
	     int kc = keycode2amiga((XKeyEvent *)&event);
	     if (kc == -1) break;
	     keystate[kc] = 0;
	     record_key ((kc << 1) | 1);
	     break;
	 }
	 case ButtonPress:
	    buttonstate[((XButtonEvent *)&event)->button-1] = 1;
	    break;
	 case ButtonRelease:
	    buttonstate[((XButtonEvent *)&event)->button-1] = 0;
	    break;
	 case EnterNotify:
	    newmousecounters = 1;
	    lastmx = ((XCrossingEvent *)&event)->x;
	    lastmy = ((XCrossingEvent *)&event)->y;
	    repeat = 1;
	    inwindow = 1;
	    break;
	 case LeaveNotify:
	    inwindow = 0;
	    repeat = 1;
	    break;
	 case FocusIn:
	    XAutoRepeatOff(display);
	    repeat = 1;
	    break;
	 case FocusOut:
	    XAutoRepeatOn(display);
	    repeat = 1;
	    break;
	 case MotionNotify:
	    if (inwindow) {		
		lastmx = ((XMotionEvent *)&event)->x;
		lastmy = ((XMotionEvent *)&event)->y;
		if(!cursorOn && use_xhair) {
		    XDefineCursor(display, mywin, xhairCursor);
		    cursorOn = 1;
		}
		gettimeofday(&lastMotionTime, NULL);
	    }
	    repeat = 1;
	    break;
	 case Expose:
	    refresh = 1;
	    repeat  = 1;
	    break;
	}
    } while (repeat);

#ifdef DONT_WANT_SHM
    if(refresh) 
	XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize);
#else
    if(refresh)
	XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0);
#endif
    if(cursorOn && use_xhair) {
	struct timeval now;
	int diff;
	gettimeofday(&now, NULL);
	diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + 
	    (now.tv_usec - lastMotionTime.tv_usec);
	if(diff > 1000000) {
	    XDefineCursor(display, mywin, blankCursor);
	    cursorOn = 0;
	}
    }
	
    /* "Affengriff" */
    if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
    	MC68000_reset();
}

int debuggable(void)
{
    return 1;
}

int needmousehack(void)
{
    return 1;
}

void LED(int on)
{
    XKeyboardControl control;
    control.led = 1; /* implementation defined */
    control.led_mode = on ? LedModeOn : LedModeOff;
    XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
}

unix.superglobalmegacorp.com

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