--- xc-6.8.1/programs/Xserver/hw/xfree86/input/keyboard/kbd.c	2004-12-11 18:33:18 -0600
+++ xc/programs/Xserver/hw/xfree86/input/keyboard/kbd.c	2004-12-15 03:29:09 -0600
@@ -535,6 +535,7 @@ PostKbdEvent(InputInfoPtr pInfo, unsigne
   int         keycode;
   unsigned long changeLock = 0;
   static int  lockkeys = 0;
+  static int  spacebarState = 0;
 
   /* Disable any keyboard processing while in suspend */
   if (xf86inSuspend)
@@ -554,6 +555,135 @@ PostKbdEvent(InputInfoPtr pInfo, unsigne
      }
   }
 
+
+  /* BEGIN MODIFICATION */
+
+  /*
+   * Half-key translation is a method of making all common keys
+   *  available to a single hand by logically mirroring the keys over
+   *  the center axis by using an easily accessible key as a toggle
+   *  (usually the space bar).
+   *  
+   * Now do half-key translation...
+   */
+  if(scanCode == 0x39) /* check for spacebar */
+  {
+     /*
+      * A state machine is at the heart of the logic of whether to
+      *  mirror the keys or not.
+      *
+      * State 0 - Indicates that the spacebar has not been pressed.
+      * State 1 - Indicates the spacebar is down, but do not know
+      *            whether mirror mode should be entered or a literal
+      *            space should be inserted. Wait until next keystroke
+      *            to decide.
+      * State 2 - Indicates the spacebar is down and a mirror-translated
+      *            key has been pressed. Do the translation and do not
+      *            insert a literal space until spacebar goes up again
+      *            at least once.
+      * State 3 - Indicates that the spacebar has come up after more
+      *            than one mirrored key has been input. All key input
+      *            events until the next key is down should be ignored.
+      */
+     switch(spacebarState)
+     {
+        case 0: spacebarState = 1;
+                return;
+
+        case 1: if(!down)
+                {
+                   xf86PostKeyboardEvent(device, scanCode+MIN_KEYCODE, !down);
+                   xf86PostKeyboardEvent(device, scanCode+MIN_KEYCODE, down);
+                   spacebarState = 0;
+                }
+                return;
+
+        case 2: if(!down)
+                   spacebarState = 3;
+                return;
+     }
+  }
+  else if(spacebarState == 3)
+  {
+     if(!down)
+        return;
+     else
+        spacebarState = 0;
+  }
+  else if(spacebarState)
+  {
+     /* Translation modifier: */
+     unsigned int transMod = 0;     
+
+     /* The half-key style layout essentially reverses the L-to-R
+      *  order of the keys, which for the most part are also found in
+      *  single-incrementing valued scanCodes. I reverse the scanCode
+      *  range in question with an xor-operation, then translate this
+      *  result into its proper place in the discrete number line
+      *  making use of the number's overflow properties.
+      *
+      * The amount the scanCode needs to be translated is dependent on
+      *  what range the number is in. Whatever the size range (single
+      *  key or many), if there are an odd number of scanCodes contained
+      *  one must be added to the result to map correctly.
+      *
+      *  single scanCode range:
+      *   transMod = (scanCodeFinal) + (scanCodeOriginal) + 1;
+      *
+      *  multiple scanCode range (odd number contained):
+      *   transMod = (lowerBound) + (upperBound) + 1;
+      *
+      *  multiple scanCode range (even number contained):
+      *   transMod = (lowerBound) + (upperBound);
+      *
+      *  This method is the way that logically made the most sense to
+      *   me. I'm sure there's other (read: better) ways, and I'm open
+      *   to suggestions.
+      *
+      *  See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html#ss1.4
+      *   for scancode reference table.
+      */
+
+     /* Check for key '`': */
+     if(scanCode == 0x29) transMod = 0x0C+0x29+1;
+     /* Check for range '1'-'-': */
+     else if(scanCode >= 0x02 && scanCode <= 0x0C) transMod = 0x02+0x0C;
+     /* Check for range TAB-'[': */
+     else if(scanCode >= 0x0F && scanCode <= 0x1A) transMod = 0x0F+0x1A+1;
+     /* Check for key CAPSLOCK: */
+     else if(scanCode == 0x3A) transMod = 0x28+0x3A+1;
+     /* Check for range 'A'-';': */
+     else if(scanCode >= 0x1E && scanCode <= 0x27) transMod = 0x1E +0x27+1;
+     /* Check for range 'Z'-'/': */
+     else if(scanCode >= 0x2C && scanCode <= 0x35) transMod = 0x2C+0x35+1;
+
+     if(transMod)
+     {
+        if(!down && spacebarState != 2)
+           return;
+
+        if(spacebarState == 1) spacebarState = 2;
+
+        /* Logically "reverse" a number range: */
+        scanCode ^= -1;
+	/* Logically translate it back to its original
+	 * position in number line (makes use of overflow): */
+        scanCode += transMod;
+
+        /* Take care of those mapped out of range: */
+        switch(scanCode)
+        {
+           case 0x01: scanCode = 0x29; /* '-' to '`' */
+                      break;
+           case 0x1A: scanCode = 0x0E; /* TAB to BS */
+                      break;
+        }
+     }
+  }
+	
+  /* END MODIFICATION */
+
+
   /*
    * and now get some special keysequences
    */
