void FcitxUnikeyCommit(FcitxUnikey* unikey)
{
    if (unikey->preeditstr->length() > 0) {
        FcitxInstanceCommitString(unikey->owner, FcitxInstanceGetCurrentIC(unikey->owner), unikey->preeditstr->c_str());
    }
    FcitxUnikeyReset(unikey);
}
Beispiel #2
0
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;
}
Beispiel #3
0
void FcitxKkcOnClose(void* arg, FcitxIMCloseEventType event)
{
    FcitxKkc *kkc = (FcitxKkc*)arg;
    if (event == CET_LostFocus) {
        // TODO
    } else if (event == CET_ChangeByUser) {
        kkc_context_reset(kkc->context);
    } else if (event == CET_ChangeByInactivate) {
        KkcSegmentList* segments = kkc_context_get_segments(kkc->context);
        FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(kkc->owner);
        if (config->bSendTextWhenSwitchEng) {
            FcitxMessagesSetMessageCount(kkc->tempMsg, 0);
            if (kkc_segment_list_get_cursor_pos(segments) >= 0) {
                int i = 0;
                for (i = 0; i < kkc_segment_list_get_size(segments); i ++) {
                    KkcSegment* segment = kkc_segment_list_get(segments, i);
                    const gchar* str = kkc_segment_get_output(segment);
                    FcitxMessagesAddMessageAtLast(kkc->tempMsg, MSG_INPUT, "%s", str);
                }
            } else {
                gchar* str = kkc_context_get_input(kkc->context);
                FcitxMessagesAddMessageAtLast(kkc->tempMsg, MSG_INPUT, "%s", str);
                g_free(str);
            }
            if (FcitxMessagesGetMessageCount(kkc->tempMsg) > 0) {
                char* commit = FcitxUIMessagesToCString(kkc->tempMsg);
                FcitxInstanceCommitString(kkc->owner, FcitxInstanceGetCurrentIC(kkc->owner), commit);
                free(commit);
            }
        }
        kkc_context_reset(kkc->context);
    }
}
Beispiel #4
0
static void
AutoEngCommit(FcitxAutoEngState *autoEngState)
{
    FcitxInstance *instance = autoEngState->owner;
    FcitxInputContext *currentIC = FcitxInstanceGetCurrentIC(instance);
    FcitxInstanceCommitString(instance, currentIC, autoEngState->buf);
    AutoEngSetBuffLen(autoEngState, 0);
}
Beispiel #5
0
static void CommitFirstCandidate(FcitxTablet* tablet) {
	char s[5]; // five chars should be plenty to hold a utf-8 char
	char* candidates = tablet->engineInstance->GetCandidates(tablet->engineData);
	int l = mblen(candidates, 10);
	memcpy(s, candidates, l);
	s[l] = '\0';
	FcitxInstanceCommitString(tablet->fcitx, FcitxInstanceGetCurrentIC(tablet->fcitx), s);
}
Beispiel #6
0
static INPUT_RETURN_VALUE
ClipboardCommitCallback(void *arg, FcitxCandidateWord *cand_word)
{
    FcitxClipboard *clipboard = arg;
    FcitxInstance *instance = clipboard->owner;
    FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance),
                              cand_word->priv);
    return IRV_FLAG_RESET_INPUT | IRV_FLAG_UPDATE_INPUT_WINDOW;
}
Beispiel #7
0
static INPUT_RETURN_VALUE
AutoEngPushKey(FcitxAutoEngState *autoEngState, char key)
{
    INPUT_RETURN_VALUE res = IRV_DISPLAY_MESSAGE;

    if (autoEngState->auto_space) {
        if (AutoEngCheckAutoSpace(autoEngState, key)) {
            return res;
        }
    }

    if (autoEngState->config.maxKeep == 0) {
        if (key == ' ') {
            FcitxInstance *instance = autoEngState->owner;
            FcitxInputContext *currentIC = FcitxInstanceGetCurrentIC(instance);
            FcitxInstanceCommitString(instance, currentIC, autoEngState->buf);
            FcitxInstanceCommitString(instance, currentIC, " ");
            ResetAutoEng(autoEngState);
            return res | IRV_CLEAN;
        }
    } else if (autoEngState->config.maxKeep > 0) {
        char *found = autoEngState->buf + autoEngState->index;
        int i = autoEngState->config.maxKeep;
        do {
            found = memrchr(autoEngState->buf, ' ', found - autoEngState->buf);
            if (!found) {
                break;
            }
        } while (--i > 0);
        if (found && found != autoEngState->buf) {
            FcitxInstance *instance = autoEngState->owner;
            FcitxInputContext *currentIC = FcitxInstanceGetCurrentIC(instance);
            *found = '\0';
            FcitxInstanceCommitString(instance, currentIC, autoEngState->buf);
            autoEngState->index = (autoEngState->buf + autoEngState->index
                                   - found);
            memmove(autoEngState->buf + 1, found + 1, autoEngState->index);
            *autoEngState->buf = ' ';
        }
    }
    autoEngState->buf[autoEngState->index++] = key;
    AutoEngSetBuffLen(autoEngState, autoEngState->index);
    return res;
}
Beispiel #8
0
FCITX_EXPORT_API
void FcitxUICommitPreedit(FcitxInstance* instance)
{
    if (instance->CurrentIC
        && !instance->config->bDontCommitPreeditWhenUnfocus
        && !(instance->CurrentIC->contextCaps & CAPACITY_CLIENT_UNFOCUS_COMMIT)) {
        FcitxInputState* input = FcitxInstanceGetInputState(instance);
        FcitxMessages* clientPreedit = FcitxInputStateGetClientPreedit(input);

        if (FcitxMessagesGetMessageCount(clientPreedit) > 0) {
            char* str = FcitxUIMessagesToCStringForCommit(clientPreedit);
            if (str[0]) {
                FcitxInstanceCommitString(instance, instance->CurrentIC, str);
            }
            free(str);
        }
        FcitxMessagesSetMessageCount(clientPreedit, 0);
    }
}
Beispiel #9
0
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;
}
Beispiel #10
0
FCITX_EXPORT_API
void FcitxUICommitPreedit(FcitxInstance* instance)
{
    if (!instance->CurrentIC)
        return;

    boolean callOnClose = false;
    boolean doServerSideCommit = false;
    if (!instance->config->bDontCommitPreeditWhenUnfocus
        && !(instance->CurrentIC->contextCaps & CAPACITY_CLIENT_UNFOCUS_COMMIT)) {
        callOnClose = true;
        doServerSideCommit = true;
    }

    if (instance->CurrentIC->contextCaps & CAPACITY_CLIENT_UNFOCUS_COMMIT) {
        callOnClose = true;
    }

    if (callOnClose) {
        FcitxIM* im = FcitxInstanceGetCurrentIM(instance);
        if (im && im->OnClose) {
            im->OnClose(im->klass, CET_LostFocus);
        }
    }

    if (doServerSideCommit) {
        FcitxInputState* input = FcitxInstanceGetInputState(instance);
        FcitxMessages* clientPreedit = FcitxInputStateGetClientPreedit(input);

        if (FcitxMessagesGetMessageCount(clientPreedit) > 0) {
            char* str = FcitxUIMessagesToCStringForCommit(clientPreedit);
            if (str[0]) {
                FcitxInstanceCommitString(instance, instance->CurrentIC, str);
            }
            free(str);
        }
        FcitxMessagesSetMessageCount(clientPreedit, 0);
    }

}
Beispiel #11
0
/**
 * @brief Process Key Input and return the status
 *
 * @param keycode keycode from XKeyEvent
 * @param state state from XKeyEvent
 * @param count count from XKeyEvent
 * @return INPUT_RETURN_VALUE
 **/
