VIA 输入法 处理流程

 

VIA
的Selle版本中集成了EZI的输入法核心,但外围的实现,如按键,候选,翻页等,都是由VIA自己实现的,其过程也比较复杂,现就移植盲人输入法所总结的与大家分享.
(以下以En输入法为例来说明,代码均为伪代码,仅为说明意图,最后有补充的IME的相关基本概念可参考)
[A]从按键到得到候选字的过程.
1.首先由ImeManagerC的KeyHandler来接收按键消息.
ImeManagerC::KeyHandler(uint32 KeyCode, uint32 KeyMsg){
  ImeC * ImeP = GetCurrentIme();
  if (ImeP->KeyHandler(KeyCode, KeyMsg))
             }
ImeP->KeyHandler多态地实现了不同Ime调用不同的keyHandler.如EN则会调用
ImeCandidateEnLowerC 这个类的实现,又由于ImeCandidateEnLowerC 没有实现KeyHandler 的处理,而是由他的基类 CandidateImeC 来实现的.
2.基类 CandidateImeC
实现了从ImeManagerC接收到的KeyHandler处理.
   bool
CandidateImeC::KeyHandler(uint32 KeyCode, uint32 KeyMsg){
        ImeEngineC *
EngineP = ImeManagerC::GetImeEngine();
        if
(
EngineP->AddElement(KeyCode))
        {
          if
(EngineP->IsElementBufferEmpty())
          {
           
CloseCandidate();
          }
          else
          {
           
ElementAdded();
          }
        }
从这里可以看出:真正由按键到候选的映射由有ImeEngine来实现的,这里的为EZI(当然还有别的其它Engine如T5),AddElement()的过程在这里不做更进一步的说明,其核心就是,把一个按键消息及其它相关变量映射出一组候选,并把此组候选放到一个Vector里.
 当按键结束后会就会调用CandidateImeC
的子类,来区别处理按键结束后的动作,这里即为,在屏幕上显示一个候选框,把在Vector里的内容,显示在此候选框中.
3.ElementAdded()的处理:
void
ImeCandidateEnLowerC::ElementAdded()
{
 GetCandidate(mSubCandidate,
0);
 bool NewCandidate =
ShowCandidate(CANDIDATE_MODE_NORMAL);
 mCandidateCtrlP->SetCandidates(&mSubCandidate,
1);
 if (!NewCandidate)
 {
   
DrawCandidate();
 }
}
GetCandidate() 实现了把由ImeEngine生成的候选Vector的内容赋值到mSubCandidate结构体中.
ShowCandidate()实现了在屏幕上显示候选区域的相关操作.
SetCandidates() 把mSubCandidate中的候选内容显示在屏幕上的候选区.
DrawCandidate()
调用DC具体实现在屏幕上的绘制工作.
至些,由按键到候选字的过程完成.下面是在候选区中选择,移动候选字的过程.
[B]选择一个候选字,切换候选字,候选字的翻页功能的实现.
1.候选区的操作与上有些类似,由ImeManagerC到CandidateImeC::KeyHandler来具体实现:
 if
(CandidateShowed())
 {
    if (KeyMsg ==
KEYMSG_PRESS)
    {
      return
HandleCandidateKey(KeyCode, KEYMSG_PRESS);
    }
    return TRUE;
    }
HandleCandidateKey()中主要实现了两个功能,第一是,处理在候选区的按键,其二是,跟据候选区移动的状态,更新候选区.
 (1)处理候选区的按键:
                    bool Ret = mCandidateCtrlP->OnKeyPress(KeyCode);
这里处理如Select按键,在候选区左右上下移动光标等操作.
 if
((KeyCode == KP_LEFT_KEY)
    ||
(KeyCode == KP_RIGHT_KEY)
    ||
(KeyCode == KP_UP_KEY)
    ||
(KeyCode == KP_DOWN_KEY)
    ||
(KeyCode == MAIN_CANIDIDATE_NAV_KEY))
 {
    return HandleNavigateKey(KeyCode);
 }
 else if
(KeyCode == KP_CENTER_SOFT_KEY)
 {
    return HandleSelectKey();
 }
如果是Select消息,则HandleSelectKey()会把一个状态变量
   mState.mType =
CANDIDATE_STATE_SELECTED;
          在HandleCandidateKey()
 if
(State.mType == CANDIDATE_STATE_SELECTED)
 {
CandidateSelected(State.mArea, State.mIndex);
   
return TRUE;
 }
CandidateSelected会处理把候选显示到屏幕上的相关操作,会回调CandidateImeC::InsertString()来处理显示,察看相关代码即可知.
这里着重说一下,在候选区移动光标,翻页的实现.以KP_RIGHT_KEY为例.首先会调用HandleNavigateKey()—->UpdateSelRect(mSubCandidateinfo, KeyCode))
UpdateSelRect()
这个函数是处理相关操作的关键,如在候选区中选右方向键,选择右边的候选字,此时要判断当前的位置,当前行,当前列(即在一行的中位置),判断是否超出此行,是否超出了此候选区中所有的内容,即在候选区中最后一位继续向后移动,显示更多候选内容.这时,会有状态变量来记录此时的变化.
     mState.mType =
CANDIDATE_STATE_NEED_MORE_DATA;
    
(
2).跟据候选区移动的状态,更新候选区.
上一步中说到若超出候选区,需要翻页,则状态变量为 CANDIDATE_STATE_NEED_MORE_DATA;
HandleCandidateKey()中会加以判断:
 if
(State.mType == CANDIDATE_STATE_NEED_MORE_DATA)
 {
    
GetCandidate(mSubCandidate, State.mIndex);
    
mCandidateCtrlP->SetCandidates(&mSubCandidate, 1);
 }
 DrawCandidate();
 这里更新了候选区的内容.
当然,这只是最大致步骤,具体会有很多变量记录候选区的内容,容量,行数与列数,在CandidateInfoT这个结构体中有记录.会读取更新这里的值,记录当前位置及相它相关操作.内容很多,这里不一一说明,具体的跟一下代码可知.
在盲人输入法中,利用第三方的API自己模拟了一个Engine来实现按键与候选的对应,然后移植并更动了上述的实现过程,实现了盲人输入法基本的功能.希望对你能有所帮助.
补充:基本概念
一个IME提供某种语言一个输入方式,它由输入法引擎(第三方提供)类ImeEngine,输入法类ImeCandidateEnLowerC,候选显示类CandidateImeC
(可选)构成.输入法引擎类Porting某个第三方的输入法引擎,实现按键序列到候选词的转换.输入法类指定输入语言,输入方法,并按它们配置输入法引擎,接收按键序列,和输入法引擎交互获取候选词,在用户选定候选词后负责向Edit输入字符串.候选显示类CandidateCtrl,以候选框的方式显示待选词.Edit Control使用IME
Manager来切换当前输入法,总汇处理各种按键分派到各输入法,各种输入法通过实现IME接口并在IME Manager中注册集成到VIA
VTUI2平台中

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.