# usbhotkey script to handle the Alphagrip AG5
# Copyright (C) 2007  Lars Krueger
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

# We assume a UK keymap here. For a US keymap exchange " and @

print "usbhotkey AG5 script starting\n"

# This script places all mappings in ruby tables which are indexed by some
# state variable and the USB scan code. The keys are mapped to a
# normalised id first.

# The basic idea of this script is to provide access to both the red and green
# colour levels. This is done by remapping the thumb keys so that they work as
# shift keys. This script maps K to green and L to the red shift key. The
# right hand side is handled accordingly.  Support for more modifiers (Ctrl,
# Alt, Windows) may be added later.
#
# A letter key produces a letter if it is pressed and release alone, thus
# K-press, K-release produces a k. K-press, N-press, N-release, K-release
# produces Green-N, therefore the question mark. This makes the shift letters
# generate events at release and therefore turns off auto-repeat for these
# keys.
#
# All keys can send X11 keycode sequences of arbitrary length.


##################################### Keymap ###################################
#================================ USB code to id ===============================
KeyId={
  USB_g         => 0 ,
  USB_r         => 1 ,
  USB_f         => 2 ,
  USB_t         => 3 ,
  USB_d         => 4 ,
  USB_e         => 5 ,
  USB_w         => 6 ,
  USB_s         => 7 ,
  USB_q         => 8 ,
  USB_a         => 9 ,
  USB_m         => 10,
  USB_h         => 11,
  USB_n         => 12,
  USB_u         => 13,
  USB_i         => 14,
  USB_Comma     => 15,
  USB_o         => 16,
  USB_Period    => 17,
  USB_p         => 18,
  USB_b         => 19,
  USB_j         => 20,
  USB_v         => 21,
  USB_x         => 22,
  USB_z         => 23,
  USB_c         => 24,
  USB_y         => 25,
  USB_k         => 26,
  USB_l         => 27,
  USB_Enter     => 28,
  USB_Backspace => 29,
  USB_Space     => 30,
  USB_Tab       => 31,
}

#================================= colour keys =================================
# Map key id to colour. Regular key codes are handled below
ColourKeys={
  # Green: k, tab
  26 => 1,
  31 => 1,
  # Red: l, space
  27 => 2,
  30 => 2,
  # Fn: v, x
  21 => 3,
  22 => 3,
  # Ctrl: c, backspace
  24 => 4,
  29 => 4,
  # Alt: j, z
  20 => 5,
  23 => 5,
  # Win: y, enter
  25 => 6,
  28 => 6,
}

#================================ Normal keymap ================================
# Dimension 1 shift state
# Dimension 2 by colorshift values
# Dimension 3 by backside ID
KeyMap=[[], []]

# Normal keymap
# g|r|f|t|d|e|w|s|q|a|m|h|n|u|i|,|o|.|p|b"
KeyMap[0][0] = [ 
  [ WIN_G],
  [ WIN_R],
  [ WIN_F],
  [ WIN_T],
  [ WIN_D],
  [ WIN_E],
  [ WIN_W],
  [ WIN_S],
  [ WIN_Q],
  [ WIN_A],
  [ WIN_M],
  [ WIN_H],
  [ WIN_N],
  [ WIN_U],
  [ WIN_I],
  [ WIN_comma],
  [ WIN_O],
  [ WIN_period],
  [ WIN_P],
  [ WIN_B],
  [ WIN_J], 
  [ WIN_V], 
  [ WIN_X], 
  [ WIN_Z], 
  [ WIN_C], 
  [ WIN_Y], 
  [ WIN_K], 
  [ WIN_L], 
  [ WIN_Return],
  [ WIN_BackSpace],
  [ WIN_space],
  [ WIN_Tab],
]

