void* FullWidthCharCreate(FcitxInstance* instance) { FcitxFullWidthChar* fwchar = fcitx_utils_malloc0(sizeof(FcitxFullWidthChar)); FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance); fwchar->owner = instance; FcitxStringFilterHook hk; hk.arg = fwchar; hk.func = ProcessFullWidthChar; FcitxInstanceRegisterCommitFilter(instance, hk); FcitxKeyFilterHook phk; phk.arg = fwchar; phk.func = FullWidthPostFilter; FcitxInstanceRegisterPostInputFilter(instance, phk); FcitxHotkeyHook hotkey; hotkey.hotkey = config->hkFullWidthChar; hotkey.hotkeyhandle = ToggleFullWidthStateWithHotkey; hotkey.arg = fwchar; FcitxInstanceRegisterHotkeyFilter(instance, hotkey); FcitxUIRegisterStatus(instance, fwchar, "fullwidth", _("Full Width Character"), _("Full Width Character"), ToggleFullWidthState, GetFullWidthState); return fwchar; }
void* ChttransCreate(FcitxInstance* instance) { FcitxChttrans* transState = fcitx_utils_malloc0(sizeof(FcitxChttrans)); FcitxAddon* transAddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_CHTTRANS_NAME); transState->owner = instance; if (!LoadChttransConfig(transState)) { free(transState); return NULL; } FcitxHotkeyHook hk; hk.arg = transState; hk.hotkey = transState->hkToggle; hk.hotkeyhandle = HotkeyToggleChttransState; FcitxStringFilterHook shk; shk.arg = transState; shk.func = ChttransOutputFilter; FcitxInstanceRegisterHotkeyFilter(instance, hk); FcitxInstanceRegisterOutputFilter(instance, shk); FcitxInstanceRegisterCommitFilter(instance, shk); FcitxUIRegisterStatus(instance, transState, "chttrans", transState->enabled ? _("Convert to Traditional Chinese") : _("Convert to Simplified Chinese"), _("Toggle Simp/Trad Chinese Conversion"), ToggleChttransState, GetChttransEnabled); FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE, ChttransLanguageChanged, transState); AddFunction(transAddon, ChttransS2T); AddFunction(transAddon, ChttransT2S); return transState; }
void* FullWidthCharCreate(FcitxInstance* instance) { FcitxFullWidthChar* fwchar = fcitx_utils_malloc0(sizeof(FcitxFullWidthChar)); FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance); fwchar->owner = instance; FcitxStringFilterHook hk; hk.arg = fwchar; hk.func = ProcessFullWidthChar; FcitxInstanceRegisterCommitFilter(instance, hk); FcitxKeyFilterHook phk; phk.arg = fwchar; phk.func = FullWidthPostFilter; FcitxInstanceRegisterPostInputFilter(instance, phk); FcitxHotkeyHook hotkey; hotkey.hotkey = config->hkFullWidthChar; hotkey.hotkeyhandle = ToggleFullWidthStateWithHotkey; hotkey.arg = fwchar; FcitxInstanceRegisterHotkeyFilter(instance, hotkey); FcitxProfile* profile = FcitxInstanceGetProfile(instance); FcitxUIRegisterStatus(instance, fwchar, "fullwidth", profile->bUseFullWidthChar ? _("Full width Character") : _("Half width Character"), _("Toggle Half/Full width Character"), ToggleFullWidthState, GetFullWidthState); FcitxInstanceRegisterWatchableContext(instance, CONTEXT_DISABLE_FULLWIDTH, FCT_Boolean, FCF_ResetOnInputMethodChange); FcitxInstanceWatchContext(instance, CONTEXT_DISABLE_FULLWIDTH, DisableFullWidthCharChanged, fwchar); return fwchar; }
void* PuncCreate(FcitxInstance* instance) { FcitxPuncState* puncState = fcitx_utils_malloc0(sizeof(FcitxPuncState)); FcitxAddon* puncaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_PUNC_NAME); puncState->owner = instance; LoadPuncDict(puncState); FcitxKeyFilterHook hk; hk.arg = puncState; hk.func = ProcessPunc; FcitxInstanceRegisterPostInputFilter(instance, hk); hk.func = PuncPreFilter; FcitxInstanceRegisterPreInputFilter(instance, hk); puncState->cLastIsAutoConvert = '\0'; puncState->bLastIsNumber = false; FcitxHotkeyHook hotkey; hotkey.hotkey = FcitxInstanceGetGlobalConfig(instance)->hkPunc; hotkey.hotkeyhandle = TogglePuncStateWithHotkey; hotkey.arg = puncState; FcitxInstanceRegisterHotkeyFilter(instance, hotkey); FcitxIMEventHook hook; hook.arg = puncState; hook.func = ResetPunc; FcitxInstanceRegisterResetInputHook(instance, hook); hook.func = ResetPuncWhichStatus; FcitxInstanceRegisterInputUnFocusHook(instance, hook); FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE, PuncLanguageChanged, puncState); FcitxProfile* profile = FcitxInstanceGetProfile(instance); FcitxUIRegisterStatus(instance, puncState, "punc", profile->bUseWidePunc ? _("Full width punct") : _("Latin punct"), _("Toggle Full Width Punctuation"), TogglePuncState, GetPuncState); puncState->slot = FcitxInstanceAllocDataForIC(instance, PuncWhichAlloc, PuncWhichCopy, PuncWhichFree, puncState); FcitxModuleAddFunction(puncaddon, PuncGetPunc); FcitxModuleAddFunction(puncaddon, PuncGetPunc2); return puncState; }
void *VKCreate(FcitxInstance* instance) { FcitxVKState *vkstate = fcitx_utils_malloc0(sizeof(FcitxVKState)); FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance); vkstate->owner = instance; FcitxHotkeyHook hotkey; hotkey.hotkey = config->hkVK; hotkey.hotkeyhandle = ToggleVKStateWithHotkey; hotkey.arg = vkstate; FcitxInstanceRegisterHotkeyFilter(instance, hotkey); FcitxUIRegisterStatus(instance, vkstate, "vk", _("Toggle Virtual Keyboard"), _("Virtual Keyboard State"), ToggleVKState, GetVKState); LoadVKMapFile(vkstate); FcitxKeyFilterHook hk; hk.arg = vkstate ; hk.func = VKPreFilter; FcitxInstanceRegisterPreInputFilter(instance, hk); FcitxIMEventHook resethk; resethk.arg = vkstate; resethk.func = VKReset; FcitxInstanceRegisterTriggerOnHook(instance, resethk); FcitxInstanceRegisterTriggerOffHook(instance, resethk); resethk.func = VKUpdate; FcitxInstanceRegisterInputFocusHook(instance, resethk); FcitxInstanceRegisterInputUnFocusHook(instance, resethk); FcitxMenuInit(&vkstate->vkmenu); vkstate->vkmenu.candStatusBind = strdup("vk"); vkstate->vkmenu.name = strdup(_("Virtual Keyboard")); vkstate->vkmenu.UpdateMenu = UpdateVKMenu; vkstate->vkmenu.MenuAction = VKMenuAction; vkstate->vkmenu.priv = vkstate; vkstate->vkmenu.isSubMenu = false; FcitxUIRegisterMenu(instance, &vkstate->vkmenu); return vkstate; }
void *ChttransCreate(FcitxInstance* instance) { FcitxChttrans *transState = fcitx_utils_new(FcitxChttrans); transState->owner = instance; transState->enableIM = fcitx_string_map_new(NULL, '\0'); if (!LoadChttransConfig(transState)) { fcitx_string_map_free(transState->enableIM); free(transState); return NULL; } FcitxHotkeyHook hk; hk.arg = transState; hk.hotkey = transState->hkToggle; hk.hotkeyhandle = HotkeyToggleChttransState; FcitxStringFilterHook shk; shk.arg = transState; shk.func = ChttransOutputFilter; FcitxIMEventHook imhk; imhk.arg = transState; imhk.func = ChttransIMChanged; FcitxInstanceRegisterHotkeyFilter(instance, hk); FcitxInstanceRegisterOutputFilter(instance, shk); FcitxInstanceRegisterCommitFilter(instance, shk); FcitxInstanceRegisterIMChangedHook(instance, imhk); FcitxUIRegisterStatus(instance, transState, "chttrans", ChttransEnabled(transState) ? _("Traditional Chinese") : _("Simplified Chinese"), _("Toggle Simp/Trad Chinese Conversion"), ToggleChttransState, GetChttransEnabled); FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE, ChttransLanguageChanged, transState); FcitxChttransAddFunctions(instance); return transState; }
FCITX_EXPORT_API FcitxInstance* FcitxInstanceCreateWithFD(sem_t *sem, int argc, char* argv[], int fd) { FcitxInstance* instance = fcitx_utils_malloc0(sizeof(FcitxInstance)); FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->modules); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uicompstats, &compstat_icd); utarray_init(&instance->uimenus, &menup_icd); utarray_init(&instance->timeout, &timeout_icd); utarray_init(&instance->icdata, &icdata_icd); instance->input = FcitxInputStateCreate(); instance->sem = sem; instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); instance->globalIMName = strdup(""); if (fd > 0) { fcntl(fd, F_SETFL, O_NONBLOCK); instance->fd = fd; } if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); if (!ProcessOption(instance, argc, argv)) goto error_exit; instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); FcitxInstanceFillAddonOwner(instance, NULL); FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (instance->loadingFatalError) return instance; if (!FcitxInstanceLoadAllIM(instance)) { FcitxInstanceEnd(instance); return instance; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", instance->profile->bUseRemind ? _("Use remind") : _("No remind"), _("Toggle Remind"), ToggleRemindState, GetRemindEnabled); FcitxUISetStatusVisable(instance, "remind", false); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); FcitxInstanceSwitchIMByIndex(instance, instance->iIMIndex); if (!FcitxInstanceLoadFrontend(instance)) { FcitxInstanceEnd(instance); return instance; } /* make in order to use block X, query is not good here */ pthread_create(&instance->pid, NULL, RunInstance, instance); return instance; error_exit: FcitxInstanceEnd(instance); return instance; }
void* RunInstance(void* arg) { FcitxInstance* instance = (FcitxInstance*) arg; FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxInstanceInitNoPreeditApps(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->modules); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uicompstats, &compstat_icd); utarray_init(&instance->uimenus, fcitx_ptr_icd); utarray_init(&instance->timeout, &timeout_icd); utarray_init(&instance->icdata, &icdata_icd); instance->input = FcitxInputStateCreate(); instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); instance->globalIMName = strdup(""); if (instance->fd >= 0) { fcntl(instance->fd, F_SETFL, O_NONBLOCK); } else { instance->fd = -1; } if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); int overrideDelay = instance->overrideDelay; if (overrideDelay < 0) overrideDelay = instance->config->iDelayStart; if (overrideDelay > 0) sleep(overrideDelay); instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); FcitxInstanceFillAddonOwner(instance, NULL); FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (instance->loadingFatalError) return NULL; if (!FcitxInstanceLoadAllIM(instance)) { goto error_exit; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", instance->profile->bUseRemind ? _("Use remind") : _("No remind"), _("Toggle Remind"), ToggleRemindState, GetRemindEnabled); FcitxUISetStatusVisable(instance, "remind", false); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); if (instance->iIMIndex < 0) { instance->iIMIndex = 0; } FcitxInstanceSwitchIMByIndex(instance, instance->iIMIndex); if (!FcitxInstanceLoadFrontend(instance)) { goto error_exit; } /* fcitx is running in a standalone thread or not */ if (instance->sem) { sem_post(&instance->notifySem); sem_wait(&instance->startUpSem); } else { instance->initialized = true; } uint64_t curtime = 0; while (1) { FcitxAddon** pmodule; uint8_t signo = 0; if (instance->fd >= 0) { while (read(instance->fd, &signo, sizeof(char)) > 0) { if (signo == SIGINT || signo == SIGTERM || signo == SIGQUIT || signo == SIGXCPU) FcitxInstanceEnd(instance); else if (signo == SIGHUP) FcitxInstanceRestart(instance); else if (signo == SIGUSR1) FcitxInstanceReloadConfig(instance); } } do { instance->eventflag &= (~FEF_PROCESS_EVENT_MASK); for (pmodule = (FcitxAddon**) utarray_front(&instance->eventmodules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->eventmodules, pmodule)) { FcitxModule* module = (*pmodule)->module; module->ProcessEvent((*pmodule)->addonInstance); } struct timeval current_time; gettimeofday(¤t_time, NULL); curtime = (current_time.tv_sec * 1000LL) + (current_time.tv_usec / 1000LL); unsigned int idx = 0; while(idx < utarray_len(&instance->timeout)) { TimeoutItem* ti = (TimeoutItem*) utarray_eltptr(&instance->timeout, idx); uint64_t id = ti->idx; if (ti->time + ti->milli <= curtime) { ti->callback(ti->arg); ti = (TimeoutItem*) utarray_eltptr(&instance->timeout, idx); /* faster remove */ if (ti && ti->idx == id) utarray_remove_quick(&instance->timeout, idx); else { FcitxInstanceRemoveTimeoutById(instance, id); idx = 0; } } else { idx++; } } if (instance->eventflag & FEF_UI_MOVE) FcitxUIMoveInputWindowReal(instance); if (instance->eventflag & FEF_UI_UPDATE) FcitxUIUpdateInputWindowReal(instance); } while ((instance->eventflag & FEF_PROCESS_EVENT_MASK) != FEF_NONE); setjmp(FcitxRecover); if (instance->destroy || instance->restart) { FcitxInstanceRealEnd(instance); break; } if (instance->eventflag & FEF_RELOAD_ADDON) { instance->eventflag &= ~(FEF_RELOAD_ADDON); FcitxInstanceReloadAddon(instance); } FD_ZERO(&instance->rfds); FD_ZERO(&instance->wfds); FD_ZERO(&instance->efds); instance->maxfd = 0; if (instance->fd > 0) { instance->maxfd = instance->fd; FD_SET(instance->fd, &instance->rfds); } for (pmodule = (FcitxAddon**) utarray_front(&instance->eventmodules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->eventmodules, pmodule)) { FcitxModule* module = (*pmodule)->module; module->SetFD((*pmodule)->addonInstance); } if (instance->maxfd == 0) break; struct timeval tval; struct timeval* ptval = NULL; if (utarray_len(&instance->timeout) != 0) { unsigned long int min_time = LONG_MAX; TimeoutItem* ti; for (ti = (TimeoutItem*)utarray_front(&instance->timeout);ti; ti = (TimeoutItem*)utarray_next(&instance->timeout, ti)) { if (ti->time + ti->milli - curtime < min_time) { min_time = ti->time + ti->milli - curtime; } } tval.tv_usec = (min_time % 1000) * 1000; tval.tv_sec = min_time / 1000; ptval = &tval; } select(instance->maxfd + 1, &instance->rfds, &instance->wfds, &instance->efds, ptval); } if (instance->restart) { fcitx_utils_restart_in_place(); } return NULL; error_exit: sem_post(&instance->startUpSem); FcitxInstanceEnd(instance); return NULL; }
FCITX_EXPORT_API FcitxInstance* FcitxInstanceCreate(sem_t *sem, int argc, char* argv[]) { FcitxInstance* instance = fcitx_utils_malloc0(sizeof(FcitxInstance)); FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uimenus, &menup_icd); instance->input = FcitxInputStateCreate(); instance->sem = sem; instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); if (!ProcessOption(instance, argc, argv)) goto error_exit; instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); /* FIXME: a walkaround for not have instance in function FcitxModuleInvokeFunction */ FcitxAddon* addon; for (addon = (FcitxAddon *) utarray_front(&instance->addons); addon != NULL; addon = (FcitxAddon *) utarray_next(&instance->addons, addon)) { addon->owner = instance; } FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (!FcitxInstanceLoadAllIM(instance)) { FcitxInstanceEnd(instance); return instance; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", _("Remind"), _("Remind"), ToggleRemindState, GetRemindEnabled); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); FcitxInstanceSwitchIM(instance, instance->iIMIndex); instance->lastIMIndex = instance->iIMIndex; if (!FcitxInstanceLoadFrontend(instance)) { FcitxInstanceEnd(instance); return instance; } if (instance->config->bFirstRun) { instance->config->bFirstRun = false; FcitxGlobalConfigSave(instance->config); const char *imname = "fcitx"; char *strTemp; asprintf(&strTemp, "@im=%s", imname); if ((getenv("XMODIFIERS") != NULL && CHECK_ENV("XMODIFIERS", strTemp, true)) || (CHECK_ENV("GTK_IM_MODULE", "xim", false) && CHECK_ENV("GTK_IM_MODULE", "fcitx", false)) || (CHECK_ENV("QT_IM_MODULE", "xim", false) && CHECK_ENV("QT_IM_MODULE", "fcitx", false))) { char *msg[12]; msg[0] = _("Please check your environment varibles."); msg[1] = _("You can use tools provided by your distribution."); msg[2] = _("Or You may need to set environment varibles below to make fcitx work correctly."); msg[3] = "export XMODIFIERS=\"@im=fcitx\""; msg[4] = "export QT_IM_MODULE=xim"; msg[5] = "export GTK_IM_MODULE=xim"; msg[6] = _("Or (Depends on you install im module or not)"); msg[7] = "export XMODIFIERS=\"@im=fcitx\""; msg[8] = "export QT_IM_MODULE=fcitx"; msg[9] = "export GTK_IM_MODULE=fcitx"; msg[10] = _("If you use login manager like gdm or kdm, put those lines in your ~/.xprofile."); msg[11] = _("If you use ~/.xinitrc and startx, put those lines in ~/.xinitrc."); FcitxUIDisplayMessage(instance, _("Setting Hint"), msg, 12); } free(strTemp); } /* make in order to use block X, query is not good here */ pthread_create(&instance->pid, NULL, RunInstance, instance); return instance; error_exit: FcitxInstanceEnd(instance); return instance; }