在炎黃中文平台上,用戶可以自行添加輸入法。炎黃中文平台的輸入部分的程序設計使用了一個主導模塊作為和平台的接口,它和各輸入法模塊之間采用統一的、規范的界面。各個輸入法可看作是一個個過濾,輸入ASCII碼,返回得到的漢字。
輸入法的主導模塊以動態連接庫(libimpi.a)的形式存在,和各輸入法模塊連接成單獨的可執行文件。對於每一個具體的輸入法,只需要按照一定的數據結構就可以鏈接成為新的可執行文件,並且添加到炎黃中文平台上。這些數據結構包括外部變量和外部函數。
1、外部變量
數組extcode[]:字符串類型,表示輸入的外碼串;
數組candstr[]:字符串類型,表示重碼的待選串;
數組result[]:字符串類型,表示得到的結果串;
數組imname[]:字符串類型,表示輸入法的名稱;
數組imdscrpt[]:字符串類型,表示對輸入法的描述。
變量maxeclen:整型,表示外碼的最大長度;
變量eclen:整型,表示外碼的長度。
這些變量的定義如下所示:
extern int maxeclen; /* The maximum length of external code */
extern int eclen; /* The length of external code */
extern char extcode[]; /* External code */
extern char candstr[]; /* Candinate string */
extern char result[]; /* Result string */
2、外部函數
外部函數一共有四個,它們分別是IMInit()、IMCleanup()、IMSelect()和IMFilter()。這四個函數的定義分別如下所示:
int IMInit();
int IMClearup();
int IMSelect(int select);
int IMFilter(int ch);
其中IMInit()函數用來完成輸入法的初始化工作;IMClearup()函數用來對輸入法被釋放時的情況進行處理; IMSelect()函數用來處理當前輸入法被選中的情況;IMFilter()是輸入法的核心函數,用來對接收的字符串進行過濾,得到正確的輸入結果。
下面以區位輸入法為例對此進行簡單的介紹。
准備工作
首先需要取得libimpi.a文件,然後可以創建一個qvwei目錄。
代碼編寫
編譯一個qvwei.c文件,接著對輸入法進行初始化,這時候的qvwei.c如下所示:
/* The qvwei input method
*/
#include
#include
#include
#include
#include "impi.h"
char imname[] = "區位";
char imdscrpt[] = "區位輸入法";
static void reset();
static void append(int ch);
static void comp_appe(int prevch, int ch);
int IMInit()
{
return 0;
}
int IMClearup()
{
return 0;
}
int IMSelect(select)
int select;
{
return 0;
}
int IMFilter(ch)
int ch;
{
}
接下來的工作就是編寫IMInit()、IMClearup()、IMSelect()和IMFilter()這四個函數了。
在IMInit()函數中添加如下的代碼:
maxeclen = 5;
reset();
return 0;
由於區位輸入法比較簡單,IMClearup()和IMSelect()函數都不需要額外添加代碼,在IMFilter()這個函數中加入如下的處理代碼:
candstr[0] = '\0';
result[0] = '\0';
/* process currnet keystroke */
if (isdigit(ch))
{
if ((eclen == 1) || (eclen == 3))
comp_appe(extcode[eclen - 1], ch);
else
append(ch);
if (eclen == 4)
{
int qv, wei;
qv = (extcode[0] - '0') * 10 + (extcode[1] - '0');
wei = (extcode[2] - '0') * 10 + (extcode[3] - '0');
reset();
result[0] = qv + 0xa0;
result[1] = wei + 0xa0;
result[2] = '\0';
}
}
else
{
if ((ch == KEY_BACKSPACE) && (eclen > 0))
extcode[--eclen] = '\0';
else
{
result[0] = ch;
result[1] = '\0';
}
}
/* generate candinates */
if ((eclen > 0) && (eclen < 4))
{
int qv, wei, i, w;
char buf[3];
char *p;
if (eclen > 1)
qv = (extcode[0] - '0') * 10 + (extcode[1] - '0');
else if (extcode[0] == '0')
qv = 1;
else
qv = (extcode[0] - '0') * 10;
wei = (eclen < 3) ? 0 : (extcode[2] - '0') * 10;
p = candstr;
for (i = 0; i <= 9; i++)
{
w = wei + i;
if ((w > 0) && (w <= 94))
{
buf[0] = qv + 0xa0;
buf[1] = wei + i + 0xa0;
buf[2] = '\0';
p += sprintf(p, " %d: %s", i, buf);
}
}
}
return 0;
上面的代碼中用到了另外三個函數,這三個函數可以定義為局部函數,它們的實現代碼如下所示:
static void reset(void)
{
eclen = 0;
extcode[0] = '\0';
candstr[0] = '\0';
result[0] = '\0';
}
static void append(ch)
int ch;
{
extcode[eclen++] = ch;
extcode[eclen] = '\0';
}
static void comp_appe(prevch, ch)
int prevch;
int ch;
{
if (prevch == '0')
{
if (ch != '0')
append(ch);
}
else if (prevch == '9')
{
if (ch <= '4')
append(ch);
}
else
append(ch);
}
把上面的代碼拼接起來,就是一個完整的qvwei.c文件。
編譯和鏈接
最後可以編寫一個MakeFile來創建可執行的輸入法文件。一個Makefile的例子如下所示:
qvwei:
cc ?c qvwei.c
cc ?o $@ qvwei.o libimpi.a
strip $@
rm ?f *.o
然後只需要在這個目錄下鍵入make,就可以創建一個可執行的qvwei文件。在運行炎黃中文平台之後運行這個qvwei文件,就可以把這個輸入法添加到炎黃中文平台中,平台會自動給這個輸入法分配切換快捷鍵。
注意事項:
1:隨同打包的還有四個文件,它們分別是impi.c、impi.h、incommon.c和imcommon.h,它們的作用是用來生成libimpi.a。提供這四個函數源代碼的用意是方便用戶對輸入法的理解。但是絕對不要改變這四個文件並且重新編譯libimi.a,否則炎黃中文平台有可能無法識別新生成的輸入法。
2:以上只是一個簡單的示例,針對不同的輸入法類型,輸入法的核心代碼可能要復雜得多。