From 5c20cf383aab37fa0e824d1a14a1d19e30d4cf5b Mon Sep 17 00:00:00 2001 From: Charlie Jiang Date: Fri, 10 Apr 2026 02:02:52 +0900 Subject: [PATCH] feat: Support overriding language ID of the text emitted --- RimeWithWeasel/RimeWithWeasel.cpp | 69 +++++++++++++++++++++++++++++-- WeaselIPC/Configurator.cpp | 7 ++-- WeaselTSF/Composition.cpp | 5 +++ WeaselTSF/DisplayAttribute.cpp | 20 +++++++++ WeaselTSF/EditSession.cpp | 8 ++-- WeaselTSF/WeaselTSF.h | 4 ++ include/RimeWithWeasel.h | 9 +++- include/WeaselIPCData.h | 6 +-- 8 files changed, 114 insertions(+), 14 deletions(-) diff --git a/RimeWithWeasel/RimeWithWeasel.cpp b/RimeWithWeasel/RimeWithWeasel.cpp index c4d3a5e22..048da5f6e 100644 --- a/RimeWithWeasel/RimeWithWeasel.cpp +++ b/RimeWithWeasel/RimeWithWeasel.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include #include #include @@ -24,6 +24,31 @@ typedef enum { COLOR_ABGR = 0, COLOR_ARGB, COLOR_RGBA } ColorFormat; using namespace weasel; static RimeApi* rime_api; + +namespace { +bool TryGetLangIdFromConfig(RimeConfig* config, + const char* key, + int* commit_langid) { + if (!config || !key || !commit_langid) + return false; + + char buffer[LOCALE_NAME_MAX_LENGTH] = {0}; + if (!rime_api->config_get_string(config, key, buffer, sizeof(buffer) - 1)) + return false; + + const auto locale_name = u8tow(buffer); + if (locale_name.empty()) + return false; + + const LCID lcid = + LocaleNameToLCID(locale_name.c_str(), LOCALE_ALLOW_NEUTRAL_NAMES); + if (!lcid) + return false; + + *commit_langid = LANGIDFROMLCID(lcid); + return true; +} + WeaselSessionId _GenerateNewWeaselSessionId(SessionStatusMap sm, DWORD pid) { if (sm.empty()) return (WeaselSessionId)(pid + 1); @@ -33,6 +58,7 @@ WeaselSessionId _GenerateNewWeaselSessionId(SessionStatusMap sm, DWORD pid) { int expand_ibus_modifier(int m) { return (m & 0xff) | ((m & 0xff00) << 16); } +} // namespace RimeWithWeaselHandler::RimeWithWeaselHandler(UI* ui) : m_ui(ui), @@ -195,6 +221,7 @@ DWORD RimeWithWeaselHandler::AddSession(LPWSTR buffer, EatLine eat) { std::string schema_id = status.schema_id; m_last_schema_id = schema_id; _LoadSchemaSpecificSettings(ipc_id, schema_id); + _LoadLanguageOverrideConfig(ipc_id, schema_id); _LoadAppInlinePreeditSet(ipc_id, true); _UpdateInlinePreeditStatus(ipc_id); _RefreshTrayIcon(session_id, _UpdateUICallback); @@ -617,6 +644,41 @@ void RimeWithWeaselHandler::_LoadSchemaSpecificSettings( rime_api->config_close(&config); } +void RimeWithWeaselHandler::_LoadLanguageOverrideConfig( + WeaselSessionId ipc_id, + const std::string& schema_id) { + SessionStatus& session_status = get_session_status(ipc_id); + session_status.commit_langid = 0; + + const auto load_global_fallback = [&]() { + RimeConfig weasel_config = {}; + if (!rime_api->config_open("weasel", &weasel_config)) + return; + + int commit_langid = 0; + if (TryGetLangIdFromConfig(&weasel_config, "commit_locale", + &commit_langid)) { + session_status.commit_langid = commit_langid; + } + rime_api->config_close(&weasel_config); + }; + + RimeConfig schema_config = {}; + if (!schema_id.empty() && + rime_api->schema_open(schema_id.c_str(), &schema_config)) { + int commit_langid = 0; + if (TryGetLangIdFromConfig(&schema_config, "schema/commit_locale", + &commit_langid)) { + session_status.commit_langid = commit_langid; + } else { + load_global_fallback(); + } + rime_api->config_close(&schema_config); + } else { + load_global_fallback(); + } +} + void RimeWithWeaselHandler::_LoadAppInlinePreeditSet(WeaselSessionId ipc_id, bool ignore_app_name) { SessionStatus& session_status = get_session_status(ipc_id); @@ -895,8 +957,8 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) { // configuration information actions.push_back("config"); - body.append(L"config.inline_preedit=") - .append(std::to_wstring((int)session_status.style.inline_preedit)) + body.append(L"config.commit_langid=") + .append(std::to_wstring(session_status.commit_langid)) .append(L"\n"); // style @@ -1451,6 +1513,7 @@ void RimeWithWeaselHandler::_GetStatus(Status& stat, if (schema_id != m_last_schema_id) { session_status.__synced = false; m_last_schema_id = schema_id; + _LoadLanguageOverrideConfig(ipc_id, schema_id); if (schema_id != ".default") { // don't load for schema select menu bool inline_preedit = session_status.style.inline_preedit; _LoadSchemaSpecificSettings(ipc_id, schema_id); diff --git a/WeaselIPC/Configurator.cpp b/WeaselIPC/Configurator.cpp index a16c4fa22..d3b779ffd 100644 --- a/WeaselIPC/Configurator.cpp +++ b/WeaselIPC/Configurator.cpp @@ -14,10 +14,9 @@ Configurator::~Configurator() {} void Configurator::Store(Deserializer::KeyType const& key, std::wstring const& value) { - if (!m_pTarget->p_context || key.size() < 2) + if (!m_pTarget->p_config || key.size() < 2) return; - bool bool_value = (!value.empty() && value != L"0"); - if (key[1] == L"inline_preedit") { - m_pTarget->p_config->inline_preedit = bool_value; + if (key[1] == L"commit_langid") { + m_pTarget->p_config->commit_langid = _wtoi(value.c_str()); } } diff --git a/WeaselTSF/Composition.cpp b/WeaselTSF/Composition.cpp index 62852bc7f..e0a237e84 100644 --- a/WeaselTSF/Composition.cpp +++ b/WeaselTSF/Composition.cpp @@ -53,6 +53,7 @@ STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec) { */ if (!_inlinePreeditEnabled) { pRangeComposition->SetText(ec, TF_ST_CORRECTION, L" ", 1); + _pTextService->_SetRangeLanguage(ec, _pContext, pRangeComposition); } /* set selection */ @@ -278,6 +279,8 @@ STDAPI CInlinePreeditEditSession::DoEditSession(TfEditCookie ec) { static_cast(preedit.length()))) != S_OK) return E_FAIL; + _pTextService->_SetRangeLanguage(ec, _pContext, pRangeComposition); + /* TODO: Check the availability and correctness of these values */ int sel_cursor = -1; for (size_t i = 0; i < _context->preedit.attributes.size(); i++) { @@ -354,6 +357,8 @@ STDMETHODIMP CInsertTextEditSession::DoEditSession(TfEditCookie ec) { static_cast(_text.length())))) return E_FAIL; + _pTextService->_SetRangeLanguage(ec, _pContext, pRange); + /* update the selection to an insertion point just past the inserted text. */ pRange->Collapse(ec, TF_ANCHOR_END); diff --git a/WeaselTSF/DisplayAttribute.cpp b/WeaselTSF/DisplayAttribute.cpp index 679c79926..e33137f02 100644 --- a/WeaselTSF/DisplayAttribute.cpp +++ b/WeaselTSF/DisplayAttribute.cpp @@ -52,6 +52,26 @@ BOOL WeaselTSF::_SetCompositionDisplayAttributes(TfEditCookie ec, return (hr == S_OK); } +BOOL WeaselTSF::_SetRangeLanguage(TfEditCookie ec, + _In_ ITfContext* pContext, + ITfRange* pRange) { + if (!pRange || !_textLangId) + return FALSE; + + ITfProperty* pLangIdProperty = nullptr; + HRESULT hr = E_FAIL; + + if (SUCCEEDED(pContext->GetProperty(GUID_PROP_LANGID, &pLangIdProperty))) { + VARIANT var; + var.vt = VT_I4; + var.lVal = _textLangId; + hr = pLangIdProperty->SetValue(ec, pRange, &var); + pLangIdProperty->Release(); + } + + return hr == S_OK; +} + BOOL WeaselTSF::_InitDisplayAttributeGuidAtom() { ITfCategoryMgr* pCategoryMgr = nullptr; HRESULT hr = diff --git a/WeaselTSF/EditSession.cpp b/WeaselTSF/EditSession.cpp index 8f4d50367..b7e2ed410 100644 --- a/WeaselTSF/EditSession.cpp +++ b/WeaselTSF/EditSession.cpp @@ -16,12 +16,14 @@ STDAPI WeaselTSF::DoEditSession(TfEditCookie ec) { _UpdateLanguageBar(_status); if (ok) { + bool inline_preedit = _cand->style().inline_preedit; + _textLangId = static_cast(config.commit_langid); if (!commit.empty()) { // For auto-selecting, commit and preedit can both exist. // Commit and close the original composition first. if (!_IsComposing()) { _StartComposition(_pEditSessionContext, - _fCUASWorkaroundEnabled && !config.inline_preedit); + _fCUASWorkaroundEnabled && !inline_preedit); } _InsertText(_pEditSessionContext, commit); _EndComposition(_pEditSessionContext, false); @@ -31,11 +33,11 @@ STDAPI WeaselTSF::DoEditSession(TfEditCookie ec) { } if (_status.composing && !_IsComposing()) { _StartComposition(_pEditSessionContext, - _fCUASWorkaroundEnabled && !config.inline_preedit); + _fCUASWorkaroundEnabled && !inline_preedit); } else if (!_status.composing && _IsComposing()) { _EndComposition(_pEditSessionContext, true); } - if (_IsComposing() && config.inline_preedit) { + if (_IsComposing() && inline_preedit) { _ShowInlinePreedit(_pEditSessionContext, context); } _UpdateCompositionWindow(_pEditSessionContext); diff --git a/WeaselTSF/WeaselTSF.h b/WeaselTSF/WeaselTSF.h index 696d3cce4..227bc4420 100644 --- a/WeaselTSF/WeaselTSF.h +++ b/WeaselTSF/WeaselTSF.h @@ -144,6 +144,9 @@ class WeaselTSF : public ITfTextInputProcessorEx, BOOL _SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext* pContext, ITfRange* pRangeComposition); + BOOL _SetRangeLanguage(TfEditCookie ec, + _In_ ITfContext* pContext, + ITfRange* pRange); BOOL _InitDisplayAttributeGuidAtom(); com_ptr _GetThreadMgr() { return _pThreadMgr; } @@ -227,6 +230,7 @@ class WeaselTSF : public ITfTextInputProcessorEx, /* IME status */ weasel::Status _status; + LANGID _textLangId = 0; // guidatom for the display attibute. TfGuidAtom _gaDisplayAttributeInput; diff --git a/include/RimeWithWeasel.h b/include/RimeWithWeasel.h index ab20d8d76..0114c5101 100644 --- a/include/RimeWithWeasel.h +++ b/include/RimeWithWeasel.h @@ -23,10 +23,15 @@ typedef std::map AppOptionsByAppName; struct SessionStatus { - SessionStatus() : style(weasel::UIStyle()), __synced(false), session_id(0) { + SessionStatus() + : style(weasel::UIStyle()), + commit_langid(0), + __synced(false), + session_id(0) { RIME_STRUCT(RimeStatus, status); } weasel::UIStyle style; + int commit_langid; RimeStatus status; bool __synced; RimeSessionId session_id; @@ -71,6 +76,8 @@ class RimeWithWeaselHandler : public weasel::RequestHandler { void _UpdateUI(WeaselSessionId ipc_id); void _LoadSchemaSpecificSettings(WeaselSessionId ipc_id, const std::string& schema_id); + void _LoadLanguageOverrideConfig(WeaselSessionId ipc_id, + const std::string& schema_id); void _LoadAppInlinePreeditSet(WeaselSessionId ipc_id, bool ignore_app_name = false); bool _ShowMessage(weasel::Context& ctx, weasel::Status& status); diff --git a/include/WeaselIPCData.h b/include/WeaselIPCData.h index 09f22f91c..f7a766eed 100644 --- a/include/WeaselIPCData.h +++ b/include/WeaselIPCData.h @@ -187,9 +187,9 @@ struct Status { // 用於向前端告知設置信息 struct Config { - Config() : inline_preedit(false) {} - void reset() { inline_preedit = false; } - bool inline_preedit; + Config() : commit_langid(0) {} + void reset() { commit_langid = 0; } + int commit_langid; }; struct UIStyle {