Repository navigation
Custom-candidate overrides via UI; async dictionary load - #11
Merged
Merged
Conversation
Two changes: 1. Async dictionary load. Switching to CantoIME parsed the whole dictionary synchronously inside ActivateEx (ApplySettings -> Dictionary::Load), which blocked the UI thread and caused the noticeable activation lag. The parse now runs on a detached background thread and the finished Dictionary is handed back to the UI thread via WM_CANTO_DICT_READY, where it is move-assigned into m_dict. The message window is created before ApplySettings so the handoff works during activation. Until the load lands (a fraction of a second) typing just produces no candidates. Stale loads (dictionary switched again mid-parse) are dropped by comparing the loaded path to the latest requested one, and the DLL is pinned (DllAddRef/DllRelease) for the worker's lifetime so a fast deactivate cannot unload it out from under the thread. 2. Custom candidates in the options dialog. Instead of hand-editing a text file, the dialog now has a "Custom candidates" section: a list plus key/candidates fields and Add-Update / Remove buttons. Overrides are stored per-user under HKCU\Software\CantoIME\Overrides (one REG_SZ value per key) and merged on top of the selected dictionary at load via Dictionary::ApplyOverrides — extra candidates are appended after the stock ones for that key (deduped); a key with no stock entry is added. Override changes funnel through the same background reload path, so removals rebuild cleanly from the base file.
Prepend each key's override candidates ahead of the dictionary candidates so the user's first extra is pickable with the 1 key. Dedup keeps a stock character that an override repeats at the front only, never twice.
actions/checkout defaults to lfs=false, so the build was bundling the LFS pointer stubs instead of the real dictionaries. Enable lfs on checkout and fail fast if either dictionary is still a pointer.
It cost a build step on every run; lfs: true on checkout is enough.
Resize: add a sizing border and an anchor-based reflow so the overrides list grows/shrinks with the window (fields and buttons track it). The dialog was too tall on some resolutions; it can now shrink until the list is ~3 rows and widen freely. Add-multiple: after Add / Update, clear the Key/Candidates fields and drop the list selection so the next Add starts a fresh entry instead of being stuck updating the row just committed.
Overrides now belong to the dictionary they were made for: one set for stock Traditional, one for stock Simplified, and one per distinct custom dictionary path. Storage moves to HKCU\...\Overrides\<dictId>, where dictId is trad/simp or custom-<hash-of-path> (DictionaryIdentity). Runtime loads the active dictionary's set. The options dialog stages a set per dictionary it touches and swaps the editor when you change the dictionary selection (mode change, Browse, or leaving the path field), writing every touched set back under its own dictionary on OK.
ArnauvGilotra
force-pushed
the
feat/candidate-overrides-async-dict
branch
from
August 11, 2026 08:08
b175f09 to
2571952
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two things from the last round, both in here.
1. Overrides, but with real UI (not a text file)
Reinstates the "associate a key with extra candidates" idea (the old
+behaviour), driven from the options dialog instead of hand-editing a.txt.HKCU\Software\CantoIME\Overrides, oneREG_SZvalue per key (candidates space-joined). Cancel discards; OK persists.Dictionary::ApplyOverrides: the extra candidates are appended after the stock ones for that key (deduped), and a key with no stock entry is added outright.One judgement call for you: I append overrides after the stock candidates (so "additional" means additional, stock ordering unchanged). If you'd rather a user's own candidate jump to position 1 (selectable with the
1key), say so and I'll flip the merge order.2. Activation lag
The lag switching to CantoIME was the whole dictionary being parsed synchronously on the UI thread inside
ActivateEx(ApplySettings->Dictionary::Load). Now:Dictionaryis posted back to the UI thread (WM_CANTO_DICT_READY) and move-assigned intom_dict. Activation returns immediately.ApplySettingsso the handoff works during activation.DllAddRef/DllRelease) for the worker's lifetime so a fast deactivate can't unload the code out from under the thread.Override changes funnel through the same background reload path, so a removed override rebuilds cleanly from the base file rather than needing an incremental un-merge.
Notes