--- Xvisual.h.orig      Sun Mar 15 09:33:49 1998
+++ Xvisual.h   Mon Apr 27 05:02:01 1998
@@ -23,6 +23,9 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#ifdef XF86MISC
+#  include <X11/extensions/xf86misc.h>
+#endif

#if defined(__CYGWIN32__) || defined (_AIX)
#define NO_SHM
@@ -77,6 +80,20 @@
       sint16 oldmousex;
       sint16 oldmousey;
       uint8 relptr_keymask;
+
+               /* default kbd rates: */
+       int  initial_key_delay;
+       int  key_delay;
+
+       struct timeval last_tv;
+       int  last_time;
+       char last_code;
+       int  last_repeating;
+       int  last_sym;
+               /* To get kbd repeat rate settings: */
+#ifdef XF86MISC
+       XF86MiscKbdSettings kbdinfo;
+#endif
};

#define XLIB_PRIV(vis) ((struct Xhooks *)VIS_PRIVATE(vis))
--- events.c.orig       Tue Mar 10 09:33:54 1998
+++ events.c    Mon Apr 27 05:02:01 1998
@@ -40,9 +40,10 @@

#include <X11/cursorfont.h>

+
static uint32 translate_key(KeySym sym)
{
-       switch(sym) {
+       switch(sym) {
               case XK_VoidSymbol: return U(K_VOID);
               case XK_BackSpace : return U(8);
               case XK_Tab       : return U(9);
@@ -663,12 +664,12 @@
                           struct timeval *t)
{
#define BUFFER_SIZE (sizeof(ggi_event)*4)
-
-
+
+
#define XlibWaitLock   while(xhook->XLibLock++!=0) \
       {xhook->XLibLock--;usleep(1000);}     /* FIXME use spinlocks here !*/
#define        XlibReleaseLock xhook->XLibLock--
-
+
       KeySym relsyms[RELPTR_NUMKEYS] = RELPTR_KEYS;
       fd_set fds;
       int err,n;
@@ -684,8 +685,50 @@
       DPRINT(",{%d,%d})\n",t->tv_sec,t->tv_usec);
}

+                               /* WHS: autorepeat stuff */
+                       if (xhook->last_sym) {
+                               long sec_diff, usec_diff, total_diff;
+
+                               gettimeofday(&tod,NULL);
+                               sec_diff = tod.tv_sec-xhook->last_tv.tv_sec;
+                               usec_diff = tod.tv_usec-xhook->last_tv.tv_usec;
+                               total_diff = (sec_diff-1)*1000+((usec_diff+1000000)/1000); /*approx milliseconds */
+
+                               ggievent.any.type=evKeyRepeat;
+                               ggievent.key.sym=xhook->last_sym;
+                               ggievent.key.code=xhook->last_code;
+
+                               ggievent.any.size=sizeof(ggi_key_event);
+                               ggievent.key.effect=0;
+                               ggievent.key.normal=0;
+                               ggievent.key.locked=0;
+                               ggievent.key.sticky=0;
+
+                               while (total_diff>xhook->key_delay) { /* assume initial_key_delay>key_delay */
+                                       if (!xhook->last_repeating) {
+                                               if (total_diff>xhook->initial_key_delay) {      /* First repeat */
+                                                       xhook->last_repeating=1;
+                                                       _ggiEvQueueAdd(vis,&ggievent);
+                                                       xhook->last_tv.tv_usec +=xhook->initial_key_delay*1000;
+                                                       if (xhook->last_tv.tv_usec >1000000) { xhook->last_tv.tv_usec -=1000000; xhook->last_tv.tv_sec++; }
+                                                       total_diff -=xhook->initial_key_delay;
+                                               }
+                                               else { /* Not time yet for first repeat */
+                                                       break;
+                                               }
+                                       }
+                                       else { /* 2+ repeat */
+                                               _ggiEvQueueAdd(vis,&ggievent);
+                                               xhook->last_tv.tv_usec +=xhook->key_delay*1000;
+                                               if (xhook->last_tv.tv_usec >1000000) { xhook->last_tv.tv_usec -=1000000; xhook->last_tv.tv_sec++; }
+                                               total_diff -=xhook->key_delay;
+                                       }
+                               }
+                       }
+
+
       evmask=_ggiEvQueueSeen(vis,mask);
-       if (evmask!=0)
+       if (evmask!=0)
               return evmask;

       gettimeofday(&tod,NULL);
@@ -742,7 +785,7 @@
                       ggievent.any.time=0;    /* FIXME ! */
                       ggievent.any.type=0;

-                       switch(event.type) {
+                       switch(event.type) {
                               case KeyPress:
                               {
                                       int i;
@@ -795,6 +838,20 @@
                                       ggievent.key.sym=translate_key(sym);
                                       XlibReleaseLock;
                                       ggievent.key.code=event.xkey.keycode;
+
+                                               /* WHS: autorepeat */
+                                       if (event.xkey.time>xhook->last_time) { /* New key press, is it a repeat-allowed one? */
+                                               if (sym<256 || sym==XK_Tab || sym==XK_Delete) { /* or allow repeats for verything but Ctrl,Shift, Alt? */
+                                                       xhook->last_sym=sym;
+                                                       xhook->last_code=event.xkey.keycode;
+                                                       xhook->last_time=event.xkey.time;
+                                                       xhook->last_tv.tv_sec=tod.tv_sec;
+                                                       xhook->last_tv.tv_usec=tod.tv_usec;
+                                                       xhook->last_repeating=0;
+                                               }
+                                               else xhook->last_sym=0;
+                                       }
+
                                       break;
                               }
                               case KeyRelease:
@@ -812,7 +869,14 @@
                                       ggievent.key.sym=translate_key(sym);
                                       XlibReleaseLock;
                                       ggievent.key.code=event.xkey.keycode;
-                                       DPRINT("KeyRelease.\n"); break;
+
+                                       if (xhook->last_sym==sym) {
+                                               xhook->last_sym=0;
+                                               xhook->last_repeating=0;
+                                       }
+                                       DPRINT("KeyRelease.\n");
+                                       break;
+
                               }
                               case ButtonPress:
                                       ggievent.any.type=evPtrButtonPress;
@@ -868,9 +932,25 @@
                                       DPRINT("MouseMove %d,%d.\n",
                                                  event.xmotion.x,event.xmotion.y);
                                       break;
+
+                       case EnterNotify:
+                                       /* Adjust settings (may have changed while we were away) */
+#ifdef XF86MISC
+                               XF86MiscGetKbdSettings(xhook->display, &kbdinfo);
+                               initial_key_delay = kbdinfo.delay;
+                               key_delay = 1000/kbdinfo.rate;
+#endif
+                               XAutoRepeatOff(xhook->display);
+                               xhook->last_sym=0;
+                               break;
+                       case LeaveNotify:
+                               XAutoRepeatOn(xhook->display);
+                               xhook->last_sym=0;
+                       break;
+
                               default:
                                       DPRINT("Other Event (%d).\n",event.type); break;
-                       }
+                       }
                       switch(ggievent.any.type) {
                               case evKeyPress:
                               case evKeyRelease:
--- mode.c.orig Thu Apr 23 20:24:27 1998
+++ mode.c      Mon Apr 27 05:24:45 1998
@@ -39,6 +39,7 @@
#include "Xvisual.h"
#include "../common/X-mode.inc"

+
int GGIsetorigin(ggi_visual *vis,int x,int y)
{
       struct Xhooks *xhook=VIS_PRIVATE(vis);
@@ -199,6 +200,28 @@
                                 xhook->visheight-xhook->ysplit);
       }

+               /* autorepeat stuff */
+               /* restore kbd even when not listening to ggi events */
+       {
+               XEvent xevent;
+               while (XCheckMaskEvent(xhook->display, EnterWindowMask | LeaveWindowMask, &xevent)) {
+                       switch (xevent.xany.type) {
+                       case EnterNotify:
+                                       /* Adjust settings (may have changed while we were away) */
+#ifdef XF86MISC
+                               XF86MiscGetKbdSettings(xhook->display, &xhook->kbdinfo);
+                               xhook->initial_key_delay = kbdinfo.delay;
+                               xhook->key_delay = 1000/kbdinfo.rate;
+#endif
+                               XAutoRepeatOff(xhook->display);
+                               xhook->last_sym=0;
+                               break;
+                       }
+               }
+       }
+
+
+
       XSync(xhook->display,0);
       xhook->XLibLock--;      /* FIXME Spinlocks ... */

@@ -294,6 +317,7 @@
       XSelectInput(xhook->display, xhook->window,
                    KeyPressMask|KeyReleaseMask|
                    ButtonPressMask|ButtonReleaseMask|
+                                EnterWindowMask | LeaveWindowMask |
                    PointerMotionMask);

       /* Tell other applications about this window */
@@ -398,6 +422,7 @@
       XSelectInput(xhook->display, xhook->window,
                                KeyPressMask|KeyReleaseMask|
                                ButtonPressMask|ButtonReleaseMask|
+                                EnterWindowMask | LeaveWindowMask |
                                PointerMotionMask);

       if (xhook->cmap)
@@ -407,10 +432,10 @@
               xhook->cmap = XCreateColormap(xhook->display, xhook->window,
                                                                         vinfo.visual,
                                                                         AllocAll);
-
+
               xhook->cmap_first=256;
               xhook->cmap_last=0;
-
+
               DPRINT("X-lib colormap allocated %x.\n",xhook->cmap);
       } else {
               xhook->cmap = XCreateColormap(xhook->display, xhook->window,
--- visual.c.orig       Fri Apr 24 02:02:22 1998
+++ visual.c    Mon Apr 27 05:19:27 1998
@@ -66,8 +66,14 @@
       xinfo->isasync=1;  /* Yes, this SHOULD be initialized to 1. */
       xinfo->relptr=0;
       xinfo->relptr_keymask = RELPTR_KEYINUSE;
-       xinfo->colormap=NULL;
-
+
+               /* autorepeat stuff */
+       xinfo->initial_key_delay = 500; /* delay until the first repeat of a key */
+       xinfo->key_delay = 50;
+       xinfo->last_repeating=0;
+       xinfo->last_sym=0;
+
+       xinfo->colormap=NULL;
//printf("colormap set to NULL\n");
       /* We do not use the XLibLock here, as there is no concurrent thread yet. */

@@ -78,6 +84,9 @@

       DPRINT("X-lib has display %s.\n",args);

+               /* autorepeat stuff */
+       XAutoRepeatOff(xinfo->display);
+
#ifndef NO_SHM
       if (XShmQueryExtension(xinfo->display)) {

@@ -114,7 +123,7 @@
       struct Xhooks *xinfo;

    ggiFlush(vis);
-
+
       /* prevents a soon-to-be unloaded function from being called */
       if (!(VIS_FLAGS(vis) & GGIFLAG_ASYNC))
               _mansync_stop(vis);
@@ -138,8 +147,10 @@
                       XFreeGC(xinfo->display,xinfo->gc);
        if (xinfo->window)
                       XDestroyWindow(xinfo->display,xinfo->window);
-               if (xinfo->display)
+               if (xinfo->display) {
+                       XAutoRepeatOn(xinfo->display); /* always on, other behaviour (getting the settings on enter/leave notify) isn't really dependable as programs running in the bg might quit and mess things up while this app has control */
                       XCloseDisplay(xinfo->display);
+               }
               free(VIS_PRIVATE(vis));
       }