# g|r|f|t|d|e|w|s|q|a|m|h|n|u|i|,|o|.|p|b"
KeyMap[1][0] = [ 
  [ WIN_Shift_L, WIN_G],
  [ WIN_Shift_L, WIN_R],
  [ WIN_Shift_L, WIN_F],
  [ WIN_Shift_L, WIN_T],
  [ WIN_Shift_L, WIN_D],
  [ WIN_Shift_L, WIN_E],
  [ WIN_Shift_L, WIN_W],
  [ WIN_Shift_L, WIN_S],
  [ WIN_Shift_L, WIN_Q],
  [ WIN_Shift_L, WIN_A],
  [ WIN_Shift_L, WIN_M],
  [ WIN_Shift_L, WIN_H],
  [ WIN_Shift_L, WIN_N],
  [ WIN_Shift_L, WIN_U],
  [ WIN_Shift_L, WIN_I],
  [ WIN_semicolon],
  [ WIN_Shift_L, WIN_O],
  [ WIN_Shift_L, WIN_semicolon],
  [ WIN_Shift_L, WIN_P],
  [ WIN_Shift_L, WIN_B],
  [ WIN_Shift_L, WIN_J],
  [ WIN_Shift_L, WIN_V],
  [ WIN_Shift_L, WIN_X],
  [ WIN_Shift_L, WIN_Z],
  [ WIN_Shift_L, WIN_C],
  [ WIN_Shift_L, WIN_Y],
  [ WIN_Shift_L, WIN_K],
  [ WIN_Shift_L, WIN_L],
  [ WIN_Shift_L, WIN_Return],
  [ WIN_Delete],
  [ WIN_Escape],
  [ WIN_Shift_L, WIN_Tab],
]

# Green keymap, ignore shift
# ~,%,"",',(,),{{},{}},[,],{^},_,?,!,&,|,<,>,``,\"
KeyMap[0][1] = [ 
  [ WIN_Shift_L, WIN_numbersign ],
  [ WIN_Shift_L, WIN_5 ],
  [ WIN_Shift_L, WIN_2 ],
  [ WIN_apostrophe],
  [ WIN_Shift_L, WIN_9 ],
  [ WIN_Shift_L, WIN_0 ],
  [ WIN_Shift_L, WIN_bracketleft ],
  [ WIN_Shift_L, WIN_bracketright ],
  [ WIN_bracketleft  ],
  [ WIN_bracketright ],
  [ WIN_Shift_L, WIN_6 ],
  [ WIN_Shift_L, WIN_minus ],
  [ WIN_Shift_L, WIN_slash ],
  [ WIN_Shift_L, WIN_1 ],
  [ WIN_Shift_L, WIN_7 ],
  [ WIN_Shift_L, WIN_backslash ],
  [ WIN_Shift_L, WIN_comma ],
  [ WIN_Shift_L, WIN_period ],
  [ WIN_quoteleft ],
  [ WIN_backslash ],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
]

KeyMap[1][1] = [ 
  [ WIN_Shift_L, WIN_numbersign ],
  [ WIN_Shift_L, WIN_5 ],
  [ WIN_Shift_L, WIN_2 ],
  [ WIN_apostrophe],
  [ WIN_Shift_L, WIN_9 ],
  [ WIN_Shift_L, WIN_0 ],
  [ WIN_Shift_L, WIN_bracketleft ],
  [ WIN_Shift_L, WIN_bracketright ],
  [ WIN_bracketleft  ],
  [ WIN_bracketright ],
  [ WIN_Shift_L, WIN_6 ],
  [ WIN_Shift_L, WIN_minus ],
  [ WIN_Shift_L, WIN_slash ],
  [ WIN_Shift_L, WIN_1 ],
  [ WIN_Shift_L, WIN_7 ],
  [ WIN_Shift_L, WIN_backslash ],
  [ WIN_Shift_L, WIN_comma ],
  [ WIN_Shift_L, WIN_period ],
  [ WIN_quoteleft ],
  [ WIN_backslash ],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
]

# Red keymap, ignore shift
# {#}|.|3|1|{+}|5|-|7|=|9|$|,|2|4|6|Enter|8|*|0|/"
KeyMap[0][2] = [ 
  [ WIN_numbersign ],
  [ WIN_period ],
  [ WIN_3 ],
  [ WIN_1 ],
  [ WIN_Shift_L, WIN_equal ],
  [ WIN_5 ],
  [ WIN_minus ],
  [ WIN_7 ],
  [ WIN_equal ],
  [ WIN_9 ],
  [ WIN_Shift_L, WIN_4 ],
  [ WIN_comma ],
  [ WIN_2 ],
  [ WIN_4 ],
  [ WIN_6 ],
  [ WIN_Return ],
  [ WIN_8 ],
  [ WIN_Shift_L, WIN_8 ],
  [ WIN_0 ],
  [ WIN_slash ],
  [ WIN_Shift_L, WIN_apostrophe],
  [],
  [],
  [],
  [ WIN_Up ],
  [ WIN_Right],
  [ WIN_Left],
  [ WIN_Down],
  [ WIN_Page_Up],
  [ WIN_End],
  [ WIN_Home],
  [ WIN_Page_Down],
]

