diff --git a/.gitignore b/.gitignore index 6ec9dae1d1..d6efab2c18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +plugins/*/ build/ build-static/ debug/ @@ -14,3 +15,4 @@ node_modules/ .*.swp .cache/ *.7z +*.bz2 diff --git a/src/rime/context.cc b/src/rime/context.cc index 905ced34ee..065388d92d 100644 --- a/src/rime/context.cc +++ b/src/rime/context.cc @@ -121,6 +121,20 @@ bool Context::Select(size_t index) { return false; } +bool Context::Hilite(size_t index) { + if (composition_.empty()) + return false; + Segment& seg(composition_.back()); + if (auto cand = seg.GetCandidateAt(index)) { + seg.selected_index = index; + seg.tags.insert("paging"); + DLOG(INFO) << "Hilited: '" << cand->text() << "', index = " << index; + update_notifier_(this); + return true; + } + return false; +} + bool Context::DeleteCandidate( function(Segment& seg)> get_candidate) { if (composition_.empty()) diff --git a/src/rime/context.h b/src/rime/context.h index e31ea3cd53..727e458f40 100644 --- a/src/rime/context.h +++ b/src/rime/context.h @@ -44,6 +44,7 @@ class RIME_API Context { // return false if there is no candidate at index bool Select(size_t index); + bool Hilite(size_t index); bool DeleteCandidate(size_t index); // return false if there's no candidate for current segment bool ConfirmCurrentSelection(); diff --git a/src/rime/gear/selector.cc b/src/rime/gear/selector.cc index 06874103dc..399209102d 100644 --- a/src/rime/gear/selector.cc +++ b/src/rime/gear/selector.cc @@ -116,7 +116,7 @@ inline static bool is_linear_layout(Context* ctx) { } ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { - if (key_event.release() || key_event.alt() || key_event.super()) + if (key_event.release() || key_event.super()) return kNoop; Context* ctx = engine_->context(); if (ctx->composition().empty()) @@ -149,7 +149,8 @@ ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { else if (ch >= XK_KP_0 && ch <= XK_KP_9) index = ((ch - XK_KP_0) + 9) % 10; if (index >= 0) { - SelectCandidateAt(ctx, index); + key_event.alt() ? HiliteCandidateAt(ctx, index) + : SelectCandidateAt(ctx, index); return kAccepted; } // not handled @@ -252,6 +253,23 @@ bool Selector::End(Context* ctx) { return Home(ctx); } +bool Selector::HiliteCandidateAt(Context* ctx, int index) { + Composition& comp = ctx->composition(); + if (comp.empty()) + return false; + int page_size = engine_->schema()->page_size(); + if (index >= page_size) + return false; + int selected_index = comp.back().selected_index; + int page_start = (selected_index / page_size) * page_size; + // hilite an already hilited candidate -> select this candidate + if (page_start + index == selected_index) + return ctx->Select(selected_index); + comp.back().selected_index = page_start + index; + comp.back().tags.insert("paging"); + return true; +} + bool Selector::SelectCandidateAt(Context* ctx, int index) { Composition& comp = ctx->composition(); if (comp.empty()) diff --git a/src/rime/gear/selector.h b/src/rime/gear/selector.h index 5e4bfce00c..91fa7341bc 100644 --- a/src/rime/gear/selector.h +++ b/src/rime/gear/selector.h @@ -36,6 +36,7 @@ class Selector : public Processor, public KeyBindingProcessor { Handler Home; Handler End; + bool HiliteCandidateAt(Context* ctx, int index); bool SelectCandidateAt(Context* ctx, int index); }; diff --git a/src/rime_api.cc b/src/rime_api.cc index 678169c0af..321e09a443 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -1038,6 +1038,15 @@ RIME_API Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, return do_with_candidate_on_current_page(session_id, index, &Context::Select); } +RIME_API Bool RimeHiliteCandidate(RimeSessionId session_id, size_t index) { + return do_with_candidate(session_id, index, &Context::Hilite); +} + +RIME_API Bool RimeHiliteCandidateOnCurrentPage(RimeSessionId session_id, + size_t index) { + return do_with_candidate_on_current_page(session_id, index, &Context::Hilite); +} + const char* RimeGetVersion() { return RIME_VERSION; } @@ -1185,6 +1194,8 @@ RIME_API RimeApi* rime_get_api() { s_api.context_proto = nullptr; s_api.status_proto = nullptr; s_api.get_state_label = &RimeGetStateLabel; + s_api.hilite_candidate = &RimeHiliteCandidate; + s_api.hilite_candidate_on_current_page = &RimeHiliteCandidateOnCurrentPage; s_api.delete_candidate = &RimeDeleteCandidate; s_api.delete_candidate_on_current_page = &RimeDeleteCandidateOnCurrentPage; s_api.get_state_label_abbreviated = &RimeGetStateLabelAbbreviated; diff --git a/src/rime_api.h b/src/rime_api.h index 54fd4c1409..fd2d30e111 100644 --- a/src/rime_api.h +++ b/src/rime_api.h @@ -299,6 +299,9 @@ RIME_API Bool RimeCandidateListFromIndex(RimeSessionId session_id, RIME_API Bool RimeSelectCandidate(RimeSessionId session_id, size_t index); RIME_API Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, size_t index); +RIME_API Bool RimeHiliteCandidate(RimeSessionId session_id, size_t index); +RIME_API Bool RimeHiliteCandidateOnCurrentPage(RimeSessionId session_id, + size_t index); RIME_API Bool RimeDeleteCandidate(RimeSessionId session_id, size_t index); RIME_API Bool RimeDeleteCandidateOnCurrentPage(RimeSessionId session_id, size_t index); @@ -635,6 +638,10 @@ typedef struct rime_api_t { const char* option_name, Bool state); + Bool (*hilite_candidate)(RimeSessionId session_id, size_t index); + Bool (*hilite_candidate_on_current_page)(RimeSessionId session_id, + size_t index); + //! delete a candidate at the given index in candidate list. Bool (*delete_candidate)(RimeSessionId session_id, size_t index); //! delete a candidate from current page.