From efdea2c14f46fec74e2e75ec60a7a1049f2391c1 Mon Sep 17 00:00:00 2001 From: Jia Sui Date: Thu, 1 Oct 2026 15:09:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(engine):=20=E5=85=A8=E6=8B=BC=E5=90=88?= =?UTF-8?q?=E6=B3=95=E9=94=AE=E5=85=A5=E8=A2=AB=E5=88=AB=E5=90=8D=E6=94=B9?= =?UTF-8?q?=E5=86=99=E5=90=8E=20preedit=20=E4=B8=8D=E5=86=8D=E7=85=A7?= =?UTF-8?q?=E6=90=AC=E6=94=B9=E5=86=99=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/core/input_session_composition.cpp | 8 +++++++- engine/tests/src/test_input_session.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/engine/core/input_session_composition.cpp b/engine/core/input_session_composition.cpp index 1cec3a7a..19446f9f 100644 --- a/engine/core/input_session_composition.cpp +++ b/engine/core/input_session_composition.cpp @@ -285,7 +285,13 @@ std::string BuildQuanpinAutocorrectDisplay(const QueryRequest &request) // bit rides along with the legacy switches. if (quanpin::looks_like_syllable_with_jianpin_tail(request.raw_input)) { - return base; + // The typed spelling is legal, but the scheme alias table may still + // have re-segmented it into a reading with copied letters (dongua -> + // dong'gua, haoyonga -> hao'yong'ga). The dictionary ranks those + // readings against the exact one by frequency, yet the preedit must + // show the typed letters (PRD R5), so a rewritten base may never + // reach it verbatim. + return letters_rewritten ? QuanpinLettersWithoutDelimiters(cased) : base; } const auto cut = quanpin::autocorrect_cut_detail(folded_input, types); diff --git a/engine/tests/src/test_input_session.cpp b/engine/tests/src/test_input_session.cpp index 7e9f5aaa..389225ca 100644 --- a/engine/tests/src/test_input_session.cpp +++ b/engine/tests/src/test_input_session.cpp @@ -824,6 +824,25 @@ int run_test() "Selecting a corrected phrase left an unconsumed input suffix."); } + // PRD R5 regression: a fully legal spelling whose alias reading won the + // query (haoyonga -> hao'yong'ga) must still preedit the typed letters. + // The rewritten segmentation used to leak into the preedit verbatim, + // adding a phantom letter and shifting the TSF caret (haoyongg|a). + struct LegalSpellingCase + { + const char *pinyin; + const char *expected_preedit; + }; + const std::array legal_spelling_preedit_cases = { + {{"haoyonga", "haoyonga"}, {"dongua", "dongua"}, {"zhonguo", "zhonguo"}, {"dongan", "dongan"}}}; + for (const auto &test_case : legal_spelling_preedit_cases) + { + metasequoia::InputSession session; + type(session, test_case.pinyin); + require(session.get_pinyin_segmentation_with_cases() == test_case.expected_preedit, + "A legal spelling with an alias reading must preedit the typed letters."); + } + metasequoia::InputSession no_autocorrect_session(SchemeType::Quanpin, 0u); require(no_autocorrect_session.quanpin_autocorrect_types() == 0, "The requested pinyin autocorrect setting was not retained.");