给他们国内做PDA,手机输入法的同行们参考(呵,写的比较粗糙):

1。字符分类:
1.1子音Cons(consonants),44个子音0xa1-0xce
这类字符比较简单,可独立对应于键盘的1-9

1( ก ข ฃ ค ฅ)2(ฆ ง จ ฉ) 3 (ช ซ ฌ ญ)

4(ฎ ฏ ฐ ฑ ฒ ณ)5(ด ต ถ ท ธ)6(น บ ป ผ ฝ)

7(พ ฟ ภ ม ย)8(ร ล ว ศ ษ)9(ส ห ฬ อ ฮ)
其中有两个0xc4,0xc6为特殊音,不在此类

1.2元音Vowels

1.3音调Tone 4个音调0xe8,0xe9.0xea,0xeb

1.4变音符Diacritics,分为上变音符,下变音符。

1.5非构成音,如数字或特殊音,一般都不提供泰文数字输入,而用阿拉伯数字替换。

具体的分类可查看<<Thai Input and output Methods>>

这个文档必须仔细阅读,要不你就没法进行输入法的编写。至少要知道LV,FV1.,FV2,FV3,BV1,.....是个什么概念

2.字符显示的属性

泰文的一个显示单位可由组成:,2.above,3.base 4.below.
就是分为四层,如กี่就有top,above,base三部分.base一般为子音
因泰文可由以上几部分组成,因此这里就会在输入一些字符后, 光标往前走,还是和前一字符全成的问题。

这里有个字义,死字符(Dead characters):
在输入死字符后,后面再输入的字符,不能与死字符合成,必须得移动光标的字符称为死字符。如上面的音调就是死字符

3.字符显示

我们可以定义泰文字符为Cn和Cn-1,Cn-1为主导字符(base),Cn为随从字符
如果Cn为一个独立字符,就显示下个显示单位
如果Cn为一个死字符,
    1.Cn-1是合成字符,则两个字符组合后,显示到下个显示单位
    2.Cn-1不是合成字符,则把Cn显示到下一个显示单位上。
    3.Cn-1与Cn组成为非法字符,则不显示

4.输入法规则

每个显示单位必须是以base字符为基本(base字符的意思为单个字符能独立构成一个意义,如子音)

这里不写很复杂,对于手机或PDA来说,输入法不同与PC键盘。
上面提到1-9对应的泰文字符,全部是子音。这里我们把除子音外的字符都放到一个键中,就如在英文输入法中的标点符号输入一样。


“*”号键包括的内容:

分为三类(8,5,14,共27个)

(一)  ั   ิ   ี   ึ   ื   ็    ุ   ู 

(二)่    ้    ๊   ๋     

(三)เ แ โ ใ ไ ะ า ำ ๅ ฯ ๆ ฤ ฦ ฿

在输入框输入泰文时,在“*”中的字符根据前一字符Cn-1进行调整。

1.      在子音后选择第一类后不能再选择一类符号,可选择二、三类符号

2.      在子音后选择第二类后不能再选择一、二类符号,可选择三类符号

3.      在子音后选择第三类后,不能再选择一、二类符号,但可以继续选择第三类符号

4.      无子音情况下能输入第三类符号,以独立的字符存在,不能在和“*”中的叠加组合成新符。

5.      第三类中“ฤ”,“ฦ”比较特殊,和子音操作一样,可在后面选择第一、二类字符。

当然以上5点规则并不完善,你可通过<<Thai Input and output Methods>>得出标准的规则:

5。

1.    代码分析:

1-9对应的泰文数组
/*  数字键与泰文字母的对应表  *///added by yrui 20050810 for thai input
ImeEnTBL ThaiTbl[IME_THAI_CONS_COUNT + 11] = {
                         {'0', '0'},
                         {'1', 0xa1},
                         {'1', 0xa2},
                         {'1', 0xa3},
                         {'1', 0xa4},
                         {'1', 0xa5},
                         {'1', '1'},
                         {'2', 0xa6},
                         {'2', 0xa7},
                         {'2', 0xa8},
                         {'2', 0xa9},
                         {'2', '2'},
                         {'3', 0xaa},
                         {'3', 0xab},
                         {'3', 0xac},
                         {'3', 0xad},
                         {'3', '3'},
                         {'4', 0xae},
                         {'4', 0xaf},
                         {'4', 0xb0},
                         {'4', 0xb1},
                         {'4', 0xb2},
                         {'4', 0xb3},
                         {'4', '4'},
                         {'5', 0xb4},
                         {'5', 0xb5},
                         {'5', 0xb6},
                         {'5', 0xb7},
                         {'5', 0xb8},
                         {'5', '5'},
                         {'6', 0xb9},
                         {'6', 0xba},
                         {'6', 0xbb},
                         {'6', 0xbc},
                         {'6', 0xbd},
                         {'6', '6'},
                         {'7', 0xbe},
                         {'7', 0xbf},
                         {'7', 0xc0},
                         {'7', 0xc1},
                         {'7', 0xc2},
                         {'7', '7'},
                         {'8', 0xc3},
                         {'8', 0xc5},
                         {'8', 0xc7},
                         {'8', 0xc8},
                         {'8', 0xc9},
                         {'8', '8'},
                         {'9', 0xca},
                         {'9', 0xcb},
                         {'9', 0xcc},
                         {'9', 0xcd},
                         {'9', 0xce},
                         {'9', '9'},
                         {'/0',  '/0'}
};
 
