;autohotkey script for use with the Alphagrip AG-5 ;version 1.00 ; - Started with by Carl F. Andersen Feb-March 2006 1.01 mapping ; - Red Shift made same as out-of-box default (numerics moved) ; (means originaln Red/Green shift work as expected) ; - Orange Fn keys moved to correspond to Red numeric keys ; - TODO: Add extra chars to yellow shift (£, ins, del, euro) ;BACK AND FORWARD #UseHook ; Needed for remapping keys to each other, e.g. A becomes B, and B becomes A. #InstallKeybdHook SetTitleMatchMode, 2 ;matches anywhere in the window title #MaxThreadsPerHotkey 10 #KeyHistory 500 ;SETUP FOR MOUSE SPEED BOOST CoordMode,Mouse,Screen MouseGetPos, OldMousePosx, OldMousePosy ;Get the active window id OldActiveID := WinExist("A") SetTimer, MouseSpeedBoost,20 ;SETUP AND CODE FOR BACK SIDE KEYS ;For this .ini file, I assign indices to each AG-5 finger-side key as well as various chords of two (usually adjacent) keys. ;Here are those indices: ;g 1 r 2 f 3 t 4 d 5 e 6 w 7 s 8 q 9 a 10 m 11 h 12 n 13 u 14 i 15 , 16 o 17 . 18 p 19 b 20 ;f+d 21 d+w 22 w+q 23 t+e 24 e+s 25 s+a 26 n+i 27 i+o 28 o+p 29 u+, 30 ,+. 31 .+b 32 ;t+n 33 e+i 34 s+o 35 a+p 36 f+u 37 d+, 38 w+. 39 q+b 40 ;The indices above are used in the following tables of key remappings. ;KeyBStr contains the remappings operative when no colored shift key is held down ;KeyBlStr contains the remappings operative when the blue shift key is held down ;KeyRStr contains the remappings operative when the (new) red shift key is held down ;KeyGStr contains the remappings operative when the (new) green shift key is held down ;KeyOStr contains the remappings operative when the orange shift key is held down ;So, for example, if you press t+e without any shift keys, you get KeyBStr[23] = "j" KeyBStr := "g|r|f|t|d|e|w|s|q|a|m|h|n|u|i|l|o|c|p|b| | | |j|v|y|k|x|z| | | |.|,|:|;| | | | " KeyBlstr := "{up}|{down}|{left}|{right}|{tab}|{space}|:|{del}|@|{esc}|{pgup}|{pgdn}|{home}|{end}|{enter}|{bs}|{wheelup}|;|{wheeldown}|{printscreen}| | | | | | | | | | | | | | | | | | | | " KeyRStr := "{#}|.|3|1|{+}|5|-|7|=|9|$|,|2|4|6|{enter}|8|*|0|/| | | | | | | | | | | | | | | | | | | | " KeyGStr := "~,%,"",',(,),{{},{}},[,],{^},_,?,{!},&,|,<,>,``,\, , , , , , , , , , , , , , , , , , , , " KeyOStr := "{F11}| |{F3}|{F1}| |{F5}| |{F7}| |{F9}|{F12}| |{F2}| |{F4}|{F6}| |{F8}| |{F10}| | | | | | | | | | | | | | | | | | | | | " ;convert the above strings into Autohotkey arrays for possible speed gain Keyind := 1 Loop,Parse,KeyBstr,|,%A_Space% { ;FileAppend, Array Copying Got Here `n,mylog.txt KeyB%Keyind% := A_LoopField Ch := KeyB%Keyind% ;FileAppend, Array Copying %Ch% `n,mylog.txt Keyind += 1 } Keyind := 1 Loop, Parse, KeyBlstr,|,%A_Space% { KeyBl%Keyind% := A_LoopField Keyind += 1 } Keyind := 1 Loop,Parse,KeyRstr,|,%A_Space% { KeyR%Keyind% := A_LoopField Keyind += 1 } Keyind := 1 Loop,Parse,KeyGstr,`,,%A_Space% { KeyG%Keyind% := A_LoopField Keyind += 1 } Keyind := 1 Loop,Parse,KeyOstr,|,%A_Space% { KeyO%Keyind% := A_LoopField Keyind += 1 } ;single-press key codes ;these are consistent with the indices introduced above Ch2 := "0" Ch1 := "g" Key2B%Ch1%_%Ch2% := 1 Ch1 := "r" Key2B%Ch1%_%Ch2% := 2 Ch1 := "f" Key2B%Ch1%_%Ch2% := 3 Ch1 := "t" Key2B%Ch1%_%Ch2% := 4 Ch1 := "d" Key2B%Ch1%_%Ch2% := 5 Ch1 := "e" Key2B%Ch1%_%Ch2% := 6 Ch1 := "w" Key2B%Ch1%_%Ch2% := 7 Ch1 := "s" Key2B%Ch1%_%Ch2% := 8 Ch1 := "q" Key2B%Ch1%_%Ch2% := 9 Ch1 := "a" Key2B%Ch1%_%Ch2% := 10 Ch1 := "m" Key2B%Ch1%_%Ch2% := 11 Ch1 := "h" Key2B%Ch1%_%Ch2% := 12 Ch1 := "n" Key2B%Ch1%_%Ch2% := 13 Ch1 := "u" Key2B%Ch1%_%Ch2% := 14 Ch1 := "i" Key2B%Ch1%_%Ch2% := 15 Ch1 := "comma" Key2B%Ch1%_%Ch2% := 16 Ch1 := "o" Key2B%Ch1%_%Ch2% := 17 Ch1 := "period" Key2B%Ch1%_%Ch2% := 18 Ch1 := "p" Key2B%Ch1%_%Ch2% := 19 Ch1 := "b" Key2B%Ch1%_%Ch2% := 20 ;dual-press key codes ;these are consistent with the indices introduced above ;inside left Ch1 := "t" Ch2 := "e" Key2B%Ch1%_%Ch2% := 24 Key2B%Ch2%_%Ch1% := 24 Ch1 := "e" Ch2 := "s" Key2B%Ch1%_%Ch2% := 25 Key2B%Ch2%_%Ch1% := 25 Ch1 := "s" Ch2 := "a" Key2B%Ch1%_%Ch2% := 26 Key2B%Ch2%_%Ch1% := 26 ;outside left Ch1 := "f" Ch2 := "d" Key2B%Ch1%_%Ch2% := 21 Key2B%Ch2%_%Ch1% := 21 Ch1 := "d" Ch2 := "w" Key2B%Ch1%_%Ch2% := 22 Key2B%Ch2%_%Ch1% := 22 Ch1 := "w" Ch2 := "q" Key2B%Ch1%_%Ch2% := 23 Key2B%Ch2%_%Ch1% := 23 ;inside right Ch1 := "n" Ch2 := "i" Key2B%Ch1%_%Ch2% := 27 Key2B%Ch2%_%Ch1% := 27 Ch1 := "i" Ch2 := "o" Key2B%Ch1%_%Ch2% := 28 Key2B%Ch2%_%Ch1% := 28 Ch1 := "o" Ch2 := "p" Key2B%Ch1%_%Ch2% := 29 Key2B%Ch2%_%Ch1% := 29 ;outside right Ch1 := "u" Ch2 := "comma" Key2B%Ch1%_%Ch2% := 30 Key2B%Ch2%_%Ch1% := 30 Ch1 := "comma" Ch2 := "period" Key2B%Ch1%_%Ch2% := 31 Key2B%Ch2%_%Ch1% := 31 Ch1 := "period" Ch2 := "b" Key2B%Ch1%_%Ch2% := 32 Key2B%Ch2%_%Ch1% := 32 ;inside Ch1 := "t" Ch2 := "n" Key2B%Ch1%_%Ch2% := 33 Key2B%Ch2%_%Ch1% := 33 Ch1 := "e" Ch2 := "i" Key2B%Ch1%_%Ch2% := 34 Key2B%Ch2%_%Ch1% := 34 Ch1 := "s" Ch2 := "o" Key2B%Ch1%_%Ch2% := 35 Key2B%Ch2%_%Ch1% := 35 Ch1 := "a" Ch2 := "p" Key2B%Ch1%_%Ch2% := 36 Key2B%Ch2%_%Ch1% := 36 ;outside Ch1 := "f" Ch2 := "u" Key2B%Ch1%_%Ch2% := 37 Key2B%Ch2%_%Ch1% := 37 Ch1 := "d" Ch2 := "comma" Key2B%Ch1%_%Ch2% := 38 Key2B%Ch2%_%Ch1% := 38 Ch1 := "w" Ch2 := "period" Key2B%Ch1%_%Ch2% := 39 Key2B%Ch2%_%Ch1% := 39 Ch1 := "q" Ch2 := "b" Key2B%Ch1%_%Ch2% := 40 Key2B%Ch2%_%Ch1% := 40 ;make sure globals are defined Simul%Ch1%_%Ch2% := false Ch = "a" ;end of auto-execute section return ;hotkeys for dual press keys ;inside left *t::AG_HK2downa("t","e","n","") *t up::AG_HK2upa("t","e","n","") *e::AG_HK2downa("e","t","s","i") *e up::AG_HK2upa("e","t","s","i") *s::AG_HK2downa("s","e","a","o") *s up::AG_HK2upa("s","e","a","o") *a::AG_HK2downa("a","s","p","") *a up::AG_HK2upa("a","s","p","") ;inside right *n::AG_HK2downa("n","i","t","") *n up::AG_HK2upa("n","i","t","") *i::AG_HK2downa("i","n","o","e") *i up::AG_HK2upa("i","n","o","e") *o::AG_HK2downa("o","i","p","s") *o up::AG_HK2upa("o","i","p","s") *p::AG_HK2downa("p","o","a","") *p up::AG_HK2upa("p","o","a","") ;outside left *f::AG_HK2downa("f","d","u","") *f up::AG_HK2upa("f","d","u","") *d::AG_HK2downa("d","f","w","comma") *d up::AG_HK2upa("d","f","w","comma") *w::AG_HK2downa("w","d","q","period") *w up::AG_HK2upa("w","d","q","period") *q::AG_HK2downa("q","w","b","") *q up::AG_HK2upa("q","w","b","") ;outside right *u::AG_HK2downa("u","comma","f","") *u up::AG_HK2upa("u","comma","f","") *,::AG_HK2downa("comma","u","period","d") *, up::AG_HK2upa("comma","u","period","d") *.::AG_HK2downa("period","comma","b","w") *. up::AG_HK2upa("period","comma","b","w") *b::AG_HK2downa("b","period","q","") *b up::AG_HK2upa("b","period","q","") ;Code for distinguishing shift+; from shift+: ;Note that because the char ";" is sent by the alphagrip as ";" and ;the char ":" is sent by the alphagrip as "shift-;" there is no ;way of uniquely distinguishing the key combination of shift+;+: from the ;key combination of shift+: ;SO - we assign to key 30 a non-letter symbol that will never require a shift *;:: ;special case for the character ":"; this is sent by the alphagrip as a shift-; ;we want to translate it to a shift-. if (GetKeyState("Shift")) AG_HK2downa("period","comma","b","w") ;special case for the character ";"; else { Send {Shift Down} AG_HK2downa("comma","u","period","d") Send {Shift Up} } return ;hotkeys for single press keys *g::AG_HK1("g") *r::AG_HK1("r") *m::AG_HK1("m") *h::AG_HK1("h") ;*,::AG_HK1(",") ;*.::AG_HK1(".") ;suspension and shift,alt,ctrl reset PrintScreen:: Suspend Toggle Pause Toggle Send {Shift Up} Send {Alt Up} Send {Ctrl Up} return ; Handle new shift keys ; NOTE that original meaning of shift keys must be disabled above ; Commented out shows both left and right used for shift) AG_Send1(Ch1,Ch2) { global SetKeyDelay -1 Key1 := Key2B%Ch1%_%Ch2% ;FileAppend, %Ch1% %Ch2%`n, mylog.txt ;FileAppend, %Key1%`n, mylog.txt ;navigational keys are only modified by the Blue key ; if (GetKeyState("k","P") or GetKeyState("Tab","P")) { ;blue if (GetKeyState("k","P") ) { ;blue Ch := KeyBl%Key1% Send {Blind}%Ch% } ; else if (GetKeyState("l","P") or GetKeyState("Space","P")) { ;red else if (GetKeyState("l","P") ) { ;red Ch := KeyR%Key1% Send {Blind}%Ch% } ; else if (GetKeyState("y","P") or GetKeyState("Enter","P")) { ;green else if (GetKeyState("y","P") ) { ;green Ch := KeyG%Key1% Send {Blind}%Ch% } ; else if (GetKeyState("c","P") or GetKeyState("BS","P")) { ;orange else if (GetKeyState("c","P") ) { ;orange Ch := KeyO%Key1% Send {Blind}%Ch% } else { Ch := KeyB%Key1% Send {Blind}%Ch% } } AG_HK1(Ch) { AG_Send1(Ch,"0") } ;note that this code presumes that if key1 is held down, then key2, the input device will emit ;key1 key2 key2 key2..... ;this seems to be the alphagrip's behavior AG_HK2downa(Ch1,Ch2,Ch3 = "",Ch4 = "") { global ;Shifton%Ch1% := GetKeyState("Shift") Critical local priorhk priorhk := A_PriorHotkey if (priorhk = "*,") priorhk := "*comma" else if (priorhk = "*.") priorhk := "*period" else if (priorhk = "*;") priorhk := "*semi" if ((priorhk = "*" . Ch2 or (priorhk = "*semi" and (Ch2 = "period" or Ch2 = "comma"))) and A_TimeSincePriorHotkey < 70) { Simul%Ch2%_%Ch1%_%Ch1% := true Simul%Ch2%_%Ch1%_%Ch2% := true } ;we assume that Ch = "" will never satisfy these conditions else if ((priorhk = "*" . Ch3 or (priorhk = "*semi" and (Ch3 = "period" or Ch3 = "comma"))) and A_TimeSincePriorHotkey < 70) { Simul%Ch3%_%Ch1%_%Ch1% := true Simul%Ch3%_%Ch1%_%Ch3% := true } ;we assume that Ch = "" will never satisfy these conditions else if ((priorhk = "*" . Ch4 or (priorhk = "*semi" and (Ch4 = "period" or Ch3 = "comma"))) and A_TimeSincePriorHotkey < 70) { Simul%Ch4%_%Ch1%_%Ch1% := true Simul%Ch4%_%Ch1%_%Ch4% := true } Critical Off ;if a match is set with this key as the second, AND ;the first key is still down, print the match if (Simul%Ch2%_%Ch1%_%Ch2%) AG_Send1(Ch1,Ch2) else if (Simul%Ch3%_%Ch1%_%Ch3%) AG_Send1(Ch1,Ch3) else if (Simul%Ch4%_%Ch1%_%Ch4%) AG_Send1(Ch1,Ch4) else { ;wait awhile to give another key the chance to go down sleep,70 Critical ;if some other key has not set a match with this key as the first, print this key if (not (Simul%Ch1%_%Ch2%_%Ch1% or Simul%Ch1%_%Ch3%_%Ch1% or Simul%Ch1%_%Ch4%_%Ch1%)) { AG_Send1(Ch1,"0") } } } AG_HK2upa(Ch1,Ch2,Ch3 = "",Ch4 = "") { global Critical Simul%Ch1%_%Ch2%_%Ch1% := false Simul%Ch1%_%Ch3%_%Ch1% := false Simul%Ch1%_%Ch4%_%Ch1% := false Simul%Ch2%_%Ch1%_%Ch1% := false Simul%Ch3%_%Ch1%_%Ch1% := false Simul%Ch4%_%Ch1%_%Ch1% := false } ;SETUP FOR FRONT SIDE KEYS ; Change meaning to new behavior for CTRL and ALT j::Ctrl @::return v::Alt x::Ctrl z::Alt ; Not sure what this set does (DJW) !Tab:: !+Tab:: ^Tab:: ^+Tab:: !^Tab:: !^+Tab:: ; Disable normal meaning of left block of keys to be used for new shift keys c::return y::return l::return k::return ; Disable normal meaning of right block of keys if to be used for new shift keys ; Comment out if meaning retained ; Enter::return ; BS::return ; Space::return ; Tab::return ;UK Keyboard changes "::return £::# ~::# ¬::~ ;****************************************** ;MOUSE SPEED BOOST ;Up:: ;SetMouseDelay -1 ;;FileAppend %A_ScreenWidth%, mylog.txt ;;FileAppend %A_ScreenHeight%, mylog.txt ;If (A_PriorHotkey = "Up" and A_TimeSincePriorHotkey < 200) ; MouseMove 0,0,0 ;else ; mousemove A_ScreenWidth / 4, A_ScreenHeight / 4,0 ;return ; ;Left::MouseMove 0,A_ScreenHeight,0 ;***************************** ;mouse speed boost MouseSpeedBoost: MouseGetPos, NewMousePosx, NewMousePosy ;if GetKeyState("v","P") { ;if OldPos gets screwed up (as has happened somehow) so it is off the screen, reset it if (OldMousePosx < 0) OldMousePosx := 0 if (OldMousePosy < 0) OldMousePosy := 0 Distx := NewMousePosx - OldMousePosx Disty := NewMousePosy - OldMousePosy ;if we just jumped to a new window, as can happen with the Mouse "Smart Move" feature, ;then pretend the mouse did not move NewActiveID := WinExist("A") if (OldActiveID != NewActiveID) { ;FileAppend %A_TickCount% Posxy: %OldMousePosx% %OldMousePosy% %NewMousePosx% %NewMousePosy% active window changed `n, mylog.txt OldMousePosx = %NewMousePosx% OldMousePosy = %NewMousePosy% OldActiveID := NewActiveID return } AbsDistx := Abs(Distx) AbsDisty := Abs(Disty) Dist := Floor(Sqrt(Abs((NewMousePosx - OldMousePosx))**2 + Abs((NewMousePosy - OldMousePosy))**2)) BoostDist := Floor(Dist**1.7) ;the following lines are algebraically derived from the constraints we wish, ie. ;1. Distx/Disty = BoostDistx / BoostDisty = AdjDistx/AdjDisty; and ;2. AdjBoostDist extends OldMousePosx,y either to BoostDist or to the edge of the screen BoostDistx := BoostDist * Distx / Dist ; if (Distx < 0) ; BoostDistx := BoostDistx * -1 BoostDisty := BoostDist * Disty / Dist ; if (Disty < 0) ; BoostDisty := BoostDisty * -1 Overx := 0 Underx := 0 Overy := 0 Undery := 0 OverAmt := 1.0 if (Boostdistx > 0) if (A_ScreenWidth = OldMousePosx) OverAmt := 0 else { Overx := BoostDistx / (A_ScreenWidth - OldMousePosx) if (Overx > 1.0 and Overx > OverAmt) OverAmt := Overx } else if (Boostdistx < 0) if (OldMousePosx = 0) OverAmt := 0 else { Underx := BoostDistx / (0 - OldMousePosx) if (Underx > 1.0 and Underx > OverAmt) OverAmt := Underx } if (Boostdisty > 0) if (A_ScreenHeight = OldMousePosy) OverAmt := 0 else { Overy := BoostDisty / (A_ScreenHeight - OldMousePosy) if (Overy > 1.0 and Overy > OverAmt) OverAmt := Overy } else if (Boostdisty < 0) if (OldMousePosy = 0) OverAmt := 0 else { Undery := BoostDisty / (0 - OldMousePosy) if (Undery > 1.0 and Undery > OverAmt) OverAmt := Undery } if (OverAmt = 0) { AdjDist := 0 AdjDistx := 0 AdjDisty := 0 } else if (OverAmt != 100000.0) { AdjDist := BoostDist / OverAmt AdjDistx := BoostDistx / OverAmt AdjDisty := BoostDisty / OverAmt } else { AdjDist := BoostDist AdjDistx := BoostDistx AdjDisty := BoostDisty } AdjMousePosx := OldMousePosx + Floor(AdjDistx) AdjMousePosy := OldMousePosy + Floor(AdjDisty) MouseMove, AdjMousePosx, AdjMousePosy,0 ;FileAppend %A_TickCount% Posxy: %OldMousePosx% %OldMousePosy% %NewMousePosx% %NewMousePosy% %AdjMousePosx% %AdjMousePosy% `n, mylog.txt ;FileAppend %A_TickCount% Dists: %Dist% %BoostDist% %AdjDist% `n, mylog.txt ;FileAppend %A_TickCount% Distsxy: %Distx% %Disty% %BoostDistx% %BoostDisty% %AdjDistx% %AdjDisty% `n, mylog.txt OldMousePosx = %AdjMousePosx% OldMousePosy = %AdjMousePosy% OldActiveID := NewActiveID ;} ;else { ; OldMousePosx = %NewMousePosx% ; OldMousePosy = %NewMousePosy% ;} return