gencin.c
来自「linux 下的 oxim 输入法,简单易用.」· C语言 代码 · 共 577 行
C
577 行
/* Copyright (C) 2006 by OXIM TEAM This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/ #ifdef HAVE_CONFIG_H# include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <locale.h>#include <unistd.h>#include "oximtool.h"#include "oxim2tab.h"static char validkey[128];static cintab_head_t th;static ichar_t *ichar = NULL;static icode_t *icode1 = NULL;static icode_t *icode2 = NULL;/* 所有詞的字元數目 */static unsigned int n_word = 0;static unsigned int table_size = 0;static char *word_table = NULL;static char *default_selection_keys = "1234567890";/*-------------------------------------------------------------------------- Normal cin2tab functions.--------------------------------------------------------------------------*/static voidcin_ename(char *arg, cintab_t *cintab){ if (! arg[0]) oxim_perr(OXIMMSG_ERROR, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); strncpy(th.ename, arg, CIN_ENAME_LENGTH); th.ename[CIN_ENAME_LENGTH - 1] = '\0';}static voidcin_cname(char *arg, cintab_t *cintab){ if (! arg[0]) oxim_perr(OXIMMSG_ERROR, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); strncpy(th.cname, arg, CIN_CNAME_LENGTH); th.cname[CIN_CNAME_LENGTH - 1] = '\0';}static voidcin_selkey(char *arg, cintab_t *cintab){ if (! arg[0]) oxim_perr(OXIMMSG_ERROR, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); th.n_selkey = strlen(arg); if (th.n_selkey > SELECT_KEY_LENGTH) { oxim_perr(OXIMMSG_NORMAL, N_("%s(%d): too many selection keys defined.\n"), cintab->fname_cin, cintab->lineno); th.n_selkey = 10; strcpy(th.selkey, "1234567890"); } else { strcpy(th.selkey, arg); } /* 設定合法字元表 */ char *s = th.selkey; for (; *s ; s++) { validkey[*s] = '\1'; }}static voidscim_selkey(char *arg, cintab_t *cintab){ unsigned int i; unsigned int len = strlen(arg); char selection_keys[256]; if (!arg[0]) { oxim_perr(OXIMMSG_ERROR, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); } bzero(selection_keys, 256); char *s = selection_keys; for (i=0 ; i < len; i++) { if (arg[i] != ',') { *s = arg[i]; s++; } } th.n_selkey = strlen(selection_keys); if (th.n_selkey > SELECT_KEY_LENGTH) { oxim_perr(OXIMMSG_NORMAL, N_("SCIM table \"%s\" line %d: too many selection keys defined. Use default selection keys \"%s\".\n"), cintab->fname_cin, cintab->lineno, default_selection_keys); th.n_selkey = strlen(default_selection_keys); strcpy(th.selkey, default_selection_keys); } else { strcpy(th.selkey, selection_keys); } /* 設定合法字元表 */ s = th.selkey; for (; *s ; s++) { validkey[*s] = '\1'; }}static voidcin_endkey(char *arg, cintab_t *cintab){ if (! arg[0]) oxim_perr(OXIMMSG_ERROR, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); th.n_endkey = strlen(arg); if (th.n_endkey > END_KEY_LENGTH) oxim_perr(OXIMMSG_ERROR, N_("%s(%d): too many end keys defined.\n"), cintab->fname_cin, cintab->lineno); strcpy(th.endkey, arg); /* 設定合法字元表 */ char *s = th.endkey; for (; *s ; s++) { validkey[*s] = '\1'; }}static voidcin_keyname(char *arg, cintab_t *cintab){ char cmd1[64], arg1[64]; int k, argc; while (argc = cmd_arg(True, cmd1, 64, arg1, 64, NULL)) { if ((strcasecmp("%keyname", cmd1) == 0 && strcasecmp("end", arg1) == 0) || strcasecmp("END_CHAR_PROMPTS_DEFINITION", cmd1) == 0) { break; } if (argc != 2 || strlen(cmd1) != 1) { continue; } cmd1[0] = tolower(cmd1[0]); if (! (k = oxim_key2code(cmd1[0]))) { oxim_perr(OXIMMSG_ERROR, N_("%s(%d): illegal key \"%c\" specified.\n"), cintab->fname_cin, cintab->lineno, cmd1[0]); } if (th.keyname[k].uch) { oxim_perr(OXIMMSG_NORMAL, N_("%s(%d): key \"%c\" is already in used.overwrite it.\n"), cintab->fname_cin, cintab->lineno, cmd1[0]); strncpy((char *)th.keyname[k].s, arg1, UCH_SIZE); continue; } validkey[cmd1[0]] = '\1'; if (! read_hexwch(th.keyname[k].s, arg1)) strncpy((char *)th.keyname[k].s, arg1, UCH_SIZE); th.n_keyname++; }}/*------------------------------------------------------------------------*/typedef struct { unsigned int key[2]; unsigned int ucs4; unsigned int order; char *keystroke; unsigned short word_len; char *word;} cin_char_t;static cin_char_t *cchar = NULL;static inticode_cmp(const void *a, const void *b){ cin_char_t *aa=(cin_char_t *)a, *bb=(cin_char_t *)b; if (aa->key[0] == bb->key[0]) { if (aa->key[1] == bb->key[1]) { if (aa->order < bb->order) { return 1; } else if (aa->order > bb->order) { return -1; } else { return 0; } } else if (aa->key[1] > bb->key[1]) { return 1; } else { return -1; } } else if (aa->key[0] > bb->key[0]) return 1; else return -1;}static voidcin_chardef(char *arg, cintab_t *cintab){ char cmd1[64], arg1[1024] = {'\0'}, arg2[32]= {'\0'}; cin_char_t *cch=NULL; int len, ret, argc; unsigned int i, key, key_len; while ((argc=cmd_arg(True, cmd1, 64, arg1, 1024, arg2, 32, NULL))) { if ((strcasecmp("%chardef", cmd1) == 0 && strcasecmp("end", arg1) == 0) || strcasecmp("END_TABLE", cmd1) == 0) { break; } if (argc < 2 || argc > 3) { oxim_perr(OXIMMSG_WARNING, N_("%s(%d): arguement expected.\n"), cintab->fname_cin, cintab->lineno); continue; } /* TODO : 字根目前限制不能超過 10 個(未來要改為不限制)*/ key_len = strlen(cmd1); if (key_len > 10) { continue; } /* * 看看字根中,是否有不合法的字元 * 所謂不合法,就是在 selkey、keyname、endkey 沒有定義的字元 */ int allkey_valid = True; for (i=0 ; i < key_len ; i++) { cmd1[i] = tolower(cmd1[i]); int kk = cmd1[i]; if (!validkey[kk]) { if (i || cmd1[i] != '#') { oxim_perr(OXIMMSG_WARNING, N_("%s(%d): illegal key \"%c\" specified.\n"), cintab->fname_cin, cintab->lineno, cmd1[i]); } allkey_valid = False; break; } } if (!allkey_valid) { continue; } th.n_icode ++; if (th.n_icode == 1) { cchar = oxim_malloc(sizeof(cin_char_t), True); } else { cchar = oxim_realloc(cchar, (th.n_icode+1) * sizeof(cin_char_t)); } cch = (cchar + th.n_icode) - 1; bzero(cch, sizeof(cin_char_t)); if ((cch->ucs4 = ccode_to_ucs4(arg1)) == 0) { n_word ++; cch->word_len = strlen(arg1); cch->word = strdup(arg1); table_size += cch->word_len + sizeof(cch->word_len); } if (arg2[0] != '\0') { cch->order = atoi(arg2); } oxim_keys2codes(cch->key, 2, cmd1); cch->keystroke = strdup(cmd1); th.n_ichar ++; len = strlen(cmd1); if (th.n_max_keystroke < len) th.n_max_keystroke = len; arg2[0] = '\0'; } /* * Determine the memory model. */ ret = (th.n_max_keystroke <= 5) ? ICODE_MODE1 : ICODE_MODE2; th.icode_mode = ret; /* * Fill in the ichar, icode_idx and icode1, icode2 arrays. */ stable_sort(cchar, th.n_icode, sizeof(cin_char_t), icode_cmp); ichar = oxim_malloc(th.n_icode * sizeof(ichar_t), True); icode1 = oxim_malloc(th.n_icode*sizeof(icode_t), True); if (ret == ICODE_MODE2) { icode2 = oxim_malloc(th.n_icode*sizeof(icode_t), True); } if (n_word) { word_table = oxim_malloc(table_size, True); } unsigned int word_idx = 0; unsigned int offset = 0; unsigned int rec_len = 0; for (i=0, cch=cchar; i<th.n_icode; i++, cch++) { ichar[i] = cch->ucs4; /* ucs4 為 0 表示該筆紀錄是詞而不是字元 */ if (!ichar[i]) { /* usc4 改成指向 offset_table 索引,再 or 0x80000000,讓程式可以判別這是字元或是指向 offset table */ /* 紀錄詞的偏移位置 */ ichar[i] = WORD_MASK | offset; /* 計算下一個 offset */ rec_len = sizeof(cch->word_len) + cch->word_len; memcpy(word_table + offset, &cch->word_len, sizeof(cch->word_len)); memcpy(word_table + offset + sizeof(cch->word_len), cch->word, cch->word_len); offset += rec_len; //free(cch->word); } icode1[i] = (icode_t)(cch->key[0]); if (ret == ICODE_MODE2) icode2[i] = (icode_t)(cch->key[1]); } //free(cchar);}/*---------------------------------------------------------------------------- Main Functions.----------------------------------------------------------------------------*/struct genfunc_s { char *name; void (*func) (char *, cintab_t *); byte_t gotit;};static struct genfunc_s genfunc[] = { {"%ename", cin_ename, 1}, {"NAME", cin_ename, 1}, {"%cname", cin_cname, 1}, {"%prompt", cin_cname, 1}, {"%keyname", cin_keyname, 1}, {"BEGIN_CHAR_PROMPTS_DEFINITION", cin_keyname, 1}, {"%selkey", cin_selkey, 1}, {"SELECT_KEYS", scim_selkey, 1}, {"%endkey", cin_endkey, 1}, {"KEY_END_CHARS", cin_endkey, 1}, {"%chardef", cin_chardef, 1}, {"BEGIN_TABLE", cin_chardef, 1}, {NULL, NULL, 0}};voidgencin(cintab_t *cintab){ int i; char cmd[64], arg1[64], arg2[64]; size_t ret; bzero(validkey, 128); bzero(&th, sizeof(cintab_head_t)); strncpy(th.version, GENCIN_VERSION, VERLEN); strncpy(th.encoding, "UTF-8", ENCLEN); while (cmd_arg(False, cmd, 64, arg1, 64, arg2, 64, NULL)) { for (i=0; genfunc[i].name != NULL; i++) { if (strcasecmp(genfunc[i].name, cmd) == 0) { if (strlen(arg1) == 1 && arg1[0] == '=') { genfunc[i].func(arg2, cintab); } else { genfunc[i].func(arg1, cintab); } genfunc[i].gotit = 1; break; } /* SCIM 的 Locale Name */ else if (strncasecmp("NAME.", cmd, 5) == 0) { cin_cname(arg2, cintab); } } if (genfunc[i].name == NULL) oxim_perr(OXIMMSG_NORMAL, N_("%s(%d): unknown command: %s, ignore.\n"), cintab->fname_cin, cintab->lineno, cmd); } for (i=0; genfunc[i].name != NULL; i++) { if (genfunc[i].gotit == 0) oxim_perr(OXIMMSG_ERROR, N_("%s: command \"%s\" not specified.\n"), cintab->fname_cin, genfunc[i].name); } oxim_perr(OXIMMSG_NORMAL, N_("number of keyname: %d\n"), th.n_keyname); oxim_perr(OXIMMSG_NORMAL, N_("max length of keystroke: %d\n"), th.n_max_keystroke); oxim_perr(OXIMMSG_NORMAL, N_("number of keystroke code defined: %d\n"), th.n_icode); oxim_perr(OXIMMSG_NORMAL, N_("number of char defined: %d\n"), th.n_icode - n_word); oxim_perr(OXIMMSG_NORMAL, N_("number of word: %d\n"), n_word); oxim_perr(OXIMMSG_NORMAL, N_("memory model: %d\n"), th.icode_mode); if (!cintab->fname_outcin) { ret = gzwrite(cintab->fw, &th, sizeof(cintab_head_t)); ret = gzwrite(cintab->fw, icode1, sizeof(icode_t) * th.n_icode); ret = gzwrite(cintab->fw, ichar, sizeof(ichar_t) * th.n_icode); if (th.icode_mode == ICODE_MODE2) { ret = gzwrite(cintab->fw, icode2, sizeof(icode_t) * th.n_icode); } if (n_word) { ret = gzwrite(cintab->fw, word_table, table_size); } return; } FILE *fp = cintab->cinfp; /* 標準 cin 檔頭標記 */ fprintf(fp, "%%gen_inp\n"); /* English Name */ if (strlen(th.ename)) { fprintf(fp, "%%ename %s\n", th.ename); } /* Chinese Name */ if (strlen(th.cname)) { fprintf(fp, "%%cname %s\n", th.cname); } /* Selection keys */ if (strlen(th.selkey)) { fprintf(fp, "%%selkey %s\n", th.selkey); } /* End keys */ if (strlen(th.endkey)) { fprintf(fp, "%%endkey %s\n", th.endkey); } /* */ if (th.n_keyname) { int k, kn; fprintf(fp, "%%keyname begin\n"); for (k=0 ; k < N_KEYCODE ; k++) { kn = oxim_code2key(k); if (th.keyname[k].uch) { kn = oxim_code2key(k); fprintf(fp, "%c %s\n", (char)kn, (char *)th.keyname[k].s); } } fprintf(fp, "%%keyname end\n"); } /* 寫入字根與字元對照段落*/ fprintf(fp, "%%chardef begin\n"); char utf8[UCH_SIZE]; cin_char_t *cch; for (i=0, cch = cchar ; i < th.n_icode ; i++, cch++) { if (ichar[i] & WORD_MASK) { char *slash = oxim_addslashes(cch->word); if (slash) { fprintf(fp, "%s\t\"%s\"\n", cch->keystroke, slash); free(slash); } else { fprintf(fp, "%s\t\"%s\"\n", cch->keystroke, cch->word); } } else { if (oxim_ucs4_to_utf8(ichar[i], utf8)) { switch (ichar[i]) { case ' ': fprintf(fp, "%s\t\" \"\n", cch->keystroke); break; case '\"': fprintf(fp, "%s\t%s\n", cch->keystroke, "\\\""); break; default: fprintf(fp, "%s\t%s\n", cch->keystroke, utf8); break; } } } } fprintf(fp, "%%chardef end\n"); return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?