Skip to content

Commit

Permalink
fix(chord_composer): more safely handle the placeholder ZWSP
Browse files Browse the repository at this point in the history
sometimes Rime outputs an invalid character, invisible among text or being
visualized as diamond with question mark in macOS. I observed this bug often
when I was using combo pinyin but still not sure if this code has to do with
the issue. just mark the placeholder segment "phony" to prevent accidentally
commiting the ZWSP character.
  • Loading branch information
lotem committed Dec 6, 2020
1 parent bb94093 commit 025d9fb
Showing 1 changed file with 22 additions and 23 deletions.
45 changes: 22 additions & 23 deletions src/rime/gear/chord_composer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
#include <rime/schema.h>
#include <rime/gear/chord_composer.h>

// U+FEFF works better with MacType
static const char* kZeroWidthSpace = "\xef\xbb\xbf"; //"\xe2\x80\x8b";
static const char* kZeroWidthSpace = "\xe2\x80\x8b"; // U+200B

namespace rime {

Expand Down Expand Up @@ -118,8 +117,9 @@ ProcessResult ChordComposer::ProcessChordingKey(const KeyEvent& key_event) {
return kAccepted;
}

inline static bool is_composing_text(Context* ctx) {
return ctx->IsComposing() && ctx->input() != kZeroWidthSpace;
inline static bool is_composing(Context* ctx) {
return !ctx->composition().empty() &&
!ctx->composition().back().HasTag("phony");
}

ProcessResult ChordComposer::ProcessKeyEvent(const KeyEvent& key_event) {
Expand All @@ -133,7 +133,7 @@ ProcessResult ChordComposer::ProcessKeyEvent(const KeyEvent& key_event) {
int ch = key_event.keycode();
if (!is_key_up && ch >= 0x20 && ch <= 0x7e) {
// save raw input
if (!is_composing_text(engine_->context()) || !raw_sequence_.empty()) {
if (!is_composing(engine_->context()) || !raw_sequence_.empty()) {
raw_sequence_.push_back(ch);
DLOG(INFO) << "update raw sequence: " << raw_sequence_;
}
Expand Down Expand Up @@ -164,18 +164,17 @@ void ChordComposer::UpdateChord() {
string code = SerializeChord();
prompt_format_.Apply(&code);
if (comp.empty()) {
// add an invisbile place holder segment
// add a placeholder segment
// 1. to cheat ctx->IsComposing() == true
// 2. to attach chord prompt to while chording
ctx->PushInput(kZeroWidthSpace);
if (comp.empty()) {
LOG(ERROR) << "failed to update chord.";
return;
}
comp.back().tags.insert("phony");
}
comp.back().tags.insert("chord_prompt");
comp.back().prompt = code;
ctx->set_input(kZeroWidthSpace);
Segment placeholder(0, ctx->input().length());
placeholder.tags.insert("phony");
ctx->composition().AddSegment(placeholder);
}
auto& last_segment = comp.back();
last_segment.tags.insert("chord_prompt");
last_segment.prompt = code;
}

void ChordComposer::FinishChord() {
Expand Down Expand Up @@ -207,20 +206,20 @@ void ChordComposer::ClearChord() {
return;
Context* ctx = engine_->context();
Composition& comp = ctx->composition();
if (comp.empty()) {
if (comp.empty())
return;
auto& last_segment = comp.back();
if (comp.size() == 1 && last_segment.HasTag("phony")) {
ctx->Clear();
}
if (comp.input().substr(comp.back().start) == kZeroWidthSpace) {
ctx->PopInput(ctx->caret_pos() - comp.back().start);
}
else if (comp.back().HasTag("chord_prompt")) {
comp.back().prompt.clear();
comp.back().tags.erase("chord_prompt");
else if (last_segment.HasTag("chord_prompt")) {
last_segment.prompt.clear();
last_segment.tags.erase("chord_prompt");
}
}

void ChordComposer::OnContextUpdate(Context* ctx) {
if (is_composing_text(ctx)) {
if (is_composing(ctx)) {
composing_ = true;
}
else if (composing_) {
Expand Down

0 comments on commit 025d9fb

Please sign in to comment.