ImeEnTBL * ThaiTblIdx[IME_NUMBER_COUNT] = {//added by yrui 20050810 for thai input
                            NULL,
                            &ThaiTbl[1],
                            &ThaiTbl[2],
                            &ThaiTbl[3],
                            &ThaiTbl[4],
                            &ThaiTbl[5],
                            &ThaiTbl[6],
                            &ThaiTbl[7],
                            &ThaiTbl[8],
                            &ThaiTbl[9]
};
 
 
//“*”号键对应的字符
//added by yrui 20050817 for thai input
char  ThaiSymbolTbl[IME_SYMBOL_ROWS][IME_THAI_SYMBOL_COLS][IME_SYMBOL_SIZE] = 
{
              {
              {(char)0xd1, 0, 0,0},     
              {(char)0xd4, 0, 0,0},     
              {(char)0xd5, 0,0,0},      
              {(char)0xd6, 0, 0,0},     
              {(char)0xd7, 0, 0,0},     
              {(char)0xe7, 0, 0,0},     
              {(char)0xd8, 0, 0,0},     
              {(char)0xd9, 0, 0,0},     
              {(char)0xda, 0,0,0},  //第一批
              {(char)0xe8, 0, 0,0},     
              //
       //     {(char)0xed, 0, 0,0},     
       //     {(char)0xda, 0,0,0},
              },                     
              
              {
              
              {(char)0xe9, 0, 0,0},     
              {(char)0xea, 0,0,0},      
              {(char)0xeb, 0, 0,0},     
              {(char)0xec, 0, 0,0},  
              {(char)0xed, 0, 0,0},   //第二批  
              {(char)0xe0, 0, 0,0},     
              {(char)0xe1, 0, 0,0},     
              {(char)0xe2, 0, 0,0},     
              {(char)0xe3, 0, 0,0},     
              {(char)0xe4, 0,0,0},    
              //
       //     {(char)0xed, 0, 0,0},     
       //     {(char)0xda, 0,0,0},
              },                    
              
              {
              {(char)0xd0, 0, 0,0},     
              {(char)0xd2, 0, 0,0},     
              {(char)0xd3, 0,0,0},      
              {(char)0xe5, 0, 0,0},     
              {(char)0xcf, 0, 0,0},     
              {(char)0xe6, 0, 0,0},     
              {(char)0xc4, 0, 0,0},     
              {(char)0xc6, 0, 0,0},     
              {(char)0xdf, 0, 0,0},     
              {(char)0xef, 0,0,0},     
              //
       //     {(char)0xed, 0, 0,0},     
       //     {(char)0xda, 0,0,0},
              }      
       
              
              
};
 
 
TACchtype数组为ascii码对应的泰文字符分类 
char TACchtype_[256] = {
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  0 -  7 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  8 - 15 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 16 - 23 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 24 - 31 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 32 - 39 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 40 - 47 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 48 - 55 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 56 - 63 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 64 - 71 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 72 - 79 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 80 - 87 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 88 - 95 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 96 - 103 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 104 - 111 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 112 - 119 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL,  /* 120 - 127 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 128 - 135 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 136 - 143 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 144 - 151 */
    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 152 - 159 */
    NON,  CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 160 - 167 */
    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 168 - 175 */
    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 176 - 183 */
    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 184 - 191 */
    CONS, CONS, CONS, CONS,  FV3, CONS,  FV3, CONS,  /* 192 - 199 */
    CONS, CONS, CONS, CONS, CONS, CONS, CONS, NON,   /* 200 - 207 */
    FV1,  AV2,  FV1,  FV1,  AV1,  AV3,  AV2,  AV3,   /* 208 - 215 */
    BV1,  BV2,  BD,   NON,  NON,  NON,  NON,  NON,   /* 216 - 223 */
    LV,   LV,   LV,   LV,   LV,   FV2,  NON,  AD2,   /* 224 - 231 */
    TONE, TONE, TONE, TONE, AD1,  AD1,  AD3,  NON,   /* 232 - 239 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 240 - 247 */
    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL   /* 248 - 255 */
}; 
TACio_op数组为Cn-1和Cn的组合规则
AC表示可接受
CP表示合成接受
SR表示严格规则下拒绝
RJ表示拒绝
XC表示接受,不显示
 
/* Table for Thai Cell Manipulation */
char TACio_op_[17][17] = {
      /* Table 2: WTT I/O sequence check rules */
      /* row: leading char,  column: following char */
/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
  ,{XC, AC, AC, AC, AC, SR, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
  ,{XC, SR, AC, SR, SR, SR, SR, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
  ,{XC, AC, AC, AC, AC, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
  ,{XC, AC, AC, AC, AC, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
  ,{XC, AC, AC, AC, SR, AC, SR, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/
  ,{XC, AC, AC, AC, AC, SR, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
  ,{XC, AC, AC, AC, SR, SR, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
}; 
int TACchtype(char c)
{
    return TACchtype_[c];
}int TACio_op(char c1, char c2)
{
    return TACio_op_[TACchtype_[c1]][TACchtype_[c2]];
} 
以上代码可从libthai开源代码中下载
有了这个规则代码,你的输入法基本就可以成型了
 
你只需得到输入框中的前一个字符Cn-1,然后与ThaiSymbolTbl数组的每个字符运算一下 
For(ThaiSymbolTbl)
{
Re=TACio_op(Cn-1, ThaiSymbolTbl[i])
  if(re!=SR&&re!=RJ)    在“*”键中显示此字符
}

 

6。编辑移动

1.子音与上下标元音或声调组成后,编辑时以整体处理。

2.但删除一个合成音时,按反过来的顺序删除合成的子字符。