__EXPORT_API
INPUT_RETURN_VALUE FcitxChewingDoInput(void* arg, FcitxKeySym sym, unsigned int state)
{
    FcitxChewing* chewing = (FcitxChewing*) arg;
    FcitxInputState *input = FcitxInstanceGetInputState(chewing->owner);
    ChewingContext * ctx = chewing->context;
    int zuin_len;
    FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);

    if (FcitxCandidateWordGetListSize(candList) > 0) {
        if (FcitxHotkeyIsHotKeyDigit(sym, state) || FcitxHotkeyIsHotKey(sym, state, FCITX_RIGHT) || FcitxHotkeyIsHotKey(sym, state, FCITX_LEFT))
            return IRV_TO_PROCESS;
        if (FcitxHotkeyIsHotKey(sym, state, FCITX_SPACE)) {
            if (FcitxCandidateWordGoNextPage(candList))
                return IRV_DISPLAY_MESSAGE;
            else
                return IRV_DO_NOTHING;
        }
    }

    if (FcitxHotkeyIsHotKeySimple(sym, state)) {
        int scan_code = (int) sym & 0xff;
        chewing_handle_Default(ctx, scan_code);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_BACKSPACE)) {
        char * zuin_str = chewing_zuin_String(ctx, &zuin_len);
        chewing_free(zuin_str);
        if (chewing_buffer_Len(ctx) + zuin_len == 0)
            return IRV_TO_PROCESS;
        chewing_handle_Backspace(ctx);
        if (chewing_buffer_Len(ctx) + zuin_len == 0)
            return IRV_CLEAN;
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_ESCAPE)) {
        chewing_handle_Esc(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_DELETE)) {
        char * zuin_str = chewing_zuin_String(ctx, &zuin_len);
        chewing_free(zuin_str);
        if (chewing_buffer_Len(ctx) + zuin_len == 0)
            return IRV_TO_PROCESS;
        chewing_handle_Del(ctx);
        if (chewing_buffer_Len(ctx) + zuin_len == 0)
            return IRV_CLEAN;
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_SPACE)) {
        chewing_handle_Space(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_CHEWING_UP)) {
        chewing_handle_Up(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_CHEWING_DOWN)) {
        chewing_handle_Down(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_CHEWING_PGUP)) {
        chewing_handle_PageDown(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_CHEWING_PGDN)) {
        chewing_handle_PageUp(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_RIGHT)) {
        chewing_handle_Right(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_LEFT)) {
        chewing_handle_Left(ctx);
    } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_ENTER)) {
        chewing_handle_Enter(ctx);
    } else if (state == FcitxKeyState_Ctrl && FcitxHotkeyIsHotKeyDigit(sym, FcitxKeyState_None)) {
        chewing_handle_CtrlNum(ctx, sym);
    } else {
        // to do: more chewing_handle
        return IRV_TO_PROCESS;
    }
    if (chewing_keystroke_CheckAbsorb(ctx)) {
        return IRV_DISPLAY_CANDWORDS;
    } else if (chewing_keystroke_CheckIgnore(ctx)) {
        return IRV_TO_PROCESS;
    } else if (chewing_commit_Check(ctx)) {
        char* str = chewing_commit_String(ctx);
        FcitxInputContext* ic = FcitxInstanceGetCurrentIC(chewing->owner);
        FcitxInstanceCommitString(chewing->owner, ic, str);
        chewing_free(str);
        return IRV_DISPLAY_CANDWORDS;
    } else
        return IRV_DISPLAY_CANDWORDS;
}
Beispiel #12
0
INPUT_RETURN_VALUE FcitxKkcGetCandWords(void* arg)
{
    FcitxKkc *kkc = (FcitxKkc*)arg;
    FcitxInputState* input = FcitxInstanceGetInputState(kkc->owner);
    FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
    FcitxMessages* clientPreedit = FcitxInputStateGetClientPreedit(input);
    FcitxMessages* preedit = FcitxInputStateGetPreedit(input);
    FcitxInstanceCleanInputWindow(kkc->owner);

    FcitxMessages* message = FcitxInstanceICSupportPreedit(kkc->owner, FcitxInstanceGetCurrentIC(kkc->owner)) ? clientPreedit : preedit;

    FcitxCandidateWordSetChoose(candList, DIGIT_STR_CHOOSE);
    FcitxCandidateWordSetPageSize(candList, kkc->config.pageSize);
    FcitxCandidateWordSetLayoutHint(candList, kkc->config.candidateLayout);
    FcitxInputStateSetShowCursor(input, true);

    KkcSegmentList* segments = kkc_context_get_segments(kkc->context);
    if (kkc_segment_list_get_cursor_pos(segments) >= 0) {
        int i = 0;
        int offset = 0;
        for (i = 0; i < kkc_segment_list_get_size(segments); i ++) {
            KkcSegment* segment = kkc_segment_list_get(segments, i);
            const gchar* str = kkc_segment_get_output(segment);
            FcitxMessageType messageType = MSG_INPUT;
            if (i < kkc_segment_list_get_cursor_pos(segments)) {
                offset += strlen(str);
            }
            if (i == kkc_segment_list_get_cursor_pos(segments)) {
                messageType = (FcitxMessageType) (MSG_HIGHLIGHT | MSG_OTHER);
            }
            FcitxMessagesAddMessageAtLast(message, messageType, "%s", str);
        }

        if (message == clientPreedit) {
            FcitxInputStateSetClientCursorPos(input, offset);
        } else {
            FcitxInputStateSetCursorPos(input, offset);
        }
    } else {
        gchar* str = kkc_context_get_input(kkc->context);
        if (str && str[0]) {
            FcitxMessagesAddMessageAtLast(message, MSG_INPUT, "%s", str);

            if (message == clientPreedit) {
                FcitxInputStateSetClientCursorPos(input, strlen(str));
            } else {
                FcitxInputStateSetCursorPos(input, strlen(str));
            }
        }
        g_free(str);
    }

    KkcCandidateList* kkcCandidates = kkc_context_get_candidates(kkc->context);
    if (kkc_candidate_list_get_page_visible(kkcCandidates)) {
        int i, j;
        guint size = kkc_candidate_list_get_size(kkcCandidates);
        gint cursor_pos = kkc_candidate_list_get_cursor_pos(kkcCandidates);
        guint page_start = kkc_candidate_list_get_page_start(kkcCandidates);
        guint page_size = kkc_candidate_list_get_page_size(kkcCandidates);
        for (i = kkc_candidate_list_get_page_start(kkcCandidates), j = 0; i < size; i ++, j++) {
            FcitxCandidateWord word;
            word.callback = FcitxKkcGetCandWord;
            word.extraType = MSG_OTHER;
            word.owner = kkc;
            int* id = fcitx_utils_new(int);
            *id = j;
            word.priv = id;
            word.strExtra = NULL;
            word.strExtra = MSG_TIPS;
            KkcCandidate* kkcCandidate = kkc_candidate_list_get(kkcCandidates, i);
            if (kkc->config.showAnnotation && kkc_candidate_get_annotation(kkcCandidate)) {
                fcitx_utils_alloc_cat_str(word.strExtra, " [", kkc_candidate_get_annotation(kkcCandidate), "]");
            }
            word.strWord = strdup(kkc_candidate_get_text(kkcCandidate));
            if (i == cursor_pos) {
                word.wordType = MSG_CANDIATE_CURSOR;
            } else {
                word.wordType = MSG_OTHER;
            }

            FcitxCandidateWordAppend(candList, &word);
        }
        FcitxCandidateWordSetFocus(candList, cursor_pos - page_start);

        FcitxCandidateWordSetOverridePaging(candList,
                                            (cursor_pos - page_start) >= page_size,
                                            (size - page_start) / page_size != (cursor_pos - page_start) / page_size,
                                            FcitxKkcPaging,
                                            kkc,
                                            NULL);
    }

    if (kkc_context_has_output(kkc->context)) {
        gchar* str = kkc_context_poll_output(kkc->context);
        FcitxInstanceCommitString(kkc->owner, FcitxInstanceGetCurrentIC(kkc->owner), str);
        g_free(str);
    }

    return IRV_DISPLAY_CANDWORDS;
}
Beispiel #13
0
Datei: vk.c Projekt: areslp/fcitx
/*
 * 处理相关鼠标键
 */