KeyMap[1][2] = [ 
  [ WIN_numbersign ],
  [ WIN_period ],
  [ WIN_3 ],
  [ WIN_1 ],
  [ WIN_Shift_L, WIN_equal ],
  [ WIN_5 ],
  [ WIN_minus ],
  [ WIN_7 ],
  [ WIN_equal ],
  [ WIN_9 ],
  [ WIN_Shift_L, WIN_4 ],
  [ WIN_comma ],
  [ WIN_2 ],
  [ WIN_4 ],
  [ WIN_6 ],
  [ WIN_Return ],
  [ WIN_8 ],
  [ WIN_Shift_L, WIN_8 ],
  [ WIN_0 ],
  [ WIN_slash ],
  [],
  [],
  [],
  [],
  [ WIN_Shift_L, WIN_Up ],
  [ WIN_Shift_L, WIN_Right],
  [ WIN_Shift_L, WIN_Left],
  [ WIN_Shift_L, WIN_Down],
  [ WIN_Shift_L, WIN_Page_Up],
  [ WIN_Shift_L, WIN_End],
  [ WIN_Shift_L, WIN_Home],
  [ WIN_Shift_L, WIN_Page_Down],
]

# Function keymap
KeyMap[0][3] = [ 
  [],
  [],
  [ WIN_F3 ],
  [ WIN_F1 ],
  [],
  [ WIN_F5 ],
  [],
  [ WIN_F7 ],
  [],
  [ WIN_F9 ],
  [],
  [],
  [ WIN_F2 ],
  [ WIN_F4 ],
  [ WIN_F6 ],
  [],
  [ WIN_F8 ],
  [],
  [ WIN_F10 ],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
]

KeyMap[1][3] = [ 
  [],
  [],
  [ WIN_Shift_L, WIN_F3 ],
  [ WIN_Shift_L, WIN_F1 ],
  [],
  [ WIN_Shift_L, WIN_F5 ],
  [],
  [ WIN_Shift_L, WIN_F7 ],
  [],
  [ WIN_Shift_L, WIN_F9 ],
  [],
  [],
  [ WIN_Shift_L, WIN_F2 ],
  [ WIN_Shift_L, WIN_F4 ],
  [ WIN_Shift_L, WIN_F6 ],
  [],
  [ WIN_Shift_L, WIN_F8 ],
  [],
  [ WIN_Shift_L, WIN_F10 ],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
]

# Ctrl keymap
KeyMap[0][4] = [ 
  [ WIN_Control_L, WIN_G],
  [ WIN_Control_L, WIN_R],
  [ WIN_Control_L, WIN_F],
  [ WIN_Control_L, WIN_T],
  [ WIN_Control_L, WIN_D],
  [ WIN_Control_L, WIN_E],
  [ WIN_Control_L, WIN_W],
  [ WIN_Control_L, WIN_S],
  [ WIN_Control_L, WIN_Q],
  [ WIN_Control_L, WIN_A],
  [ WIN_Control_L, WIN_M],
  [ WIN_Control_L, WIN_H],
  [ WIN_Control_L, WIN_N],
  [ WIN_Control_L, WIN_U],
  [ WIN_Control_L, WIN_I],
  [ WIN_Control_L, WIN_comma],
  [ WIN_Control_L, WIN_O],
  [ WIN_Control_L, WIN_period],
  [ WIN_Control_L, WIN_P],
  [ WIN_Control_L, WIN_B],
  [ WIN_Control_L, WIN_J], 
  [ WIN_Control_L, WIN_V], 
  [ WIN_Control_L, WIN_X], 
  [ WIN_Control_L, WIN_Z], 
  [ WIN_Control_L, WIN_C], 
  [ WIN_Control_L, WIN_Y], 
  [ WIN_Control_L, WIN_K], 
  [ WIN_Control_L, WIN_L], 
  [ WIN_Control_L, WIN_Return],
  [ WIN_Control_L, WIN_BackSpace],
  [ WIN_Control_L, WIN_space],
  [ WIN_Control_L, WIN_Tab],
]

