From 8b7f6b746b4f7790ade50f60c5d4b89488bc8f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=85=E6=88=8E=E6=B0=8F?= Date: Sat, 2 Mar 2024 11:42:50 +0800 Subject: [PATCH] fix(context): tag selected segment after editing call Context::BeginEditing when input is edited after selection. move cursor also counts as edit. the tag is used to tell if BackSpace should delete the last input character or revert a recent selection. the information was previously denoted by kConfirmed status which caused the side-effect of breaking a user phrase into individual segments. fixed #746, fixed #830 --- src/rime/context.cc | 18 ++++++++++++++---- src/rime/context.h | 4 ++-- src/rime/gear/editor.cc | 5 +++-- src/rime/gear/navigator.cc | 2 +- src/rime/gear/speller.cc | 3 +-- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/rime/context.cc b/src/rime/context.cc index 0372ceffc..77bc41bb3 100644 --- a/src/rime/context.cc +++ b/src/rime/context.cc @@ -12,6 +12,8 @@ namespace rime { +const string kSelectedBeforeEditing = "selected_before_editing"; + bool Context::Commit() { if (!IsComposing()) return false; @@ -185,16 +187,20 @@ bool Context::ConfirmCurrentSelection() { return true; } -bool Context::ConfirmPreviousSelection() { +void Context::BeginEditing() { for (auto it = composition_.rbegin(); it != composition_.rend(); ++it) { if (it->status > Segment::kSelected) { - return false; + return; } if (it->status == Segment::kSelected) { - it->status = Segment::kConfirmed; - return true; + it->tags.insert(kSelectedBeforeEditing); + return; } } +} + +bool Context::ConfirmPreviousSelection() { + BeginEditing(); return false; } @@ -225,6 +231,10 @@ bool Context::ReopenPreviousSelection() { if (it->status > Segment::kSelected) return false; if (it->status == Segment::kSelected) { + // do not reopen the previous selection after editing input. + if (it->tags.count(kSelectedBeforeEditing) != 0) { + return false; + } while (it != composition_.rbegin()) { composition_.pop_back(); } diff --git a/src/rime/context.h b/src/rime/context.h index 8eb793fd7..1d714efe0 100644 --- a/src/rime/context.h +++ b/src/rime/context.h @@ -50,8 +50,8 @@ class RIME_API Context { // return false if there's no candidate for current segment bool ConfirmCurrentSelection(); bool DeleteCurrentSelection(); - - bool ConfirmPreviousSelection(); + void BeginEditing(); + bool ConfirmPreviousSelection(); // deprecated bool ReopenPreviousSegment(); bool ClearPreviousSegment(); bool ReopenPreviousSelection(); diff --git a/src/rime/gear/editor.cc b/src/rime/gear/editor.cc index 7247be029..37b3dda62 100644 --- a/src/rime/gear/editor.cc +++ b/src/rime/gear/editor.cc @@ -123,7 +123,8 @@ bool Editor::CommitComposition(Context* ctx) { } bool Editor::RevertLastEdit(Context* ctx) { - // different behavior in regard to previous operation type + // revert last selection or delete last input character + // depending on recent operation type ctx->ReopenPreviousSelection() || (ctx->PopInput() && ctx->ReopenPreviousSegment()); return true; @@ -181,7 +182,7 @@ ProcessResult Editor::DirectCommit(Context* ctx, int ch) { ProcessResult Editor::AddToInput(Context* ctx, int ch) { ctx->PushInput(ch); - ctx->ConfirmPreviousSelection(); + ctx->BeginEditing(); return kAccepted; } diff --git a/src/rime/gear/navigator.cc b/src/rime/gear/navigator.cc index 3b51c449a..9a2d128d0 100644 --- a/src/rime/gear/navigator.cc +++ b/src/rime/gear/navigator.cc @@ -123,7 +123,7 @@ bool Navigator::End(Context* ctx) { } void Navigator::BeginMove(Context* ctx) { - ctx->ConfirmPreviousSelection(); + ctx->BeginEditing(); // update spans if (input_ != ctx->input() || ctx->caret_pos() > spans_.end()) { input_ = ctx->input(); diff --git a/src/rime/gear/speller.cc b/src/rime/gear/speller.cc index 8abcb83d3..5b9888c93 100644 --- a/src/rime/gear/speller.cc +++ b/src/rime/gear/speller.cc @@ -121,8 +121,7 @@ ProcessResult Speller::ProcessKeyEvent(const KeyEvent& key_event) { } DLOG(INFO) << "add to input: '" << (char)ch << "', " << key_event.repr(); ctx->PushInput(ch); - ctx->ConfirmPreviousSelection(); // so that next BackSpace won't revert - // previous selection + ctx->BeginEditing(); if (AutoSelectPreviousMatch(ctx, &previous_segment)) { DLOG(INFO) << "auto-select previous match."; // after auto-selecting, if only the current non-initial key is left,