Compare commits

...

63 Commits

Author SHA1 Message Date
ferdinym 5338830383 neovars: fix some pixels in on-screen board images 2020-11-02 16:14:06 +01:00
ferdinym b1d839a3dd neovars: error-messages on missing unicode-support revised 2020-11-02 14:57:31 +01:00
ferdinym 742d6b982d neovars: tray-menu revised, keyboard-shortcturs quick-help added 2020-11-02 14:57:31 +01:00
ferdinym f9941b572f neovars: update on-screen board immediately after suspension ends
A hidden suspended board with active BST (e.g. by double-right click)
is now made visible again immediately after suspension ends.
2020-11-02 14:07:47 +01:00
ferdinym ebcc37d068 neovars: unicode keypress replaced with native send
Notes:
- "SendUnicodeChar(charCode)" can be replaced by send % {Chr(charCode)}
  since AHK 1.1.27; this should produce similar results
  (compare with SendUnicodeChar in  522e83eee0/source/keyboard_mouse.cpp (L91))
- however "up", "down" events cannot be replaced similarly for most keys
  (see also https://www.autohotkey.com/docs/commands/Send.htm)
2020-11-02 14:07:47 +01:00
ferdinym 33d6dfbc87 neovars: Sendmode changed to "Input"
- "Input" is faster and more reliable according to AHK's documentation.
- However, it caused some unspecified "lost characters" issues 12 years ago
  (see commit bea2956dea), so beware
2020-11-02 14:07:47 +01:00
ferdinym ef8d9c61f5 neovars: build-tool "compose-update" performance improved
Significant speedup (~ 100%)
2020-11-02 14:07:47 +01:00
ferdinym 3df333fa02 neovars: build-tool's logging window improvements (window updates)
Main changes are
- Selections made in the edit control are no longer cleared on updates
- Track only changes to be made in the edit control's text instead of
  manipulating the entire logText with every logWrite, logProgressUpdate
2020-11-02 14:07:47 +01:00
ferdinym a2da10cdc1 neovars: minor on-screen board code-cleanup 2020-11-02 14:07:47 +01:00
ferdinym badb746eef neovars: make progress-counter stay below entries in build-tools log
Entries written to the log no longer stop and overwrite an active progress
counter, but instead are prepended to it.
2020-11-02 14:07:47 +01:00
ferdinym 2adeac4aa5 neovars: include util.ahk in more scripts explicitly
Make dependencies visible
2020-11-02 14:07:46 +01:00
ferdinym 5eb8478348 neovars: update shortcuts for "Wie mit Neo" Tool
Improves "Wie mit Neo" output readability with new shortcuts for protected
spaces, and by grouping level-modifiers in parentheses.
2020-11-02 14:07:46 +01:00
ferdinym 23bd680691 neovars: unshift bug fixed
- There were two places were UNSH%..% variables had been changed,
  depending on where characters are placed in the layout
- This resulted in a bug where the wrong (un)-shifted variants of a
  character was sent out, for example when entering the compose sequence
  <compose><Mod5+space><Mod5+space> the "_" character was sent out instead
  of the correct compose character "-"

Note: This fix removes code which I do not understand why it was ever
needed (commit messages are missing/not helpful) so this may break stuff.
2020-11-02 14:07:46 +01:00
ferdinym 840053c8e9 neovars: thread criticality added (correctness + stability + performance)
- Make hotkeys uninterruptible:
  This might prevent side-effects that may be caused by interrupting
  a hotkey with another one, causing global variables (such as modifier
  states) to be corrupted and output to be sent in the wrong order.
- Put on-screen board update in separate (interruptible) thread:
  A timer-spawned thread ensures the board gets updated but does not block
  hotkey events, and that update requests are canceled as soon as a new
  update request is made.
2020-11-02 14:07:46 +01:00
ferdinym 9e5953f5ce neovars: initialization cleaned, functions reordered and removed 2020-11-02 14:07:46 +01:00
ferdinym 1812ec7a43 neovars: Compose and key-event processing rewritten for clarity
Major changes:
- "Everything is a compose", incl. invididual keystrokes:
  Keys and composes are now on equal footing, their processing unified.
- Key event processing through AllStar and subsequent procedures
  rewritten for clarity.
- Parts of "Wie mit Neo"-Tool rewritten (while adjusting to new compose)

Compose:
- Compose-definitions cannot overwrite (or make unreachable) existing ones,
  so the order of generating composes from files etc. matters
- Reordered Xcompose-files (now base.module is first)
- Compose-definitions in compose.generated.ahk updated
- custom.ahk gets two new initialization event functions so that user can
  declare custom composes before/after others.

Key events:
- Multi-character compose-sequences no longer automatically release the last
  key in the sequence (instead, it will be released once the key which
  triggered the sequence's output is lifted)
- Keyboard-autorepeat no longer sends key-up (release) events

Other changes:
- The reliance on global variables has been reduced, resorting to local
  variables and passing arguments to called functions instead.
- CharProc's receive the keyName of the invoking key as first argument
- Keyhooks must return True (to stop event bubbling) or False
- Keyboard autorepeat is now managed with just two global variables,
  instead of one per individual key.
- Unused arguments (ActKey) removed from functions
2020-11-02 14:07:46 +01:00
ferdinym 52f606b18a neovars: BST window message handlers update
- now only messages from BST-GUI are processed
- handlers are unregistered when BST is closed
- renamed since BST specific now
2020-11-02 14:07:06 +01:00
ferdinym b5b42de5a5 neovars: fix Uni-tool, internal unicode string too long
The resulting codepoint string "Uxxxxxx" was truncated at 8 instead of 6
characters.

Seemed not to cause much trouble, but might in future!
2020-10-29 04:41:52 +01:00
ferdinym 3412662982 neovars: keydefinitions table reformatted 2020-10-29 04:41:51 +01:00
ferdinym e9fcc2c85c neovars: EbeneAktualisieren alias removed, static function call
The ability to overload the dynamic function variable was never used*,
not documented, and its benefits were not clear. On the contrary,
dynamic calls are error prone, perform worse, and reduce code readability.

Therefore, call EbeneActualisieren() statically.
Reverts 155b64cd2d

*) No use-case found in official repository, checked with
$ git  rev-list --all | xargs git grep <???>
and for instance <???> = "EbeneAktualisieren :=", "EbeneAktualisieren:=", "EbeneAktualisieren =", "EbeneAktualisieren="
2020-10-29 04:41:51 +01:00
ferdinym 5c1c346e0c neovars: on-screen keyboard layout- and performance updates
- move layout-definitions from individual variables to assoc. array
- make layout-filenames more consistent
- add more GUISYM symbols for non-printable characters (e.g. from compose)
- allow styles to adjust keycap font-size (scales with GUI size)
- code cleanup and comments added
2020-10-29 04:41:51 +01:00
ferdinym 9a2e731253 neovars: on-screen-board keycap symbols moved to associative array
Replace global variables lookups of the form val := dict%key% with
associative array lookup, improving on-screen-board performance
(especially the first time a new level is displayed) and no longer
spamming global namespace.
2020-10-29 04:40:49 +01:00
ferdinym 42231d3ea3 neovars: initialization process update
most important changes:
- Modules now initialize themselves when their "Initialize<modulename>"
  function is called, instead of doing so in the auto-execute section
  when being included.
- The entire startup process is now organized much more transparently
  in initialize.ahk
- The "performance.ahk" module was renamed "global_switches.ahk"
  and serves as unified place for defaulting all global script settings.
- custom.ahk: new InitializeCustom() and renamed LoadCustomCompose()
2020-10-29 04:40:49 +01:00
ferdinym 0d0691ab35 neovars: compose generator/parser update
- drop ANSI-Autohotkey support, make AutoHotkey_L Unicode mandatory
  (ANSI wasn't fully supported anyways, also compare 41738845d1)
- new tool compose-update.ahk replaces make-compose.bat
- removed makecompose.ahk, which was mostly redundant
  (but subtly different in Unicode- vs. ANSI native encoding)
- new compose-parse.ahk and util.ahk replace most of makecompose.ahk and
  compose-gen.ahk, and improves performance
- configurable compose-update.ahk and dynamic compose (on startup):
  compose-files can be specified in ini-files (fully backwarts-compatible
  with the "dynamischesCompose" Neo2.ini setting)
2020-10-29 04:40:49 +01:00
ferdinym 116cf47c42 neovars: native tool-sequences overwrite generated compose defs.
c11c590100 introduced collisions such as
<Multi_key> <u> <u> in Compose/src/en_US.UTF-8 which conflicts with the
unicode tool which is activated on <compose><u><u>.
Since the tools are documented features of neovars, they should have
precedence (at least by default).
2020-10-29 04:40:49 +01:00
ferdinym 181770f077 neovars: Compose/ directory-specific revision info in make-compose.bat
"CompRevision" in the generated compose files now identifies the last
commit reachable from HEAD that affects the projects Compose/-directory.
Similarly, the "compose-tainted.generated.ahk" file is only created in
place of "compose.generated.ahk" if git diff reports changes that affect
tge Compose/-directory.
2020-10-29 04:40:49 +01:00
ferdinym 5788878de6 neovars: fix compose-generators
Fixes corrupted (or entirely missing) compose-definitions generated with
make-compose.bat or by setting "dynamischesCompose=1".
2020-10-29 04:40:49 +01:00
ferdinym fc1cdcf4f6 neovars: templates for Neo2.ini and custom.ahk with user-defined compose defs.
- Adds dist/ folder with templates Neo2.ini and custom.ahk
- New user-definable function LoadUserdefinedCompose() called on startup:
  -- allows user to add neovars-specific compose commands
  -- see examples in custom.ahk template for CM.., CD.., CRC.., and
     CF.. usage (as introduced with commit 97f4584533)
2020-10-29 04:40:48 +01:00
ferdinym 8076baeec0 neovars: new build-scripts and build-configuration
Replace the batch-file based build process with more powerful AHK scripts.
The most important changes are summarized below.

New build tools:
- Add tools/ folder which replaces build/
- Add tools/build-make.ahk main build script

New build configuration:
- Add build-config.ini which can be edited to configure the build process.
  For example, the option custom=1 includes the user's custom.ahk script,
  and portable=1 compiles a portable version.
- Add tools/build-configure.ahk which processes build-config.ini and
  autogenerates configuration scripts included in the compiled version.
- The user's custom.ahk file is no loger moved around under %Appdata%,
  but instead included indirectly in compile-specific includes.
2020-10-29 04:40:48 +01:00
ferdinym c54aed8b19 neovars: preparations for a portable version
- Introduce global variable "isPortable"
- In portable version,
  -- "File Install" does not overwrite already extracted resources
     (useful if we lack write-permissions or run from slow external device)
  -- "ApplicationFolder" and "ResourceFolder" point to script-local folder
     %A_SkriptDir%/Neo2-portable
2020-10-29 04:40:48 +01:00
ferdinym 543c7b96a4 neovars: modifier locks can be turned off
- Introduce two new Neo2.ini-keys "Mod2LockOff" and "Mod4LockOff",
  in analogy to the existing "NumLockOff" option
- Both options disable modifier-locking internally, but may not fix issues
  caused by failure to send correct sequences of shift events (#243 ?)
- Lower-case'd UseMod4Light -> useMod4Light
2020-10-29 04:40:48 +01:00
ferdinym 04bc40a93c neovars: remove "edit" option from compiled script's tray-icon context menu
Compiled scripts are not editable
2020-10-29 04:40:48 +01:00
ferdinym f5096615f6 neovars: GUI handling with hWND's + window event functions
- Identify GUI windows by their hWNDs instead of naming the GUIs
  -- allows the compiler to unload running instances of the script
     by closing the respective window, even when e.g. the on-screen
     keyboard board is active
  -- allows to have multiple persistent windows of the "Wie mit Neo"
     tool (so users can lookup sequences, compare them, etc.)
- Removed generic GUI event handlers from keyhooks module;
  instead modules shall define and handle their own events
2020-10-29 04:40:48 +01:00
ferdinym 7ca4999413 neovars: allow lang-s-modus in qwertz-mode
- seems to work properly?
- why would customLayout (i.e. with the QWERTZ layout string) work, but not qwertz-mode,
  when both use the same custom-layout capabilities internally?
2020-10-29 04:40:48 +01:00
ferdinym 037e2bc112 neovars: register tab as *-hotkey so it works properly in einhandneo and BST
- Tab is now processed through neovars even if shift is pressed simulatenously.
- Einhandneo now reacts to shift+M3+tab also on the left tab (toggle caps-lock)
- Einhandneo sets up a caps-lock symbol for the on-screen keyboard
- (fix) On-screen board now displays the tab correctly on level 5
2020-10-29 04:40:48 +01:00
ferdinym a5a4708f41 neovars: simplified code for custom layouts
- removes all global variables LOSE... which were used to cache the original layout's characters and capitalization options (LOSE2%e1%, LOSE5%e1%, LOSE6%e1%, LOSEC%e1% for every layout characrer e1)
- Change1256Layout(..) no longer restores the cached LOSE... properties, but instead permutes all keys with their currently defined properties
  This reduces the chance of "undoing" changes made to the keys in other modules.
- Setup for the unicode-tool program key P___Uni moved back to tools.ahk
2020-10-29 04:40:48 +01:00
ferdinym 3057731f8e neovars: "Wie mit Neo"-tool gets standard font, window always on top
(1) The font was changed to sytem default.
This fixes ugly output and missing changes in font-weight in cases were
only one of the DejaVu font-series was installed.

(2) The AlwaysOnTop option is added to the window.
This allows typing in the proposed compose sequences in an editor window
that would otherwise conceal the tool window.
2020-10-29 04:40:47 +01:00
ferdinym a8c4a26f30 neovars: add alternative compose-sequence for tools
Changes:
- Calculator new sequences: <compose>+"Uc" and <compose>+"uC" (echo)
- "Wie mit Neo?" new sequences: <compose>+"Uw" and <compose>+"uW"

Purpose:
- make the compose-sequences more fault tolerant
- user can defer his choice between calculator variants until right before the
  command completes (and only after the commands become visible on the on-screen board)

Note: colliding user-defined or non-standard/generated compose sequences will overwrite the new definitions.
2020-10-29 04:40:47 +01:00
ferdinym 901df9fefe neovars: minor BST performance enhancement, flicker reduced
Delay redrawing of key cap labels until the the background image is updated.
Use sleep -1 before doing so to reduce flicker.
2020-10-29 04:40:47 +01:00
ferdinym b120ced8dd neovars: minor performance enhancements for BSTUpdate
- skip font-commands for layouts that do not update font options
- remove font (last option) from "Gui, BST:Font" commands, only change options
2020-10-16 16:15:21 +02:00
ferdinym b530868980 neovars: BST-layouts can highlight tools
At the on-screen board,
- layouts can highlight keys that invoke tools
  (helps to distinguish them from printed characters)
- the "Wie mit Neo?" tool key is displayed with symbol "UW"
2020-10-16 16:15:21 +02:00
ferdinym a8632fce82 neovars: add "uc" and "UC" symbols for calculator-tool to BST 2020-10-16 16:15:21 +02:00
ferdinym 02aecf1108 neovars: improved handling of compose/dead keys in on-screen keyboard
Adds options for BST-layouts:
- configurable font-style/color and replacement text ('**' originally) for keys starting or appending to a compose sequence
- optionally show characters that can be appended to an active compose-sequence instead of the (fixed) replacement text
  (which partially defeated the purpose of the on-screen keyboard)

Fixes:
- Always show characters on keys that have a CF.. compose definition associated with them
 (originally, '**' was displayed even on letters)
- Keep labels on modifier keys while composing
2020-10-16 16:15:21 +02:00
ferdinym 9005003ec5 neovars: new on-screen keyboard symbols for space- and hyphen variants
Changes:
On-screen board now displays
- Soft hyphen (U+00AD, <Mod6+->) enclosed in small parentheses
- Non-breaking hyphen (U+2011, <Mod5+->) enclosed in top corners
- Narrow no-break space (U+202F, <Mod6+space>) enclosed in single
  angle quotation marks instead of the larger "> <" characters

Reasoning:
- all three symbols add left/right enclosing characters to indicate that
  the enclosed character is modified to it's *soft*, *non-breaking* or
  *narrow* variant
- narrow no-break space symbol changes only minimally, fits better
  with the hyphens
- new symbols for hyphens reduce the chance to mix up different variants
- soft hyphen symbol resembles ISO/IEC 9995-7:2009/Amd 1:2012
- non-breaking hyphen symbol resembles non-breaking space notation
  and still partially resembles ISO/IEC 9995-7 (unicode lacks small
  square brackets)

Notes:
- Narrow No-Break Space = U+202F = <Mod6+space>
- Non-Breaking Hyphen = U+2011 = <Mod5+->
- Soft Hyphen = U+00AD = <Mod6+->
2020-10-16 16:15:05 +02:00
ferdinym fea1d07362 neovars: BST symbole für tote Tasten leicht überarbeitet
- kombinierende Diakritika auf T1-T3 (beim wiederholtem Betätigen) werden immer mit gepunktetem Kreis und dem jeweiligen ausgegebenen kombinierenden Unicode-Zeichen dargestellt
- Compose-Key mit den verbundenen Viertelnoten beschriftet
- minimale visuelle Anpassungen aufgrund von Positionierungsproblemen des DejaVu-Fonts
2020-10-15 02:29:04 +02:00
ferdinym 315ac73b77 neovars: hide BST on double-right-click temporarily 2020-10-15 02:29:04 +02:00
ferdinym d3b58224e3 neovars: simplified handling of modifier keys in BST
- Removed GuyAddKeySM and global IM.. variables from BST
- Modifier keys recognized by key-pos (CP..) variable in BSTUpdate()
- Fixes presumably inadvertent mixups of GuyAddKeySM and GuyAddKeyM in some layouts
- Fixes potential issues with layouts that define modifiers differently due to persistent global IM.. := 1 variables
2020-10-15 02:29:04 +02:00
ferdinym db927144dc neovars: disable special treatment of ampersands in BST text controls 2020-10-15 02:29:04 +02:00
ferdinym bab835e530 neovars: reset BST-window by double-clicking it 2020-10-15 02:29:04 +02:00
ferdinym 14104c0e6b neovars: ini-input sanitization + some cleanup 2020-10-15 02:29:04 +02:00
ferdinym 3a3b07886a neovars: move graphics, icons into new "/res" folder
Remove non-sourcecode files from the "/src" folder
2020-10-15 02:29:04 +02:00
ferdinym ac73bb53c0 neovars: translucent BST on suspend
Adds BSTStartSuspend() and BSTEndSuspend() where BST can react to suspension.
For now, simply make it translucent to give the user graphical feedback of the suspension.
2020-10-15 02:29:03 +02:00
ferdinym b13cd8e876 neovars: add "bstAnimate" ini-parameter
Responsive BST-layouts normally adjust graphically to the active modifiers / caps
of the current level, which may distract users and increase flickering.
It can now be disabled with "bstAnimate = 0" in the .ini file.
2020-10-15 02:29:03 +02:00
ferdinym 5644628ff7 neovars: add 2 animated BST layouts (iso, isoTKL)
Adds 2 on-screen keyboard layouts without colored keys that can be toggled:
A standard 105-key ISO layout and a 88-key (TKL) variant (without number pad), both with staggered columns.
Both layouts graphically highlight the active modifier- and caps-keys of the current level.
2020-10-15 02:29:03 +02:00
ferdinym ecfb794d75 neovars: avoid redundant BST updates (flicker) in BSTOnSize() 2020-10-15 02:29:03 +02:00
ferdinym 951c84b568 neovars: add "bstScale" ini-param
With "bstScale" the on-screen board size can be adjusted permanently.
2020-10-15 02:29:03 +02:00
ferdinym 594bbd4cc7 neovars: lift BST by 1 pixel
Useful to bring up a hidden taskbar with the mouse
2020-10-15 02:29:03 +02:00
ferdinym 14be2fecd3 neovars: fix several BST issues, make transforms static (einhandneo)
Bugfixes:
- deactivate "Einhandmodus" while space pressed fails (despite tray-tip reporting deactivation) and crashes BST (board instantly hides after toggle on)
- deactivate DBST in the middle of a composite character sequence fails to hide the on-screen board
- toggle on-screen-layout with DBST enabled instantaneously brings up the board even when it should'nt; can no longer be deactivated

Other changes:
- stateful BST and DBST modes can be en- and disabled independently; board is shown when required by either one or both
- less delay in bringing up on-screen board in dynamic mode (DBST) by toggling window visibility instead of recreating the entire GUI
- changes to the window size made while in DBST mode are now persistent
- (BST) keyboard transformations are considered to be static permutations different from the identity
2020-10-15 02:29:03 +02:00
ferdinym e0a3e6b32f neovars: add "UseMod4LightCaps" ini-option
Mod4-lock optionally activates the capslock-LED.
Helpful if keyboard has just one LED.
2020-10-15 02:29:03 +02:00
ferdinym 2b4ae2a7cf neovars: update LEDs of *all* connected keyboards 2020-10-15 02:29:03 +02:00
ferdinym 2687ece681 neovars: fix keyboard LEDs (DllCall + unicode string) 2020-10-15 02:29:03 +02:00
ferdinym 00649b9409 neovars: do not delete "isQwertz" ini key
Use IniWrite instead of IniDelete in qwertz.ahk.
Deleting keys entirely is disrespectful to user-defined ini-files.
2020-10-15 02:29:03 +02:00
ferdinym ce70846593 neovars: (fix) unicode-tool key no longer hardcoded
Removes the hardcoded unicode-tool "P___Uni" from layer 5 of the key next to left shift,
and instead places it generically on level 5 of the "u" key -- before that key is rotated to a custom position by a custom layout string.

Fixes the following:
- any (greek) character in level 5 next to left shift was overwritten,
  which caused problems with custom-layouts and startup in QWERTZ mode.
- activating the QWERTZ-mode would overwrite the unicode-tool function,
  and it would not be restored even by switching back to the original layout.
2020-10-15 02:29:02 +02:00
62 changed files with 13007 additions and 22866 deletions

3
.gitignore vendored
View File

@ -49,7 +49,10 @@
/windows/neo-vars/src/neo20-r*.ahk
/windows/neo-vars/src/_gitwcrev.generated.ahk
/windows/neo-vars/src/compose.generated.ahk~
/windows/neo-vars/src/compose-tainted.generated.ahk
/windows/neo-vars/src/compose-tainted.generated.ahk~
/windows/neo-vars/src/config-iscompiled1.generated.ahk
# /yaml/
/yaml/.git

View File

@ -1,6 +0,0 @@
@echo off
set bindir=..\bin
set fnexe=%bindir%\neo20-custom.exe
call "make-build.bat" %fnexe%

View File

@ -1,50 +0,0 @@
@echo off
echo Setting default local path variables
set ahkpath=C:\Program Files (x86)\AutoHotkey
if not exist "%ahkpath%" set ahkpath=C:\Program Files\AutoHotkey
set Ahk2Exe=%ahkpath%\Compiler\Ahk2Exe.exe
set srcdir=..\src
set bindir=..\bin
set ahkrevoutput1=%srcdir%\_gitwcrev.generated.ahk
set NEO2AppData=%APPDATA%\Neo2
set customahk=%NEO2AppData%\custom.ahk
set customahkbuild=%customahk%.buildtmp
echo Generating version file
for /f "tokens=* USEBACKQ" %%R in (`"git rev-parse HEAD"`) do set Revision=%%R
set Revision=%Revision:~0,7%
echo Revision:="%Revision%" > "%ahkrevoutput1%"
if NOT EXIST %bindir% mkdir %bindir%
set fnexe=%bindir%\neo20.exe
git diff --exit-code > nul
if %ERRORLEVEL% EQU 1 (
set fnexe=%bindir%\neo20-r%Revision%.exe
)
REM Overwrite binary output name if given as parameter
if "%1:" NEQ ":" (
set fnexe=%1
)
echo Removing old version(s) of Neo AHK Exe file
del "%bindir%\neo20-r*.exe" 2> nul
set fnahk=%srcdir%\neo20-all.ahk
if exist "%customahk%" (
move "%customahk%" "%customahkbuild%"
)
echo Compiling the new driver using AutoHotkey
"%Ahk2Exe%" /in "%fnahk%" /out "%fnexe%" /icon "%srcdir%\neo_enabled.ico"
if exist "%customahkbuild%" (
move "%customahkbuild%" "%customahk%"
)
echo Driver update complete! You can now close this log window.
pause

View File

@ -1,30 +0,0 @@
@echo off
echo Setting default local path variables
set ahkpath=C:\Programme\AutoHotkey
set AutoHotKey=%ahkpath%\AutoHotKeyU32.exe
set srcdir=..\src
set bindir=..\bin
REM The path to the directory used for generating a consistent SVN version (revision number)
set gitversiondir=..\..\..\Compose
echo Getting git revision
for /f "tokens=* USEBACKQ" %%R in (`"git rev-parse HEAD"`) do set CompRevision=%%R
set CompRevision=%CompRevision:~0,7%
set fncomp=%srcdir%\compose.generated.ahk
git diff --exit-code > nul
if %ERRORLEVEL% EQU 1 (
set fncomp=%srcdir%\compose-tainted.generated.ahk
)
echo Deleting old compose sequences
del "%srcdir%\Compose.generated.ahk" "%srcdir%\Compose-tainted.generated.ahk" 2> nul
echo Compiling compose sequences
"%AutoHotkey%" "%srcdir%\makecompose.ahk" "%CompRevision%" "%fncomp%" "%gitversiondir%\src\en_US.UTF-8" "%gitversiondir%\src\base.module" "%gitversiondir%\src\greek.module" "%gitversiondir%\src\math.module" "%gitversiondir%\src\lang.module" "%gitversiondir%\src\weiter_Definitionen.txt"
echo Compose update complete! You can now close this log window.
pause

View File

@ -0,0 +1,35 @@
; Build-Konfiguration
;
; Diese Datei wird von tools/build-config.ahk und tools/build-config.ahk gelesen.
; Durch Ändern der Werte können Anpassungen am Buildprozess vorgenommen werden.
; Dabei gilt stets 0 = Nein, 1 = Ja (soweit nicht anders angegeben).
;
; Hinweise:
; - Diese Datei muss in "ANSI"-Kodierung gespeichert werden.
[Global]
; Soll eine portable Version (z.B. für USB-Stick) erzeugt werden?
; (Legt benötigte Dateien im Anwendungsverzeichnis ab)
portable=0
; Sollen benutzerdefinierte Skripte in das Programm eingebaut werden?
; (Skript wird aus %AppData%\Neo2\custom.ahk gelesen)
custom=0
; Benutzerdefinierter Dateinamensteil der compilierten Exe-Datei.
; Wenn leer, wird der Name automatisch aus Konfigurationsoptionen
; und evtl. Revisionsinformationen zusammengestellt.
customName=
; Dateipfad des Ahk2Exe-Compilers.
; Wenn leer, wird automatisch im Verzeichnis des Skriptausführenden AHK-
; Interpreters gesucht (https://www.autohotkey.com/docs/Variables.htm#AhkPath).
; Nicht-absolute Pfade werden relativ zum tools/-Verzeichnis ausgewertet.
ahk2ExePath=
; Zusätzliche Komandozeilenparameter für den Ahk2Exe-Compiler.
; Nützlich sind z.B. "/gui", "/bin <file>" und "/compress <n>".
; Die Parameter "/in" "/out" "/icon" werden bereits vom build-script verwendet.
; Referenz: https://www.autohotkey.com/docs/Scripts.htm#ahk2exe
ahk2ExeParams=

View File

@ -0,0 +1,28 @@
; Compsoe-Konfiguration
;
; Diese Datei wird von tools/compose-update.ahk gelesen.
; Durch Ändern der Werte kann die Komposita-Generierung angepasst werden.
; Dabei gilt stets 0 = Nein, 1 = Ja (soweit nicht anders angegeben).
;
; Hinweise:
; - Diese Datei muss in "ANSI"-Kodierung gespeichert werden.
[Global]
; Zeichenkette, welche allen Dateinamen in composeFiles vorangestellt wird.
; Hinweis: Alle notwendigen (Back-)Slashes müssen enthalten sein!
composeFilesPrefix=..\..\..\Compose\src\
; Komma-separierte Liste der zu ladenden compose-Dateien.
; Hinweise:
; - Zuerst gelistete Compose-Definitionen haben vorrang. Spätere Sequenzen werden ignoriert,
; wenn sie bestehende Definitionen verändern noch unerreichbar machen würden.
; - Nicht-absolute Pfade werden relativ zum "tools"-Verzeichnis ausgewertet.
; - In einer vollständigen lokalen Kopie des neo-layout Projektes
; können die Dateien unter "..\..\..\Compose\src" verwendet werden.
composeFiles=base.module, en_US.UTF-8, greek.module, math.module, cyrillic.module, lang.module
; Sollen von den bestehenden Skripten mit früheren Compose-Definitionen
; Sicherheitskopien erstellt werden, bevor diese gelöscht werden?
; Hinweis: Sicherheitskopien wird eine Tilde "~" an den Dateinamen angehängt.
makeBackups=1

132
windows/neo-vars/dist/Neo2.ini vendored Normal file
View File

@ -0,0 +1,132 @@
; Neovars Konfiguration
;
; Durch Ändern der Werte können Anpassungen vorgenommen werden.
; Dabei gilt stets 0 = Nein, 1 = Ja (soweit nicht anders angegeben).
;
; Hinweise:
; - Um von Neovars gelesen zu werden, muss diese Datei in "ANSI"-Kodierung
; unter "%APPDATA%\Neo2\Neo2.ini" (bzw. für die portable Version unter
; "<Verzeichnis der Neo2-exe>\Neo2-portable\Neo2.ini") abgespeichert werden.
; - Änderungen werden erst nach Neustart des Skripes wirksam
; (bei aktiviertem Neovars über Mod-3 + Esc oder das Tray-Icon).
;
; Weitere Informationen:
; https://mkdocs.neo.uber.space/Benutzerhandbuch/neovars/
[Global]
; LAYOUT -----------------------------
; Ein benutzerdefiniertes Layout festlegen
; (33 Standardzeichen, in QUERTZ: "ßqwertzuiopüasdfghjklöäyxcvbnm,.-")
; Neo2 (immer auch default):
;customLayout="-xvlcwkhgfqßuiaeosnrtdyüöäpzbm,.j"
; Bone:
;customLayout="-jduaxphlmwßctieobnrsgqfvüäöyz,.k"
; AdNW:
;customLayout="-kuü.ävgcljfhieaodtrnsßxyö,qbpwmz"
; KOY:
;customLayout="-k.o,yvgclßzhaeiudtrnsfxqäüöbpwmj"
; Qwertz:
;customLayout="ßqwertzuiopüasdfghjklöäyxcvbnm,.-"
; Soll die rechte Mod-3-Taste mit der links davon liegenden Taste (Ä in Qwertz) vertauscht werden?
Mod3RAufAe=0
; MODI -------------------------------
; Soll der Qwertz-Modus beim Programmstart bereits aktiviert sein?
isQwertz=0
; Soll der Ein-Hand-Modus beim Programmstart bereits aktiviert sein?
einHandNeo=0
; Soll der Lern-Modus beim Programmstart bereits aktiviert sein?
lernModus=0
; Soll der Lang-s-Modus beim Programmstart bereits aktiviert sein?
LangSTastatur=0
; TRAY-TIPPS -------------------------
; Soll beim Einschalten des Mod4-Locks eine Warnmeldung ausgegeben werden?
zeigeLockBox=1
; Sollen Veränderungen an den Einstellungen auf dem Desktop angezeigt werden? (Tray-Tips)
zeigeModusBox=1
; LEDS -------------------------------
; Soll das Aktivieren des Mod-4-Locks über das 3. Numpad-Licht (Scroll-Lock) angezeigt werden?
useMod4Light=1
; Soll das Aktivieren des Mod-4-Locks auch über das Caps-Lock-Licht angezeigt werden?
; Hinweis: Diese Funktion ist hilfreich, wenn keine weiteren LEDs vorhanden sind
useMod4LightCaps=0
; BILDSCHIRM-TASTATUR ----------------
; Soll die Bildschirm-Tastatur beim Programmstart bereits aktiviert sein?
useBST=0
; Soll die dynamische Bildschirm-Tastatur beim Programmstart bereits eingeschaltet sein?
; Hinweis: Die dynamische Tastatur wird in Ebenen 5/6 sowie aktivem Compose eingeblendet.
useDBST=0
; In welchem Layout soll die Bildschirmtastatur dargestellt werden (0=Standard, 1=ErgoDox, 2=ISO, 3=ISO-TKL)?
bstLayout=0
; Um welchen Faktor soll die Bildschirmtastatur standardmäßig vergrößert werden? (1=nicht skalieren)
bstScale=1
; Soll die Bildschirmtastatur die Mod-Tasten der jeweilige Ebene grafisch hervorheben?
; Hinweis: Fähigkeit ist Layoutabhängig (bstLayout). Verlangsamung oder Flackern möglich.
bstAnimate=1
; LOCKS ------------------------------
; Soll Caps-Lock auch bei den Ziffern und Satzzeichen wirken?
striktesMod2Lock=0
; Soll die Caps-Lock-Funktion (gleichzeitiges Drücken beider Mod-2-/Umschalttasten) abgestellt werden?
Mod2LockOff=0
; Soll Mod-4-Lock-Funktion (gleichzeitiges Drücken beider Mod-4-Tasten) abgestellt werden?
Mod4LockOff=0
; Soll die Num-Lock-Funktion abgestellt werden?
; Hinweis: Hilfreich bei Notebooks und anderen Tastaturen mit integriertem Fn-Ziffernblock.
NumLockOff=0
; COMPOSE-SEQUENZEN ------------------
; Sollen Compose-Kombinationen dynamisch aus XCompose-Dateien erzeugt werden?
dynamischesCompose=0
; Zeichenkette, welche allen Dateinamen in dynComposeFiles vorangestellt wird.
; Hinweis: Alle notwendigen (Back-)Slashes müssen enthalten sein!
dynComposeFilesPrefix=..\..\..\Compose\src\
; Komma-separierte Liste der bei dynamischem Compose geladenen Dateien.
; Hinweise:
; - Zuerst gelistete Compose-Definitionen haben vorrang. Spätere Sequenzen werden ignoriert,
; wenn sie bestehende Definitionen verändern noch unerreichbar machen würden.
; - Nicht-absolute Dateipfade werden relativ zum Programmverzeichnis ausgewertet.
; - Werden keine Dateien angegeben, werden einige Standarddateien innerhalb einer
; lokalen Kopie des neo-layout Projektverzeichnisses gesucht.
dynComposeFiles=base.module, en_US.UTF-8, greek.module, math.module, cyrillic.module, lang.module
; WEITERE EINSTELLUNGEN --------------
; Soll das Programm deaktiviert gestartet werden?
; Hinweis: Kann jederzeit über das Tray-Icon oder per Shift + Pause (de)aktiviert werden
startSuspended=0

95
windows/neo-vars/dist/custom.ahk vendored Normal file
View File

@ -0,0 +1,95 @@
; -*- encoding: utf-8 -*-
;
; Benutzerdefiniertes Neovars-Skript
;
; Damit dieses AHK-Skript beim Programmstart ausgeführt wird, muss es unter
; "%APPDATA%\Neo2\custom.ahk" (bzw. für die portable Version unter
; "<Verzeichnis der Neo2-exe>\Neo2-portable\Neo2.ini") abgelegt werden.
;
; Sind die Funktionen InitializeCustom1() und InitializeCustom2() definiert,
; werden diese zu verschiedenen Zeitpunkten in der Initialisierung aufgerufen
; und können für eigene Komposita-Definitionen genutzt werden.
;
; *Hinweise zu Komposita*
; Einfache statische (XCompose-) Definitionen können per XCompose-Datei beim
; Kompilieren oder dynamisch (per Neo2.ini-Einstellung) geladen werden.
; Sollen Neovars-spezifische Komposita erzeugt werden, können diese hier per
; "makeCompose(sequence, resultChars, fallback)" erzeugt werden.
; Dabei enthält sequence = ["<char1>", "<char2>", ...] die Zeichensequenz,
; welche in die Ausgabe resultChars = "<char1><char2>..." umgewandelt wird.
; Die Zeichen <charN> sind jeweils durch einen hexadezimalen Unicode-Codepoint
; mit vorangestelltem "U" (z.B. "U00266B"), oder durch einen Spezialzeichen-
; Namen zu ersetzen (z.B. "S__Comp" für die <compose>-Taste oder "P___WMN" um
; das "Wie mit Neo" - Werkzeug aufzurufen). In sequence können Unicode-Symbole
; auch direkt eingegeben werden.
; Wird optional fallback = "<char1><char2>..." angegeben, so wird dieses bei
; Fehleingabe des letzten Zeichens der sequenz, gefolgt von dem falsch
; eingegeben Zeichen, gesendet.
; Bereits bestehende Komposita können nicht mehr verändert oder unerreichbar
; gemacht werden.
; Siehe auch compose.ahk.
;
; *Hinweise zu Symbolen auf der Bildschirmtastatur*
; Manchmal ist es sinvoll, Komposita oder Zeichen auf der Bildschirmtastatur
; mit einem Ersatzsymbol darzustellen (insbesondere bei nicht druckbaren
; Zeichen oder langem Text). Dazu kann die Funktion "GUISYM(chars, sym, style)"
; genutzt werden, welche chars = "<char1><char2>..." durch das Unicode-Zeichen
; sym ersetzt. Optional kann die Darstellung per style verändert werden.
; Siehe screenkeyboard.ahk
; Diese Funktion wird während der Programminitialisierung aufgerufen,
; vor Definition der Komposita, Tastenbelegung und Modulinitialisierung.
;
; Hinweise:
; - Hier definierte Komposita überschreiben alle weiteren, einschließlich der
; Originaltastenbelegung.
; - Es sind nicht alle globalen Variablen aus Modulen oder der Tastenbelegung
; verfügbar.
InitializeCustom1() {
global
; Beispiele für Kompose-Definitionen:
; <compose>-Taste abschalten und durch Tabulator ersetzen
; Hinweis: Alle später definierten über <compose> erreichbaren
; Komposita können diese Definition nicht mehr überschreiben
; und werden daher unerreichbar.
;makeCompose(["S__Comp"], "U000009")
; Werkzeug-Aufrufsequenzen erweitern
;makeCompose(["S__Comp", "U000055", "U000063"], "P__Cal1") ; Uc
;makeCompose(["S__Comp", "U000075", "U000043"], "P__Cal2") ; uC
;makeCompose(["S__Comp", "U000055", "U000077"], "P___WMN") ; Uw
;makeCompose(["S__Comp", "U000075", "U000057"], "P___WMN") ; uW
}
; Diese Funktion wird nach Abschluss der Programminitialisierung aufgerufen,
; nach Definition der Komposita, Tastenbelegung und Modulinitialisierung.
;
; Hinweise:
; - Hier definierte Komposita können bestehende Komposita, einschließlich der
; Originaltastenbelegung, weder verändern noch unerreichbar machen.
InitializeCustom2() {
global
; Beispiele für Kompose-Definitionen:
; <compose> + <enter> → Tastaturbelegung
; Hinweis: Tastaturbelegung wie zu Programmstart ohne Neovars-Modi
;layoutstringEnc := util_str2UCodes(layoutstring)
;makeCompose(["S__Comp", "U00000D"], layoutstringEnc)
; verzögert ßß → ſs auslösen
; (nach commit 97f45845332229b0d7a1344157e04b24d856856b)
;makeCompose(["ß", "ß"], "U0000DFFU0000DF", "U0000DF")
; Beispiele für Bildschirmtastatur-Symbole:
; Tastaturbelegung → ⌨ (Tastatur-Emoji)
; Hinweis: layoutstringEnc aus obigem Beispiel muss definiert sein.
;GUISYM(layoutstringEnc,"⌨")
; Unbelegte Tasten als "Nichts-machen"-Werkzeug darstellen
;GUISYM("","❎","t")
}

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
; -*- 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
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
; -*- encoding: utf-8 -*-
;
; This file is included in interpreted scripts only (not running as .exe)
;
; Run portable version?
isPortable := 0
; Include user-defined scripts?
#include *i %A_AppData%\Neo2\custom.ahk
; Change name of executable?
customName := ""
; Placeholder for revision number (only available when compiled)
revision := "<unknown>"

View File

@ -1,28 +1,21 @@
; -*- encoding: utf-8 -*-
IniRead,einHandNeo,%ini%,Global,einHandNeo,0
If (einHandNeo)
CharProc___EH1()
CP3F10 := "P___EHt"
CP5TAB := "P__M2LT"
CharProc___EHt() {
CharProc___EHt(keyName) {
global
; Einhandmodus togglen
einHandNeo := !(einHandNeo)
if (einHandNeo) {
CharProc___EH1()
CharProc___EH1(keyName)
if (zeigeModusBox)
TrayTip,NEO-Einhandmodus,Der NEO-Einhand-Modus wurde aktiviert. Zum Deaktivieren Mod3+F10 drücken.,10,1
} else {
CharProc___EH0()
CharProc___EH0(keyName)
if (zeigeModusBox)
TrayTip,NEO-Einhand-Modus,Der Einhandmodus wurde deaktiviert.,10,1
}
}
CharProc___EH1() {
CharProc___EH1(keyName) {
global
; Einhand-NEO aktivieren
; Funktionstasten
@ -61,14 +54,13 @@ CharProc___EH1() {
TKEH_VKBDSC035 := "VK59SC02C" ; j -> ü
; Modify Space
ED1("space","P__EHSd")
GUISYM("P__EHSd","EH")
ED("EHSpace",0,"U000020","U000020","U000020","S__N__0","U0000A0","U00202F")
TransformProc := "Einhand"
TransformBSTProc := "Einhand"
; Modify Tab for caps-lock
if (!Mod2LockOff)
ED("tab" ,0,"U000009","U000009","S__Comp","U000009","P__M2LT","U000009")
}
CharProc___EH0() {
CharProc___EH0(keyName) {
global
; Einhand-NEO deaktivieren
; Funktionstasten
@ -106,44 +98,41 @@ CharProc___EH0() {
TKEH_VKBESC034 := "" ; .
TKEH_VKBDSC035 := "" ; j
ED("space",0,"U000020","U000020","U000020","S__N__0","U0000A0","U00202F")
GUISYM("P__EHSd","")
if (!Mod2LockOff)
ED("tab" ,0,"U000009","U000009","S__Comp","U000009","U000009","U000009")
TransformProc := ""
TransformBSTProc := ""
RemoveTransformEinhand() ; make sure we remove trafo
}
CharProc__EHSd() {
CharProc__EHSd(keyName) {
global
; Space im Einhandmodus gedrückt
PRspace := "P__EHSu"
if (!EHSpacePressed) {
EHSpacePressed := 1
Check_BSTUpdate(1)
}
PR%keyName% := "P__EHSu"
InstallTransformEinhand()
}
CharProc__EHSu() {
CharProc__EHSu(keyName) {
global
; Space im Einhandmodus losgelassen
if (!EHKeyPressed) {
AllStar("EHSpace", True, "*EHSpace")
AllStar("EHSpace", False, "*EHSpace up")
AllStar("EHSpace", True)
AllStar("EHSpace", False)
}
EHKeyPressed := 0
EHSpacePressed := 0
Check_BSTUpdate(1)
RemoveTransformEinhand()
}
CharProc__M2LT() {
CharProc__M2LT(keyName) {
global
; Mod2Lock Toggle
ToggleMod2Lock()
%EbeneAktualisieren%()
EbeneAktualisieren()
}
TransformEinhand(PhysKey) {
global
if (EHSpacePressed and (TKEH_%PhysKey% != "")) {
if (TKEH_%PhysKey% != "") {
EHKeyPressed := 1
return TKEH_%PhysKey%
}
@ -152,8 +141,35 @@ TransformEinhand(PhysKey) {
TransformBSTEinhand(PhysKey) {
global
if (EHSpacePressed and (TKEH_%PhysKey% != "")) {
if (TKEH_%PhysKey% != "") {
return TKEH_%PhysKey%
}
return PhysKey
}
InstallTransformEinhand() {
global
; install static layout trafo (non-identity)
TransformProc := "Einhand"
TransformBSTProc := "Einhand"
Check_BSTUpdateAsync()
}
RemoveTransformEinhand() {
global
; remove static layout trafo
TransformProc := ""
TransformBSTProc := ""
Check_BSTUpdateAsync()
}
InitializeEinHandNeo() {
global
IniRead,einHandNeo,%ini%,Global,einHandNeo,0
If (einHandNeo)
CharProc___EH1("")
CP3F10 := "P___EHt"
GUISYM("P__EHSd","EH")
GUISYM("P__M2LT","") ; alternativ "⇫"
}

View File

@ -0,0 +1,20 @@
; -*- encoding: utf-8 -*-
; General
#SingleInstance Force
#NoEnv
FileEncoding, UTF-8 ; read/write files in utf-8 (+BOM) encoding by default
; Threading
#MaxThreadsPerHotKey 1 ; (concurrent critical threads get buffered)
Critical, On ; make all threads uninterruptible by default
; Performance
Process, Priority, , High
SetBatchLines, -1 ; (implied by critical on)
; Key events
#MaxHotkeysPerInterval 2000
#UseHook On
SendMode Input ; Event ; "Input" caused some issues 12 years ago, see commit bea2956deafd12fe0347a25822829647063bbc07
SetKeyDelay,-1

View File

@ -1,44 +1,68 @@
; -*- encoding: utf-8 -*-
if (A_IsCompiled) {
; Revisionsinformation bereits verfügbar
} else {
; Revisionsinformation nicht verfügbar oder nicht zuverlässig, nicht neu generieren
Revision := "<unknown>"
;
; Initialize neovars driver program
;
name := Format("Neo 2.0 r{:s}-r{:s} ({:s})", revision, CompRevision, A_ScriptName)
OnExit, exitprogram
; Make sure AHK runs in Unicode version
if (not A_IsUnicode) {
MsgBox, 52, Fehlende Unicode-Unterstützung!,
(LTrim
Das Skript benötigt die Unicode-Version von AutoHotkey
(AutoHotkey_L), wird aber von ANSI-AutoHotkey ausgeführt.
Trotzdem fortfahren?`n
)
IfMsgBox, No
ExitApp
}
name=Neo 2.0 r%Revision%-r%CompRevision% (%A_ScriptName%)
enable=Aktiviere %name%
disable=Deaktiviere %name%
#LTrim ; Quelltext kann eingerückt werden
; Sync lock states
NEONumLockLEDState := "Off"
NEOCapsLockLEDState := "Off"
NEOScrollLockLEDState := "Off"
OnExit, exitprogram
SetNEOLockStates()
ApplicationFolder := A_AppData . "\Neo2"
FileCreateDir, %ApplicationFolder%
ini := ApplicationFolder . "\Neo2.ini"
; Reset global mod-key states
wasNonShiftKeyPressed := 0
isShiftRPressed := 0
isShiftLPressed := 0
isShiftPressed := 0
isMod2Locked := 0
isMod3RPressed := 0
isMod3LPressed := 0
isMod3Pressed := 0
isMod4RPressed := 0
isMod4LPressed := 0
isMod4Pressed := 0
isMod4Locked := 0
; Read program main configuration
IniRead,zeigeLockBox,%ini%,Global,zeigeLockBox,1
IniRead,zeigeModusBox,%ini%,Global,zeigeModusBox,1
IniRead,UseMod4Light,%ini%,Global,UseMod4Light,1
IniRead,useMod4Light,%ini%,Global,useMod4Light,1
IniRead,useMod4LightCaps,%ini%,Global,useMod4LightCaps,0
IniRead,striktesMod2Lock,%ini%,Global,striktesMod2Lock,0
IniRead,dynamischesCompose,%ini%,Global,dynamischesCompose,0
IniRead,NumLockOff,%ini%,Global,NumLockOff,0
IniRead,Mod2LockOff,%ini%,Global,Mod2LockOff,1
IniRead,Mod4LockOff,%ini%,Global,Mod4LockOff,1
IniRead,customLayout,%ini%,Global,customLayout,%A_Space%
IniRead,Mod3RAufAe,%ini%,Global,Mod3RAufAe,0
SetNEOLockStates()
; Tray-Icon erstellen
TrayAktivieren()
; Read input keyboard layout
regread,inputlocale,HKEY_CURRENT_USER,Keyboard Layout\Preload,1
regread,inputlocalealias,HKEY_CURRENT_USER,Keyboard Layout\Substitutes,%inputlocale%
if (inputlocalealias<>"")
if (inputlocalealias != "")
inputlocale := inputlocalealias
if (inputlocale<>"00000407" and inputlocale<>"00000807" and inputlocale<>"00010407") {
; Make sure we run a supported layout
if (inputlocale != "00000407" and inputlocale != "00000807" and inputlocale != "00010407") {
suspend
regread,inputlocale,HKEY_LOCAL_MACHINE,SYSTEM\CurrentControlSet\Control\Keyboard Layouts\%inputlocale%,Layout Text
msgbox, 52, Warnung!,
@ -60,58 +84,38 @@ if (inputlocale<>"00000407" and inputlocale<>"00000807" and inputlocale<>"000104
suspend
}
wasNonShiftKeyPressed := 0
isShiftRPressed := 0
isShiftLPressed := 0
isShiftPressed := 0
isMod2Locked := 0
IsMod3RPressed := 0
IsMod3LPressed := 0
IsMod3Pressed := 0
IsMod4RPressed := 0
IsMod4LPressed := 0
IsMod4Pressed := 0
IsMod4Locked := 0
EbeneAktualisieren := "NEOEbeneAktualisieren"
; Run custom initialization (part I)
; (may include compose definitions)
InitializeCustomFun := "InitializeCustom1"
if (IsFunc(InitializeCustomFun))
%InitializeCustomFun%()
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 == 1)
SetNumLockState, Off
else
SetNumLockState, On
SetScrollLockState, Off
SetCapsLockState, Off
Sleep,1
UpdateNEOLEDS()
}
SetOldLockStates() {
global
UpdateOldLEDS()
Sleep,1
SetNumLockState,% SavedNumLockState
SetScrollLockState,% SavedScrollLockState
SetCapsLockState,% SavedCapsLockState
}
%EbeneAktualisieren%()
ActivateLayOut(inputlocale)
TheKeys()
if (dynamischesCompose)
; Load compose-definitions
; Later definitions cannot modify prior ones.
LoadToolsCompose() ; tool invocation sequences (as documented)
if (dynamischesCompose) ; parse external XCompose
LoadCurrentCompose()
else
LoadDefaultCompose()
LoadDefaultCompose() ; precompiled XCompose
; Activate driver with default- or custom layout
ActivateLayOut(inputlocale)
TheKeys()
ChangeCustomLayout()
EbeneAktualisieren()
; Initialize auxiliary modules
; (may modify or add keys to the layout)
InitializeLangSTastatur()
InitializeEinHandNeo()
InitializeLernModus()
InitializeQwertz()
InitializeTools()
InitializeBST() ; Bildschirmtastatur erst nach Anpassungen laden
; Run custom initialization (part II)
; (may include compose definitions)
InitializeCustomFun := "InitializeCustom2"
if (IsFunc(InitializeCustomFun))
%InitializeCustomFun%()

View File

@ -19,13 +19,34 @@ UpdateNEOLEDS() {
;ScrollLock=1, NumLock=2, CapsLock=4, bzw. eine beliebige Summe dieser Werte
KeyboardLED(LEDvalue, Cmd){ ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cmd = on/off/switch
Static h_device
If ! h_device ; initialise
Static h_devices := Array()
; initialise
If (h_devices.Length() == 0)
{
device=\Device\KeyBoardClass0
SetUnicodeStrLED(fn,device)
h_device:=NtCreateFileLED(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0)
; find keyboards in registry
Loop, Reg, HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\KeyboardClass
{
If (A_LoopRegType == "REG_SZ")
{
If (SubStr(A_LoopRegName, 1,21) == "\Device\KeyboardClass")
{
SetUnicodeStrLED(fn, A_LoopRegName)
h_devices.Push(NtCreateFileLED(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0))
}
}
}
; fallback: default to Class0
If (h_devices.Length() == 0)
{
SetUnicodeStrLED(fn, "\Device\KeyBoardClass0")
h_devices.Push(NtCreateFileLED(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0))
}
}
; send LED cmd to all keyboard drivers
Loop % h_devices.Length()
{
VarSetCapacity(output_actual,4,0)
input_size=4
VarSetCapacity(input,input_size,0)
@ -39,22 +60,20 @@ KeyboardLED(LEDvalue, Cmd){ ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cm
KeyLED:=LEDvalue & (GetKeyState("ScrollLock","T") + 2*GetKeyState("NumLock","T") + 4*GetKeyState("CapsLock","T"))
}
; EncodeIntegerLED(KeyLED,1,&input,2) ;input bit pattern (KeyLED): bit 0 = scrolllock ;bit 1 = numlock ;bit 2 = capslock
input:=Chr(1) Chr(1) Chr(KeyLED)
input:=Chr(1)
input=
success:=DllCall("DeviceIoControl"
, "uint", h_device
, "ptr" , h_devices[A_Index]
, "uint", CTL_CODE_LED( 0x0000000b ; FILE_DEVICE_KEYBOARD
, 2
, 0 ; METHOD_BUFFERED
, 0 ) ; FILE_ANY_ACCESS
, "uint", &input
, "int*", KeyLED << 16
, "uint", input_size
, "uint", 0
, "uint", 0
, "uint", &output_actual
, "uint", 0 )
}
}
CTL_CODE_LED(p_device_type,p_function,p_method,p_access ){
Return, ( p_device_type << 16 ) | ( p_access << 14 ) | ( p_function << 2 ) | p_method
@ -77,10 +96,8 @@ NtCreateFileLED(ByRef wfilename,desiredaccess,sharemode,createdist,flags,fattrib
}
SetUnicodeStrLED(ByRef out, str_){
VarSetCapacity(st1, 8, 0)
InsertIntegerLED(0x530025, st1)
VarSetCapacity(out, (StrLen(str_)+1)*2, 0)
DllCall("wsprintfW", "str", out, "str", st1, "str", str_, "Cdecl UInt")
VarSetCapacity(out, 2*StrPut(str_, "utf-16"))
StrPut(str_, &out, "utf-16")
}
ExtractIntegerLED(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4){

View File

@ -1,5 +1,8 @@
; -*- encoding:utf-8 -*-
#Include %A_LineFile%\..\util.ahk
thekeys() {
global
layoutstring := ""
@ -115,26 +118,27 @@ ED1S("138","P__M4RD") ; Mod4R (AltGr)
SetKeyPos(pos,char) {
global
; Generate lookup table for "Wie mit Neo" tool
current := %pos%
if (current != "")
StringReplace,CRK%current%,CRK%current%,% " " . pos . " ",% " "
if (SubStr(CRK%char%,0) != " ")
CRK%char% .= " "
CRK%char% .= pos . " "
; Map layout-position (CP.VK...SC...) to character
%pos% := char
; Add trivial compose (echo itself)
; (will be ignored if compose exists already,
; e.g. in case of dupliate keys)
makeCompose([char], char)
}
EDR(pos,caps,e1,e2,e3,e4,e5,e6,e7="",e8="") {
global
if (caps == 0)
NOC%pos% := 1
else {
NOC%pos% := 0
if (e1 != "")
UNSH%e1% := 1 ; unshift wenn caps lock + Shift?
else
UNSH%e1% := 0
}
NOC%pos% := !caps ; capslock sensitivity
SetKeyPos("CP1" . pos,e1)
SetKeyPos("CP2" . pos,e2)
SetKeyPos("CP3" . pos,e3)
@ -147,14 +151,14 @@ EDR(pos,caps,e1,e2,e3,e4,e5,e6,e7="",e8="") {
ED(pos,caps,e1a,e2a,e3a,e4a,e5a,e6a,e7a="",e8a="") {
global
e1 := EncodeUniComposeA(e1a)
e2 := EncodeUniComposeA(e2a)
e3 := EncodeUniComposeA(e3a)
e4 := EncodeUniComposeA(e4a)
e5 := EncodeUniComposeA(e5a)
e6 := EncodeUniComposeA(e6a)
e7 := EncodeUniComposeA(e7a)
e8 := EncodeUniComposeA(e8a)
e1 := util_char2UCode(e1a)
e2 := util_char2UCode(e2a)
e3 := util_char2UCode(e3a)
e4 := util_char2UCode(e4a)
e5 := util_char2UCode(e5a)
e6 := util_char2UCode(e6a)
e7 := util_char2UCode(e7a)
e8 := util_char2UCode(e8a)
EDR(pos,caps,e1,e2,e3,e4,e5,e6,e7,e8)
}
@ -178,34 +182,62 @@ EDS(scpos,caps,e1a,e2a,e3a,e4a,e5a,e6a,e7a="",e8a="") {
ED(vksc%scpos%,caps,e1a,e2a,e3a,e4a,e5a,e6a,e7a,e8a)
}
; = EDS + append key to custom layout
EDSK(scpos,caps,e1a,e2a,e3a,e4a,e5a,e6a,e7a="",e8a="") {
global
EDS(scpos,caps,e1a,e2a,e3a,e4a,e5a,e6a,e7a,e8a)
layoutstringpos := strlen(layoutstring) + 1
layoutstring .= e1a
e1 := EncodeUniComposeA(e1a)
; remember scancodes in original layout order
LOSP%layoutstringpos%:=scpos
LOSE2%e1% := e2a
LOSE5%e1% := e5a
LOSE6%e1% := e6a
LOSEC%e1% := caps
}
; replace level 'eb' of layout character 'la' with 'ea'
EDSKUpdate(la, ea, eb) {
global layoutstring
; locate key position in current layout
lspos := InStr(layoutstring, la)
scpos := LOSP%lspos%
pos := vksc%scpos%
; set properties
SetKeyPos("CP" . eb . pos, util_char2UCode(ea))
}
Change1256Layout(newlayoutstring) {
global
local lspos, scpos, pos, e1a, e1
if (strlen(newlayoutstring) != 33) {
MsgBox,Falscher Layoutstring, zu wenige Zeichen!
return
}
layoutstring := ""
layoutstringpos := 1
while (layoutstringpos <= 33) {
e1a := substr(newlayoutstring,layoutstringpos,1)
e1 := EncodeUniComposeA(e1a)
ED1256(LOSP%layoutstringpos%, LOSEC%e1%, e1a, LOSE2%e1%, LOSE5%e1%, LOSE6%e1%)
layoutstring .= e1a
layoutstringpos := layoutstringpos + 1
; read levels 2 (with caps option),5,6 from current layout
local keyProps := []
Loop, Parse, newlayoutstring
{
; position of new layout char. in current layout
e1a := A_LoopField
lspos := InStr(layoutstring, A_LoopField)
; make a copy of the current key's properties
scpos := LOSP%lspos%
pos := vksc%scpos%
keyProps.Push([(NOC%pos%==0 ? 1 : 0), CP2%pos%, CP5%pos%, CP6%pos%])
}
; apply levels 1,2 (with caps option),5,6 in new layout order
Loop, Parse, newlayoutstring
{
e1a := A_LoopField
e1 := util_char2UCode(e1a)
scpos := LOSP%A_Index%
pos := vksc%scpos%
; apply cached properties (plus new level 1 char.) in new order
EDR1256(pos, keyProps[A_Index][1], e1, keyProps[A_Index][2], keyProps[A_Index][3], keyProps[A_Index][4])
}
; update layoutstring
layoutstring := newlayoutstring
}
Change1256LayoutNeo20() {
@ -235,44 +267,15 @@ ED1S(scpos,e1a) {
EDS(scpos,0,e1a,e1a,e1a,e1a,e1a,e1a)
}
ED12(scpos,caps,e1a,e2a) {
EDR1256(pos,caps,e1,e2,e5,e6) {
global
pos := vksc%scpos%
e1 := EncodeUniComposeA(e1a)
e2 := EncodeUniComposeA(e2a)
if (caps == 0) {
NOC%pos% := 1
UNSH%e1% := 0
} else {
NOC%pos% := 0
UNSH%e1% := 1 ; unshift wenn caps lock + Shift?
}
SetKeyPos("CP1" . pos, e1)
SetKeyPos("CP2" . pos, e2)
}
ED1256(scpos,caps,e1a,e2a,e5a,e6a) {
global
pos := vksc%scpos%
e1 := EncodeUniComposeA(e1a)
e2 := EncodeUniComposeA(e2a)
e5 := EncodeUniComposeA(e5a)
e6 := EncodeUniComposeA(e6a)
if (caps == 0) {
NOC%pos% := 1
UNSH%e1% := 0
} else {
NOC%pos% := 0
UNSH%e1% := 1 ; unshift wenn caps lock + Shift?
}
NOC%pos% := !caps ; capslock sensitivity
SetKeyPos("CP1" . pos, e1)
SetKeyPos("CP2" . pos, e2)
SetKeyPos("CP5" . pos, e5)
SetKeyPos("CP6" . pos, e6)
}
Comp := ""
; RegisterAndHookSC
RSC(sc,vk) {
global
@ -300,10 +303,11 @@ RKEYS(keys) {
}
}
; Register hotkeys for up, down key activation events
RKEYN(dnkey, key) {
upkey := dnkey . " up"
upfn := Func("AllStar").Bind(key, False, upkey)
dnfn := Func("AllStar").Bind(key, True, dnkey)
upfn := Func("AllStar").Bind(key, False)
dnfn := Func("AllStar").Bind(key, True)
Hotkey,% dnkey,% dnfn
Hotkey,% upkey,% upfn
}
@ -380,10 +384,9 @@ Layout00000407() {
RSCN("053","6E","2E") ; NumpadDot/NumpadDel
; Diverses
RKEYS("F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12")
RKEYS("space,enter,backspace")
RKEYS("tab,space,enter,backspace")
RKEYS("del,ins,home,end,pgup,pgdn,up,down,left,right")
; Diverses ohne *
RKEYN("tab", "tab")
RKEYN("esc", "esc")
RKEYN("numpadenter", "numpadenter")
; Modifier
@ -593,10 +596,9 @@ Layout00000807() {
RSCN("053","6E","2E") ; NumpadDot/NumpadDel
; Diverses
RKEYS("F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12")
RKEYS("space,enter,backspace")
RKEYS("tab,space,enter,backspace")
RKEYS("del,ins,home,end,pgup,pgdn,up,down,left,right")
; Diverses ohne *
RKEYN("tab", "tab")
RKEYN("esc", "esc")
RKEYN("numpadenter", "numpadenter")
; Modifier

View File

@ -1,27 +1,19 @@
; -*- encoding: utf-8 -*-
; Wir müssen F24 nicht hooken, aber bei einem Restart hat AHK den Bug,
; dass manchmal der erste Hook ausgeführt wird, als wäre diese Taste
; gedrückt worden. Da F24 auf den wenigsten Tastaturen vorkommt und daher für
; NEO uninteressant ist, kehren wir einfach wieder zurück.
~F24::return
; Suspend on shift+pause
; Lines marked * are needed with "SendMode, Input", since the Shift
; keys are already captured hotkeys and cannot trigger other hotkeys
pause:: ; *
+pause::
Suspend, Permit
if (GetKeyState("Shift")) ; *
Traytogglesuspend()
return
; Ein paar andere Hooks kommen hier auch noch. GUIs springen hier her, wenn
; sich bei ihnen etwas auf die entsprechende Art tut.
GuiClose:
if (GuiCurrent!="")
%GuiCurrent%OnClose()
else
Gui, Destroy
return
GuiSize:
if (GuiCurrent!="")
%GuiCurrent%OnSize()
return

View File

@ -1,33 +1,31 @@
; -*- encoding: utf-8 -*-
IniRead,LangSTastatur,%ini%,Global,LangSTastatur,0
If (LangSTastatur)
CharProc__LnS1()
#Include %A_LineFile%\..\util.ahk
CP3F11 := "P__LnSt"
CharProc__LnSt() {
CharProc__LnSt(keyName) {
global
; Nur aktivieren, wenn kein Qwertz aktiv ist
if (isQwertz) {
TrayTip,Lang-S-Tastatur,Die Lang-S-Belegungsvariante kann nicht im QWERTZ-Modus aktiviert werden.,10,1
Return
}
;if (isQwertz) {
; TrayTip,Lang-S-Tastatur,Die Lang-S-Belegungsvariante kann nicht im QWERTZ-Modus aktiviert werden.,10,1
; Return
;}
;Lang-s-Tastatur: Toggle
LangSTastatur := !(LangSTastatur)
if (LangSTastatur) {
CharProc__LnS1()
CharProc__LnS1(keyName)
if (zeigeModusBox)
TrayTip,Lang-S-Tastatur,Die Lang-S-Belegungsvariante wurde aktiviert. Zum Deaktivieren`, Mod3+F11 drücken.,10,1
} else {
CharProc__LnS0()
CharProc__LnS0(keyName)
if (zeigeModusBox)
TrayTip,Lang-S-Tastatur,Lang-S-Belegungsvariante wurde deaktiviert.,10,1
}
}
CharProc__LnS1() {
CharProc__LnS1(keyName) {
global
; Lange-s-Tastatur aktivieren
spos := InStr(layoutstring, "s")
@ -36,17 +34,17 @@ CharProc__LnS1() {
; ſ, s und ß zyklisch vertauschen auf den drei Positionen
scpos := LOSP%spos%
pos := vksc%scpos%
SetKeyPos("CP1" . pos, EncodeUniComposeA("ſ"))
SetKeyPos("CP1" . pos, util_char2UCode("ſ"))
scpos := LOSP%eszettpos%
pos := vksc%scpos%
SetKeyPos("CP1" . pos, EncodeUniComposeA("s"))
SetKeyPos("CP1" . pos, util_char2UCode("s"))
pos := vksc01A
SetKeyPos("CP3" . pos, EncodeUniComposeA("ß"))
SetKeyPos("CP3" . pos, util_char2UCode("ß"))
}
CharProc__LnS0() {
CharProc__LnS0(keyName) {
global
; Lange-s-Tastatur deaktivieren
spos := InStr(layoutstring, "s")
@ -55,12 +53,21 @@ CharProc__LnS0() {
; ſ, s und ß wieder auf die Originalpositionen setzen
scpos := LOSP%spos%
pos := vksc%scpos%
SetKeyPos("CP1" . pos, EncodeUniComposeA("s"))
SetKeyPos("CP1" . pos, util_char2UCode("s"))
scpos := LOSP%eszettpos%
pos := vksc%scpos%
SetKeyPos("CP1" . pos, EncodeUniComposeA("ß"))
SetKeyPos("CP1" . pos, util_char2UCode("ß"))
pos := vksc01A
SetKeyPos("CP3" . pos, EncodeUniComposeA("ſ"))
SetKeyPos("CP3" . pos, util_char2UCode("ſ"))
}
InitializeLangSTastatur() {
global
IniRead,LangSTastatur,%ini%,Global,LangSTastatur,0
If (LangSTastatur)
CharProc__LnS1("")
CP3F11 := "P__LnSt"
}

View File

@ -17,28 +17,22 @@ lernModus_std_ZahlenReihe := 0
lernModus_neo_Backspace := 1
lernModus_neo_Entf := 1
CP3F9 := "P___LMt"
IniRead,lernModus,%ini%,Global,lernModus,0
If (lernModus)
CharProc___LM1()
CharProc___LMt() {
CharProc___LMt(keyName) {
global
; Lernmodus togglen
lernModus := !(lernModus)
if (lernModus) {
CharProc___LM1()
CharProc___LM1(keyName)
if (zeigeModusBox)
TrayTip,NEO-Lernmodus,NEO-Lernmodus wurde aktiviert. Zum Deaktivieren`, Mod3+F9 drücken.,10,1
} else {
CharProc___LM0()
CharProc___LM0(keyName)
if (zeigeModusBox)
TrayTip,NEO-Lernmodus,Lernmodus wurde deaktiviert.,10,1
}
}
CharProc___LM1() {
CharProc___LM1(keyName) {
global
; Lernmodus aktivieren
if (!lernModus_std_Return)
@ -71,7 +65,7 @@ CharProc___LM1() {
CP4VK52SC013 := "" ; Ebene 4 unter c (QWERTZ: r)
}
CharProc___LM0() {
CharProc___LM0(keyName) {
global
; Lernmodus deaktivieren
ED1("enter" ,"U00000D")
@ -89,3 +83,12 @@ CharProc___LM0() {
CP4VK57SC011 := "U000008"
CP4VK52SC013 := "S___Del"
}
InitializeLernModus() {
global
IniRead,lernModus,%ini%,Global,lernModus,0
If (lernModus)
CharProc___LM1("")
CP3F9 := "P___LMt"
}

View File

@ -1,6 +1,6 @@
; -*- encoding: utf-8 -*-
NEOEbeneAktualisieren() {
EbeneAktualisieren() {
global
Ebene7 := 0
Ebene8 := 0
@ -22,77 +22,47 @@ NEOEbeneAktualisieren() {
Ebene7 := SubStr("00000000010100000101000000000000",ModPos,1)
Ebene8 := SubStr("00000000000001010000000000000101",ModPos,1)
Check_BSTUpdate()
}
IsShiftActive() {
global
if (isMod2Locked)
if (isShiftPressed)
return 0
else
return 1
else
if (isShiftPressed)
return 1
else
return 0
}
IsMod3Active() {
global
return isMod3Pressed
}
IsMod4Active() {
global
if (isMod4Locked)
if (isMod4Pressed)
return 0
else
return 1
else
if (isMod4Pressed)
return 1
else
return 0
Check_BSTUpdateAsync()
}
ToggleMod2Lock() {
global
if (Mod2LockOff)
return
if (isMod2Locked)
{
isMod2Locked := 0
NEOCapsLockLEDState := "Off"
UpdateNEOLEDS()
}
else
{
isMod2Locked := 1
NEOCapsLockLEDState := "On"
; LEDs
if (not (useMod4LightCaps and isMod4Locked)) {
NEOCapsLockLEDState := isMod2Locked ? "On" : "Off"
UpdateNEOLEDS()
}
}
ToggleMod4Lock() {
global
if (IsMod4Locked) {
IsMod4Locked := 0
if (UseMod4Light) {
NEOScrollLockLEDState := "Off"
UpdateNEOLEDS()
}
if (Mod4LockOff)
return
if (isMod4Locked) {
isMod4Locked := 0
if (zeigeLockBox)
TrayTip,Mod4-Feststellung,Die Feststellung wurde aufgehoben.,3,1
} else {
IsMod4Locked := 1
if (UseMod4Light) {
NEOScrollLockLEDState := "On"
UpdateNEOLEDS()
}
isMod4Locked := 1
if (zeigeLockBox)
TrayTip,Mod4-Feststellung,Um Mod4 wieder zu lösen`, drücke beide Mod4-Tasten gleichzeitig!,3,1
}
; LEDs
local LEDChange := 0
if (useMod4Light) {
NEOScrollLockLEDState := isMod4Locked ? "On" : "Off"
LEDChange := 1
}
if (useMod4LightCaps and not isMod2Locked) {
NEOCapsLockLEDState := isMod4Locked ? "On" : "Off"
LEDChange := 1
}
if (LEDChange)
UpdateNEOLEDS()
}

File diff suppressed because it is too large Load Diff

View File

@ -3,46 +3,49 @@
SetWorkingDir, %A_ScriptDir%
#include %A_ScriptDir%\
; globale Schalter
#include global_switches.ahk
; Revision Information (don't moun)
#include *i _gitwcrev.generated.ahk
; globale Konfiguration des interpretierten/kompilierten Skriptes
; Lädt optional benutzerdefinierte Skripte (custom.ahk)
#include *i config-iscompiled%A_IsCompiled%.ahk
#include *i config-iscompiled%A_IsCompiled%.generated.ahk
; Ressourcen und Hilfsmittel
#include resources.ahk
#include util.ahk
; die Compose-Definitionen
#include compose.ahk
#include compose-parse.ahk
#include *i compose.generated.ahk
#include *i compose-tainted.generated.ahk
#include compose-gen.ahk
; Hier liegt die Tastaturbelegung
#include keydefinitions.ahk
; Shortcuts, um die Zeichen wieder sauber zur Applikation bringen zu können
#include performance.ahk
#include shortcuts.ahk
; Good-old AHK-Skripts, enthalten die ersten Key-Hooks für Mod-Tasten
; Achtung: Hinter dem ersten Keyboard-Hook werden keine globalen Variablen
; mehr gesetzt!
#include initialize.ahk
#include resources.ahk
; Das Herz von neo20.ahk: die Tasten- und Zeichen-Behandlungsroutinen
#include varsfunctions.ahk
#include levelfunctions.ahk
; Mitgelieferte Belegungsvarianten
#include langstastatur.ahk
#include einhandneo.ahk
#include lernmodus.ahk
#include qwertz.ahk
#include tools.ahk
; Die Bildschirmtastatur
; Funktionale Module
#include tray.ahk
#include tools.ahk
#include keyboardleds.ahk
#include screenkeyboard.ahk
; individuelle Einstellungen
#include *i %A_AppData%\Neo2\custom.ahk
; Startup
#include initialize.ahk
#include tray.ahk
; - Ende der Auto-Execute Sektion -
#include keyhooks.ahk
#include levelfunctions.ahk
#include keyboardleds.ahk

View File

@ -1,14 +0,0 @@
; -*- encoding: utf-8 -*-
#MaxThreadsPerHotKey 1
Thread,Interrupt,-1,-1
SetBatchLines -1
#singleinstance force
Process,Priority,,High
#MaxHotkeysPerInterval 2000
#usehook on
Sendmode Event
SetKeyDelay,-1

View File

@ -2,55 +2,47 @@
; QWERTZ
; (c) 2011 Matthias Wächter
CharProcQwertT() {
CharProcQwertT(keyName) {
global
; Custom Layout togglen
if (isQwertz == 0) {
isQwertz := 1
CharProcQwerT1()
CharProcQwerT1(keyName)
if (zeigeModusBox)
TrayTip,QWERTZ-Belegungsvariante,Die Belegungsvariante QWERTZ wurde aktiviert. Zum Umschalten`, Mod3+F6 drücken.,10,1
} else {
isQwertz := 0
CharProcQwerT0()
CharProcQwerT0(keyName)
if (zeigeModusBox)
TrayTip,Voreingestellte Belegungsvariante,Die voreingestellte Belegungsvariante wurde wieder aktiviert.,10,1
}
}
CharProcQwerT1() {
CharProcQwerT1(keyName) {
; Tastaturbelegungsvariante QWERTZ aktivieren
Change1256Layout("ßqwertzuiopüasdfghjklöäyxcvbnm,.-")
}
CharProcQwerT0() {
CharProcQwerT0(keyName) {
; Ursprüngliche Belegung wieder aktivieren
ChangeCustomLayout()
}
CharProcQwerts() {
CharProcQwerts(keyName) {
global
if (isQwertz == 0)
IniDelete,%ini%,Global,isQwertz
else
IniWrite,%isQwertz%,%ini%,Global,isQwertz
if ErrorLevel
TrayTip,QWERTZ-Belegungsvariante,Beim Speichern der Einstellung ist ein Fehler aufgetreten.,10,1
else if (zeigeModusBox)
TrayTip,QWERTZ-Belegungsvariante,Die aktuelle Einstellung wurde gespeichert.,10,1
}
ActivateQwertz() {
InitializeQwertz() {
global
IniRead,isQwertz,%ini%,Global,isQwertz,0
if (isQwertz == 1)
CharProcQwerT1("")
CP3F6 := "PQwertt" ; M3+F6: Aktiviere/Deaktiviere QWERTZ
CP4F6 := "PQwerts" ; M4+F6: Speichere QWERTZ
IniRead,isQwertz,%ini%,Global,isQwertz,0
if (isQwertz == 1)
CharProcQwerT1()
}
ActivateQwertz()

View File

@ -1,11 +1,23 @@
; -*- encoding: utf-8 -*-
if isPortable
ApplicationFolder := A_ScriptDir . "\Neo2-portable"
else
ApplicationFolder := A_AppData . "\Neo2"
FileCreateDir, %ApplicationFolder%
ini := ApplicationFolder . "\Neo2.ini"
if isPortable
ResourceFolder := ApplicationFolder
else {
EnvGet, WindowsEnvTempFolder, TEMP
ResourceFolder = %WindowsEnvTempFolder%\Neo2
ResourceFolder := WindowsEnvTempFolder . "\Neo2"
}
FileCreateDir, %ResourceFolder%
if (FileExist("ResourceFolder")<>false) {
FileInstall,neo_enabled.ico,%ResourceFolder%\neo_enabled.ico,1
FileInstall,neo_disabled.ico,%ResourceFolder%\neo_disabled.ico,1
if InStr(FileExist(ResourceFolder), "D") {
installOverwrite := (isPortable ? 0 : 1)
FileInstall, ..\res\neo_enabled.ico, %ResourceFolder%\neo_enabled.ico, % installOverwrite
FileInstall, ..\res\neo_disabled.ico, %ResourceFolder%\neo_disabled.ico, % installOverwrite
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
; -*- encoding: utf-8 -*-
; -*- encoding: utf-8 -*-
/* SHORTCUTS
Da in diesem AHK-Skript sämtliche Tastendrücke zur weiteren Verarbeitung
@ -121,15 +121,15 @@ CSS__L_M2 := "LShift"
CSS__R_M2 := "RShift"
/*
Jetzt noch ein paar Verschönerungsabkürzungen
Jetzt noch ein paar Verschönerungsabkürzungen (menschenlesbar, Wie mit Neo-Tool)
*/
CBS____M2 := "Shift+"
CBS____M3 := "Mod3+"
CBS____M4 := "Mod4+"
CBS____M5 := "Mod5=Shift+Mod3+"
CBS____M6 := "Mod6=Mod3+Mod4+"
CBS____M7 := "Mod7=Shift+Mod4+"
CBS____M8 := "Mod8=Shift+Mod3+Mod4+"
CBS____M5 := "[Mod5=Shift+Mod3]+"
CBS____M6 := "[Mod6=Mod3+Mod4]+"
CBS____M7 := "[Mod7=Shift+Mod4]+"
CBS____M8 := "[Mod8=Shift+Mod3+Mod4]+"
CBS__Comp := "Compose"
CBT__Acut := "Akut"
@ -147,6 +147,9 @@ CBT__drss := "Trema"
CBT__dbac := "Doppelakut"
CBT__strk := "Schrägstrich"
CBU0000A0 := "geschütztes Leerzeichen"
CBU00202F := "schmales geschütztes Leerzeichen"
CBU00005E := "^"
CBU000060 := "``"
CBU0000B4 := "´"

View File

@ -1,28 +1,25 @@
; -*- encoding: utf-8 -*-
#Include %A_LineFile%\..\util.ahk
; Römische Zahlen
CMS__Comp := 1
CMS__CompU000072 := 1
CMS__CompU000052 := 1
CDS__CompU000072U00004F := "P__Rom1"
;CDS__CompU000072U000031 := "P__Rom1"
;CDS__CompU000052U000031 := "P__Rom1"
CDS__CompU000052U00004F := "P__Rom2"
;CDS__CompU000072U000032 := "P__Rom2"
;CDS__CompU000052U000032 := "P__Rom2"
CDS__CompU000072U00006F := "P__Rom3"
;CDS__CompU000072U000033 := "P__Rom3"
;CDS__CompU000052U000033 := "P__Rom3"
CDS__CompU000052U00006F := "P__Rom4"
;CDS__CompU000072U000034 := "P__Rom4"
;CDS__CompU000052U000034 := "P__Rom4"
LoadToolComposeRoman() {
makeCompose(["S__Comp", "U000072", "U00004F"], "P__Rom1") ; rO
makeCompose(["S__Comp", "U000052", "U00004F"], "P__Rom2") ; RO
makeCompose(["S__Comp", "U000072", "U00006F"], "P__Rom3") ; ro
makeCompose(["S__Comp", "U000052", "U00006F"], "P__Rom4") ; RO
}
GUISYM("P__Rom1","")
GUISYM("P__Rom2","")
GUISYM("P__Rom3","vii")
GUISYM("P__Rom4","VII")
InitializeToolRoman() {
global
GUISYM("P__Rom1","","t")
GUISYM("P__Rom2","","t")
GUISYM("P__Rom3","vii","t")
GUISYM("P__Rom4","VII","t")
}
CharProc__Rom1() {
CharProc__Rom1(keyName) {
global
; starte klein geschriebene römische Zahlen, verwende U2160++
PressHookProc := "Roman"
@ -30,7 +27,7 @@ CharProc__Rom1() {
RomanSum := 0
}
CharProc__Rom2() {
CharProc__Rom2(keyName) {
global
; starte groß geschriebene römische Zahlen, verwende U2160++
PressHookProc := "Roman"
@ -38,7 +35,7 @@ CharProc__Rom2() {
RomanSum := 0
}
CharProc__Rom3() {
CharProc__Rom3(keyName) {
global
; starte klein geschriebene römische Zahlen, verwende Buchstaben
PressHookProc := "Roman"
@ -46,7 +43,7 @@ CharProc__Rom3() {
RomanSum := 0
}
CharProc__Rom4() {
CharProc__Rom4(keyName) {
global
; starte groß geschriebene römische Zahlen, verwende Buchstaben
PressHookProc := "Roman"
@ -57,14 +54,14 @@ CharProc__Rom4() {
GenRomanDigit(Pos, DigitIs, DigitTest, str0, str1, str2, str3, str4, str5) {
res := ""
if (DigitIs == DigitTest)
res := EncodeUniComposeA(str%Pos%)
res := util_char2UCode(str%Pos%)
return res
}
PressHookRoman(PhysKey, ActKey, Char) {
PressHookRoman(PhysKey, Char) {
global
if (SubStr(Char,1,1) == "P")
CharStarDown(PhysKey, ActKey, Char)
return True
else if ((Char == "U000030") or (Char == "S__N__0"))
RomanSum := 10*RomanSum
else if ((Char == "U000031") or (Char == "S__N__1"))
@ -166,42 +163,46 @@ PressHookRoman(PhysKey, ActKey, Char) {
PressHookProc := ""
} else
PressHookProc := ""
return False
}
CMS__CompU000075 := 1
CMS__CompU000055 := 1
CDS__CompU000075U000075 := "P___Uni"
CDS__CompU000075U000055 := "P___Uni"
CDS__CompU000055U000075 := "P___Uni"
CDS__CompU000055U000055 := "P___Uni"
CMS__CompU000064 := 1
CMS__CompU000044 := 1
CDS__CompU000064U000064 := "P__DUni"
CDS__CompU000064U000044 := "P__DUni"
CDS__CompU000044U000064 := "P__DUni"
CDS__CompU000044U000044 := "P__DUni"
; Unicode <> Hex converter
LoadToolComposeUni() {
global
makeCompose(["S__Comp", "U000075", "U000075"], "P___Uni")
makeCompose(["S__Comp", "U000075", "U000055"], "P___Uni")
makeCompose(["S__Comp", "U000055", "U000075"], "P___Uni")
makeCompose(["S__Comp", "U000055", "U000055"], "P___Uni")
makeCompose(["S__Comp", "U000064", "U000064"], "P__DUni")
makeCompose(["S__Comp", "U000064", "U000044"], "P__DUni")
makeCompose(["S__Comp", "U000044", "U000064"], "P__DUni")
makeCompose(["S__Comp", "U000044", "U000044"], "P__DUni")
}
CP5VK41SC01E := "P___Uni"
GUISYM("P___Uni","UU")
GUISYM("P__DUni","DD")
InitializeToolUni() {
global
EDSKUpdate("u","P___Uni",5)
GUISYM("P___Uni","UU","t")
GUISYM("P__DUni","DD","t")
}
CharProc___Uni() {
CharProc___Uni(keyName) {
global
; starte Unicode-Hex-in-Zeichen-Umwandlung
PressHookProc := "Uni"
UniSum := ""
}
CharProc__DUni() {
CharProc__DUni(keyName) {
global
; starte Unicode-Zeichen-in-Hex-Umwandlung
CharOutFilterProc := "DUni"
}
PressHookUni(PhysKey, ActKey, Char) {
PressHookUni(keyName, Char) {
global
if (SubStr(Char,1,1) == "P")
CharStarDown(PhysKey, ActKey, Char)
return True
else if ((Char == "U000030") or (Char == "S__N__0"))
UniSum := UniSum . "0"
else if ((Char == "U000031") or (Char == "S__N__1"))
@ -235,13 +236,15 @@ PressHookUni(PhysKey, ActKey, Char) {
else if ((Char == "U000046") or (Char == "U000066"))
UniSum := UniSum . "F"
else if ((Char == "U00000D") or (Char == "U000020")) {
UniSum := "U" . SubStr("000000" . UniSum, -7)
PP%PhysKey% := UniSum
PR%PhysKey% := UniSum
UniSum := "U" . SubStr("000000" . UniSum, -5)
kbdRepChars := UniSum
kbdRepKey := keyName
PR%keyName% := UniSum
CharOutDown(UniSum)
PressHookProc := ""
} else
PressHookProc := ""
return False
}
CharOutFilterDUni(char,down,up) {
@ -256,64 +259,20 @@ CharOutFilterDUni(char,down,up) {
return char
}
EncodeUni(str) {
SetFormat, Integer, hex
; MsgBox % Asc(SubStr(str,1,1)) . Asc(SubStr(str,2,1))
result := ""
loop {
char := asc(SubStr(str,1,1))
str := SubStr(str,2)
if (char < 0x80)
result .= "U" . SubStr("000000" . SubStr(char,3),-5)
else if (char < 0xC0) {
; error
} else if (char < 0xE0) {
char2 := asc(Substr(str,1,1))
str := SubStr(str,2)
if ((char2 < 0x80) or (char2 > 0xBF)) {
; error
} else {
result .= "U" . SubStr("000000" . SubStr((((char & 0x1F) << 6) + (char2 & 0x3F)),3),-5)
}
} else if (char < 0xF8) {
char2 := asc(SubStr(str,1,1))
char3 := asc(SubStr(str,2,1))
str := SubStr(str,3)
if ((char2 < 0x80) or (char2 > 0xBF)
or (char3 < 0x80) or (char3 > 0xBF)) {
; error
} else {
result .= "U" . SubStr("000000" . SubStr((((char & 0x0F) << 12) + ((char2 & 0x3F) << 6) + (char3 & 0x3F)),3),-5)
}
} else if (char < 0xFC) {
char2 := asc(SubStr(str,1,1))
char3 := asc(SubStr(str,2,1))
char3 := asc(SubStr(str,3,1))
str := SubStr(str,4)
if ( (char2 < 0x80) or (char2 > 0xBF)
or (char3 < 0x80) or (char3 > 0xBF)
or (char4 < 0x80) or (char4 > 0xBF)) {
; error
} else {
result .= "U" . SubStr("000000" . SubStr((((char & 0x07) << 18) + ((char2 & 0x3F) << 12) + ((char3 & 0x3F) << 6) + (char4 & 0x3F)),3),-5)
}
}
if (str == "")
break
}
SetFormat, Integer, d
StringUpper,result,result
return result
}
; Simple calculator
LoadToolComposeCalc() {
global
makeCompose(["S__Comp", "U000075", "U000063"], "P__Cal1") ; uc
makeCompose(["S__Comp", "U000055", "U000043"], "P__Cal2") ; UC
}
CDS__CompU000075U000063 := "P__Cal1"
CDS__CompU000055U000043 := "P__Cal2"
InitializeToolCalc() {
global
GUISYM("P__Cal1","uc","t")
GUISYM("P__Cal2","UC","t")
}
CharProc__Cal1() {
CharProc__Cal1(keyName) {
global
; starte Calculator ohne Echo
PressHookProc := "Calc"
@ -325,7 +284,7 @@ CharProc__Cal1() {
CalcHexOut := 0
}
CharProc__Cal2() {
CharProc__Cal2(keyName) {
global
; starte Calculator mit Echo
PressHookProc := "Calc"
@ -337,10 +296,10 @@ CharProc__Cal2() {
CalcHexOut := 0
}
PressHookCalc(PhysKey, ActKey, Char) {
PressHookCalc(keyName, Char) {
global
if (SubStr(Char,1,1) == "P")
CharStarDown(PhysKey, ActKey, Char)
return True
else if (CalcPhase == 0) {
if ((Char == "U000030") or (Char == "S__N__0"))
CalcVar1 := CalcVar1 . "0"
@ -402,8 +361,9 @@ PressHookCalc(PhysKey, ActKey, Char) {
} else
PressHookProc := ""
if (CalcEcho) {
PP%PhysKey% := Char
PR%PhysKey% := Char
kbdRepChars := Char
kbdRepKey := keyName
PR%keyName% := Char
CharOutDown(Char)
}
} else if (CalcPhase == 1) {
@ -464,161 +424,153 @@ PressHookCalc(PhysKey, ActKey, Char) {
CalcResult := CalcResult + 0
SetFormat,Integer,d
}
tosend := EncodeUni(CalcResult)
tosend := util_str2UCodes(CalcResult)
if (CalcEcho) {
Char := "U00003D"
PP%PhysKey% := Char
PR%PhysKey% := Char
kbdRepChars := Char
kbdRepKey := keyName
PR%keyName% := Char
CharOutDown(Char)
}
loop {
if (SubStr(tosend,1,1)=="P") {
SubProc := SubStr(tosend,2,6)
CharProc%SubProc%()
} else {
CharOut(SubStr(tosend,1,7))
}
tosend := SubStr(tosend,8)
if (tosend == "")
break ; erledigt
}
PressHookProc := ""
return ; vermeide, bei CharEcho das aktuelle Zeichen nach dem Ergebnis noch einmal auszugeben
return False ; vermeide, bei CharEcho das aktuelle Zeichen nach dem Ergebnis noch einmal auszugeben
} else
PressHookProc := ""
if (CalcEcho) {
PP%PhysKey% := Char
PR%PhysKey% := Char
kbdRepChars := Char
kbdRepKey := keyName
PR%keyName% := Char
CharOutDown(Char)
}
} else {
PressHookProc := ""
if (CalcEcho) {
PP%PhysKey% := Char
PR%PhysKey% := Char
kbdRepChars := Char
kbdRepKey := keyName
PR%keyName% := Char
CharOutDown(Char)
}
}
return False
}
CDS__CompU000055U000057 := "P___WMN"
CDS__CompU000075U000077 := "P___WMN"
CharProc___WMN() {
; "Wie mit Neo?" assistant
LoadToolComposeWMN() {
global
ok := DllCall("User32.dll\OpenClipboard", "Ptr", 0)
if (!ok) {
TrayTip,Wie mit NEO,Fehler in OpenClipboard,10,1
makeCompose(["S__Comp", "U000075", "U000077"], "P___WMN") ; uw
makeCompose(["S__Comp", "U000055", "U000057"], "P___WMN") ; UW
}
InitializeToolWMN() {
global
GUISYM("P___WMN","UW","t")
}
CharProc___WMN(keyName) {
global
; Read first unicode symbol from clipboard-text
clipText := SubStr(clipboard,1,2)
if (not clipText) {
MsgBox, 16, "Wie mit Neo" Tool, Kein Zeichen in der Zwischenablage gefunden!
return
}
uclph:=DllCall("GetClipboardData","uint",CF_UNICODETEXT:=13)
if (uclph == 0) {
DllCall("CloseClipboard")
TrayTip,Wie mit NEO,Fehler in GetClipboardData,10,1
return
}
uclp := DllCall("GlobalLock","uint",uclph)
if (uclp == 0) {
DllCall("CloseClipboard")
TrayTip,Wie mit NEO,Fehler in GlobalLock,10,1
return
}
a := *(uclp+0)
b := *(uclp+1)
resultCharOrd := Ord(clipText) ; unicode codepoint
resultChar := Format("U{:06X}", resultCharOrd) ; keyId (U-code)
a += 256*b
Gui, New, +AlwaysOnTop +HwndWMNGuiHwnd +LabelWMNGuiOn
Gui, %WMNGuiHwnd%:Font, norm
Gui, %WMNGuiHwnd%:Add, Text, ,% Format("Das Zeichen U+{:X} kann wie folgt eingegeben werden:", resultCharOrd)
if ((a >= 0xD800) and (a <= 0xDBFF)) {
c := *(uclp+2)
d := *(uclp+3)
c += 256*d
if ((c >= 0xDC00) and (c <= 0xDFFF)) {
a := (a & 0x3FF) * 1024 + (c & 0x3FF) + 65536
}
}
DllCall("GlobalUnlock","uint",uclph)
DllCall("CloseClipboard")
SetFormat,Integer,h
a += 0
SetFormat,Integer,d
if (a < 0x10000) {
ap := "U" . substr("000000" . substr(a,3),-3)
a := "U" . substr("000000" . substr(a,3),-5)
} else {
ap := "U" . substr("000000" . substr(a,3),-5)
a := ap
}
Gui,2:Destroy
Gui,2:Font,,DejaVu Sans
Gui,2:Margin,10,0
Gui,2:Add,Text,,% "`r`nDas Zeichen " . ap . " kann wie folgt eingegeben werden:"
loop,parse,CRC%a%,%A_Space%
; List all possible compose-sequences resulting in "resultChar"
hasStandaloneKey := False
for i, trace in composeSequences[resultChar]
{
this_wmn := ""
this_wmnk := ""
nthis := 0
this_wtt := A_LoopField
if (this_wtt == "")
continue ; probably at first or last entry
loop {
if (this_wtt == "")
break
this_char7 := substr(this_wtt,1,7)
this_char := this_char7
this_wtt := substr(this_wtt,8)
if (CB%this_char% != "")
this_char := CB%this_char%
else if (CS%this_char% != "")
this_char := CS%this_char%
; this_char will contain Uxxxx if no shortcut is present. Fix this here.
this_wmn .= " <" . this_char . ">"
if (CRK%this_char7% == "") {
nthis := 1
this_wmnk .= " <" . this_char7 . ">"
this_wmn := "" ; sequence of <symbol names>
this_wmnk := "" ; sequence of <individual keystrokes incl. modifiers>
isSequenceInLayout := True
sequenceLength := 0
; Join characters compose-sequence into a readable string (going backwards)
While (trace != composeDict)
{
; keyId (U-code or special key name) of next key in compose-sequence
sequenceLength++
char := trace._sequenceChar
; resolve keyId to character symbol or name
if (CB%char% != "")
charName := CB%char%
else if (CS%char% != "")
charName := CS%char%
else if (SubStr(char,1,1) == "U") {
; fallback: character from U-code "Uxxxxxx"
charOrd := "0x" . SubStr(char,2,6)
charName := Chr(charOrd)
} else
this_wmnk .= " " . KeyLong(CRK%this_char7%)
}
if (this_wmn != "")
this_wmn := SubStr(this_wmn,2)
if (this_wmnk != "")
this_wmnk := SubStr(this_wmnk,2)
Gui,2:Font,,Dejavu Sans Bold
if (nthis == 1)
Gui,2:Add,Text,,% "Wegen fehlender Tastenbelegung nicht als Compose:"
else
Gui,2:Add,Text,,% "Als Compose:"
Gui,2:Font,,Dejavu Sans
Gui,2:Add,Text,,% this_wmn . "`r`noder`r`n" . this_wmnk
}
; fallback: special key name, e.g. "S__Comp"
charName := char
charName := "<" . charName . ">"
wmnk := KeyLong(CRK%a%)
Gui,2:Font,,Dejavu Sans Bold
if (wmnk != "") {
Gui,2:Add,Text,,% "Als Tastendruck:"
Gui,2:Font,,Dejavu Sans
Gui,2:Add,Text,,% wmnk
; additionally list all alternative ways to create "char",
; each broken down into individual keys incl. modifiers
charNameLong := WMNKeyLong(char)
if (charNameLong == "") {
; key cannot be created on keyboard
isSequenceInLayout := False
if (SubStr(char,1,1) == "U") {
; fallback: character from U-code "Uxxxxxx"
charOrd := "0x" . SubStr(char,2)
charNameLong := Format("<[{:s}=U+{:X}]>", Chr(charOrd), charOrd)
} else
Gui,2:Add,Text,,% "Als Tastendruck nicht verfuegbar"
Gui,2:Add, Button, Default xp+100 yp+40, OK
Gui,2:Show
return
2ButtonOK:
2GuiEscape:
Gui,2:Destroy
return
charNameLong := "<" . char . ">"
}
KeyLong(key) {
; prepend labels to sequence-string
this_wmn := charName . " " . this_wmn
this_wmnk := charNameLong . " " . this_wmnk
; continue with previous char in compose-sequence
trace := trace[COMP_BACK_CHAR]
}
this_wmn := SubStr(this_wmn,1,-1)
this_wmnk := SubStr(this_wmnk,1,-1)
if (sequenceLength == 0)
continue ; ignore corrupt (zero-length) sequences
if (sequenceLength == 1)
hasStandaloneKey := True
Gui, %WMNGuiHwnd%:Font,bold
Gui, %WMNGuiHwnd%:Add,Text, y+m,% "Als " . (sequenceLength > 1 ? "Compose" : "Tastendruck") . (isSequenceInLayout ? ":" : " (wegen fehlender Tastenbelegung nicht erreichbar!):")
Gui, %WMNGuiHwnd%:Font,norm
Gui, %WMNGuiHwnd%:Add,Text, y+m,% this_wmn . (this_wmnk != this_wmn ? "`r`noder`r`n" . this_wmnk : "")
}
if (not hasStandaloneKey) {
Gui, %WMNGuiHwnd%:Font,bold
Gui, %WMNGuiHwnd%:Add,Text,,% "Als Tastendruck nicht verfügbar."
Gui, %WMNGuiHwnd%:Font,norm
}
btnEventFun := Func("WMNGuiOnClose").Bind(WMNGuiHwnd) ; button closes assocaited GUI
Gui, %WMNGuiHwnd%:Add, Button, Default xm+100 y+m vWMNButton, OK
GuiControl +g, WMNButton, %btnEventFun%
Gui, %WMNGuiHwnd%:Show
}
WMNGuiOnEscape(hwnd) {
WMNGuiOnClose(hwnd)
}
WMNGuiOnClose(hwnd) {
Gui, %hwnd%:Destroy
}
WMNKeyLong(char) {
global
num := 0
twmnk := ""
loop,parse,key,%A_Space%
loop,parse,CRK%char%,%A_Space%
{
tis_wmn := ""
tis_wtt := A_LoopField
@ -634,6 +586,11 @@ KeyLong(key) {
base_key := CB%base_key%
else if (CS%base_key% != "")
base_key := CS%base_key%
else if (SubStr(base_key,1,1) == "U") {
; fallback: character from U-code "Uxxxxxx"
base_ord := "0x" . SubStr(base_key,2)
base_key := Format("[{:s}=U+{:X}]", Chr(base_ord), base_ord)
}
twmnk .= "/<" . CBS____M%tis_layer% . base_key . ">"
num := num + 1
@ -645,3 +602,24 @@ KeyLong(key) {
else
return "(" . SubStr(twmnk,2) . ")"
}
;
; Tools global
;
; Load compose definitions used by tools
; Overwrites existing compose definitions!
; (compositions with similar or shared initial sequence may become unreachable)
LoadToolsCompose() {
LoadToolComposeRoman()
LoadToolComposeUni()
LoadToolComposeCalc()
LoadToolComposeWMN()
}
InitializeTools() {
InitializeToolRoman()
InitializeToolUni()
InitializeToolCalc()
InitializeToolWMN()
}

View File

@ -1,28 +1,36 @@
; -*- encoding: utf-8 -*-
TrayTextEnable := "Aktivieren"
TrayTextDisable := "Deaktivieren"
TrayAktivieren() {
global
menu,tray,icon,%ResourceFolder%\neo_enabled.ico,,1
menu,tray,nostandard
menu,tray,add,Öffnen,open
menu,helpmenu,add,About,about
menu,helpmenu,add,Tastaturkurzbefehle,shortcuts
menu,helpmenu,add
menu,helpmenu,add,Zur AutoHotkey-Homepage (autohotkey.com),autohotkey
menu,helpmenu,add,Zur Neo-Homepage (neo-layout.org),neo
menu,tray,add,Hilfe,:helpmenu
menu,tray,add
menu,tray,add,%disable%,togglesuspend
menu,tray,add,%TrayTextDisable%,togglesuspend
menu,tray,add
;@Ahk2Exe-IgnoreBegin
menu,tray,add,Bearbeiten,edit
;@Ahk2Exe-IgnoreEnd
menu,tray,add,Neu Laden,reload
menu,tray,add
menu,tray,add,Nicht im Systray anzeigen,hide
menu,tray,add,%name% beenden, exitprogram
menu,tray,default,%disable%
menu,tray,default,%TrayTextDisable%
menu,tray,tip,%name%
IniRead,startSuspended,%ini%,Global,startSuspended
if (startSuspended == 1)
if (startSuspended)
Traytogglesuspend()
return
@ -34,6 +42,10 @@ about:
TrayAbout()
return
shortcuts:
TrayShortcuts()
return
neo:
run https://neo-layout.org/
return
@ -68,36 +80,69 @@ return
Traytogglesuspend() {
global
if A_IsSuspended {
menu, tray, rename, %enable%, %disable%
menu, tray, rename, %TrayTextEnable%, %TrayTextDisable%
menu, tray, tip, %name%
menu, tray, icon, %ResourceFolder%\neo_enabled.ico,,1
SetNEOLockStates()
BSTEndSuspend()
suspend, off ; Schaltet Suspend aus -> NEO
} else {
menu, tray, rename, %disable%, %enable%
menu, tray, rename, %TrayTextDisable%, %TrayTextEnable%
menu, tray, tip, %name% : Deaktiviert
menu, tray, icon, %ResourceFolder%\neo_disabled.ico,,1
SetOldLockStates()
; Allow all other threads to finish first
; (incl. pending keyboard repeats of shift, when suspended on <shift>+<pause>,
; which could send shift down after suspension and after user released it)
Critical, Off
Sleep -1
suspend, on ; Schaltet Suspend ein -> QWERTZ
BSTStartSuspend()
SetOldLockStates()
}
}
TrayAbout() {
global
msgbox, 64, %name% Ergonomische Tastaturbelegung,
(
%name%
`nDas Neo-Layout ersetzt das übliche deutsche
Tastaturlayout mit der Alternative Neo,
beschrieben auf http://neo-layout.org/.
`nDazu sind keine Administratorrechte nötig.
`nWenn Autohotkey aktiviert ist, werden alle Tastendrucke
MsgBox, , Ergonomische Tastaturbelegung,
(LTrim
Version: %name%
Das Neo-Layout ersetzt das übliche deutsche Tastaturlayout
mit der Alternative Neo, beschrieben auf http://neo-layout.org/.
Dazu sind keine Administratorrechte nötig.
Wenn Autohotkey aktiviert ist, werden alle Tastendrucke
abgefangen und statt dessen eine Übersetzung weitergeschickt.
`nDies geschieht transparent für den Anwender,
es muss nichts installiert werden.
`nDie Zeichenübersetzung kann leicht über das Icon im
Systemtray deaktiviert werden. `n
Dies geschieht transparent für den Anwender, es muss nichts
installiert werden.
Die Zeichenübersetzung kann leicht über das Icon im
Systemtray deaktiviert werden.
)
}
TrayAktivieren()
TrayShortcuts() {
global
MsgBox, , Tastaturkurzbefehle,
(LTrim
M3+ESC: Neovars neu laden
Shift+Pause: Neovars deaktivieren/aktivieren
M3+F1: Bildschirmtastatur ein/aus
M4+F1: Bildschirmtastatur Layout wechseln*
M3+F2: Bildschirmtastatur Fenstermodus wechseln
M3+F3: Bildschirmtastatur (dynamisch) ein/aus
M3+F6: Qwertz-Modus ein/aus
M4+F6: Qwertz-Modus ein/aus-Zustand speichern*
M3+F9: Lernmodus ein/aus
M3+F10: Ein-Hand-Mods ein/aus
M3+F11: Lang-s-Modus ein/aus
*) wird persistent in "%ini%" gespeichert
)
}

View File

@ -0,0 +1,77 @@
; -*- encoding: utf-8 -*-
; Noovars utilities module
; Transform string into sequence of codepoints "UxxxxxxUyyyyyyU..."
;
; Input string must be UTF-16 encoded (native in Unicode-AutoHotkey).
; For each unicode character encountered in the input string,
; it's unicode-codepoint is appended to the output string in the
; format Uxxxxxx where U is a leading "U" character, followed by
; the (right-adjusted, zero-padded, six-digit upper-case) hexadecimal
; representation of the codepoint.
;
; Example: util_str2UCodes("A♫7") returns "U000041U00266BU000037"
;
util_str2UCodes(str) {
result := ""
i := 1
While (i <= StrLen(str)) {
cp := Ord(SubStr(str,i,2))
i += 1 + (cp >= 0x10000)
result .= Format("U{:06X}", cp)
}
return result
}
; Transform unicode-character into codepoint string "Uxxxxxx" or keyId
;
; If input is a zero- or 7-character sequence, it is returned as is.
; (It is assumed that a 7 character sequence is a neovars keyId, i.e. either
; a "Uxxxxxx" format or a 7-character special key name such as "S__Comp").
;
; Otherwise input shall be either a single utf-16 encoded unicode character
; (StrLen of 1 or 2), and it's unicode codepoint is returned in the
; string "Uxxxxxx" where xxxxxx represent the right-adjusted, zero-padded
; six-digit upper-case hexadecimal representation of the codepoint.
;
; Examples:
; util_char2UCode("") returns ""
; util_char2UCode("A") returns "U000041"
; util_char2UCode("U000041") returns "U000041"
; util_char2UCode("T__tlde") returns "T__tlde"
;
util_char2UCode(str) {
if (str == "" or StrLen(str) == 7)
return str
return Format("U{:06X}", Ord(str))
}
; Unescapes string by performing the following substitutions:
; - Replace "\\" by "\"
; - Replace "\n" by line-feed
; - Replace "\x" by "x" (where x is any character other than "\", "n")
; - Remove a trailing "\"
; Replacements are performed left-to-right and do not overlap.
; An alternative (single) escape character can be provided with esc.
util_strUnescape(str, esc:="\") {
static LF_CHAR := chr(0x000d) ; line-feed
out := ""
, j := 1 ; pos. of next character added to output
, k := 1 ; pos. of next character to be scanned
Loop {
; scan for next "\"
k := InStr(str, "\", true, k)
if not k
break
out .= SubStr(str, j, k - j)
, j := k + 1
, k += 2
; substitions
if (SubStr(str, j, 1) == "n") {
out .= LF_CHAR
, j++
}
}
return out . SubStr(str, j)
}

View File

@ -1,142 +1,167 @@
; -*- encoding: utf-8 -*-
; -*- encoding: utf-8 -*-
#NoEnv
; Global neovars objects
Comp := composeDict ; current compose-plane
AllStar(KeyId, IsDown, This_HotKey) {
; 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.
;
; Notes:
; This function serves as hotkey thread entry point.
; It assumes that the current thread is uninterruptible, which ensures that
; hotkey threads are executed one after another in the order of activation.
; This guarantees that we send out the sequences of translated keystrokes
; in the correct order.
AllStar(keyName, isDown) {
global
PhysKey := KeyId
local char, actKeyName
if (TransformProc != "")
ActKey := Transform%TransformProc%(PhysKey)
actKeyName := Transform%TransformProc%(keyName)
else
ActKey := PhysKey
if ((striktesMod2Lock == 0) && (NOC%ActKey% == 1))
Ebene := EbeneNC
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
Ebene := EbeneC
if (Ebene7 and (CP7%ActKey% != ""))
Char := CP7%ActKey%
else if (Ebene8 and (CP8%ActKey% != ""))
Char := CP8%ActKey%
else
Char := CP%Ebene%%ActKey%
if (PressHookProc != "") {
if (IsDown == 1)
PressHook%PressHookProc%(PhysKey, ActKey, Char)
else
CharStarUp(PhysKey)
} else if (IsDown == 1)
CharStarDown(PhysKey, ActKey, Char)
else
CharStarUp(PhysKey)
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)
}
}
CharStarDown(PhysKey, ActKey, char) {
; 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%()
CharProc%SubProc%(keyName)
return
}
rerun:
wasNonShiftKeyPressed := 1
if (PP%PhysKey% != "")
CompNew := PP%PhysKey% ; Von Tastaturwiederholung
else
CompNew := Comp . char ; Hängen wir mal das neue Zeichen zum Compositum an
if (CD%CompNew% != "") { ; Compose hat getroffen: wird geschickt, Compose gelöscht
tosend := CD%CompNew%
PP%PhysKey% := CompNew
Comp := ""
} else if (CM%CompNew% == 1) { ; Compose muss sich noch was merken: Jetzt noch nichts schicken.
tosend := ""
PP%PhysKey% := ""
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
} else if (CF%Comp% != "") {
tosend := CF%Comp%
if (PR%PhysKey% != "") { ; Eventuell vergessenen Key-Release aufräumen
CharOutUp(PR%PhysKey%)
PR%PhysKey% := ""
}
loop {
if (SubStr(tosend,1,1)=="P") {
SubProc := SubStr(tosend,2,6)
CharProc%SubProc%()
; 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 {
CharOut(SubStr(tosend,1,7))
; Send out key down + up event
CharOut(charSend)
}
tosend := SubStr(tosend,8)
if (tosend == "")
break ; erledigt
}
Comp := ""
PP%PhysKey% := ""
goto rerun
} else if (Comp == "") { ; noch kein Zeichen in der Compose-Queue: Ein einzelnes Zeichen wird geschickt
tosend := char
PP%PhysKey% := char
} else { ; Compose hat verfehlt: nichts schicken, auch aktuelles Zeichen nicht schicken
tosend := ""
PP%PhysKey% := ""
Comp := ""
}
if (strlen(tosend) > 7) { ; Ausgabe mehrerer Zeichen
if (PR%PhysKey% != "") { ; Eventuell vergessenen Key-Release aufr�umen
CharOutUp(PR%PhysKey%)
PR%PhysKey% := ""
; Notify on-screen board to check for updates
Check_BSTUpdateAsync()
}
loop {
if (SubStr(tosend,1,1)=="P") {
SubProc := SubStr(tosend,2,6)
CharProc%SubProc%()
} else {
CharOut(SubStr(tosend,1,7))
}
tosend := SubStr(tosend,8)
if (tosend == "")
break ; erledigt
}
} else if (tosend != "") {
if (SubStr(tosend,1,1)=="P") {
if (PR%PhysKey% != "") {
CharOutUp(PR%PhysKey%)
PR%PhysKey% := ""
}
SubProc := SubStr(tosend,2,6)
CharProc%SubProc%()
} else {
if ((PR%PhysKey% != "") and (PR%PhysKey% != tosend))
CharOutUp(PR%PhysKey%)
PR%PhysKey% := tosend
CharOutDown(tosend)
}
} else if (PR%PhysKey% != "") {
CharOutUp(PR%PhysKey%)
PR%PhysKey% := ""
}
Check_BSTUpdate()
}
CharStarUp(PhysKey) {
; Key event up
; Send out key-up event with layout-characters memorized in PR%keyname%
; and disable active keyboard repeats
CharStarUp(keyName) {
global
if (PR%PhysKey% != "") {
tosend := PR%PhysKey%
PR%PhysKey% := ""
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%()
CharProc%SubProc%(keyName)
} else
CharOutUp(tosend)
}
PP%PhysKey% := ""
; Stop current key repeat
kbdRepChars := ""
}
;
; Send characters to output
;
; Send out activation event "key down, then up"
CharOut(char) {
global
if (CharOutFilterProc != "") {
@ -148,10 +173,14 @@ CharOut(char) {
SendBlindShiftFixed(char, DNCS%char% . UPCS%char%)
else if (CS%char% != "")
SendBlindShiftFixed(char, "{" . CS%char% . "}")
else
SendUnicodeChar("0x" . SubStr(char,2))
else {
;SendUnicodeChar("0x" . SubStr(char,2))
charOrd := "0x" . SubStr(char,2) ; should be equivalent
send % "{" . Chr(charOrd) . "}" ;
}
}
; Send out activation event "key down"
CharOutDown(char) {
global
if (CharOutFilterProc != "") {
@ -167,6 +196,7 @@ CharOutDown(char) {
SendUnicodeCharDown("0x" . SubStr(char,2))
}
; Send out activation event "key up"
CharOutUp(char) {
global
if (CharOutFilterProc != "") {
@ -211,149 +241,16 @@ SendBlindShiftFixed(char, theseq) {
send % "{blind}" . theseq
}
CharProc(name) {
CharProc%name%()
}
;
; Unicode output
;
CharProc__Rlod() {
global
; Neustart des AHK-Skripts
SetOldLockStates()
reload
}
; Modifier
CharProc__M2LD() {
global
if (!isShiftLPressed) {
if (isShiftRPressed and !wasNonShiftKeyPressed)
ToggleMod2Lock()
isShiftLPressed := 1
isShiftPressed := 1
wasNonShiftKeyPressed := 0
%EbeneAktualisieren%()
PR%PhysKey% := "P__M2LU"
}
CharOutDown("S__L_M2")
}
CharProc__M2LU() {
global
isShiftLPressed := 0
isShiftPressed := isShiftRPressed
%EbeneAktualisieren%()
CharOutUp("S__L_M2")
}
CharProc__M2RD() {
global
if (!isShiftRPressed) {
if (isShiftLPressed and !wasNonShiftKeyPressed)
ToggleMod2Lock()
isShiftRPressed := 1
isShiftPressed := 1
wasNonShiftKeyPressed := 0
%EbeneAktualisieren%()
PR%PhysKey% := "P__M2RU"
}
CharOutDown("S__R_M2")
}
CharProc__M2RU() {
global
isShiftRPressed := 0
isShiftPressed := isShiftLPressed
%EbeneAktualisieren%()
CharOutUp("S__R_M2")
}
CharProc__M3LD() {
global
if (!isMod3LPressed) {
if (isMod3RPressed and !wasNonShiftKeyPressed)
CharStarDown("MOD3", "MOD3", "S__Comp")
isMod3LPressed := 1
isMod3Pressed := 1
wasNonShiftKeyPressed := 0
%EbeneAktualisieren%()
PR%PhysKey% := "P__M3LU"
}
}
CharProc__M3LU() {
global
if (isMod3RPressed)
CharStarUp("MOD3")
isMod3LPressed := 0
isMod3Pressed := isMod3RPressed
%EbeneAktualisieren%()
}
CharProc__M3RD() {
global
if (!Mod3RPressed) {
if (isMod3LPressed and !wasNonShiftKeyPressed)
CharStarDown("MOD3", "MOD3", "S__Comp")
isMod3RPressed := 1
isMod3Pressed := 1
wasNonShiftKeyPressed := 0
%EbeneAktualisieren%()
PR%PhysKey% := "P__M3RU"
}
}
CharProc__M3RU() {
global
if (isMod3LPressed)
CharStarUp("MOD3")
isMod3RPressed := 0
isMod3Pressed := isMod3LPressed
%EbeneAktualisieren%()
}
CharProc__M4LD() {
global
if (!isMod4LPressed) {
isMod4LPressed := 1
isMod4Pressed := 1
%EbeneAktualisieren%()
PR%PhysKey% := "P__M4LU"
if (isMod4RPressed and !wasNonShiftKeyPressed) {
wasNonShiftKeyPressed := 0
ToggleMod4Lock()
} else
wasNonShiftKeyPressed := 0
}
}
CharProc__M4LU() {
global
isMod4LPressed := 0
isMod4Pressed := isMod4RPressed
%EbeneAktualisieren%()
}
CharProc__M4RD() {
global
if (!isMod4RPressed) {
isMod4RPressed := 1
isMod4Pressed := 1
%EbeneAktualisieren%()
PR%PhysKey% := "P__M4RU"
if (isMod4LPressed and !wasNonShiftKeyPressed) {
wasNonShiftKeyPressed := 0
ToggleMod4Lock()
} else
wasNonShiftKeyPressed := 0
}
}
CharProc__M4RU() {
global
isMod4RPressed := 0
isMod4Pressed := isMod4LPressed
%EbeneAktualisieren%()
}
; Notes:
; - "SendUnicodeChar(charCode)" can be replaced by send % {Chr(charCode)}
; since AHK 1.1.27; this should produce similar results
; (compare with SendUnicodeChar in https://github.com/Lexikos/AutoHotkey_L/blob/522e83eee0287cf02388aff179b3fcb6da33d268/source/keyboard_mouse.cpp#L91)
; - however "up", "down" events cannot be replaced similarly for most keys
; (see also https://www.autohotkey.com/docs/commands/Send.htm)
SendUnicodeChar(charCode){
static ki := "#"
@ -417,3 +314,184 @@ SendUnicodeCharUp(charCode){
}
}
;
; 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
}

View File

@ -0,0 +1,204 @@
; Configure future builds
;
; Usage:
; When included in another script, the function "build_configure" is provided.
; When running as a standalone script, build_configuration is run with defaults.
;
; Requires AutoHotkey_L (Unicode-Version of AutoHotkey).
#Include %A_LineFile%\..\script\logwindow.ahk
#Include %A_LineFile%\..\script\util.ahk
; -------------------------------------
; Configure Build
; -------------------------------------
; Reads user-defined configuration fom 'iniFile'.
; Updates include-scripts in 'buildIncludeFile' which should be included
; by the sources and parsed by the compiler during the build process.
;
; Arguments:
;
; srcDir, binDir, configDir
; Sources-, (output-) binaries-, and configuration-files directory
; iniFile
; Name of an ini-file from which to read the build configuration.
; buildIncludeFile
; Name of the ahk-script file that is overwritten with build-specific
; commands and declarations.
;
; Relative paths are understood relative to the current working directory.
; Supported ini-keys: portable, custom, customName
; (for details, see "..\config\build-config.ini").
;
; Result:
; An associative array with the configurations made.
; Keys: portable, custom, customName, revision, exeName
;
; Notes:
; Prints messages to a logging window, which shall be initialized on entry.
; Stops on errors with exit code 1.
;
build_configure(srcDir:="", binDir:="", configDir:="", iniFile:="", buildIncludeFile:="")
{
; Default paths (absolute so we don't rely on working dir.)
if not srcDir
srcDir := A_ScriptDir . "\..\src"
if not binDir
binDir := A_ScriptDir . "\..\bin"
configDir := A_ScriptDir . "\..\config"
if not iniFile
iniFile := util_getFullPath(configDir . "\build-config.ini")
if not buildIncludeFile
buildIncludeFile := util_getFullPath(srcDir . "\config-iscompiled1.generated.ahk")
;
; Read user-defined configuration
;
; Default configs (keys are not case-sensitive)
userConfigDefaults := {portable: 0, custom: 0, customName: "", ahk2ExeParams: "", ahk2ExePath: ""}
configs := {revision: "<unknown>", exeName: ""}
; Read user-defined configs from ini-file
logEntry("Read user-defined configuration...")
if not FileExist(iniFile)
{
logError("Configuration file not found at '" . iniFile . "'")
logFinal()
}
for key, value in userConfigDefaults
{
IniRead, valueNew, %iniFile%, Global, %key% , %value%
configs[key] := valueNew
}
;
; Other configurations
;
; Try to obtain revsion information (requires git)
logEntry("Query revision information...")
exitCode := util_runWaitCMD("git rev-parse HEAD", strOut, strErr)
if not exitCode and StrLen(strOut) >= 7
configs["revision"] := SubStr(strOut, 1, 7)
else
logWarning("Could not query revision information from git repository. " . strErr)
; Output file name
logEntry("Configure executable filename...")
exeName := "neo20"
if (configs["customName"])
{
; Strip to filename if path provided
SplitPath, % configs["customName"] , customNameStripped
; Add userdefined string "-<customName>"
exeName .= "-" . customNameStripped
}
else
{
; Add "-custom" if exe includes custom script
if configs["custom"]
exeName .= "-custom"
; Add "-portable" if exe is portable
if configs["portable"]
exeName .= "-portable"
; Add revision info "-r<revision>" if uncommitted changes were made
; TODO: restrict diff to compose- and neovars subtrees (?)
exitCode := util_runWaitCMD("git diff --quiet")
if exitCode ; git index or working-tree not clean, or other failure
exeName .= "-r" . configs["revision"]
}
exeName .= ".exe"
; Normalized path is used by the compiler to check against running processes
configs["exeName"] := util_getFullPath(binDir . "\" . exeName)
;
; Update build-specific inlude file
;
logEntry("Update build-specific includes in '" . buildIncludeFile . "'...")
tmpFile := buildIncludeFile . ".tmp"
; Clear old tmp. files (if exist)
FileDelete, % tmpFile
if FileExist(tmpFile)
{
logError("Could not delete old configuration file '" . tmpFile . "'")
logFinal()
}
; Write include-file line-by-line
scriptGeneratedBy := A_ScriptName
scriptLinePortable := "isPortable := " . configs["portable"]
scriptLineCustom := (configs["custom"] ? "" : ";") . "#include *i %A_AppData%\Neo2\custom.ahk"
scriptLineCustomName := "customName := """ . configs["customName"] . """"
scriptLineRevision := "revision := """ . configs["revision"] . """"
scriptLineExeName := ";@Ahk2Exe-ExeName " . configs["exeName"]
FileAppend,
(LTRIM
; -*- encoding: utf-8 -*-
;
; ** THIS FILE WAS GENERATED BY %scriptGeneratedBy% **
; ** DO NOT EDIT BY HAND -- FILE MAY BE OVERWRITTEN ANYTIME **
;
; This file is included in compiled scripts only
;
; Run portable version?
%scriptLinePortable%
; Include user-defined scripts?
%scriptLineCustom%
; Modified name for executable
%scriptLineCustomName%
; Revision information
%scriptLineRevision%
; Binaries output path
%scriptLineExeName%
), % tmpFile, UTF-8
if ErrorLevel
{
logError("Failed to write the new configuration to '" . tmpFile . "'...")
logFinal()
}
; Overwrite old file with new
FileMove, % tmpFile, % buildIncludeFile, 1
if ErrorLevel
{
logError("Could not replace the old configuration in '" . buildIncludeFile . "'...")
logFinal()
}
; Return all configurations to caller
Return configs
}
; -------------------------------------
; Run as standalone
; -------------------------------------
if (A_LineFile == A_ScriptFullPath)
{
logInit("Build-configuration")
; Make sure AHK runs in Unicode version
if (not A_IsUnicode)
{
logError("Unicode support missing! Restart this script with the Unicode-version of AutoHotkey, e.g. through AutoHotkeyU32.exe or AutoHotkeyU64.exe.")
logFinal()
}
; Run with defaults
build_configure(srcDir, binDir, iniFile, buildIncludeFile)
logEntry("Build-configuration completed.")
logFinal()
}

View File

@ -0,0 +1,89 @@
; Build executable from sources
;
; Usage:
; Run as standalone script in AutoHotkey_L (Unicode-Version).
;
; Compiles the neovars source-scripts in "..\src" into an executable
; by invoking the Ahk2Exe AutoHotkey compiler.
; Configurations can be made in "..\config\build-config.ini".
; All output is written by default to the "..\bin" directory which will be
; created if it does not yet exist, and all existing revision-specific
; binaries will be removed from it unless a custom buildName is configured.
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%\
#Include build-configure.ahk
#Include script/logwindow.ahk
#Include script/util.ahk
logInit("Build")
; Make sure AHK runs in Unicode version
if (not A_IsUnicode)
{
logError("Unicode support missing! Restart this script with the Unicode-version of AutoHotkey, e.g. through AutoHotkeyU32.exe or AutoHotkeyU64.exe.")
logFinal()
}
; Paths
srcDir := A_ScriptDir . "\..\src"
resDir := A_ScriptDir . "\..\res"
binDir := A_ScriptDir . "\..\bin"
; Configure the build
configs := build_configure()
; Create bin directory if it doesn't exist
logEntry("Create output directory if it doesn't exist...")
FileCreateDir, % binDir
if ErrorLevel
{
logError("Failed to create output directory '" . binDir . "'")
logFinal()
}
; Clear old revision versions
; TODO: ask user or add switch for cleaning?
;if (not configs["customName"])
;{
; logEntry("Clear old revision binaries...")
; FileDelete, % binDir . "\neo20*-r???????.exe"
;}
; Compiler paths
mainScriptFile := util_getFullPath(srcDir . "\neo20-all.ahk")
iconFile := resDir . "\neo_enabled.ico"
if configs["ahk2ExePath"]
{
ahk2ExePath := util_getFullPath(configs["ahk2ExePath"])
if not FileExist(ahk2ExePath)
{
logError("Compiler executable not found at '" . ahk2ExePath . "'")
logFinal()
}
}
else
{
SplitPath, A_AhkPath, , ahkDir
ahk2ExePath := ahkDir . "\Compiler\Ahk2Exe.exe"
}
; Compile
logEntry("Compile sources into '" . configs["exeName"] . "'")
ahk2ExeCmd := """" . ahk2ExePath . """ /in """ . mainScriptFile . """ /out """ . configs["exeName"] . """ /icon """ . iconFile . """"
ahk2ExeCmd .= " " . configs["ahk2ExeParams"]
exitCode := util_runWaitCMD(ahk2ExeCmd, strOut, strErr)
if exitCode
{
logError("Compilation error, Error-Code " . Format("0x{:x}", exitCode) . " (see https://github.com/AutoHotkey/Ahk2Exe/blob/master/ErrorCodes.md)." . strErr)
logFinal()
}
if not FileExist(configs["exeName"])
{
logError("Failed to create executable.")
logFinal()
}
; Successful exit
logEntry("Build completed.")
logFinal()

View File

@ -0,0 +1,257 @@
; Generate script with compose-definitions from XCompose files
;
; Usage:
; Run as standalone script in AutoHotkey_L (Unicode-Version).
;
; Generates the AHK-source-script which sets up the available compose-
; sequences in the neovars driver.
;
; Compose-sequences must be provided in input files, whose names along
; with other configuration are read from "..\config\compose-config.ini",
;
; The output script is written to "..\src\compos.generated.ahk", if all
; input files reside inside the neovars git-repository and have no uncommitted
; changes; or "..\src\composee-tainted.generated.ahk" otherwise.
; If either output script exist, it will be removed. Depending on
; configuration options, a backup copy is made (overwriting existing backups).
;
; Only a subset of the XCompose syntax is supported. For instance,
; input files shall not define includes, and must not specify modifiers.
; See also https://www.x.org/releases/X11R7.7/doc/man/man5/Compose.5.xhtml
SetBatchLines, 100ms
FileEncoding, UTF-8
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%\
#Include script/logwindow.ahk
#Include script/util.ahk
#include ../src/compose-parse.ahk
#include ../src/compose.ahk ; simulate neovars makeCompose process to find errors
#include ../src/util.ahk
logInit("Compose-update")
; Make sure AHK runs in Unicode version
if (not A_IsUnicode)
{
logError("Unicode support missing! Restart this script with the Unicode-version of AutoHotkey, e.g. through AutoHotkeyU32.exe or AutoHotkeyU64.exe.")
logFinal()
}
; Paths
srcDir := A_ScriptDir . "\..\src"
binDir := A_ScriptDir . "\..\bin"
configDir := A_ScriptDir . "\..\config"
iniFile := util_getFullPath(configDir . "\compose-config.ini")
;
; Read user-defined configuration
;
; Default configs (keys are not case-sensitive)
userConfigDefaults := {composeFilesPrefix: "", composeFiles: "", makeBackups: True}
configs := {revision: "<unknown>", composeFilesFull: [], outputFile: ""}
; Read user-defined configs from ini-file
if not FileExist(iniFile)
{
logError("Configuration file not found at '" . iniFile . "'")
logFinal()
}
logEntry("Read user-defined configuration...")
for key, value in userConfigDefaults
{
IniRead, valueNew, %iniFile%, Global, %key% , %value%
configs[key] := valueNew
}
; Asseble full pathnames for input files
composeFilesCSV := configs["composeFiles"]
Loop, parse, composeFilesCSV, CSV, %A_Space%%A_Tab%
{
configs["composeFilesFull"].push(util_getFullPath(configs["composeFilesPrefix"] . A_LoopField))
}
numComposeFiles := configs["composeFilesFull"].Length()
if (numComposeFiles == 0)
logWarning("No compose-files provided! Compose-definitions will be empty.")
; Validate input filenames (early exit on errors)
Loop, % numComposeFiles
{
file := configs["composeFilesFull"][A_Index]
if not FileExist(file)
{
logError("Compose-file not found at '" . file . "'")
logFinal()
}
}
;
; Other configurations
;
; Query revsion information for the compose files (requires git)
; If no revision can be determined (e.g. git not installed or input-
; files from outside the repository), a warning will be printed.
logEntry("Query revision information...")
composePathsQuoted := ""
for i, file in configs["composeFilesFull"]
composePathsQuoted .= """" . file . """ "
exitCode := util_runWaitCMD("git rev-list -n 1 HEAD -- " . composePathsQuoted, strOut, strErr)
if not exitCode and StrLen(strOut) >= 7
configs["revision"] := SubStr(strOut, 1, 7)
else
logWarning("Could not query revision information from git repository. " . strErr)
; Clear any existing output files (if exist)
logEntry("Deleting old compose scripts")
outputFileDefault := util_getFullPath(srcDir . "\compose.generated.ahk")
outputFileTainted := util_getFullPath(srcDir . "\compose-tainted.generated.ahk")
for i,f in [outputFileDefault, outputFileTainted]
{
; Move existing scripts to backup copy (overwrite existing backups)
if (configs["makeBackups"])
{
backupFile := f . "~"
FileMove, % f, % backupFile, 1
}
else
FileDelete, % f
if FileExist(f)
{
logError("Could not remove old compose script '" . f . "'")
logFinal()
}
}
; Name of the output script (in source-directory):
; - If uncommitted changes pending: (over-)write to "compose-tainted.generated.ahk"
; - If working-dir clean: (over-)write to "compose.generated.ahk"
exitCode := util_runWaitCMD("git diff --quiet -- " . composePathsQuoted)
configs["outputFile"] := (exitCode ? outputFileTainted : outputFileDefault)
logEntry("Set output file to '" . configs["outputFile"] . "'")
;
; Parse compose-definitions into source script
;
outputFileObj := FileOpen(configs["outputFile"], "w `n", "UTF-8")
if (not IsObject(outputFileObj))
{
logError("Output file cannot be opened for writing at '" . configs["outputFile"] . "'")
logFinal()
}
; Write header
logEntry("Write header information.")
scriptGeneratedBy := A_ScriptName
scriptLineRevision := "compRevision := """ . configs["revision"] . """"
outputFileObj.WriteLine(
(
"; -*- encoding: utf-8 -*-
;
; ** THIS FILE WAS GENERATED BY " . scriptGeneratedBy . " **
; ** DO NOT EDIT BY HAND -- FILE MAY BE OVERWRITTEN ANYTIME **
;
; Revision information
" . scriptLineRevision . "
; Make compose-definitions globally available
LoadDefaultCompose() {"
))
; Initialize parsing
makeComposeFun := Func("appendMakeComposeCmd").Bind(outputFileObj)
onParseErrorFun := Func("onParseError")
onProgressFun := Func("onProgress")
keySym2KeyIdMap := makekeySym2KeyIdMap()
; Parse and write out compose-definitions
totalErrorCount := 0
Loop, % numComposeFiles
{
inputFile := configs["composeFilesFull"][A_Index]
logEntry("Parse compose-definitions from '" . inputFile . "'...")
if not FileExist(inputFile)
{
logError("Compose-file not found at '" . inputFile . "'")
continue ; try to complete output with footer etc.
}
try
totalErrorCount += parseComposeFile(inputFile, keySym2KeyIdMap, makeComposeFun, , onParseErrorFun, onProgressFun)
catch e
{
logError("Unhandled exception '" . e.What . (e.Message == "" ? "" : "' reports '" . e.Message) . "' while processing '" . inputFile . "'")
continue ; try to complete output with footer etc.
}
}
logEntry(Format("Parsing finished with {:i} parsing-error{:s} in {:i} file{:s}.", totalErrorCount, util_pluralS(totalErrorCount), numComposeFiles, util_pluralS(numComposeFiles)))
; Write footer
logEntry("Write footer information.")
outputFileObj.WriteLine("}")
outputFileObj.Close()
; Exit
logEntry("Compose-update completed.")
logFinal()
; -------------------------------------
; Functions
; -------------------------------------
; Compose-parser compose-sequence processor
appendMakeComposeCmd(outputFileObj, sequence, resultChars)
{
; Add new compose to global 'composeDict' and 'composeSequences'.
; Simulates the neovars makeCompose process in order to detect problems early, including
; - invalid sequences,
; - attempting to overwrite existing (shorter or equal) sequences, or
; - sequences that would make existing (longer) sequences inaccessible
; However, these checks can not take into account all compose-definitions available at runtime
; (user-defined composes, neovars layout keys and internal composes for tool invocation, etc.)
success := makeCompose(sequence, resultChars)
; Append compose-definition as a AHK-script command to output file
if (success) {
; Make AHK script command that creates the compose definition when interpreted
sequenceLiteral := "["
for i, char in sequence
sequenceLiteral .= """" . char . ""","
sequenceLiteral := SubStr(sequenceLiteral,1,-1) . "]"
cmd := Format(" makeCompose({:s},""{:s}"")", sequenceLiteral, resultChars)
; Append cmd to file
outputFileObj.WriteLine(cmd)
}
return success
}
; Compose-parser progress handler
onParseError(e, errorCount)
{
if (e.type == "key_sym")
logWarning(Format("Ignored unknown <{:s}> on line {:u} '{:s}'", e.keySym, e.lineNo, e.line))
else if (e.type == "result")
logWarning(Format("Ignored empty result on line {:u} '{:s}'", e.lineNo, e.line))
else if (e.type == "make")
logWarning(Format("Ignored invalid or occupied sequence on line {:u} '{:s}'", e.lineNo, e.line))
else
logWarning(Format("Ignored bad line {:u} '{:s}'", e.lineNo, e.line))
}
; Compose-parser error handler
onProgress(count, total, errorCount)
{
progress := 100 * count / total
msgStr := Format("complete - {:u} line{:s} with {:u} parsing-error{:s}", count, util_pluralS(count), errorCount, util_pluralS(errorCount))
logProgressUpdate(progress, msgStr)
if (count == total)
logProgressStop()
}

View File

@ -0,0 +1,206 @@
; A terminal-style script logging window
; -----------------------------------------------
; Public interface
; -----------------------------------------------
; Set up window and activate logging
logInit(title)
{
global logGui, logEdit, logProgress := ""
, logUpdateText := "", logUpdateBack := 0
, logComplete := False, logExitCode := 0, logErrorCount := 0
, logNeedsUpdate := False, logHasTimeout := False
static ES_NOHIDESEL := 0x100, WS_EX_CLIENTEDGE := "E0x200"
Gui, New, +Resize +hwndlogGui label_logOn
Gui, %logGui%:Margin, 0, 0
Gui, %logGui%:Font, s12,
Gui, %logGui%:Font, , Courier
Gui, %logGui%:Font, , Consolas
Gui, %logGui%:Add, Edit, +%ES_NOHIDESEL% -%WS_EX_CLIENTEDGE% cBlack hwndlogEdit w600 r16 ReadOnly VScroll
Gui, %logGui%:Color, F0FFF0
Gui, %logGui%:Show, , % title
FormatTime, timeStamp, Ln
_logWrite(title . " log from " . timeStamp . "`r`n")
_logUpdate()
}
; End logging thread, keep window open
logFinal(exitCode:="")
{
global logGui, logComplete := True, logExitCode, logErrorCount
logProgressStop()
logExitCode := exitCode == "" ? !!logErrorCount : exitCode
SetTimer, _logUpdate, Off
status := exitCode ? "failure" : ""
if (logErrorCount)
status .= (status ? " - " : "") . Format("{:i} error{:s}", logErrorCount, logErrorCount > 1 ? "s" : "")
_logWrite("`r`nPress ESC to exit" . (status ? " (" . status . ")" : ""))
_logUpdate()
if (logExitCode)
Gui, %logGui%:Color, FFF0F0
Exit logExitCode
}
; Log messages
logEntry(msgStr)
{
_logWrite("[*] " . msgStr)
}
logWarning(msgStr)
{
_logWrite("[WARNING] " . msgStr)
}
logError(msgStr)
{
global logGui, logErrorCount
logErrorCount++
Gui, %logGui%:Color, FFF8F0
_logWrite("[ERROR!] " . msgStr)
}
; Progress counter (percent) under last entry
logProgressUpdate(progress, msgStr:="")
{
global logProgress
activeProgLen := StrLen(logProgress)
logProgress := Format("... ({:3.1f}%",progress) . (msgStr != "" ? " " . msgStr : "") . ")`r`n"
_logTextAppend(logProgress, activeProgLen)
_logRequestUpdate()
}
logProgressStop()
{
global logProgress := ""
}
; -----------------------------------------------
; Private methods
; -----------------------------------------------
; Append entry in a new line
_logWrite(entry)
{
global logProgress
_logTextAppend(entry . "`r`n" . logProgress, StrLen(logProgress))
_logRequestUpdate()
}
_logTextAppend(text:="", back:=0) {
global logUpdateText, logUpdateBack
if (back > 0)
{
if (back > StrLen(logUpdateText))
logUpdateBack += back - StrLen(logUpdateText)
logUpdateText := SubStr(logUpdateText, 1, -back)
}
logUpdateText .= text
}
; Display update, but wait for cooldown
_logRequestUpdate()
{
global logNeedsUpdate, logHasTimeout
if (logHasTimeout)
logNeedsUpdate := True
else
_logUpdate()
}
_logOnTimeoutEnd()
{
global logNeedsUpdate, logHasTimeout := False
if (logNeedsUpdate)
_logUpdate()
}
; Display update, redraw text
_logUpdate()
{
SetTimer, _logOnTimeoutEnd, Off
global logNeedsUpdate := False, logHasTimeout := True
; Redraw-delay, improves performance and reduces flicker
static LOG_COOLDOWN_PERIOD := 35
_logRedraw()
SetTimer, _logOnTimeoutEnd, % -LOG_COOLDOWN_PERIOD
}
_logRedraw()
{
global logEdit, logUpdateText, logUpdateBack
static WM_SETREDRAW := 0x0B, WM_SETTEXT := 0x0C, WM_GETTEXT := 0x0D, WM_GETTEXTLENGTH := 0x0E
, WM_VSCROLL := 0x115, EM_SETSEL := 0xB1, EM_SETCARETINDEX := 0x1511, SB_BOTTOM := 0x07
, CHR_SIZE := (A_IsUnicode? 2 : 1)
logEditId := "ahk_id " . logEdit
; Update text
SendMessage, WM_GETTEXTLENGTH, 0, 0, , %logEditId%
logTextLenOld := ErrorLevel ; excl. null-char
, logTextLenNew := logTextLenOld + StrLen(logUpdateText) - logUpdateBack
VarSetCapacity(logText, CHR_SIZE*(logTextLenNew + 1)) ; capacity incl. null-char
SendMessage, WM_GETTEXT, logTextLenOld + 1, &logText, , %logEditId% ; wParam incl. null-char
StrPut(logUpdateText, &logText + CHR_SIZE*(logTextLenOld - logUpdateBack))
logUpdateText := ""
, logUpdateBack := 0
; Put updated text into edit control
_logGetSelStartEnd(selStart, selEnd) ; remember current selection
SendMessage, WM_SETREDRAW, False, 0, , %logEditId% ; pause drawing
SendMessage, WM_SETTEXT, 0, &logText, , %logEditId% ; update text
SendMessage, WM_VSCROLL, SB_BOTTOM, 0, , %logEditId% ; scroll down
SendMessage, WM_SETREDRAW, True, 0, , %logEditId% ; resume drawing
if (selStart < logTextLenOld)
SendMessage, EM_SETSEL, selStart, selEnd, , %logEditId% ; restore selection
else
SendMessage, EM_SETCARETINDEX, StrLen(logText), 0, , %logEditId% ; keep caret at end
}
; Retrieve selection start- and endpoints
_logGetSelStartEnd(byRef selStart, byRef selEnd)
{
global logEdit
static EM_GETSEL := 0xB0, EM_GETCARETINDEX := 0x1512
logEditId := "ahk_id " . logEdit
; Selection range
VarSetCapacity(selStart, 4)
VarSetCapacity(selPosAfter, 4)
SendMessage, EM_GETSEL, &selStart, &selPosAfter, , %logEditId%
selStart := NumGet(selStart, 0, "UInt")
, selPosAfter := NumGet(selPosAfter, 0, "UInt")
; Selection start (=anchor) and end (=active end)
SendMessage, EM_GETCARETINDEX, 0, 0, , %logEditId%
selEnd := ErrorLevel
if (selEnd != selPosAfter)
selStart := selPosAfter
}
; GUI events
_logOnClose()
{
global logGui, logComplete
if (not logComplete)
{
MsgBox, % 0x4 | 0x20 | 0x2000, , Are you sure you want to cancel the running process?
IfMsgBox No
return 1 ; do not close
}
Gui, %logGui%:Destroy
ExitApp, 1
}
_logOnEscape()
{
global logGui, logComplete, logExitCode
if (logComplete)
{
Gui, %logGui%:Destroy
ExitApp, logExitCode
}
}
_logOnSize()
{
global logGui, logEdit
GuiControl, %logGui%:MoveDraw, logEdit, x0 y0 w%A_GuiWidth% h%A_GuiHeight%
}

View File

@ -0,0 +1,55 @@
; Utilities module for tools
; Run a command and returns its exit code,
; and retrieves standard (error-)output.
;
; Uses the Windows-Script Host to run cmd.exe.
;
; Known limitations:
; - Opens terminal window in foreground for the duration of the command.
; - Character encoding: uses shell codepage; problems with unicode.
;
; References:
; - https://www.autohotkey.com/docs/commands/Run.htm#StdOut
; - https://docs.microsoft.com/en-us/previous-versions//2f38xsxe(v=vs.85)
util_runWaitCMD(command, ByRef strOut:="", ByRef strErr:="")
{
; create WshScriptExec object running our command
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec(ComSpec . " /C " . """" . command . """")
; bring our window on front of shell window
if (exec.Status == 0)
sleep 100
Gui, %A_DefaultGui%: Show
; read from output-streams until finished
strOut := exec.StdOut.ReadAll()
strErr := exec.StdErr.ReadAll()
return exec.ExitCode
}
; Path normalization
;
; Returns the fully expanded, normalized and simplified absolute path.
; Relative paths are expanded relative to the current working directory.
; Input path does not need to be a valid file or directory.
;
; Reference/Source:
; - https://www.autohotkey.com/docs/misc/LongPaths.htm
; - https://github.com/AutoHotkey/Ahk2Exe/blob/faec21a5d8ad9a7fcab6849b4329ea2887731f4b/Compiler.ahk
util_getFullPath(path)
{
; count characters; ANSI limits pathlength
cc := A_IsUnicode
? DllCall("GetFullPathName", "str", path, "uint", 0, "ptr", 0, "ptr", 0, "uint")
: 260
VarSetCapacity(buf, cc * (A_IsUnicode ? 2 : 1))
return DllCall("GetFullPathName", "str", path, "uint", cc, "str", buf, "ptr", 0) ? buf : ""
}
; Return "s" if val is plural or zero, "" otherwise
util_pluralS(val)
{
return (Abs(val) == 1 ? "" : "s")
}