四码(不论是否唯一)之后继续敲字母时,先上屏该码的首选候选,再把这个字母 保留为下一次组合的开头。根因是两侧对「组合里有几个字母」认知不一致:TSF 的 本地按键缓冲跟着敲键涨(raw 预编辑样式下 preedit 就是它),服务端的五笔 raw 被引擎裁在四码;空格提交时组合文本被整段替换成候选并清掉本地缓冲,多敲的 字母随之丢失。 - 新增 worker 消息 CommitCandidateAndContinue(27),payload "<consumed>\t<text>": TSF 按服务端给出的消费数裁**自己**的组合缓冲,而不是套用服务端按旧视图算好 的剩余串——快打时用户已多敲的字母因此不会被覆盖 - TSF 处理序列全部复用既有原语:_InsertTextToComposition + _HandleCompleteCommitFirst 真提交,_StartComposition + AddVirtualKey + _HandleCompositionInputWorker(NO_REQUEST_ID) 重建余下字母的组合;无组合时退化为直写 - 服务端顶字不看自动上屏开关:开关只决定唯一码要不要多敲一键才上屏, 不决定丢不丢输入;自动上屏那条路也改用同一消息,顺带收掉快打竞态 - 引擎新增 wubi_four_code_is_complete(完整四码、码表作答、不要求唯一; 空码不算——没有候选可提交时不触发顶字) 已知限制:光标在组合中间时的改码行为维持现状;空码继续敲字母仍会被忽略。
63 lines
1.7 KiB
C++
63 lines
1.7 KiB
C++
#include "IPC/CommitCandidateAndContinuePayload.h"
|
|
|
|
#include <string>
|
|
|
|
int main()
|
|
{
|
|
// Do not use assert: Release builds must execute these checks too.
|
|
std::size_t consumed = 0;
|
|
std::wstring text;
|
|
|
|
if (!ParseCommitCandidateAndContinuePayload(L"4\t数据", consumed, text) || consumed != 4 || text != L"数据")
|
|
{
|
|
return 1;
|
|
}
|
|
// Empty text still consumes: the Server mirrors a cleared composition.
|
|
if (!ParseCommitCandidateAndContinuePayload(L"4\t", consumed, text) || consumed != 4 || !text.empty())
|
|
{
|
|
return 2;
|
|
}
|
|
// A two-digit count is legal as long as it parses.
|
|
if (!ParseCommitCandidateAndContinuePayload(L"12\tab", consumed, text) || consumed != 12 || text != L"ab")
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
// Missing tab.
|
|
if (ParseCommitCandidateAndContinuePayload(L"4", consumed, text))
|
|
{
|
|
return 4;
|
|
}
|
|
// Empty count.
|
|
if (ParseCommitCandidateAndContinuePayload(L"\t数据", consumed, text))
|
|
{
|
|
return 5;
|
|
}
|
|
// Non-digit count.
|
|
if (ParseCommitCandidateAndContinuePayload(L"4x\t数据", consumed, text))
|
|
{
|
|
return 6;
|
|
}
|
|
// Negative count.
|
|
if (ParseCommitCandidateAndContinuePayload(L"-4\t数据", consumed, text))
|
|
{
|
|
return 7;
|
|
}
|
|
// Oversized count.
|
|
if (ParseCommitCandidateAndContinuePayload(L"99999999\t数据", consumed, text))
|
|
{
|
|
return 8;
|
|
}
|
|
// Empty payload.
|
|
if (ParseCommitCandidateAndContinuePayload(L"", consumed, text))
|
|
{
|
|
return 9;
|
|
}
|
|
// Tab inside the text is part of the text, not another separator.
|
|
if (!ParseCommitCandidateAndContinuePayload(L"1\ta\tb", consumed, text) || consumed != 1 || text != L"a\tb")
|
|
{
|
|
return 10;
|
|
}
|
|
return 0;
|
|
}
|