static void ClassicUIRegisterStatus(void *arg, FcitxUIStatus* status) { FcitxClassicUI* classicui = (FcitxClassicUI*) arg; FcitxSkin* sc = &classicui->skin; status->uipriv[classicui->isfallback] = fcitx_utils_new(FcitxClassicUIStatus); char *name; fcitx_utils_alloc_cat_str(name, status->name, "_active.png"); LoadImage(sc, name, false); free(name); fcitx_utils_alloc_cat_str(name, status->name, "_inactive.png"); LoadImage(sc, name, false); free(name); }
static void* LuaCallCommand(void* arg, FcitxModuleFunctionArg args) { LuaModule *luamodule = (LuaModule *)arg; UT_array *result = InputCommand(luamodule, (const char *)args.args[0]); if (result) { FcitxInputState* input = FcitxInstanceGetInputState(GetFcitx(luamodule)); LuaResultItem *p = NULL; while ((p = (LuaResultItem *)utarray_next(result, p))) { FcitxCandidateWord candWord; if (args.args[1] && args.args[2]) { candWord.callback = args.args[1]; candWord.owner = args.args[2]; } else { candWord.callback = LuaGetCandWord; candWord.owner = luamodule; } candWord.priv = p->help ? strdup(p->help) : NULL; if (p->help || p->tip) { fcitx_utils_alloc_cat_str(candWord.strExtra, p->help, p->help && p->tip ? " " : "", p->tip); } else { candWord.strExtra = NULL; } candWord.strWord = strdup(p->result); candWord.wordType = MSG_TIPS; candWord.extraType = MSG_CODE; FcitxCandidateWordAppend(FcitxInputStateGetCandidateList(input), &candWord); } utarray_free(result); } return NULL; }
INPUT_RETURN_VALUE UnicodeGetCandWords(UnicodeModule* uni) { FcitxInputState *input = FcitxInstanceGetInputState(uni->owner); FcitxInstanceCleanInputWindow(uni->owner); FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetPreedit(input), MSG_INPUT, uni->buffer); FcitxInputStateSetShowCursor(input, true); FcitxInputStateSetCursorPos(input, strlen(uni->buffer)); FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input); FcitxCandidateWordSetLayoutHint(candList, CLH_Vertical); UT_array* result = CharSelectDataFind(uni->charselectdata, uni->buffer); utarray_foreach(c, result, uint32_t) { char* s = fcitx_utils_malloc0(sizeof(char) * (UTF8_MAX_LENGTH + 1)); fcitx_ucs4_to_utf8(*c, s); FcitxCandidateWord candWord; candWord.callback = UnicodeGetCandWord; candWord.owner = uni; candWord.priv = NULL; candWord.extraType = MSG_OTHER; candWord.wordType = MSG_CODE; candWord.strWord = s; char* name = CharSelectDataName(uni->charselectdata, *c); fcitx_utils_alloc_cat_str(candWord.strExtra, " ", name); free(name); FcitxCandidateWordAppend(candList, &candWord); }
void FcitxXkbDBusGetLayouts(FcitxXkbDBus* xkbdbus, DBusMessage* message) { DBusMessageIter iter, sub; dbus_message_iter_init_append(message, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssss)", &sub); FcitxXkbRules* rules = xkbdbus->rules; FcitxIsoCodes* isocodes = xkbdbus->isocodes; char* lang = NULL; #define GET_LANG \ do { \ char** plang = NULL; \ plang = (char**) utarray_front(layoutInfo->languages); \ lang = NULL; \ if (plang) { \ FcitxIsoCodes639Entry* entry = FcitxIsoCodesGetEntry(isocodes, *plang); \ if (entry) { \ lang = entry->iso_639_1_code; \ } \ } \ } while (0) if (rules) { FcitxXkbLayoutInfo* layoutInfo; for (layoutInfo = (FcitxXkbLayoutInfo*) utarray_front(rules->layoutInfos); layoutInfo != NULL; layoutInfo = (FcitxXkbLayoutInfo*) utarray_next(rules->layoutInfos, layoutInfo)) { char* description = dgettext("xkeyboard-config", layoutInfo->description); GET_LANG; FcitxXkbDBusAppendLayout(&sub, layoutInfo->name, "", description, lang); FcitxXkbVariantInfo* variantInfo; for (variantInfo = (FcitxXkbVariantInfo*) utarray_front(layoutInfo->variantInfos); variantInfo != NULL; variantInfo = (FcitxXkbVariantInfo*) utarray_next(layoutInfo->variantInfos, variantInfo)) { char *description; fcitx_utils_alloc_cat_str( description, dgettext("xkeyboard-config", layoutInfo->description), " - ", dgettext("xkeyboard-config", variantInfo->description)); GET_LANG; FcitxXkbDBusAppendLayout(&sub, layoutInfo->name, variantInfo->name, description, lang); free(description); } } } else { char *description = dgettext("xkeyboard-config", "English (US)"); FcitxXkbDBusAppendLayout(&sub, "us", "", description, "en"); } dbus_message_iter_close_container(&iter, &sub); }
void _fcitx_compose_table_find_compose_file(FcitxComposeTable* table) { bool found = false; char* env; // check if XCOMPOSEFILE points to a Compose file if ((env = getenv("XCOMPOSEFILE")) != NULL) { // TODO: check end with found = _fcitx_compose_table_process_file(table, env); } // check if user’s home directory has a file named .XCompose if (!found && table->state == FCTS_NoErrors) { do { char* home = getenv("HOME"); if (!home) { break; } char* composeFile; fcitx_utils_alloc_cat_str(composeFile, home, "/.XCompose"); found = _fcitx_compose_table_process_file(table, composeFile); free(composeFile); } while(0); } // check for the system provided compose files if (!found && table->state == FCTS_NoErrors) { _fcitx_compose_table_read_locale_mappings(table); if (table->state == FCTS_NoErrors) { char* item; if (!fcitx_dict_lookup_by_str(table->localeToTable, table->locale, (void**) &item)) { table->state = FCTS_UnsupportedLocale; } else { char* composeFile; fcitx_utils_alloc_cat_str(composeFile, table->systemComposeDir, "/", item); found = _fcitx_compose_table_process_file(table, composeFile); free(composeFile); } } } if (found && utarray_len(table->composeTable) == 0) { table->state = FCTS_EmptyTable; } if (!found) { table->state = FCTS_MissingComposeFile; } }
FCITX_EXPORT_API char* fcitx_utils_get_fcitx_path(const char* type) { char* fcitxdir = getenv("FCITXDIR"); char* result = NULL; if (strcmp(type, "datadir") == 0) { if (fcitxdir) { fcitx_utils_alloc_cat_str(result, fcitxdir, "/share"); } else { result = strdup(DATADIR); } } else if (strcmp(type, "pkgdatadir") == 0) { if (fcitxdir) { fcitx_utils_alloc_cat_str(result, fcitxdir, "/share/"PACKAGE); } else { result = strdup(PKGDATADIR); } } else if (strcmp(type, "bindir") == 0) { if (fcitxdir) { fcitx_utils_alloc_cat_str(result, fcitxdir, "/bin"); } else result = strdup(BINDIR); } else if (strcmp(type, "libdir") == 0) { if (fcitxdir) { fcitx_utils_alloc_cat_str(result, fcitxdir, "/lib"); } else result = strdup(LIBDIR); } else if (strcmp(type, "localedir") == 0) { if (fcitxdir) { fcitx_utils_alloc_cat_str(result, fcitxdir, "/share/locale"); } else result = strdup(LOCALEDIR); } return result; }
FCITX_EXPORT_API char* fcitx_utils_get_fcitx_path_with_filename(const char* type, const char* filename) { char* path = fcitx_utils_get_fcitx_path(type); if (path == NULL) return NULL; char *result; fcitx_utils_alloc_cat_str(result, path, "/", filename); free(path); return result; }
/** * Open the dict file, return -1 if failed. **/ static int SpellCustomGetSysDictFile(FcitxSpell *spell, const char *lang) { int fd; char *path; char *fname; path = fcitx_utils_get_fcitx_path("pkgdatadir"); fcitx_utils_alloc_cat_str(fname, path, "/data/", lang, "_dict.fscd"); free(path); fd = open(fname, O_RDONLY); free(fname); return fd; }
void* _fcitx_library_get_symbol(FcitxLibrary* library, const char* addonName, const char* symbolName) { char *p; char *escapedAddonName; fcitx_utils_alloc_cat_str(escapedAddonName, addonName, "_", symbolName); for (p = escapedAddonName;*p;p++) { if (*p == '-') { *p = '_'; } } void *result = fcitx_library_resolve(library, escapedAddonName); free(escapedAddonName); return result; }
void* FcitxGetSymbol(void* handle, const char* addonName, const char* symbolName) { char *p; char *escapedAddonName; fcitx_utils_alloc_cat_str(escapedAddonName, addonName, "_", symbolName); for (p = escapedAddonName;*p;p++) { if (*p == '-') { *p = '_'; } } void *result = dlsym(handle, escapedAddonName); free(escapedAddonName); if (!result) return dlsym(handle, symbolName); return result; }
void LoadSkinDirectory(FcitxClassicUI* classicui) { UT_array* skinBuf = &classicui->skinBuf; utarray_clear(skinBuf); int i ; DIR *dir; struct dirent *drt; struct stat fileStat; size_t len; char **skinPath = FcitxXDGGetPathWithPrefix(&len, "skin"); for (i = 0; i < len; i++) { dir = opendir(skinPath[i]); if (dir == NULL) continue; while ((drt = readdir(dir)) != NULL) { if (strcmp(drt->d_name , ".") == 0 || strcmp(drt->d_name, "..") == 0) continue; char *pathBuf; fcitx_utils_alloc_cat_str(pathBuf, skinPath[i], "/", drt->d_name); int statresult = stat(pathBuf, &fileStat); free(pathBuf); if (statresult == -1) continue; if (S_ISDIR(fileStat.st_mode)) { /* check duplicate name */ int j = 0; for (; j < skinBuf->i; j++) { char **name = (char**) utarray_eltptr(skinBuf, j); if (strcmp(*name, drt->d_name) == 0) break; } if (j == skinBuf->i) { char *temp = drt->d_name; utarray_push_back(skinBuf, &temp); } } } closedir(dir); } FcitxXDGFreePath(skinPath); return; }
SkinImage* GetIMIcon(FcitxClassicUI* classicui, FcitxSkin *sc, const char* fallbackIcon, int flag, boolean fallbackToDefault) { FcitxIM* im = FcitxInstanceGetCurrentIM(classicui->owner); if (!im) return NULL; const char *path; char *tmpstr = NULL; if (im->strIconName[0] == '/') { path = im->strIconName; } else { fcitx_utils_alloc_cat_str(tmpstr, im->strIconName, ".png"); path = tmpstr; } SkinImage *imicon = NULL; if (strncmp(im->uniqueName, "fcitx-keyboard-", strlen("fcitx-keyboard-")) == 0) { SkinImage* activeIcon = LoadImage(sc, fallbackIcon, fallbackToDefault); char temp[LANGCODE_LENGTH + 1] = { '\0', }; char* iconText = 0; if (*im->langCode) { strncpy(temp, im->langCode, LANGCODE_LENGTH); iconText = temp; iconText[0] = toupper(iconText[0]); } else { iconText = im->uniqueName + strlen("fcitx-keyboard-"); } imicon = LoadImageWithText( classicui, sc, path, iconText, cairo_image_surface_get_width(activeIcon->image), cairo_image_surface_get_height(activeIcon->image), true); } if (imicon == NULL) imicon = LoadImage(sc, path, flag); fcitx_utils_free(tmpstr); if (imicon == NULL) { imicon = LoadImage(sc, fallbackIcon, fallbackToDefault); } else { SkinImage* activeIcon = LoadImage(sc, fallbackIcon, fallbackToDefault); if (activeIcon) { ResizeSurface(&imicon->image, cairo_image_surface_get_width(activeIcon->image), cairo_image_surface_get_height(activeIcon->image)); } } return imicon; }
char* FcitxNotificationItemGetIconNameString(FcitxNotificationItem* notificationitem) { char* iconName = NULL; FcitxIM* im = FcitxInstanceGetCurrentIM(notificationitem->owner); const char* icon = ""; if (im) { if (strncmp(im->uniqueName, "fcitx-keyboard-", strlen("fcitx-keyboard-")) != 0) { icon = im->strIconName; } else { return strdup("input-keyboard"); } } fcitx_utils_alloc_cat_str(iconName, (icon[0] == '\0' || icon[0] == '/') ? "" : "fcitx-", icon); return iconName; }
char* FcitxNotificationItemGetIconNameString(FcitxNotificationItem* notificationitem) { char* iconName = NULL; FcitxIM* im = FcitxInstanceGetCurrentIM(notificationitem->owner); const char* icon = ""; if (im) { if (strncmp(im->uniqueName, "fcitx-keyboard-", strlen("fcitx-keyboard-")) != 0) { icon = im->strIconName; } else { return strdup("input-keyboard"); } } boolean result = CheckAddPrefix(&icon); fcitx_utils_alloc_cat_str(iconName, result ? "fcitx-" : "", icon); return iconName; }
void _fcitx_compose_table_read_locale_mappings(FcitxComposeTable* table) { char* mappingsDir; fcitx_utils_alloc_cat_str(mappingsDir, table->systemComposeDir, "/compose.dir"); FILE* mappings = fopen(mappingsDir, "r"); if (mappings) { char* line = NULL; size_t bufSize = 0; while (getline(&line, &bufSize, mappings) != -1) { char* trimLine = fcitx_utils_trim(line); if (trimLine[0] != '#' && trimLine[0] != '\0' && fcitx_utils_islower(trimLine[0])) { FcitxStringList* list = fcitx_utils_string_split_full(trimLine, FCITX_WHITESPACE, false); if (utarray_len(list) >= 2) { char **plocale = utarray_eltptr(list, 1); char **pitem = utarray_eltptr(list, 0); char *locale = *plocale, *item = *pitem; // we steal this string from list *pitem = NULL; size_t itemLen = strlen(item); if (itemLen > 0 && item[itemLen - 1] == ':') { item[itemLen - 1] = '\0'; } char* p = locale; while(*p) { *p = fcitx_utils_toupper(*p); p++; } fcitx_dict_insert_by_str(table->localeToTable, locale, item, true); } fcitx_utils_string_list_free(list); } free(trimLine); } free(line); fclose(mappings); } free(mappingsDir); }
void _fcitx_compose_table_find_system_compose_dir(FcitxComposeTable* table, int nPossibleLocation, const char* possibleLocation[]) { bool found = false; for (int i = 0; i < nPossibleLocation; ++i) { char* path; fcitx_utils_alloc_cat_str(path, possibleLocation[i], "/compose.dir"); if (fcitx_utils_isreg(path)) { table->systemComposeDir = strdup(possibleLocation[i]); found = true; } free(path); if (found) { break; } } if (!found) { // should we ask to report this in the qt bug tracker? table->state = FCTS_UnknownSystemComposeDir; } }
/** @加载皮肤配置文件 */ int LoadSkinConfig(FcitxSkin* sc, char** skinType) { FILE *fp; boolean isreload = False; int ret = 0; if (sc->config.configFile) { utarray_done(&sc->skinMainBar.skinPlacement); FcitxConfigFree(&sc->config); UnloadImage(sc); } memset(sc, 0, sizeof(FcitxSkin)); utarray_init(&sc->skinMainBar.skinPlacement, &place_icd); reload: if (!isreload) { char *buf; fcitx_utils_alloc_cat_str(buf, *skinType, "/fcitx_skin.conf"); fp = FcitxXDGGetFileWithPrefix("skin", buf, "r", NULL); free(buf); } else { char *path = fcitx_utils_get_fcitx_path_with_filename( "pkgdatadir", "/skin/default/fcitx_skin.conf"); fp = fopen(path, "r"); free(path); } if (fp) { FcitxConfigFile *cfile; FcitxConfigFileDesc* skinDesc = GetSkinDesc(); if (sc->config.configFile == NULL) { cfile = FcitxConfigParseConfigFileFp(fp, skinDesc); } else { cfile = sc->config.configFile; cfile = FcitxConfigParseIniFp(fp, cfile); } if (!cfile) { fclose(fp); fp = NULL; } else { FcitxSkinConfigBind(sc, cfile, skinDesc); FcitxConfigBindSync((FcitxGenericConfig*)sc); } } if (!fp) { if (isreload) { FcitxLog(FATAL, _("Can not load default skin, is installion correct?")); perror("fopen"); ret = 1; // 如果安装目录里面也没有配置文件,那就只好告诉用户,无法运行了 } else { perror("fopen"); FcitxLog(WARNING, _("Can not load skin %s, return to default"), *skinType); if (*skinType) free(*skinType); *skinType = strdup("default"); isreload = true; goto reload; } } if (fp) fclose(fp); sc->skinType = skinType; return ret; }
SkinImage* LoadImageFromTable(SkinImage** imageTable, const char* skinType, const char* name, int flag) { cairo_surface_t *png = NULL; SkinImage *image = NULL; char *buf; fcitx_utils_alloc_cat_str(buf, "skin/", skinType); const char* fallbackChainNoFallback[] = { buf }; const char* fallbackChainPanel[] = { buf, "skin/default" }; const char* fallbackChainTray[] = { "imicon" }; const char* fallbackChainPanelIMIcon[] = { buf, "imicon", "skin/default" }; HASH_FIND_STR(*imageTable, name, image); if (image != NULL) { free(buf); return image; } const char** fallbackChain; int fallbackSize; switch(flag) { case 1: fallbackChain = fallbackChainPanel; fallbackSize = 2; break; case 2: fallbackChain = fallbackChainTray; fallbackSize = 1; break; case 3: fallbackChain = fallbackChainPanelIMIcon; fallbackSize = 3; break; case 0: default: /* fall through */ fallbackChain = fallbackChainNoFallback; fallbackSize = 1; break; } if (strlen(name) > 0 && strcmp(name , "NONE") != 0) { int i = 0; for (i = 0; i < fallbackSize; i ++) { char* filename; const char* skintype = fallbackChain[i]; FILE* fp = FcitxXDGGetFileWithPrefix(skintype, name, "r", &filename); if (fp) { png = cairo_image_surface_create_from_png(filename); if (cairo_surface_status (png)) { png = NULL; } } free(filename); if (png) break; } } free(buf); if (png != NULL) { image = fcitx_utils_new(SkinImage); image->name = strdup(name); image->image = png; HASH_ADD_KEYPTR(hh, *imageTable, image->name, strlen(image->name), image); return image; } return NULL; }
char* CharSelectDataName(CharSelectData* charselect, uint32_t unicode) { char* result = NULL; do { if ((unicode >= 0x3400 && unicode <= 0x4DB5) || (unicode >= 0x4e00 && unicode <= 0x9fa5) || (unicode >= 0x20000 && unicode <= 0x2A6D6)) { asprintf(&result, "CJK UNIFIED IDEOGRAPH-%x", unicode); } else if (unicode >= 0xac00 && unicode <= 0xd7af) { /* compute hangul syllable name as per UAX #15 */ int SIndex = unicode - SBase; int LIndex, VIndex, TIndex; if (SIndex < 0 || SIndex >= SCount) { result = strdup(""); break; } LIndex = SIndex / NCount; VIndex = (SIndex % NCount) / TCount; TIndex = SIndex % TCount; fcitx_utils_alloc_cat_str(result, "HANGUL SYLLABLE ", JAMO_L_TABLE[LIndex], JAMO_V_TABLE[VIndex], JAMO_T_TABLE[TIndex]); } else if (unicode >= 0xD800 && unicode <= 0xDB7F) result = strdup(_("<Non Private Use High Surrogate>")); else if (unicode >= 0xDB80 && unicode <= 0xDBFF) result = strdup(_("<Private Use High Surrogate>")); else if (unicode >= 0xDC00 && unicode <= 0xDFFF) result = strdup(_("<Low Surrogate>")); else if (unicode >= 0xE000 && unicode <= 0xF8FF) result = strdup(_("<Private Use>")); else { const char* data = charselect->dataFile; const uint32_t offsetBegin = FromLittleEndian32(data+4); const uint32_t offsetEnd = FromLittleEndian32(data+8); int min = 0; int mid; int max = ((offsetEnd - offsetBegin) / 8) - 1; while (max >= min) { mid = (min + max) / 2; const uint32_t midUnicode = FromLittleEndian32(data + offsetBegin + mid*8); if (unicode > midUnicode) min = mid + 1; else if (unicode < midUnicode) max = mid - 1; else { uint32_t offset = FromLittleEndian32(data + offsetBegin + mid*8 + 4); result = strdup(charselect->dataFile + offset + 1); break; } } } } while(0); if (!result) { result = strdup(_("<not assigned>")); } return result; }
void FcitxDBusMenuFillProperty(FcitxNotificationItem* notificationitem, int32_t id, FcitxStringHashSet* properties, DBusMessageIter* iter) { FcitxInstance* instance = notificationitem->owner; /* append a{sv} */ DBusMessageIter sub; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &sub); int32_t menu = ACTION_MENU(id); int32_t index = ACTION_INDEX(id); /* index == 0 means it has a sub menu */ if (index == 0) { const char* value = "submenu"; FcitxDBusMenuAppendProperty(&sub, properties, "children-display", DBUS_TYPE_STRING, &value); } if (menu == 0) { if (index <= 8 && index > 0) { const char* value; switch(index) { case 1: value = _("Online Help"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "help-contents"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; case 2: case 3: case 8: value = "separator"; FcitxDBusMenuAppendProperty(&sub, properties, "type", DBUS_TYPE_STRING, &value); break; case 4: value = _("Configure Current Input Method"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); break; case 5: value = _("Configure"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); /* this icon sucks on KDE, why configure doesn't have "configure" */ #if 0 value = "preferences-system"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); #endif break; case 6: value = _("Restart"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "view-refresh"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; case 7: value = _("Exit"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "application-exit"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; } } else { int index = STATUS_INDEX(id); const char* name = NULL; const char* icon = NULL; char* needfree = NULL; if (STATUS_ISCOMP(id)) { UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance); FcitxUIComplexStatus* compstatus = (FcitxUIComplexStatus*) utarray_eltptr(uicompstats, index); if (compstatus) { name = compstatus->shortDescription; icon = compstatus->getIconName(compstatus->arg); if (CheckAddPrefix(&icon)) { fcitx_utils_alloc_cat_str(needfree, "fcitx-", icon); icon = needfree; } } } else { UT_array* uistats = FcitxInstanceGetUIStats(instance); FcitxUIStatus* status = (FcitxUIStatus*) utarray_eltptr(uistats, index); if (status) { name = status->shortDescription; fcitx_utils_alloc_cat_str(needfree, "fcitx-", status->name, ((status->getCurrentStatus(status->arg)) ? "-active" : "-inactive")); icon = needfree; } } if (name) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &name); } if (icon) { FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &icon); } fcitx_utils_free(needfree); } } else { UT_array* uimenus = FcitxInstanceGetUIMenus(instance); FcitxUIMenu** menupp = (FcitxUIMenu**) utarray_eltptr(uimenus, menu - 1), *menup; if (menupp) { menup = *menupp; if (index == 0) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &menup->name); } else if (index > 0) { FcitxMenuItem* item = (FcitxMenuItem*) utarray_eltptr(&menup->shell, index - 1); if (item) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &item->tipstr); if (menup->mark != -1) { const char* radio = "radio"; FcitxDBusMenuAppendProperty(&sub, properties, "toggle-type", DBUS_TYPE_STRING, &radio); int32_t toggleState = 0; if (menup->mark == index - 1) { toggleState = 1; } FcitxDBusMenuAppendProperty(&sub, properties, "toggle-state", DBUS_TYPE_INT32, &toggleState); } } } } } dbus_message_iter_close_container(iter, &sub); }
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; }
boolean LoadTableDict(TableMetaData* tableMetaData) { char strCode[MAX_CODE_LENGTH + 1]; char *strHZ = 0; FILE *fpDict; RECORD *recTemp; unsigned int i = 0; uint32_t iTemp, iTempCount; char cChar = 0, cTemp; int8_t iVersion = 1; int iRecordIndex; TableDict *tableDict; //读入码表 FcitxLog(DEBUG, _("Loading Table Dict")); int reload = 0; do { boolean error = false; if (!reload) { /** * kcm saves a absolute path here but it is then interpreted as * a relative path? **/ fpDict = FcitxXDGGetFileWithPrefix("table", tableMetaData->strPath, "r", NULL); } else { char *tablepath; char *path = fcitx_utils_get_fcitx_path("pkgdatadir"); fcitx_utils_alloc_cat_str(tablepath, path, "/table/", tableMetaData->strPath); fpDict = fopen(tablepath, "r"); free(tablepath); } if (!fpDict) return false; tableMetaData->tableDict = fcitx_utils_new(TableDict); tableDict = tableMetaData->tableDict; tableDict->pool = fcitx_memory_pool_create(); #define CHECK_LOAD_TABLE_ERROR(SIZE) if (size < (SIZE)) { error = true; goto table_load_error; } //先读取码表的信息 //判断版本信息 size_t size; size = fcitx_utils_read_uint32(fpDict, &iTemp); CHECK_LOAD_TABLE_ERROR(1); if (!iTemp) { size = fread(&iVersion, sizeof(int8_t), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); iVersion = (iVersion < INTERNAL_VERSION); size = fcitx_utils_read_uint32(fpDict, &iTemp); CHECK_LOAD_TABLE_ERROR(1); } tableDict->strInputCode = (char*)realloc(tableDict->strInputCode, sizeof(char) * (iTemp + 1)); size = fread(tableDict->strInputCode, sizeof(char), iTemp + 1, fpDict); CHECK_LOAD_TABLE_ERROR(iTemp + 1); /* * 建立索引,加26是为了为拼音编码预留空间 */ size_t tmp_len = strlen(tableDict->strInputCode) + 26; tableDict->recordIndex = (RECORD_INDEX*)fcitx_memory_pool_alloc(tableDict->pool, tmp_len * sizeof(RECORD_INDEX)); for (iTemp = 0; iTemp < tmp_len; iTemp++) { tableDict->recordIndex[iTemp].cCode = 0; tableDict->recordIndex[iTemp].record = NULL; } /********************************************************************/ size = fread(&(tableDict->iCodeLength), sizeof(uint8_t), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); UpdateTableMetaData(tableMetaData); if (!iVersion) { size = fread(&(tableDict->iPYCodeLength), sizeof(uint8_t), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); } else tableDict->iPYCodeLength = tableDict->iCodeLength; size = fcitx_utils_read_uint32(fpDict, &iTemp); CHECK_LOAD_TABLE_ERROR(1); tableDict->strIgnoreChars = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (iTemp + 1)); size = fread(tableDict->strIgnoreChars, sizeof(char), iTemp + 1, fpDict); CHECK_LOAD_TABLE_ERROR(iTemp + 1); size = fread(&(tableDict->bRule), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); if (tableDict->bRule) { //表示有组词规则 tableDict->rule = (RULE*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(RULE) * (tableDict->iCodeLength - 1)); for (i = 0; i < tableDict->iCodeLength - 1; i++) { size = fread(&(tableDict->rule[i].iFlag), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); size = fread(&(tableDict->rule[i].iWords), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); tableDict->rule[i].rule = (RULE_RULE*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(RULE_RULE) * tableDict->iCodeLength); for (iTemp = 0; iTemp < tableDict->iCodeLength; iTemp++) { size = fread(&(tableDict->rule[i].rule[iTemp].iFlag), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); size = fread(&(tableDict->rule[i].rule[iTemp].iWhich), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); size = fread(&(tableDict->rule[i].rule[iTemp].iIndex), sizeof(unsigned char), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); } } } tableDict->recordHead = (RECORD*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(RECORD)); tableDict->currentRecord = tableDict->recordHead; size = fcitx_utils_read_uint32(fpDict, &tableDict->iRecordCount); CHECK_LOAD_TABLE_ERROR(1); for (i = 0; i < SINGLE_HZ_COUNT; i++) { tableDict->tableSingleHZ[i] = (RECORD*)NULL; tableDict->tableSingleHZCons[i] = (RECORD*)NULL; } iRecordIndex = 0; size_t bufSize = 0; for (i = 0; i < tableDict->iRecordCount; i++) { size = fread(strCode, sizeof(int8_t), tableDict->iPYCodeLength + 1, fpDict); CHECK_LOAD_TABLE_ERROR(tableDict->iPYCodeLength + 1); size = fcitx_utils_read_uint32(fpDict, &iTemp); CHECK_LOAD_TABLE_ERROR(1); /* we don't actually have such limit, but sometimes, broken table * may break this, so we need to give a limitation. */ if (iTemp > UTF8_MAX_LENGTH * 30) { error = true; goto table_load_error; } if (iTemp > bufSize) { bufSize = iTemp; strHZ = realloc(strHZ, bufSize); } size = fread(strHZ, sizeof(int8_t), iTemp, fpDict); CHECK_LOAD_TABLE_ERROR(iTemp); recTemp = (RECORD*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(RECORD)); recTemp->strCode = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (tableDict->iPYCodeLength + 1)); memset(recTemp->strCode, 0, sizeof(char) * (tableDict->iPYCodeLength + 1)); strcpy(recTemp->strCode, strCode); recTemp->strHZ = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * iTemp); strcpy(recTemp->strHZ, strHZ); if (!iVersion) { size = fread(&cTemp, sizeof(int8_t), 1, fpDict); CHECK_LOAD_TABLE_ERROR(1); recTemp->type = cTemp; } size = fcitx_utils_read_uint32(fpDict, &recTemp->iHit); CHECK_LOAD_TABLE_ERROR(1); size = fcitx_utils_read_uint32(fpDict, &recTemp->iIndex); CHECK_LOAD_TABLE_ERROR(1); if (recTemp->iIndex > tableDict->iTableIndex) tableDict->iTableIndex = recTemp->iIndex; /* 建立索引 */ if (cChar != recTemp->strCode[0]) { cChar = recTemp->strCode[0]; tableDict->recordIndex[iRecordIndex].cCode = cChar; tableDict->recordIndex[iRecordIndex].record = recTemp; iRecordIndex++; } /******************************************************************/ /** 为单字生成一个表 */ if (fcitx_utf8_strlen(recTemp->strHZ) == 1 && !IsIgnoreChar(tableDict, strCode[0])) { RECORD** tableSingleHZ = NULL; if (recTemp->type == RECORDTYPE_NORMAL) tableSingleHZ = tableDict->tableSingleHZ; else if (recTemp->type == RECORDTYPE_CONSTRUCT) tableSingleHZ = tableDict->tableSingleHZCons; if (tableSingleHZ) { iTemp = CalHZIndex(recTemp->strHZ); if (iTemp < SINGLE_HZ_COUNT) { if (tableSingleHZ[iTemp]) { if (strlen(strCode) > strlen(tableDict->tableSingleHZ[iTemp]->strCode)) tableSingleHZ[iTemp] = recTemp; } else tableSingleHZ[iTemp] = recTemp; } } } if (recTemp->type == RECORDTYPE_PINYIN) tableDict->bHasPinyin = true; if (recTemp->type == RECORDTYPE_PROMPT && strlen(recTemp->strCode) == 1) tableDict->promptCode[(uint8_t) recTemp->strCode[0]] = recTemp; tableDict->currentRecord->next = recTemp; recTemp->prev = tableDict->currentRecord; tableDict->currentRecord = recTemp; } if (strHZ) { free(strHZ); strHZ = NULL; } tableDict->currentRecord->next = tableDict->recordHead; tableDict->recordHead->prev = tableDict->currentRecord; table_load_error: fclose(fpDict); if (error) { fcitx_memory_pool_destroy(tableDict->pool); tableDict->pool = NULL; reload++; } else { break; } } while(reload < 2); if (!tableDict->pool) return false; FcitxLog(DEBUG, _("Load Table Dict OK")); //读取相应的特殊符号表 fpDict = FcitxXDGGetFileWithPrefix("table", tableMetaData->strSymbolFile, "r", NULL); if (fpDict) { tableDict->iFH = fcitx_utils_calculate_record_number(fpDict); tableDict->fh = (FH*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(FH) * tableDict->iFH); char* strBuf = NULL; size_t bufLen = 0; for (i = 0; i < tableDict->iFH; i++) { if (getline(&strBuf, &bufLen, fpDict) == -1) break; if (!fcitx_utf8_check_string(strBuf)) break; if (fcitx_utf8_strlen(strBuf) > FH_MAX_LENGTH) break; strcpy(tableDict->fh[i].strFH, strBuf); } fcitx_utils_free(strBuf); tableDict->iFH = i; fclose(fpDict); } tableDict->strNewPhraseCode = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (tableDict->iCodeLength + 1)); tableDict->strNewPhraseCode[tableDict->iCodeLength] = '\0'; tableDict->iAutoPhrase = 0; if (tableMetaData->bAutoPhrase) { tableDict->autoPhrase = (AUTOPHRASE*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(AUTOPHRASE) * AUTO_PHRASE_COUNT); //读取上次保存的自动词组信息 FcitxLog(DEBUG, _("Loading Autophrase.")); char *temppath; fcitx_utils_alloc_cat_str(temppath, tableMetaData->uniqueName, "_LastAutoPhrase.tmp"); fpDict = FcitxXDGGetFileWithPrefix("table", temppath, "r", NULL); free(temppath); i = 0; if (fpDict) { size_t size = fcitx_utils_read_int32(fpDict, &tableDict->iAutoPhrase); if (size == 1) { for (; i < tableDict->iAutoPhrase; i++) { tableDict->autoPhrase[i].strCode = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (tableDict->iCodeLength + 1)); tableDict->autoPhrase[i].strHZ = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH + 1)); size = fread(tableDict->autoPhrase[i].strCode, tableDict->iCodeLength + 1, 1, fpDict); if (size != 1) { tableDict->iAutoPhrase = i; break; } size = fread(tableDict->autoPhrase[i].strHZ, PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH + 1, 1, fpDict); tableDict->autoPhrase[i].strHZ[PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH] = 0; if (size != 1 || !fcitx_utf8_check_string(tableDict->autoPhrase[i].strHZ)) { tableDict->iAutoPhrase = i; break; } size = fcitx_utils_read_uint32(fpDict, &iTempCount); if (size != 1) { tableDict->iAutoPhrase = i; break; } tableDict->autoPhrase[i].iSelected = iTempCount; if (i == AUTO_PHRASE_COUNT - 1) tableDict->autoPhrase[i].next = &tableDict->autoPhrase[0]; else tableDict->autoPhrase[i].next = &tableDict->autoPhrase[i + 1]; } } fclose(fpDict); } for (; i < AUTO_PHRASE_COUNT; i++) { tableDict->autoPhrase[i].strCode = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (tableDict->iCodeLength + 1)); tableDict->autoPhrase[i].strHZ = (char*)fcitx_memory_pool_alloc(tableDict->pool, sizeof(char) * (PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH + 1)); tableDict->autoPhrase[i].iSelected = 0; if (i == AUTO_PHRASE_COUNT - 1) tableDict->autoPhrase[i].next = &tableDict->autoPhrase[0]; else tableDict->autoPhrase[i].next = &tableDict->autoPhrase[i + 1]; } if (i == AUTO_PHRASE_COUNT) tableDict->insertPoint = &tableDict->autoPhrase[0]; else tableDict->insertPoint = &tableDict->autoPhrase[i - 1]; FcitxLog(DEBUG, _("Load Autophrase OK")); } else tableDict->autoPhrase = (AUTOPHRASE *) NULL; return true; }
void SaveTableDict(TableMetaData *tableMetaData) { RECORD *recTemp; char *pstr, *tempfile; FILE *fpDict; uint32_t iTemp; unsigned int i; int fd; int8_t cTemp; TableDict *tableDict = tableMetaData->tableDict; if (!tableDict->iTableChanged) return; // make ~/.config/fcitx/table/ dir FcitxXDGGetFileUserWithPrefix("table", "", "w", NULL); FcitxXDGGetFileUserWithPrefix("table", TABLE_TEMP_FILE, NULL, &tempfile); fd = mkstemp(tempfile); fpDict = NULL; if (fd > 0) fpDict = fdopen(fd, "w"); if (!fpDict) { FcitxLog(ERROR, _("Save dict error")); free(tempfile); return; } // write version number fcitx_utils_write_uint32(fpDict, 0); fwrite(&iInternalVersion, sizeof(char), 1, fpDict); iTemp = strlen(tableDict->strInputCode); fcitx_utils_write_uint32(fpDict, iTemp); fwrite(tableDict->strInputCode, sizeof(char), iTemp + 1, fpDict); fwrite(&(tableDict->iCodeLength), sizeof(char), 1, fpDict); fwrite(&(tableDict->iPYCodeLength), sizeof(char), 1, fpDict); iTemp = strlen(tableDict->strIgnoreChars); fcitx_utils_write_uint32(fpDict, iTemp); fwrite(tableDict->strIgnoreChars, sizeof(char), iTemp + 1, fpDict); fwrite(&(tableDict->bRule), sizeof(unsigned char), 1, fpDict); if (tableDict->bRule) { // table contains rule for (i = 0; i < tableDict->iCodeLength - 1; i++) { fwrite(&(tableDict->rule[i].iFlag), sizeof(unsigned char), 1, fpDict); fwrite(&(tableDict->rule[i].iWords), sizeof(unsigned char), 1, fpDict); for (iTemp = 0; iTemp < tableDict->iCodeLength; iTemp++) { fwrite(&(tableDict->rule[i].rule[iTemp].iFlag), sizeof(unsigned char), 1, fpDict); fwrite(&(tableDict->rule[i].rule[iTemp].iWhich), sizeof(unsigned char), 1, fpDict); fwrite(&(tableDict->rule[i].rule[iTemp].iIndex), sizeof(unsigned char), 1, fpDict); } } } fcitx_utils_write_uint32(fpDict, tableDict->iRecordCount); recTemp = tableDict->recordHead->next; while (recTemp != tableDict->recordHead) { fwrite(recTemp->strCode, sizeof(char), tableDict->iPYCodeLength + 1, fpDict); iTemp = strlen(recTemp->strHZ) + 1; fcitx_utils_write_uint32(fpDict, iTemp); fwrite(recTemp->strHZ, sizeof(char), iTemp, fpDict); cTemp = recTemp->type; fwrite(&cTemp, sizeof(int8_t), 1, fpDict); fcitx_utils_write_uint32(fpDict, recTemp->iHit); fcitx_utils_write_uint32(fpDict, recTemp->iIndex); recTemp = recTemp->next; } fclose(fpDict); fpDict = FcitxXDGGetFileUserWithPrefix("table", tableMetaData->strPath, NULL, &pstr); if (access(pstr, 0)) unlink(pstr); rename(tempfile, pstr); free(pstr); free(tempfile); FcitxLog(DEBUG, _("Rename OK")); tableDict->iTableChanged = 0; if (tableDict->autoPhrase) { // Save auto phrase // make ~/.config/fcitx/table/ dir FcitxXDGGetFileUserWithPrefix("table", "", "w", NULL); FcitxXDGGetFileUserWithPrefix("table", TABLE_TEMP_FILE, NULL, &tempfile); fd = mkstemp(tempfile); fpDict = NULL; if (fd > 0) fpDict = fdopen(fd, "w"); if (fpDict) { fcitx_utils_write_uint32(fpDict, tableDict->iAutoPhrase); for (i = 0; i < tableDict->iAutoPhrase; i++) { fwrite(tableDict->autoPhrase[i].strCode, tableDict->iCodeLength + 1, 1, fpDict); fwrite(tableDict->autoPhrase[i].strHZ, PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH + 1, 1, fpDict); fcitx_utils_write_int32( fpDict, tableDict->autoPhrase[i].iSelected); } fclose(fpDict); } char *strPath; fcitx_utils_alloc_cat_str(strPath, tableMetaData->uniqueName, "_LastAutoPhrase.tmp"); fpDict = FcitxXDGGetFileUserWithPrefix("table", strPath, NULL, &pstr); free(strPath); if (access(pstr, F_OK)) unlink(pstr); rename(tempfile, pstr); free(pstr); free(tempfile); } }
void test_string() { const char *test = TEST_STR; FcitxStringList* list = fcitx_utils_string_split(test, ","); assert(utarray_len(list) == 4); assert(fcitx_utils_string_list_contains(list, "a")); assert(fcitx_utils_string_list_contains(list, "b")); assert(fcitx_utils_string_list_contains(list, "c")); assert(fcitx_utils_string_list_contains(list, "d")); assert(!fcitx_utils_string_list_contains(list, "e")); char* join = fcitx_utils_string_list_join(list, ','); assert(strcmp(join, test) == 0); fcitx_utils_string_list_append_split(list, TEST_STR, "\n"); fcitx_utils_string_list_printf_append(list, "%s", TEST_STR); char *join2 = fcitx_utils_string_list_join(list, ','); assert(strcmp(join2, TEST_STR","TEST_STR","TEST_STR) == 0); char* cat = NULL; fcitx_utils_alloc_cat_str(cat, join, ",e"); assert(strcmp(cat, TEST_STR",e") == 0); fcitx_utils_set_cat_str(cat, join, ",e,", join); assert(strcmp(cat, TEST_STR",e,"TEST_STR) == 0); join = fcitx_utils_set_str(join, join2); assert(strcmp(join, join2) == 0); free(cat); free(join); free(join2); fcitx_utils_string_list_free(list); list = fcitx_utils_string_split_full("a b", " ", false); assert(utarray_len(list) == 2); fcitx_utils_string_list_free(list); char localcat[20]; const char *array[] = {"a", ",b", ",c", ",d"}; fcitx_utils_cat_str_simple(localcat, 4, array); assert(strcmp(localcat, test) == 0); char localcat2[6]; fcitx_utils_cat_str_simple_with_len(localcat2, 4, 4, array); assert(strcmp(localcat2, "a,b") == 0); fcitx_utils_cat_str_simple_with_len(localcat2, 5, 4, array); assert(strcmp(localcat2, "a,b,") == 0); fcitx_utils_cat_str_simple_with_len(localcat2, 6, 4, array); assert(strcmp(localcat2, "a,b,c") == 0); const char *orig = "\r78\"1\n\\\e\\3\f\a\v\'cc\td\b"; char *escape = fcitx_utils_set_escape_str(NULL, orig); assert(strcmp(escape, "\\r78\\\"1\\n\\\\\\e\\\\3\\f\\a\\v\\\'cc\\td\\b") == 0); char *back = fcitx_utils_set_unescape_str(NULL, escape); assert(strcmp(orig, back) == 0); fcitx_utils_unescape_str_inplace(escape); assert(strcmp(orig, escape) == 0); free(escape); free(back); char* replace_result = fcitx_utils_string_replace("abcabc", "a", "b", true); assert(strcmp(replace_result, "bbcbbc") == 0); free(replace_result); #define REPEAT 2049 char largeReplace[3 * REPEAT + 1]; char largeReplaceCorrect[REPEAT + 1]; char largeReplaceCorrect2[4 * REPEAT + 1]; int i = 0, j = 0, k = 0; for (int n = 0; n < REPEAT; n ++) { largeReplace[i++] = 'a'; largeReplace[i++] = 'b'; largeReplace[i++] = 'c'; largeReplaceCorrect[j++] = 'e'; largeReplaceCorrect2[k++] = 'a'; largeReplaceCorrect2[k++] = 'b'; largeReplaceCorrect2[k++] = 'c'; largeReplaceCorrect2[k++] = 'd'; } largeReplace[i] = '\0'; largeReplaceCorrect[j] = '\0'; largeReplaceCorrect2[k] = '\0'; replace_result = fcitx_utils_string_replace(largeReplace, "abc", "e", true); assert(strcmp(replace_result, largeReplaceCorrect) == 0); char* replace_result2 = fcitx_utils_string_replace(replace_result, "e", "abcd", true); free(replace_result); assert(strcmp(replace_result2, largeReplaceCorrect2) == 0); free(replace_result2); assert(fcitx_utils_string_replace(largeReplace, "de", "bcd", true) == NULL); }
FcitxAddon* FcitxAddonsLoadInternal(UT_array* addons, boolean reloadIM) { char **addonPath; size_t len; size_t start; if (!reloadIM) utarray_clear(addons); start = utarray_len(addons); FcitxStringHashSet* sset = FcitxXDGGetFiles("addon", NULL, ".conf"); addonPath = FcitxXDGGetPathWithPrefix(&len, "addon"); char *paths[len]; HASH_FOREACH(string, sset, FcitxStringHashSet) { // FIXME: if it will cause realloc, then it's evil for fcitx 4.2 series if (reloadIM && addons->i == addons->n) { break; } int i; for (i = len - 1; i >= 0; i--) { fcitx_utils_alloc_cat_str(paths[i], addonPath[len - i - 1], "/", string->name); FcitxLog(DEBUG, "Load Addon Config File:%s", paths[i]); } FcitxConfigFile* cfile = FcitxConfigParseMultiConfigFile(paths, len, FcitxAddonGetConfigDesc()); if (cfile) { utarray_extend_back(addons); FcitxAddon *a = (FcitxAddon*) utarray_back(addons); utarray_init(&a->functionList, fcitx_ptr_icd); FcitxAddonConfigBind(a, cfile, FcitxAddonGetConfigDesc()); FcitxConfigBindSync((FcitxGenericConfig*)a); FcitxLog(DEBUG, _("Addon Config %s is %s"), string->name, (a->bEnabled) ? "Enabled" : "Disabled"); boolean error = false; if (reloadIM) { if (a->category != AC_INPUTMETHOD) error = true; } /* if loaded, don't touch the old one */ if (FcitxAddonsGetAddonByNameInternal(addons, a->name, true) != a) error = true; if (error) utarray_pop_back(addons); else FcitxLog(INFO, _("Load Addon Config File:%s"), string->name); } for (i = len - 1;i >= 0;i--) { free(paths[i]); } } FcitxXDGFreePath(addonPath); fcitx_utils_free_string_hash_set(sset); size_t to = utarray_len(addons); utarray_sort_range(addons, AddonPriorityCmp, start, to); return (FcitxAddon*)utarray_eltptr(addons, start); }