diff --git a/src/rime/context.cc b/src/rime/context.cc index 905ced34ee..c1dee3dd82 100644 --- a/src/rime/context.cc +++ b/src/rime/context.cc @@ -121,6 +121,27 @@ bool Context::Select(size_t index) { return false; } +bool Context::Highlight(size_t index) { + if (composition_.empty() || !composition_.back().menu) + return false; + Segment& seg(composition_.back()); + size_t new_index = index; + size_t candidate_count = seg.menu->Prepare(index + 1); + if (index >= candidate_count) { + DLOG(INFO) << "selection index exceeds candidate pool, fallback to last"; + new_index = candidate_count - 1; + } + size_t previous_index = seg.selected_index; + if (previous_index == new_index) { + DLOG(INFO) << "selection has not changed, currently at " << new_index; + return false; + } + seg.selected_index = new_index; + update_notifier_(this); + DLOG(INFO) << "selection changed from: " << previous_index << " to: " << new_index; + return true; +} + 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..8eb793fd79 100644 --- a/src/rime/context.h +++ b/src/rime/context.h @@ -44,6 +44,8 @@ class RIME_API Context { // return false if there is no candidate at index bool Select(size_t index); + // return false if the selected index has not changed + bool Highlight(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_api.cc b/src/rime_api.cc index 1baf679fbd..f44ee4a81e 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -1066,6 +1066,37 @@ static bool do_with_candidate_on_current_page( return (ctx->*verb)(page_start + index); } +Bool RimeChangePage(RimeSessionId session_id, Bool backward) { + an session(Service::instance().GetSession(session_id)); + if (!session) + return False; + Context *ctx = session->context(); + if (!ctx || !ctx->HasMenu()) + return False; + Schema *schema = session->schema(); + if (!schema) + return False; + size_t page_size = (size_t)schema->page_size(); + auto& seg(ctx->composition().back()); + size_t current_index = seg.selected_index; + size_t index = + backward ? (current_index <= page_size ? 0 : current_index - page_size) + : (current_index + page_size); + DLOG(INFO) << "current selection: " << current_index + << ", flipping " << (backward ? "backward" : "forward") + << ", new selection " << index; + seg.tags.insert("paging"); + return ctx->Highlight(index); +} + +Bool RimeHighlightCandidate(RimeSessionId session_id, size_t index) { + return do_with_candidate(session_id, index, &Context::Highlight); +} + +Bool RimeHighlightCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { + return do_with_candidate_on_current_page(session_id, index, &Context::Highlight); +} + RIME_API Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) { return do_with_candidate(session_id, index, &Context::Select); } @@ -1231,6 +1262,9 @@ RIME_API RimeApi* rime_get_api() { s_api.get_prebuilt_data_dir_s = &RimeGetPrebuiltDataDirSecure; s_api.get_staging_dir_s = &RimeGetStagingDirSecure; s_api.get_sync_dir_s = &RimeGetSyncDirSecure; + s_api.highlight_candidate = &RimeHighlightCandidate; + s_api.highlight_candidate_on_current_page = &RimeHighlightCandidateOnCurrentPage; + s_api.change_page = &RimeChangePage; } return &s_api; } diff --git a/src/rime_api.h b/src/rime_api.h index d679c147eb..264f35dd05 100644 --- a/src/rime_api.h +++ b/src/rime_api.h @@ -664,6 +664,13 @@ typedef struct rime_api_t { void (*get_prebuilt_data_dir_s)(char* dir, size_t buffer_size); void (*get_staging_dir_s)(char* dir, size_t buffer_size); void (*get_sync_dir_s)(char* dir, size_t buffer_size); + + //! highlight a selection without committing + Bool (*highlight_candidate)(RimeSessionId session_id, size_t index); + //! highlight a selection without committing + Bool (*highlight_candidate_on_current_page)(RimeSessionId session_id, size_t index); + + Bool (*change_page)(RimeSessionId session_id, Bool backward); } RimeApi; //! API entry