static void FcitxRimeStart(FcitxRime* rime, boolean fullcheck) { char* user_path = NULL; FILE* fp = FcitxXDGGetFileUserWithPrefix("rime", ".place_holder", "w", NULL); if (fp) fclose(fp); FcitxXDGGetFileUserWithPrefix("rime", "", NULL, &user_path); //char* shared_data_dir = fcitx_utils_get_fcitx_path_with_filename("pkgdatadir", "rime"); const char* shared_data_dir = RIME_DATA_DIR; RIME_STRUCT(RimeTraits, fcitx_rime_traits); fcitx_rime_traits.shared_data_dir = shared_data_dir; fcitx_rime_traits.app_name = "rime.fcitx-rime"; fcitx_rime_traits.user_data_dir = user_path; fcitx_rime_traits.distribution_name = "Rime"; fcitx_rime_traits.distribution_code_name = "fcitx-rime"; fcitx_rime_traits.distribution_version = "0.2.3"; if (rime->firstRun) { rime->api->setup(&fcitx_rime_traits); rime->firstRun = false; } rime->api->initialize(&fcitx_rime_traits); rime->api->set_notification_handler(FcitxRimeNotificationHandler, rime); rime->api->start_maintenance(fullcheck); rime->session_id = rime->api->create_session(); free(user_path); }
void FcitxRimeUpdateStatus(FcitxRime* rime) { if (rime->api->is_maintenance_mode()) { return; } if (!rime->api->find_session(rime->session_id)) { rime->session_id = rime->api->create_session(); } RIME_STRUCT(RimeStatus, status); if (rime->api->get_status(rime->session_id, &status)) { char* text = ""; if (status.is_disabled) { text = "\xe2\x8c\x9b"; } else if (status.is_ascii_mode) { text = "A"; } else if (status.schema_name && status.schema_name[0] != '.') { text = status.schema_name; } else { text = "δΈ"; } FcitxUISetStatusString(rime->owner, "rime-enzh", text, text); rime->api->free_status(&status); } else { FcitxUISetStatusString(rime->owner, "rime-enzh", "\xe2\x8c\x9b", "\xe2\x8c\x9b"); } }
INPUT_RETURN_VALUE FcitxRimeDoInputReal(void* arg, FcitxKeySym sym, unsigned int state) { FcitxRime *rime = (FcitxRime *)arg; if (rime->api->is_maintenance_mode()) { return IRV_TO_PROCESS; } if (!rime->api->find_session(rime->session_id)) { rime->session_id = rime->api->create_session(); } if (!rime->session_id) { // service disabled FcitxRimeUpdateStatus(rime); return IRV_TO_PROCESS; } boolean result = rime->api->process_key(rime->session_id, sym, state); RIME_STRUCT(RimeCommit, commit); if (rime->api->get_commit(rime->session_id, &commit)) { FcitxInputContext* ic = FcitxInstanceGetCurrentIC(rime->owner); FcitxInstanceCommitString(rime->owner, ic, commit.text); rime->api->free_commit(&commit); } FcitxRimeUpdateStatus(rime); if (!result) { FcitxRimeGetCandWords(rime); FcitxUIUpdateInputWindow(rime->owner); return IRV_TO_PROCESS; } else return IRV_DISPLAY_CANDWORDS; }
static jboolean get_status(JNIEnv *env, jobject thiz, jint session_id) { RIME_STRUCT(RimeStatus, status); Bool r = RimeGetStatus(session_id, &status); if (r) { jclass jc = env->GetObjectClass(thiz); jfieldID fid = env->GetFieldID(jc, "schema_id", "Ljava/lang/String;"); env->SetObjectField(thiz, fid, newJstring(env, status.schema_id)); fid = env->GetFieldID(jc, "schema_name", "Ljava/lang/String;"); env->SetObjectField(thiz, fid, newJstring(env, status.schema_name)); fid = env->GetFieldID(jc, "is_disabled", "Z"); env->SetBooleanField(thiz, fid, status.is_disabled); fid = env->GetFieldID(jc, "is_composing", "Z"); env->SetBooleanField(thiz, fid, status.is_composing); fid = env->GetFieldID(jc, "is_ascii_mode", "Z"); env->SetBooleanField(thiz, fid, status.is_ascii_mode); fid = env->GetFieldID(jc, "is_full_shape", "Z"); env->SetBooleanField(thiz, fid, status.is_full_shape); fid = env->GetFieldID(jc, "is_simplified", "Z"); env->SetBooleanField(thiz, fid, status.is_simplified); fid = env->GetFieldID(jc, "is_traditional", "Z"); env->SetBooleanField(thiz, fid, status.is_traditional); fid = env->GetFieldID(jc, "is_ascii_punct", "Z"); env->SetBooleanField(thiz, fid, status.is_ascii_punct); RimeFreeStatus(&status); } return r; }
void RimeWithWeaselHandler::_GetContext(weasel::Context & weasel_context, UINT session_id) { RIME_STRUCT(RimeContext, ctx); if (RimeGetContext(session_id, &ctx)) { if (ctx.composition.length > 0) { weasel_context.preedit.str = utf8towcs(ctx.composition.preedit); if (ctx.composition.sel_start < ctx.composition.sel_end) { weasel::TextAttribute attr; attr.type = weasel::HIGHLIGHTED; attr.range.start = utf8towcslen(ctx.composition.preedit, ctx.composition.sel_start); attr.range.end = utf8towcslen(ctx.composition.preedit, ctx.composition.sel_end); weasel_context.preedit.attributes.push_back(attr); } } if (ctx.menu.num_candidates) { weasel::CandidateInfo &cinfo(weasel_context.cinfo); _GetCandidateInfo(cinfo, ctx); } RimeFreeContext(&ctx); } }
INPUT_RETURN_VALUE FcitxRimeGetCandWord(void* arg, FcitxCandidateWord* candWord) { FcitxRime *rime = (FcitxRime *)arg; RIME_STRUCT(RimeContext, context); INPUT_RETURN_VALUE retVal = IRV_TO_PROCESS; if (rime->api->get_context(rime->session_id, &context)) { if (context.menu.num_candidates) { int i = *(int*) candWord->priv; const char* digit = DIGIT_STR_CHOOSE; int num_select_keys = context.menu.select_keys ? strlen(context.menu.select_keys) : 0; FcitxKeySym sym = FcitxKey_None; if (i < 10) { if (i < num_select_keys) sym = context.menu.select_keys[i]; else sym = digit[i]; } if (sym != FcitxKey_None) { boolean result = rime->api->process_key(rime->session_id, sym, 0); RIME_STRUCT(RimeCommit, commit); if (rime->api->get_commit(rime->session_id, &commit)) { FcitxInputContext* ic = FcitxInstanceGetCurrentIC(rime->owner); FcitxInstanceCommitString(rime->owner, ic, commit.text); rime->api->free_commit(&commit); } if (!result) { FcitxRimeGetCandWords(rime); FcitxUIUpdateInputWindow(rime->owner); retVal = IRV_TO_PROCESS; } else retVal = IRV_DISPLAY_CANDWORDS; } } rime->api->free_context(&context); } return retVal; }
static void start(JNIEnv *env, jobject thiz, jstring shared_data_dir, jstring user_data_dir) { RIME_STRUCT(RimeTraits, traits); const char* str1 = shared_data_dir == NULL ? NULL : env->GetStringUTFChars(shared_data_dir, NULL); const char* str2 = user_data_dir == NULL ? NULL : env->GetStringUTFChars(user_data_dir, NULL); if (str1 != NULL) traits.shared_data_dir = str1; if (str2 != NULL) traits.user_data_dir = str2; traits.app_name = "rime.jni"; ALOGE("setup...\n"); RimeInitialize(&traits); env->ReleaseStringUTFChars(shared_data_dir, str1); env->ReleaseStringUTFChars(user_data_dir, str2); }
// output static jboolean get_commit(JNIEnv *env, jobject thiz, jint session_id) { RIME_STRUCT(RimeCommit, commit); Bool r = RimeGetCommit((RimeSessionId)session_id, &commit); jclass jc = env->GetObjectClass(thiz); jfieldID fid = env->GetFieldID(jc, "commit_text", "Ljava/lang/String;"); jstring s = NULL; if (r) { s = newJstring(env, commit.text); RimeFreeCommit(&commit); } env->SetObjectField(thiz, fid, s); return r; }
void RimeWithWeaselHandler::_Setup() { RIME_STRUCT(RimeTraits, weasel_traits); weasel_traits.shared_data_dir = weasel_shared_data_dir(); weasel_traits.user_data_dir = weasel_user_data_dir(); const int len = 20; char utf8_str[len]; memset(utf8_str, 0, sizeof(utf8_str)); WideCharToMultiByte(CP_UTF8, 0, WEASEL_IME_NAME, -1, utf8_str, len - 1, NULL, NULL); weasel_traits.distribution_name = utf8_str; weasel_traits.distribution_code_name = WEASEL_CODE_NAME; weasel_traits.distribution_version = WEASEL_VERSION; weasel_traits.app_name = "rime.weasel"; RimeSetup(&weasel_traits); RimeSetNotificationHandler(&RimeWithWeaselHandler::OnNotify, this); }
static jboolean get_context(JNIEnv *env, jobject thiz, jint session_id) { RIME_STRUCT(RimeContext, context); Bool r = RimeGetContext(session_id, &context); if (r) { jclass jc = env->GetObjectClass(thiz); jfieldID fid; fid = env->GetFieldID(jc, "commit_text_preview", "Ljava/lang/String;"); env->SetObjectField(thiz, fid, newJstring(env, context.commit_text_preview)); fid = env->GetFieldID(jc, "menu_num_candidates", "I"); env->SetIntField(thiz, fid, context.menu.num_candidates); fid = env->GetFieldID(jc, "menu_page_size", "I"); env->SetIntField(thiz, fid, context.menu.page_size); fid = env->GetFieldID(jc, "menu_page_no", "I"); env->SetIntField(thiz, fid, context.menu.page_no); fid = env->GetFieldID(jc, "menu_highlighted_candidate_index", "I"); env->SetIntField(thiz, fid, context.menu.highlighted_candidate_index); fid = env->GetFieldID(jc, "menu_is_last_page", "Z"); env->SetBooleanField(thiz, fid, context.menu.is_last_page); fid = env->GetFieldID(jc, "menu_select_keys", "Ljava/lang/String;"); env->SetObjectField(thiz, fid, newJstring(env, context.menu.select_keys)); fid = env->GetFieldID(jc, "composition_length", "I"); env->SetIntField(thiz, fid, context.composition.length); fid = env->GetFieldID(jc, "composition_cursor_pos", "I"); env->SetIntField(thiz, fid, context.composition.cursor_pos); fid = env->GetFieldID(jc, "composition_sel_start", "I"); env->SetIntField(thiz, fid, context.composition.sel_start); fid = env->GetFieldID(jc, "composition_sel_end", "I"); env->SetIntField(thiz, fid, context.composition.sel_end); fid = env->GetFieldID(jc, "composition_preedit", "Ljava/lang/String;"); env->SetObjectField(thiz, fid, newJstring(env, context.composition.preedit)); int n = context.menu.num_candidates; fid = env->GetFieldID(jc, "candidates_text", "[Ljava/lang/String;"); jobjectArray texts = (jobjectArray) env->GetObjectField(thiz, fid); fid = env->GetFieldID(jc, "candidates_comment", "[Ljava/lang/String;"); jobjectArray comments = (jobjectArray) env->GetObjectField(thiz, fid); for (int i = 0; i < n; ++i) { env->SetObjectArrayElement(texts, i, newJstring(env, context.menu.candidates[i].text)); env->SetObjectArrayElement(comments, i, newJstring(env, context.menu.candidates[i].comment)); } RimeFreeContext(&context); } return r; }
void Configurator::Initialize() { RIME_STRUCT(RimeTraits, weasel_traits); weasel_traits.shared_data_dir = weasel_shared_data_dir(); weasel_traits.user_data_dir = weasel_user_data_dir(); const int len = 20; char utf8_str[len]; memset(utf8_str, 0, sizeof(utf8_str)); WideCharToMultiByte(CP_UTF8, 0, WEASEL_IME_NAME, -1, utf8_str, len - 1, NULL, NULL); weasel_traits.distribution_name = utf8_str; weasel_traits.distribution_code_name = WEASEL_CODE_NAME; weasel_traits.distribution_version = WEASEL_VERSION; weasel_traits.app_name = "rime.weasel"; RimeSetup(&weasel_traits); LOG(INFO) << "WeaselDeployer reporting."; RimeDeployerInitialize(NULL); }
void RimeWithWeaselHandler::_GetStatus(weasel::Status & stat, UINT session_id) { RIME_STRUCT(RimeStatus, status); if (RimeGetStatus(session_id, &status)) { std::string schema_id = status.schema_id; if (schema_id != m_last_schema_id) { m_last_schema_id = schema_id; RimeSetOption(session_id, "__synced", false); // Sync new schema options with front end _LoadSchemaSpecificSettings(schema_id); } stat.schema_name = utf8towcs(status.schema_name); stat.ascii_mode = !!status.is_ascii_mode; stat.composing = !!status.is_composing; stat.disabled = !!status.is_disabled; RimeFreeStatus(&status); } }
INPUT_RETURN_VALUE FcitxRimeGetCandWords(void* arg) { FcitxRime *rime = (FcitxRime *)arg; FcitxInputState *input = FcitxInstanceGetInputState(rime->owner); FcitxInstanceCleanInputWindow(rime->owner); RIME_STRUCT(RimeContext, context); if (!rime->api->get_context(rime->session_id, &context)) { return IRV_DISPLAY_CANDWORDS; } if (context.composition.length == 0) { rime->api->free_context(&context); return IRV_DISPLAY_CANDWORDS; } FcitxMessages* msgPreedit = FcitxInputStateGetPreedit(input); FcitxMessages* msgClientPreedit = FcitxInputStateGetClientPreedit(input); FcitxInputStateSetShowCursor(input, true); FcitxInputStateSetCursorPos(input, context.composition.cursor_pos); if (context.commit_text_preview) { FcitxInputStateSetClientCursorPos(input, strlen(context.commit_text_preview)); } /* converted text */ if (context.composition.sel_start > 0) { char* temp = strndup(context.composition.preedit, context.composition.sel_start); FcitxMessagesAddMessageAtLast(msgPreedit, MSG_OTHER, "%s", temp); free(temp); if (context.commit_text_preview) { temp = strndup(context.commit_text_preview, context.composition.sel_start); FcitxMessagesAddMessageAtLast(msgClientPreedit, MSG_INPUT, "%s", temp); free(temp); } } /* converting candidate */ if (context.composition.sel_start < context.composition.sel_end) { char* temp = strndup(&context.composition.preedit[context.composition.sel_start], context.composition.sel_end - context.composition.sel_start); FcitxMessagesAddMessageAtLast(msgPreedit, MSG_HIGHLIGHT | MSG_CODE, "%s", temp); free(temp); if (context.commit_text_preview) { FcitxMessagesAddMessageAtLast(msgClientPreedit, MSG_HIGHLIGHT, "%s", &context.commit_text_preview[context.composition.sel_start]); } } /* remaining input to convert */ if (context.composition.sel_end < strlen(context.composition.preedit)) { FcitxMessagesAddMessageAtLast(msgPreedit, MSG_CODE, "%s", &context.composition.preedit[context.composition.sel_end]); } if (context.menu.num_candidates) { FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input); const char* digit = DIGIT_STR_CHOOSE; char strChoose[11]; strChoose[10] = '\0'; FcitxCandidateWordSetPageSize(candList, 10); int num_select_keys = context.menu.select_keys ? strlen(context.menu.select_keys) : 0; int i; for (i = 0; i < context.menu.num_candidates; ++i) { FcitxCandidateWord candWord; candWord.strWord = strdup (context.menu.candidates[i].text); if (i == context.menu.highlighted_candidate_index) candWord.wordType = MSG_CANDIATE_CURSOR; else candWord.wordType = MSG_OTHER; candWord.strExtra = context.menu.candidates[i].comment ? strdup (context.menu.candidates[i].comment) : NULL; candWord.extraType = MSG_CODE; candWord.callback = FcitxRimeGetCandWord; candWord.owner = rime; int* priv = fcitx_utils_new(int); *priv = i; candWord.priv = priv; FcitxCandidateWordAppend(candList, &candWord); if (i < 10) { if (i < num_select_keys) { strChoose[i] = context.menu.select_keys[i]; } else { strChoose[i] = digit[i]; } } } FcitxCandidateWordSetChoose(candList, strChoose); FcitxCandidateWordSetOverridePaging(candList, context.menu.page_no != 0, !context.menu.is_last_page, FcitxRimePaging, rime, NULL); }
bool RimeWithWeaselHandler::_Respond(UINT session_id, EatLine eat) { std::set<std::string> actions; std::list<std::string> messages; // extract information RIME_STRUCT(RimeCommit, commit); if (RimeGetCommit(session_id, &commit)) { actions.insert("commit"); messages.push_back(std::string("commit=") + commit.text + '\n'); RimeFreeCommit(&commit); } bool is_composing = false; RIME_STRUCT(RimeStatus, status); if (RimeGetStatus(session_id, &status)) { is_composing = !!status.is_composing; actions.insert("status"); messages.push_back(std::string("status.ascii_mode=") + std::to_string(status.is_ascii_mode) + '\n'); messages.push_back(std::string("status.composing=") + std::to_string(status.is_composing) + '\n'); messages.push_back(std::string("status.disabled=") + std::to_string(status.is_disabled) + '\n'); RimeFreeStatus(&status); } RIME_STRUCT(RimeContext, ctx); if (RimeGetContext(session_id, &ctx)) { if (is_composing) { actions.insert("ctx"); switch (m_ui->style().preedit_type) { case weasel::UIStyle::PREVIEW: if (ctx.commit_text_preview != NULL) { std::string first = ctx.commit_text_preview; messages.push_back(std::string("ctx.preedit=") + first + '\n'); messages.push_back(std::string("ctx.preedit.cursor=") + std::to_string(utf8towcslen(first.c_str(), 0)) + ',' + std::to_string(utf8towcslen(first.c_str(), first.size())) + '\n'); break; } // no preview, fall back to composition case weasel::UIStyle::COMPOSITION: messages.push_back(std::string("ctx.preedit=") + ctx.composition.preedit + '\n'); if (ctx.composition.sel_start <= ctx.composition.sel_end) { messages.push_back(std::string("ctx.preedit.cursor=") + std::to_string(utf8towcslen(ctx.composition.preedit, ctx.composition.sel_start)) + ',' + std::to_string(utf8towcslen(ctx.composition.preedit, ctx.composition.sel_end)) + '\n'); } break; } } if (ctx.menu.num_candidates) { weasel::CandidateInfo cinfo; std::wstringstream ss; boost::archive::text_woarchive oa(ss); _GetCandidateInfo(cinfo, ctx); oa << cinfo; messages.push_back(std::string("ctx.cand=") + wcstoutf8(ss.str().c_str()) + '\n'); } RimeFreeContext(&ctx); } // configuration information actions.insert("config"); messages.push_back(std::string("config.inline_preedit=") + std::to_string((int)m_ui->style().inline_preedit) + '\n'); // style bool has_synced = RimeGetOption(session_id, "__synced"); if (!has_synced) { std::wstringstream ss; boost::archive::text_woarchive oa(ss); oa << m_ui->style(); actions.insert("style"); messages.push_back(std::string("style=") + wcstoutf8(ss.str().c_str()) + '\n'); RimeSetOption(session_id, "__synced", true); } // summarize if (actions.empty()) { messages.insert(messages.begin(), std::string("action=noop\n")); } else { std::string actionList(join(actions, ",")); messages.insert(messages.begin(), std::string("action=") + actionList + '\n'); } messages.push_back(std::string(".\n")); return std::all_of(messages.begin(), messages.end(), [&eat](std::string &msg) { return eat(std::wstring(utf8towcs(msg.c_str()))); }); }