forked from neo/neo-layout
146 lines
5.1 KiB
AutoHotkey
146 lines
5.1 KiB
AutoHotkey
; -*- encoding:utf-8 -*-
|
|
|
|
;
|
|
; Global compose definitions
|
|
;
|
|
|
|
; Compose-definitions root object:
|
|
; Hosts compose-sequences in a nested structure of associative arrays
|
|
; ("compose-planes").
|
|
; A child-plane listed under a key "x" corresponds to the character "x"
|
|
; to be appended to the compose-sequence (where "x" is a keyId).
|
|
; The key that is the special character 'COMP_BACK_CHAR' links back to
|
|
; the parent plane. Special keys such as '_result' or '_fallback' hold
|
|
; compose-result and fallback characters; a plane with '_result' is
|
|
; assumed to be a leaf without child-planes.
|
|
composeDict := {} ; first compose-plane
|
|
|
|
; Reverse-lookup associative array, synchronized to composeDict:
|
|
; composeSequences[resultChars] = array of all leaf-planes whose '_result'
|
|
; is equal to 'resultChars'.
|
|
composeSequences := {}
|
|
|
|
|
|
; Read compose-definitions from XCompose-files ("dynamic compose")
|
|
; Appends sequences in provided order to global compose definitions
|
|
LoadCurrentCompose() {
|
|
global ini
|
|
|
|
; Read compose-input files from ini-file
|
|
IniRead, dynComposeFilesPrefix, %ini%, Global, dynComposeFilesPrefix , ""
|
|
IniRead, dynComposeFiles, %ini%, Global, dynComposeFiles , ""
|
|
|
|
; Backwards-compatible defaults
|
|
if (not dynComposeFiles) {
|
|
dynComposeFilesPrefix := "..\..\..\Compose\src\"
|
|
dynComposeFiles := "base.module, en_US.UTF-8, greek.module, math.module, cyrillic.module, lang.module"
|
|
}
|
|
|
|
; Parse and load compose sequences:
|
|
keySym2KeyIdMap := makeKeySym2KeyIdMap()
|
|
Loop, parse, dynComposeFiles, CSV, %A_Space%%A_Tab%
|
|
{
|
|
f := dynComposeFilesPrefix . A_LoopField
|
|
if FileExist(f)
|
|
parseComposeFile(f, keySym2KeyIdMap, "makeCompose")
|
|
}
|
|
}
|
|
|
|
; Add a new compose-sequence to global compose-definitions
|
|
;
|
|
; Arguments:
|
|
;
|
|
; sequence (in)
|
|
; Array of one or more single characters or neovars keyIds
|
|
; (U-code or special key name). If empty, False is returned.
|
|
; resultChars (in)
|
|
; One or more characters that shall be sent in place of the sequence,
|
|
; encoded in a consecutive string of keyIds (e.g. "UxxxxxxUyyyyyyPzzzzzz..").
|
|
; If empty, no compose-definition will be created, all conflicts
|
|
; with existing sequences will be ignored, and False is returned.
|
|
; fallback:="" (in)
|
|
; If a non-empty string is provided, it must be a consecutive string
|
|
; of U-codes, and becomes the fallback characters sent out when a
|
|
; compose-miss on the last character in the provided sequence occurs.
|
|
; If an empty string is provided (default), fallback is not enabled.
|
|
; Any existing (non-empty) fallback can not be overwritten, and False
|
|
; is returned in any attempt to do so (ignoring the provided sequence).
|
|
;
|
|
; Returns:
|
|
; True on success, False otherwise.
|
|
;
|
|
; Notes:
|
|
;
|
|
; Updates global dictionaries 'composeDict' and 'composeSequences'
|
|
; On entry, 'composeDict' may hold previously defined compose-sequences.
|
|
; On successful exit, the provided sequence is added to composeDict
|
|
; without overwriting or making inaccessible any existing sequences.
|
|
; Similarly, 'composeSequences' is updated with 'sequence' on successful exit.
|
|
;
|
|
; If the sequence contains any COMP_BACK_CHAR (backspaces by default)
|
|
; following any othe character, the COMP_BACK_CHAR acts as "compose-undo"
|
|
; and effectively remove the preceding character from the compose sequence
|
|
; (if no more such characters exist, the COMP_BACK_CHAR acts litterally)
|
|
;
|
|
; If the same, a longer, or a shorter sequence already exists, the existing
|
|
; sequence will not be overwritten, and False is returned instead.
|
|
;
|
|
makeCompose(sequence, resultChars, fallback:="") {
|
|
global composeDict, composeSequences, COMP_BACK_CHAR
|
|
|
|
; Quick return: empty result
|
|
; (not distinguishable from compose-fail)
|
|
if (resultChars == "")
|
|
return False
|
|
|
|
; Quick return: empty sequence
|
|
if (sequence.Length() == 0)
|
|
return False
|
|
|
|
; Set up sub-compose planes along the sequence
|
|
nextSubDict := composeDict ; current compose-plane
|
|
depth := 0
|
|
While (depth < sequence.Length())
|
|
{
|
|
; Enter next compose-plane
|
|
subDict := nextSubDict
|
|
char := util_char2Ucode(sequence[++depth])
|
|
nextSubDict := subDict[char]
|
|
if (not nextSubDict) {
|
|
; plane does not exist, create it
|
|
nextSubDict := {(COMP_BACK_CHAR):subDict, _sequenceChar: char}
|
|
subDict[char] := nextSubDict
|
|
} else if (nextSubDict._result) {
|
|
; error: shorter or equal sequence exists already
|
|
return False
|
|
} else if (depth == sequence.Length()) {
|
|
; error: longer sequence exists already
|
|
return False
|
|
}
|
|
}
|
|
|
|
; Enable fallback on compose-miss
|
|
if (fallback != "") {
|
|
if (subDict._fallback)
|
|
; error: fallback is already defined
|
|
return False
|
|
else
|
|
subDict._fallback := fallback
|
|
}
|
|
|
|
; Resolve sequence in last plane
|
|
nextSubDict._result := resultChars
|
|
|
|
; Update reverse lookup
|
|
; (map result to last plane; sequences can then be rebuild backwards
|
|
; from _sequenceChar's, going back step by step through COMP_BACK_CHAR)
|
|
compSeqList := composeSequences[resultChars]
|
|
if (not compSeqList) {
|
|
compSeqList := []
|
|
composeSequences[resultChars] := compSeqList
|
|
}
|
|
compSeqList.push(nextSubDict)
|
|
|
|
; Successfully updated compose definitions
|
|
return True
|
|
} |