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.");