KeyMap[1][4] = [ 
  [  WIN_Shift_L, WIN_Control_L, WIN_G],
  [  WIN_Shift_L, WIN_Control_L, WIN_R],
  [  WIN_Shift_L, WIN_Control_L, WIN_F],
  [  WIN_Shift_L, WIN_Control_L, WIN_T],
  [  WIN_Shift_L, WIN_Control_L, WIN_D],
  [  WIN_Shift_L, WIN_Control_L, WIN_E],
  [  WIN_Shift_L, WIN_Control_L, WIN_W],
  [  WIN_Shift_L, WIN_Control_L, WIN_S],
  [  WIN_Shift_L, WIN_Control_L, WIN_Q],
  [  WIN_Shift_L, WIN_Control_L, WIN_A],
  [  WIN_Shift_L, WIN_Control_L, WIN_M],
  [  WIN_Shift_L, WIN_Control_L, WIN_H],
  [  WIN_Shift_L, WIN_Control_L, WIN_N],
  [  WIN_Shift_L, WIN_Control_L, WIN_U],
  [  WIN_Shift_L, WIN_Control_L, WIN_I],
  [  WIN_Shift_L, WIN_Control_L, WIN_comma],
  [  WIN_Shift_L, WIN_Control_L, WIN_O],
  [  WIN_Shift_L, WIN_Control_L, WIN_period],
  [  WIN_Shift_L, WIN_Control_L, WIN_P],
  [  WIN_Shift_L, WIN_Control_L, WIN_B],
  [  WIN_Shift_L, WIN_Control_L, WIN_J], 
  [  WIN_Shift_L, WIN_Control_L, WIN_V], 
  [  WIN_Shift_L, WIN_Control_L, WIN_X], 
  [  WIN_Shift_L, WIN_Control_L, WIN_Z], 
  [  WIN_Shift_L, WIN_Control_L, WIN_C], 
  [  WIN_Shift_L, WIN_Control_L, WIN_Y], 
  [  WIN_Shift_L, WIN_Control_L, WIN_K], 
  [  WIN_Shift_L, WIN_Control_L, WIN_L], 
  [  WIN_Shift_L, WIN_Control_L, WIN_Return],
  [  WIN_Shift_L, WIN_Control_L, WIN_BackSpace],
  [  WIN_Shift_L, WIN_Control_L, WIN_space],
  [  WIN_Shift_L, WIN_Control_L, WIN_Tab],
]

# Alt keymap
KeyMap[0][5] = [ 
  [ WIN_Alt_L, WIN_G],
  [ WIN_Alt_L, WIN_R],
  [ WIN_Alt_L, WIN_F],
  [ WIN_Alt_L, WIN_T],
  [ WIN_Alt_L, WIN_D],
  [ WIN_Alt_L, WIN_E],
  [ WIN_Alt_L, WIN_W],
  [ WIN_Alt_L, WIN_S],
  [ WIN_Alt_L, WIN_Q],
  [ WIN_Alt_L, WIN_A],
  [ WIN_Alt_L, WIN_M],
  [ WIN_Alt_L, WIN_H],
  [ WIN_Alt_L, WIN_N],
  [ WIN_Alt_L, WIN_U],
  [ WIN_Alt_L, WIN_I],
  [ WIN_Alt_L, WIN_comma],
  [ WIN_Alt_L, WIN_O],
  [ WIN_Alt_L, WIN_period],
  [ WIN_Alt_L, WIN_P],
  [ WIN_Alt_L, WIN_B],
  [ WIN_Alt_L, WIN_J], 
  [ WIN_Alt_L, WIN_V], 
  [ WIN_Alt_L, WIN_X], 
  [ WIN_Alt_L, WIN_Z], 
  [ WIN_Alt_L, WIN_C], 
  [ WIN_Alt_L, WIN_Y], 
  [ WIN_Alt_L, WIN_K], 
  [ WIN_Alt_L, WIN_L], 
  [ WIN_Alt_L, WIN_Return],
  [ WIN_Alt_L, WIN_BackSpace],
  [ WIN_Alt_L, WIN_space],
  [ WIN_Alt_L, WIN_Tab],
]

