int main(int argc, char* argv[]) { char* localedir = fcitx_utils_get_fcitx_path("localedir"); setlocale(LC_ALL, ""); bindtextdomain("fcitx", localedir); free(localedir); bind_textdomain_codeset("fcitx", "UTF-8"); textdomain("fcitx"); if (pipe(selfpipe) < 0) { fprintf(stderr, "Could not create self-pipe.\n"); exit(1); } fcntl(selfpipe[0], F_SETFL, O_NONBLOCK); fcntl(selfpipe[1], F_SETFL, O_NONBLOCK); SetMyExceptionHandler(); int instanceCount = 1; sem_t sem; sem_init(&sem, 0, 0); instance = FcitxInstanceCreateWithFD(&sem, argc, argv, selfpipe[0]); WaitForEnd(&sem, instanceCount); if (instance->loadingFatalError) { return 1; } return 0; }
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; }
int main(int argc, char* argv[]) { char* localedir = fcitx_utils_get_fcitx_path("localedir"); setlocale(LC_ALL, ""); bindtextdomain("fcitx", localedir); free(localedir); bind_textdomain_codeset("fcitx", "UTF-8"); textdomain("fcitx"); WrapperApp app(argc, argv); return app.exec(); }
void* fcitx_keyboard_init(FcitxAddonManager* manager, const FcitxAddonConfig* config) { FCITX_UNUSED(manager); FCITX_UNUSED(config); FcitxKeyboard* keyboard = fcitx_utils_new(FcitxKeyboard); char* localepath = fcitx_utils_get_fcitx_path("localedir"); bindtextdomain("xkeyboard-config", localepath); bind_textdomain_codeset("xkeyboard-config", "UTF-8"); free(localepath); return keyboard; }
/** * 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; }
FCITX_EXPORT_API FILE *FcitxXDGGetLibFile(const char *filename, const char *mode, char **retFile) { size_t len; char ** path; char* libdir = fcitx_utils_get_fcitx_path("libdir"); path = FcitxXDGGetPath(&len, "XDG_CONFIG_HOME", ".config", PACKAGE "/lib" , libdir, PACKAGE); free(libdir); FILE* fp = FcitxXDGGetFile(filename, path, mode, len, retFile); FcitxXDGFreePath(path); return fp; }
FCITX_EXPORT_API FILE *FcitxXDGGetFileWithPrefix(const char* prefix, const char *fileName, const char *mode, char **retFile) { size_t len; char *prefixpath; asprintf(&prefixpath, "%s/%s", PACKAGE, prefix); char* datadir = fcitx_utils_get_fcitx_path("datadir"); char ** path = FcitxXDGGetPath(&len, "XDG_CONFIG_HOME", ".config", prefixpath , datadir, prefixpath); free(datadir); free(prefixpath); FILE* fp = FcitxXDGGetFile(fileName, path, mode, len, retFile); FcitxXDGFreePath(path); return fp; }
FcitxStringList* fcitx_standard_default_paths_construct(const char* env, const char* defaultPath, const char* fcitxPath) { FcitxStringList* dirs = fcitx_utils_string_list_new(); if (fcitxPath) { char* path = fcitx_utils_get_fcitx_path(fcitxPath); fcitx_utils_string_list_append_no_copy(dirs, path); } const char* dir = getenv(env); if (!dir) { dir = defaultPath; } dirs = fcitx_utils_string_list_append_split_full(dirs, dir, ":", false); return dirs; }
FCITX_EXPORT_API FcitxStringHashSet* FcitxXDGGetFiles( char* path, char* prefix, char* suffix ) { char **xdgPath; size_t len; char *pathBuf; size_t i = 0; DIR *dir; struct dirent *drt; struct stat fileStat; FcitxStringHashSet* sset = NULL; char *prefixpath; asprintf(&prefixpath, "%s/%s", PACKAGE, path); char* datadir = fcitx_utils_get_fcitx_path("datadir"); xdgPath = FcitxXDGGetPath(&len, "XDG_CONFIG_HOME", ".config" , prefixpath , datadir , prefixpath); free(datadir); free(prefixpath); for (i = 0; i < len; i++) { asprintf(&pathBuf, "%s", xdgPath[i]); dir = opendir(pathBuf); free(pathBuf); if (dir == NULL) continue; size_t suffixlen = 0; size_t prefixlen = 0; if (suffix) suffixlen = strlen(suffix); if (prefix) prefixlen = strlen(prefix); /* collect all *.conf files */ while ((drt = readdir(dir)) != NULL) { size_t nameLen = strlen(drt->d_name); if (nameLen <= suffixlen + prefixlen) continue; if (suffix && strcmp(drt->d_name + nameLen - suffixlen, suffix) != 0) continue; if (prefix && strncmp(drt->d_name, prefix, prefixlen) != 0) continue; asprintf(&pathBuf, "%s/%s", xdgPath[i], drt->d_name); int statresult = stat(pathBuf, &fileStat); free(pathBuf); if (statresult == -1) continue; if (fileStat.st_mode & S_IFREG) { FcitxStringHashSet *string; HASH_FIND_STR(sset, drt->d_name, string); if (!string) { char *bStr = strdup(drt->d_name); string = malloc(sizeof(FcitxStringHashSet)); memset(string, 0, sizeof(FcitxStringHashSet)); string->name = bStr; HASH_ADD_KEYPTR(hh, sset, string->name, strlen(string->name), string); } } } closedir(dir); } FcitxXDGFreePath(xdgPath); return sset; }
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; }
int main(int argc, char* argv[]) { char* localedir = fcitx_utils_get_fcitx_path("localedir"); setlocale(LC_ALL, ""); bindtextdomain("fcitx", localedir); free(localedir); bind_textdomain_codeset("fcitx", "UTF-8"); textdomain("fcitx"); FcitxLogSetLevel(FCITX_NONE); int c; char* addonList = NULL, *sandboxDirectory = NULL; char *buf = NULL, *buf1 = NULL; FILE* fp = NULL; char* enableAddon = NULL; char* imname = NULL; int ret = 1; int fd = -1; while ((c = getopt(argc, argv, "d:i:h")) != EOF) { switch (c) { case 'i': imname = strdup(optarg); break; case 'd': sandboxDirectory = strdup(optarg); break; case 'h': default: goto option_error_end; } } /* processs [addon list] */ if (optind >= argc) goto option_error_end; addonList = strdup(argv[optind]); /* script file */ if (optind + 1 < argc) { fp = fopen(argv[optind + 1], "rt"); } else { fp = stdin; } if (!fp) { goto option_error_end; } if (!addonList) { goto option_error_end; } sem_t sem; sem_init(&sem, 0, 0); asprintf(&enableAddon, "fcitx-simple-module,fcitx-simple-frontend,%s", addonList); /* reset optind, since FcitxInstanceCreatePause will use getopt again */ optind = 1; char* args[] = { argv[0], "-D", "--disable", "all", "--enable", enableAddon, "--ui", "fcitx-simple-ui" }; char temp[] = "/tmp/fcitx_sandbox_XXXXXX"; if (sandboxDirectory) { setenv("XDG_CONFIG_HOME", sandboxDirectory, 1); } else { /* * we make a file on purpose, since XDG_CONFIG_HOME should be a directory * hence this will prevent every write operation under XDG_CONFIG_HOME */ fd = mkstemp(temp); if (fd == -1) { setenv("XDG_CONFIG_HOME", "/", 1); } else { close(fd); setenv("XDG_CONFIG_HOME", temp, 1); } } instance = FcitxInstanceCreatePause(&sem, 8, args, -1); if (sem_trywait(&sem) == 0) goto option_error_end; FcitxSimpleInit(instance, TestbedCallback, NULL); FcitxInstanceStart(instance); size_t len = 0; if (imname) { FcitxSimpleSetCurrentIM(instance, imname); } while (getline(&buf, &len, fp) != -1) { fcitx_utils_free(buf1); buf1 = fcitx_utils_trim(buf); FcitxKeySym sym = FcitxKey_None; unsigned int state = 0; FcitxHotkeyParseKey(buf1, &sym, &state); if (FcitxSimpleSendKeyEvent(instance, false, sym, state, 0) == 0) { fprintf(stderr, "FORWARD:%s\n", buf1); } usleep(1000); } FcitxSimpleEnd(instance); FcitxInstanceWaitForEnd(instance); ret = 0; option_error_end: if (fd >= 0) unlink(temp); if (fp) fclose(fp); if (ret) usage(); fcitx_utils_free(imname); fcitx_utils_free(buf); fcitx_utils_free(buf1); fcitx_utils_free(enableAddon); fcitx_utils_free(addonList); fcitx_utils_free(sandboxDirectory); return ret; }