neo-layout/windows/neo-vars/src/varsfunctions.ahk

481 lines
13 KiB
AutoHotkey

; -*- encoding: utf-8 -*-
; Global neovars objects
Comp := composeDict ; current compose-plane
; Hotkey activation event handler (all modifiers)
;
; keyName
; Activation key-name used by AHK, typically a (combined) vk/sc code-string
; "VK<vk>SC<sc>" or a key-name such as "space", "backspace" etc.
; (see https://www.autohotkey.com/docs/KeyList.htm)
; isDown
; If True, activation event is key pressed down (including auto-repeats).
; If False, activation event is a key release.
; in the correct order.
AllStar(keyName, isDown) {
global
local char, actKeyName
if (TransformProc != "")
actKeyName := Transform%TransformProc%(keyName)
else
actKeyName := keyName
; Find layout character associated with the key
; char: U-code (Uxxxxxx) or special key name (7 characters)
if (Ebene7 and (CP7%actKeyName% != ""))
char := CP7%actKeyName%
else if (Ebene8 and (CP8%actKeyName% != ""))
char := CP8%actKeyName%
else if ((striktesMod2Lock == 0) && (NOC%actKeyName% == 1))
char := CP%EbeneNC%%actKeyName%
else
char := CP%EbeneC%%actKeyName%
; Process activation event through Hook-procedure
; if installed, or default up/down handler otherwise
if (isDown) {
; hook function returns false if event was handled conclusively
if (PressHookProc == "" or PressHook%PressHookProc%(keyName, char))
CharStarDown(keyName, char)
} else {
CharStarUp(keyName)
}
}
; Key event down
CharStarDown(keyName, char) {
global
local CompNew, charSend, SubProc, tosend, tosend1, tosend2, i
; has special key-procedure
if (SubStr(char,1,1) == "P") {
SubProc := SubStr(char,2,6)
CharProc%SubProc%(keyName)
return
}
wasNonShiftKeyPressed := 1
if (kbdRepChars != "" and kbdRepKey == keyName) {
; Keyboard repeat: replay last characters sent
tosend1 := ""
tosend2 := kbdRepChars
} else {
; New key is down, append it's character to the compose
CompNew := Comp[char]
; Compose-miss (fallback)
tosend1 := (CompNew ? "" : Comp._fallback)
if (tosend1 != "")
; Send fallback and restart compose
CompNew := composeDict[char]
; Compose-miss (fail)
if (not CompNew) {
; Compose hat verfehlt: nichts schicken, auch aktuelles Zeichen nicht schicken
tosend2 := ""
Comp := composeDict
; Compose-hit
} else if (CompNew._result) {
; Compose hat getroffen: wird geschickt, Compose gelöscht
tosend2 := CompNew._result
Comp := composeDict
; Compose-more
} else {
; Compose muss sich noch was merken: Jetzt noch nichts schicken.
tosend2 := ""
Comp := CompNew
}
; Enable keyboard repeat (useful to repeat a compose-result)
kbdRepChars := tosend2
kbdRepKey := keyName
; Clear out forgotten key release
; (in rare cases, the script window may e.g. go to background and miss events)
if (PR%keyName% != "") {
CharOutUp(PR%keyName%)
PR%keyName% := ""
}
}
tosend := tosend1 . tosend2
; Send out and release all characters in tosend1; then
; send out and release all characters except the last in tosend2
i := 1
While (StrLen(tosend) > i) {
charSend := SubStr(tosend,i,7)
i += 7
if (SubStr(charSend,1,1) == "P") {
; Invoke character-procedure
SubProc := SubStr(charSend,2,6)
CharProc%SubProc%(keyName)
} else if (StrLen(tosend)+1 == i and StrLen(tosend2) > 0) {
; Send out key down event and set up release cache
; for last character in tosend2
CharOutDown(charSend)
PR%keyName% := charSend
} else {
; Send out key down + up event
CharOut(charSend)
}
}
; Notify on-screen board to check for updates
Check_BSTUpdate()
}
; Key event up
; Send out key-up event with layout-characters memorized in PR%keyname%
; and disable active keyboard repeats
CharStarUp(keyName) {
global
local SubProc, tosend
; Release cached characters from prior down-event
if (PR%keyName% != "") {
tosend := PR%keyName%
PR%keyName% := ""
if (SubStr(tosend,1,1) == "P") {
SubProc := SubStr(tosend,2,6)
CharProc%SubProc%(keyName)
} else
CharOutUp(tosend)
}
; Stop current key repeat
kbdRepChars := ""
}
;
; Send characters to output
;
; Send out activation event "key down, then up"
CharOut(char) {
global
if (CharOutFilterProc != "") {
char := CharOutFilter%CharOutFilterProc%(char,1,1)
if (char == "")
return
}
if (DNCS%char% != "")
SendBlindShiftFixed(char, DNCS%char% . UPCS%char%)
else if (CS%char% != "")
SendBlindShiftFixed(char, "{" . CS%char% . "}")
else
SendUnicodeChar("0x" . SubStr(char,2))
}
; Send out activation event "key down"
CharOutDown(char) {
global
if (CharOutFilterProc != "") {
char := CharOutFilter%CharOutFilterProc%(char,1,0)
if (char == "")
return
}
if (DNCS%char% != "")
SendBlindShiftFixed(char, DNCS%char%)
else if (CS%char% != "")
SendBlindShiftFixed(char, "{" . CS%char% . " down}")
else
SendUnicodeCharDown("0x" . SubStr(char,2))
}
; Send out activation event "key up"
CharOutUp(char) {
global
if (CharOutFilterProc != "") {
char := CharOutFilter%CharOutFilterProc%(char,0,1)
if (char == "")
return
}
if (DNCS%char% != "") {
if (UPCS%char% != "")
SendBlindShiftFixed(char, UPCS%char%)
} else if (CS%char% != "")
SendBlindShiftFixed(char, "{" . CS%char% . " up}")
else
SendUnicodeCharUp("0x" . SubStr(char,2))
}
SendBlindShiftFixed(char, theseq) {
global
if (UNSH%char%)
if (isShiftLPressed)
if (isShiftRPressed)
send % "{blind}{RShift Up}{Shift Up}" . theseq . "{Shift Down}{RShift Down}"
else
send % "{blind}{Shift Up}" . theseq . "{Shift Down}"
else
if (isShiftRPressed)
send % "{blind}{RShift Up}" . theseq . "{RShift Down}"
else
send % "{blind}" . theseq
else if (DOSH%char%)
if (isShiftLPressed)
if (isShiftRPressed)
send % "{blind}" . theseq
else
send % "{blind}{RShift Down}" . theseq . "{RShift Up}"
else
if (isShiftRPressed)
send % "{blind}{Shift Down}" . theseq . "{Shift Up}"
else
send % "{blind}{Shift Down}" . theseq . "{Shift Up}"
else
send % "{blind}" . theseq
}
;
; Unicode output
;
SendUnicodeChar(charCode){
static ki := "#"
if (ki =="#") {
VarSetCapacity(ki,28*4,0)
DllCall("RtlFillMemory","uint",&ki+ 0,"uint",1,"uint",1)
DllCall("RtlFillMemory","uint",&ki+ 28+0,"uint",1,"uint",1)
DllCall("RtlFillMemory","uint",&ki+2*28+0,"uint",1,"uint",1)
DllCall("RtlFillMemory","uint",&ki+3*28+0,"uint",1,"uint",1)
}
if (charCode < 0x10000) {
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x40000|charCode) ;KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+28+6,"uint",4,"uint",0x60000|charCode) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("SendInput","UInt",2,"UInt",&ki,"Int",28)
} else {
hi_surrogate := 0xD800|((charCode-0x10000)/1024)
lo_surrogate := 0xDC00|((charCode-0x10000)&0x3FF)
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x40000|hi_surrogate) ;KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 28+6,"uint",4,"uint",0x40000|lo_surrogate) ;KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+2*28+6,"uint",4,"uint",0x60000|hi_surrogate) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+3*28+6,"uint",4,"uint",0x60000|lo_surrogate) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("SendInput","UInt",4,"UInt",&ki,"Int",28)
}
}
SendUnicodeCharDown(charCode){
static ki := "#"
if (ki =="#") {
VarSetCapacity(ki,28*2,0)
DllCall("RtlFillMemory","uint",&ki+ 0,"uint",1,"uint",1)
DllCall("RtlFillMemory","uint",&ki+ 28+0,"uint",1,"uint",1)
}
if (charCode < 0x10000) {
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x40000|charCode) ;KEYEVENTF_UNICODE
DllCall("SendInput","UInt",1,"UInt",&ki,"Int",28)
} else {
hi_surrogate := 0xD800|((charCode-0x10000)/1024)
lo_surrogate := 0xDC00|((charCode-0x10000) & 0x3FF)
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x40000|hi_surrogate) ;KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 28+6,"uint",4,"uint",0x40000|lo_surrogate) ;KEYEVENTF_UNICODE
DllCall("SendInput","UInt",2,"UInt",&ki,"Int",28)
}
}
SendUnicodeCharUp(charCode){
static ki := "#"
if (ki =="#") {
VarSetCapacity(ki,28*2,0)
DllCall("RtlFillMemory","uint",&ki+ 0,"uint",1,"uint",1)
DllCall("RtlFillMemory","uint",&ki+ 28+0,"uint",1,"uint",1)
}
if (charCode < 0x10000) {
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x60000|charCode) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("SendInput","UInt",1,"UInt",&ki,"Int",28)
} else {
hi_surrogate := 0xD800|((charCode-0x10000)/1024)
lo_surrogate := 0xDC00|((charCode-0x10000)&0x3FF)
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 6,"uint",4,"uint",0x60000|hi_surrogate) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("ntdll.dll\RtlFillMemoryUlong","uint",&ki+ 28+6,"uint",4,"uint",0x60000|lo_surrogate) ;KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
DllCall("SendInput","UInt",2,"UInt",&ki,"Int",28)
}
}
;
; Modifier procedures
;
CharProc__M2LD(keyName) {
global
if (!isShiftLPressed) {
if (isShiftRPressed and !wasNonShiftKeyPressed)
ToggleMod2Lock()
isShiftLPressed := 1
isShiftPressed := 1
wasNonShiftKeyPressed := 0
EbeneAktualisieren()
PR%keyName% := "P__M2LU"
}
CharOutDown("S__L_M2")
}
CharProc__M2LU(keyName) {
global
isShiftLPressed := 0
isShiftPressed := isShiftRPressed
EbeneAktualisieren()
CharOutUp("S__L_M2")
}
CharProc__M2RD(keyName) {
global
if (!isShiftRPressed) {
if (isShiftLPressed and !wasNonShiftKeyPressed)
ToggleMod2Lock()
isShiftRPressed := 1
isShiftPressed := 1
wasNonShiftKeyPressed := 0
EbeneAktualisieren()
PR%keyName% := "P__M2RU"
}
CharOutDown("S__R_M2")
}
CharProc__M2RU(keyName) {
global
isShiftRPressed := 0
isShiftPressed := isShiftLPressed
EbeneAktualisieren()
CharOutUp("S__R_M2")
}
CharProc__M3LD(keyName) {
global
if (!isMod3LPressed) {
if (isMod3RPressed and !wasNonShiftKeyPressed)
CharStarDown("MOD3", "S__Comp")
isMod3LPressed := 1
isMod3Pressed := 1
wasNonShiftKeyPressed := 0
EbeneAktualisieren()
PR%keyName% := "P__M3LU"
}
}
CharProc__M3LU(keyName) {
global
if (isMod3RPressed)
CharStarUp("MOD3")
isMod3LPressed := 0
isMod3Pressed := isMod3RPressed
EbeneAktualisieren()
}
CharProc__M3RD(keyName) {
global
if (!Mod3RPressed) {
if (isMod3LPressed and !wasNonShiftKeyPressed)
CharStarDown("MOD3", "S__Comp")
isMod3RPressed := 1
isMod3Pressed := 1
wasNonShiftKeyPressed := 0
EbeneAktualisieren()
PR%keyName% := "P__M3RU"
}
}
CharProc__M3RU(keyName) {
global
if (isMod3LPressed)
CharStarUp("MOD3")
isMod3RPressed := 0
isMod3Pressed := isMod3LPressed
EbeneAktualisieren()
}
CharProc__M4LD(keyName) {
global
if (!isMod4LPressed) {
isMod4LPressed := 1
isMod4Pressed := 1
EbeneAktualisieren()
PR%keyName% := "P__M4LU"
if (isMod4RPressed and !wasNonShiftKeyPressed) {
wasNonShiftKeyPressed := 0
ToggleMod4Lock()
} else
wasNonShiftKeyPressed := 0
}
}
CharProc__M4LU(keyName) {
global
isMod4LPressed := 0
isMod4Pressed := isMod4RPressed
EbeneAktualisieren()
}
CharProc__M4RD(keyName) {
global
if (!isMod4RPressed) {
isMod4RPressed := 1
isMod4Pressed := 1
EbeneAktualisieren()
PR%keyName% := "P__M4RU"
if (isMod4LPressed and !wasNonShiftKeyPressed) {
wasNonShiftKeyPressed := 0
ToggleMod4Lock()
} else
wasNonShiftKeyPressed := 0
}
}
CharProc__M4RU(keyName) {
global
isMod4RPressed := 0
isMod4Pressed := isMod4LPressed
EbeneAktualisieren()
}
;
; Other character procedures
;
; See also keyhooks.ahk
; Neustart des AHK-Skripts
CharProc__Rlod(keyName) {
global
SetOldLockStates()
reload
}
;
; Lock states
;
SetNEOLockStates() {
global
SavedNumLockState := GetKeyState("NumLock","T")
SavedScrollLockState := GetKeyState("ScrollLock","T")
SavedCapsLockState := GetKeyState("CapsLock","T")
SwitchIs0 := "Off"
SwitchIs1 := "On"
SavedNumLockState := SwitchIs%SavedNumLockState%
SavedScrollLockState := SwitchIs%SavedScrollLockState%
SavedCapsLockState := SwitchIs%SavedCapsLockState%
if (NumLockOff)
SetNumLockState, Off
else
SetNumLockState, On
SetScrollLockState, Off
SetCapsLockState, Off
Sleep,1
UpdateNEOLEDS()
}
SetOldLockStates() {
global
UpdateOldLEDS()
Sleep,1
SetNumLockState,% SavedNumLockState
SetScrollLockState,% SavedScrollLockState
SetCapsLockState,% SavedCapsLockState
}