KeyMap[1][5] = [ 
  [  WIN_Shift_L, WIN_Alt_L, WIN_G],
  [  WIN_Shift_L, WIN_Alt_L, WIN_R],
  [  WIN_Shift_L, WIN_Alt_L, WIN_F],
  [  WIN_Shift_L, WIN_Alt_L, WIN_T],
  [  WIN_Shift_L, WIN_Alt_L, WIN_D],
  [  WIN_Shift_L, WIN_Alt_L, WIN_E],
  [  WIN_Shift_L, WIN_Alt_L, WIN_W],
  [  WIN_Shift_L, WIN_Alt_L, WIN_S],
  [  WIN_Shift_L, WIN_Alt_L, WIN_Q],
  [  WIN_Shift_L, WIN_Alt_L, WIN_A],
  [  WIN_Shift_L, WIN_Alt_L, WIN_M],
  [  WIN_Shift_L, WIN_Alt_L, WIN_H],
  [  WIN_Shift_L, WIN_Alt_L, WIN_N],
  [  WIN_Shift_L, WIN_Alt_L, WIN_U],
  [  WIN_Shift_L, WIN_Alt_L, WIN_I],
  [  WIN_Shift_L, WIN_Alt_L, WIN_comma],
  [  WIN_Shift_L, WIN_Alt_L, WIN_O],
  [  WIN_Shift_L, WIN_Alt_L, WIN_period],
  [  WIN_Shift_L, WIN_Alt_L, WIN_P],
  [  WIN_Shift_L, WIN_Alt_L, WIN_B],
  [  WIN_Shift_L, WIN_Alt_L, WIN_J], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_V], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_X], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_Z], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_C], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_Y], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_K], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_L], 
  [  WIN_Shift_L, WIN_Alt_L, WIN_Return],
  [  WIN_Shift_L, WIN_Alt_L, WIN_BackSpace],
  [  WIN_Shift_L, WIN_Alt_L, WIN_space],
  [  WIN_Shift_L, WIN_Alt_L, WIN_Tab],
]

# Win keymap
KeyMap[0][6] = [ 
  [ WIN_Super_L, WIN_G],
  [ WIN_Super_L, WIN_R],
  [ WIN_Super_L, WIN_F],
  [ WIN_Super_L, WIN_T],
  [ WIN_Super_L, WIN_D],
  [ WIN_Super_L, WIN_E],
  [ WIN_Super_L, WIN_W],
  [ WIN_Super_L, WIN_S],
  [ WIN_Super_L, WIN_Q],
  [ WIN_Super_L, WIN_A],
  [ WIN_Super_L, WIN_M],
  [ WIN_Super_L, WIN_H],
  [ WIN_Super_L, WIN_N],
  [ WIN_Super_L, WIN_U],
  [ WIN_Super_L, WIN_I],
  [ WIN_Super_L, WIN_comma],
  [ WIN_Super_L, WIN_O],
  [ WIN_Super_L, WIN_period],
  [ WIN_Super_L, WIN_P],
  [ WIN_Super_L, WIN_B],
  [ WIN_Super_L, WIN_J], 
  [ WIN_Super_L, WIN_V], 
  [ WIN_Super_L, WIN_X], 
  [ WIN_Super_L, WIN_Z], 
  [ WIN_Super_L, WIN_C], 
  [ WIN_Super_L, WIN_Y], 
  [ WIN_Super_L, WIN_K], 
  [ WIN_Super_L, WIN_L], 
  [ WIN_Super_L, WIN_Return],
  [ WIN_Super_L, WIN_BackSpace],
  [ WIN_Super_L, WIN_space],
  [ WIN_Super_L, WIN_Tab],
]

KeyMap[1][6] = [ 
  [  WIN_Shift_L, WIN_Super_L, WIN_G],
  [  WIN_Shift_L, WIN_Super_L, WIN_R],
  [  WIN_Shift_L, WIN_Super_L, WIN_F],
  [  WIN_Shift_L, WIN_Super_L, WIN_T],
  [  WIN_Shift_L, WIN_Super_L, WIN_D],
  [  WIN_Shift_L, WIN_Super_L, WIN_E],
  [  WIN_Shift_L, WIN_Super_L, WIN_W],
  [  WIN_Shift_L, WIN_Super_L, WIN_S],
  [  WIN_Shift_L, WIN_Super_L, WIN_Q],
  [  WIN_Shift_L, WIN_Super_L, WIN_A],
  [  WIN_Shift_L, WIN_Super_L, WIN_M],
  [  WIN_Shift_L, WIN_Super_L, WIN_H],
  [  WIN_Shift_L, WIN_Super_L, WIN_N],
  [  WIN_Shift_L, WIN_Super_L, WIN_U],
  [  WIN_Shift_L, WIN_Super_L, WIN_I],
  [  WIN_Shift_L, WIN_Super_L, WIN_comma],
  [  WIN_Shift_L, WIN_Super_L, WIN_O],
  [  WIN_Shift_L, WIN_Super_L, WIN_period],
  [  WIN_Shift_L, WIN_Super_L, WIN_P],
  [  WIN_Shift_L, WIN_Super_L, WIN_B],
  [  WIN_Shift_L, WIN_Super_L, WIN_J], 
  [  WIN_Shift_L, WIN_Super_L, WIN_V], 
  [  WIN_Shift_L, WIN_Super_L, WIN_X], 
  [  WIN_Shift_L, WIN_Super_L, WIN_Z], 
  [  WIN_Shift_L, WIN_Super_L, WIN_C], 
  [  WIN_Shift_L, WIN_Super_L, WIN_Y], 
  [  WIN_Shift_L, WIN_Super_L, WIN_K], 
  [  WIN_Shift_L, WIN_Super_L, WIN_L], 
  [  WIN_Shift_L, WIN_Super_L, WIN_Return],
  [  WIN_Shift_L, WIN_Super_L, WIN_BackSpace],
  [  WIN_Shift_L, WIN_Super_L, WIN_space],
  [  WIN_Shift_L, WIN_Super_L, WIN_Tab],
]
##################################### state ####################################
# List of keys currently down. Used for error detection.
$is_down={}