boolean VKMouseKey(FcitxVKState* vkstate, int x, int y)
{
    int             iIndex = 0;
    char            strKey[3] = { 0, 0, 0};
    char           *pstr = NULL;
    FcitxInstance* instance = vkstate->owner;

    if (FcitxUIIsInBox(x, y, 1, 1, VK_WINDOW_WIDTH, 16))
        ChangVK(vkstate);
    else {
        if (FcitxInstanceGetCurrentIC(instance) == NULL)
            return false;

        strKey[1] = '\0';
        pstr = strKey;
        if (y >= 28 && y <= 55) {   //第一行
            if (x < 4 || x > 348)
                return false;

            x -= 4;
            if (x >= 313 && x <= 344) { //backspace
                FcitxInstanceForwardKey(instance, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, FcitxKey_BackSpace, 0);
                return true;
            } else {
                iIndex = x / 24;
                if (iIndex > 12)    //避免出现错误
                    iIndex = 12;
                pstr = vkstate->vks[vkstate->iCurrentVK].strSymbol[iIndex][vkstate->bShiftPressed ^ vkstate->bVKCaps];
                if (vkstate->bShiftPressed) {
                    vkstate->bShiftPressed = false;
                    DrawVKWindow(vkstate->vkWindow);
                }
            }
        } else if (y >= 56 && y <= 83) { //第二行
            if (x < 4 || x > 350)
                return false;

            if (x >= 4 && x < 38) { //Tab
                FcitxInstanceForwardKey(instance, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, FcitxKey_Tab, 0);
                return true;
            } else {
                iIndex = 13 + (x - 38) / 24;
                pstr = vkstate->vks[vkstate->iCurrentVK].strSymbol[iIndex][vkstate->bShiftPressed ^ vkstate->bVKCaps];
                if (vkstate->bShiftPressed) {
                    vkstate->bShiftPressed = false;
                    DrawVKWindow(vkstate->vkWindow);
                }
            }
        } else if (y >= 84 && y <= 111) { //第三行
            if (x < 4 || x > 350)
                return false;

            if (x >= 4 && x < 44) { //Caps
                //改变大写键状态
                vkstate->bVKCaps = !vkstate->bVKCaps;
                pstr = (char *) NULL;
                DrawVKWindow(vkstate->vkWindow);
            } else if (x > 308 && x <= 350) //Return
                strKey[0] = '\n';
            else {
                iIndex = 26 + (x - 44) / 24;
                pstr = vkstate->vks[vkstate->iCurrentVK].strSymbol[iIndex][vkstate->bShiftPressed ^ vkstate->bVKCaps];
                if (vkstate->bShiftPressed) {
                    vkstate->bShiftPressed = false;
                    DrawVKWindow(vkstate->vkWindow);
                }
            }
        } else if (y >= 112 && y <= 139) {  //第四行
            if (x < 4 || x > 302)
                return false;

            if (x >= 4 && x < 62) { //SHIFT
                //改变SHIFT键状态
                vkstate->bShiftPressed = !vkstate->bShiftPressed;
                pstr = (char *) NULL;
                DrawVKWindow(vkstate->vkWindow);
            } else {
                iIndex = 37 + (x - 62) / 24;
                pstr = vkstate->vks[vkstate->iCurrentVK].strSymbol[iIndex][vkstate->bShiftPressed ^ vkstate->bVKCaps];
                if (vkstate->bShiftPressed) {
                    vkstate->bShiftPressed = false;
                    DrawVKWindow(vkstate->vkWindow);
                }
            }
        } else if (y >= 140 && y <= 162) {  //第五行
            if (x >= 4 && x < 38) { //Ins
                //改变INS键状态
                FcitxInstanceForwardKey(instance, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, FcitxKey_Insert, 0);
                return true;
            } else if (x >= 61 && x < 98) { //DEL
                FcitxInstanceForwardKey(instance, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, FcitxKey_Delete, 0);
                return true;
            } else if (x >= 99 && x < 270)  //空格
                strcpy(strKey, " ");
            else if (x >= 312 && x <= 350) {    //ESC
                SwitchVK(vkstate);
                pstr = (char *) NULL;
            } else
                return false;
        }

        if (pstr) {
            FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), pstr);
        }
    }

    return true;
}
Beispiel #14
0
boolean ProcessPunc(void* arg, FcitxKeySym sym, unsigned int state, INPUT_RETURN_VALUE* retVal)
{
    FcitxPuncState* puncState = (FcitxPuncState*) arg;
    FcitxInstance* instance = puncState->owner;
    FcitxInputState* input = FcitxInstanceGetInputState(puncState->owner);
    FcitxProfile* profile = FcitxInstanceGetProfile(instance);
    FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance);

    char *pPunc = NULL;

    if (*retVal != IRV_TO_PROCESS)
        return false;

    FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
    if (FcitxCandidateWordPageCount(candList) != 0 && FcitxCandidateWordGetHasGoneToNextPage(candList) ) {
        const FcitxHotkey* hkPrevPage = FcitxInstanceGetContextHotkey(instance, CONTEXT_ALTERNATIVE_PREVPAGE_KEY);
        if (hkPrevPage == NULL)
            hkPrevPage = config->hkPrevPage;

        if (FcitxHotkeyIsHotKey(sym, state, hkPrevPage)) {
            return false;
        }
    }

    /*
     * comparing with upper case, if paging is occupied,
     * punc will not let next page pass
     */
    if (FcitxCandidateWordPageCount(candList) != 0) {
        const FcitxHotkey* hkNextPage = FcitxInstanceGetContextHotkey(instance, CONTEXT_ALTERNATIVE_NEXTPAGE_KEY);
        if (hkNextPage == NULL)
            hkNextPage = config->hkNextPage;

        if (FcitxHotkeyIsHotKey(sym, state, hkNextPage)) {
            return false;
        }
    }

    FcitxKeySym origsym = sym;
    sym = FcitxHotkeyPadToMain(sym);
    if (profile->bUseWidePunc) {

        if (puncState->bLastIsNumber && config->bEngPuncAfterNumber
                && (FcitxHotkeyIsHotKey(origsym, state, FCITX_PERIOD)
                    || FcitxHotkeyIsHotKey(origsym, state, FCITX_SEMICOLON)
                    || FcitxHotkeyIsHotKey(origsym, state, FCITX_COMMA))) {
            puncState->cLastIsAutoConvert = origsym;
            puncState->bLastIsNumber = false;
            *retVal = IRV_DONOT_PROCESS;
            return true;
        }
        if (FcitxHotkeyIsHotKeySimple(sym, state))
            pPunc = GetPunc(puncState, origsym);
    }

    /*
     * 在有候选词未输入的情况下,选择第一个候选词并输入标点
     */
    if (IsHotKeyPunc(sym, state)) {
        FcitxInputStateGetOutputString(input)[0] = '\0';
        INPUT_RETURN_VALUE ret = IRV_TO_PROCESS;
        if (!FcitxInputStateGetIsInRemind(input))
            ret = FcitxCandidateWordChooseByTotalIndex(FcitxInputStateGetCandidateList(input), 0);

        /* if there is nothing to commit */
        if (ret == IRV_TO_PROCESS) {
            if (pPunc) {
                strcat(FcitxInputStateGetOutputString(input), pPunc);
                *retVal = IRV_PUNC;
                FcitxInstanceCleanInputWindow(instance);
                return true;
            } else
                return false;
        } else {
            if (pPunc)
                strcat(FcitxInputStateGetOutputString(input), pPunc);
            else {
                char buf[2] = { sym, 0 };
                strcat(FcitxInputStateGetOutputString(input), buf);
            }

            FcitxInstanceCleanInputWindow(instance);
            *retVal = IRV_PUNC;
            return true;
        }

        return false;
    }

    if (profile->bUseWidePunc) {
        if (FcitxHotkeyIsHotKey(sym, state, FCITX_BACKSPACE)
                && puncState->cLastIsAutoConvert) {
            char *pPunc;

            FcitxInstanceForwardKey(puncState->owner, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, sym, state);
            pPunc = GetPunc(puncState, puncState->cLastIsAutoConvert);
            if (pPunc)
                FcitxInstanceCommitString(puncState->owner, FcitxInstanceGetCurrentIC(instance), pPunc);

            puncState->cLastIsAutoConvert = 0;
            *retVal = IRV_DO_NOTHING;
            return true;
        } else if (FcitxHotkeyIsHotKeySimple(sym, state)) {
            if (FcitxHotkeyIsHotKeyDigit(sym, state))
                puncState->bLastIsNumber = true;
            else {
                puncState->bLastIsNumber = false;
            }
        }
    }
    puncState->cLastIsAutoConvert = 0;
    return false;
}