# Current colour shift active.
$activeColour=0

# Id of key that caused colour change
$activeColourId=0

# True if colour key was used as a modifier
$colourIsModifier=0

# An error has occurred. Wait for all keys to come up. Keep the colour state
# so all release codes are sent properly.
$error=0

##################################### action ###################################

# Send the key presses in the list.
def process_keydn_list( list)
  for i in 0...list.length
    UHK_keydn( list[i])
  end
end

# Send the key releases in the list in reverse order.
def process_keyup_list( list)
  n=list.length
  n1=n-1
  for i in 0...n
    UHK_keyup( list[n1-i])
  end
end

# Handle the start and stop marks.
def UHK_USB_mark( code, millisecs)
  # print "Mark: #{code}, #{millisecs}\n"
end

# Handle key press events.
def UHK_USB_keydn( code)
  # print "keydn: #{code}\n"
  $is_down[code]=1

  # Turn the key code into a key id or quit

  shiftInd=0
  if $is_down.has_key?( USB_SHIFT_L) or $is_down.has_key?( USB_SHIFT_R)
    shiftInd=1
  end
  # print "Down: #{shiftInd} #{code}\n"
  # First handle the special case of shift-, send as ;. Turn it into shift-,
  if (code==USB_Semicolon)
    if (shiftInd==0) 
      code=USB_Comma
      shiftInd=1
    else
      code=USB_Period
    end
  end
  if not KeyId.has_key?(code)
    return
  end
  id=KeyId[code]

  # print "Down: #{shiftInd} #{$activeColour} #{code} #{id}\n"

  # Handle the fake colour keys
  if $activeColour == 0 and ColourKeys.has_key?( id)
    $activeColour=ColourKeys[id]
    $activeColourId=id
    $colourIsModifier=0
    return
  end

  # Regular key, send code according to color and shift state
  if $activeColour != 0
    $colourIsModifier=1
  end

  process_keydn_list( KeyMap[shiftInd][$activeColour][id])
end

def UHK_USB_keyup( code)
  # print "keyup: #{code}\n"
  $is_down.delete( code)


  # Turn the key code into a key id or quit
  shiftInd=0
  if $is_down.has_key?( USB_SHIFT_L) or $is_down.has_key?( USB_SHIFT_R)
    shiftInd=1
  end
  # First handle the special case of shift-, send as ;. Turn it into shift-,
  if (code==USB_Semicolon)
    if (shiftInd==0) 
      code=USB_Comma
      shiftInd=1
    else
      code=USB_Period
    end
  end
  if not KeyId.has_key?(code)
    return
  end
  id=KeyId[code]

  # Handle the fake colour keys
  if $activeColour != 0 and id == $activeColourId
    if $colourIsModifier == 0
      process_keydn_list( KeyMap[shiftInd][0][id])
      process_keyup_list( KeyMap[shiftInd][0][id])
      $activeColour=0
    else
      if $is_down.empty?
        $activeColour=0
      else
        $error=1
      end
    end
    return
  end

  process_keyup_list( KeyMap[shiftInd][$activeColour][id])
  
  # Error handling
  if $error != 0
    if $is_down.empty?
      $error=0
      $activeColour=0
      $colourIsModifier=0
    end
    return
  end
end

# Connect to the alphagrip if present.
UHK_connect( 0x510, 0x100b, 0x81)

# Preload the shift level images

print "usbhotkey AG5 script started\n"



syntax highlighted by Code2HTML, v. 0.9.1