關於輸入法的工作原理及編程

緣起

windows下使用的sougou輸入法,除了經常彈出廣告,沒有什麼異常行爲,Linux下的中文輸入法似乎沒那麼強大好用了。起初用的是Ibus中的pinyin,後來因爲機緣巧合裝了yong輸入法,發現挺好用的,就一直用着。漸漸的發現yong輸入法在一些自由軟件中不起作用,有時還行爲詭異,雖然大多數的時候,工作的很正常。本着程序員好奇的心態,我想打開輸入法這個黑匣子,看看裏面有些什麼。

正文

1. 簡介

輸入法的工作原理是擊鍵消息(window中消息)首先送給輸入法管理器(前端),輸入法管理器調用輸入法的轉換函數(輸入法引擎),輸入法的轉換函數得到擊鍵消息並保存在自己的數組中,當符合規定條件時(如五筆輸入法輸入:四鍵、兩鍵+空格等),輸入法把適當的字、詞返回給輸入法管理器,輸入法管理器再把結果字、詞傳給關聯的應用窗口。

簡單的來說,輸入法就是一個查表操作,輸入的信息是鍵盤信息,根據擊鍵消息到表中查找對應的漢字。舉個例子:將碼錶導入到Excel。假設碼錶是基於拼音的,碼錶分兩列,一列是拼音,一列是漢字串,那麼用鼠標點擊編輯->查找,在查找內容框中敲入shishi,點擊查找下一個按鈕,黑色矩形框立即就跳到A列的shishi的行上面,對應的B列就是試試、事事、實施、時世、史實……”等等這些漢字串,輸入法的原理就是這樣[2]PS:計算機程序中都可以簡化爲查表程序,這個表可能是數組,字符串或者數據庫。表驅動編程本質上就是從數據的角度出發,根據數據來編程(參考《代碼大全 第二版》)。

由於輸入法編程中涉及消息處理機制,而消息處理機制是操作系統的核心機制,理解起來比較麻煩。但是,學習輸入法編程,要帶着問題學,活學活用,學用結合,急用先學,立杆見影,在字上狠下功夫。爲了把輸入法編程的精髓真正學到手,要反覆學習輸入法編程的結構和算法,有些概念、算法最好要背熟,反覆學習,反覆運用。”[2] PS:這段話可以簡化爲:世上無難事,只要肯攀登。

關於在windows下學習輸入法編程的資料蒐集如下

1.輸入法工作原理:http://blog.csdn.net/shuilan0066/article/details/6883629

2.輸入法漫談:http://wenku.baidu.com/view/3d179422bcd126fff7050b9d.html(備註:原文發佈在某論壇上,地址爲:)

Linux下的輸入法框架無非Scim/Ibus/Fcitx這三類。在網上搜了一通,僅發現一篇關於Scim工作原理的論文,ibusfcitx都是相應的google代碼庫,估計源碼和文檔都應該很全。個人感覺,用scim的人不如ibusfcitx多了,開發也不及後兩者了。但是scim有這麼一篇2頁的論文,省去看ibus之類的文檔和源碼,而且既然同樣都是輸入法框架,總會存在一些共性的特徵,相差不到那裏去。

2. SCIM

基於XIM結構的輸入法與X Windows系統結合過於緊密,無法支持國際化語言環境,SCIM就是針對這些問題的。Smart Common Input Method(SCIM)SCIM輸入法架構的優越性: 1.支持語言多 2.面向對象設計 3.高度模塊化,功能模塊,插件形式 編程接口簡單 5. 獨立於圖形界面,便於開發和移植

2.1. SCIM的結構設計

SCIM包含的模塊:

  • l 配置模塊(Config):配置模塊最主要的功能就是爲應用程序配置共享信息,以防衝突。所有的配置信息都由Config統一進行管理,其他模塊存取配置信息都需要通過向它發送請求。SCIM的配置文件由Config文件和Global文件組成,前者保存的是與輸入法相關的配置信息,輸入法引擎、快捷鍵等參數,後者保存的是與輸入法無關的配置信息,socket超時、socket地址等信息。SCIM中的配置模塊有不同的實現,但這些實現都必須遵循ConfigBase接口規範
  • l 前端模塊(FrontEnd):前端模塊的主要功能是接受輸入法服務進程中來自客戶端應用程序的的請求,然後把請求轉發給具體的輸入法引擎或者配置模塊,最後把處理的結果返回給剛纔請求的客戶端應用程序(在這裏,輸入法是作爲一個服務進程來實現的)SCIM輸入法前端也有不同的實現,這些實現都遵循FrontEndBase接口規範
  • l 引擎模塊(IMEngine):輸入法引擎的功能是實現具體的輸入法。比如要實現全拼輸入法,五筆輸入法,首先需要實現一個輸入法引擎,然後將其編譯成一個動態庫,放在指定的目錄之中。所以其它輸入法都是以單獨的軟件包發行的,不屬於SCIM的核心。SCIM中的輸入法引擎也有多種實現,這些實現都遵循IMEngineInstanceBase接口
  • l 進程間通信模塊(IPC):SCIM採用的本地socket(參考*uixBSD Socket API,是一種進程間通信的方式)方式。應用層協議封裝在Transaction中,它主要負責把特定的請求或事件等打包成數據包和從數據包中取出請求或事件。Socket實現數據的實際傳輸。服務器端使用SocketServer,客戶端使用SocketClient。無論是服務器端還是客戶端,Transaction並不關心,因爲它使用的是Socket的抽象接口。
  • l 輸入法Panel:對於輸入法來說,Panel是不可缺少的一部分。Panel的主要功能是提供給用戶比較直觀的感受,如候選字,聯想詞組等,也提供了一些輔助功能,如全角半角切換,中英文切換、標點切換、查看幫助信息等。Panel是有圖形用戶界面的,且必須要與特定的GUI綁定起來,SCIM雖然實現了一個基於GTKPanel,但它是一個完全獨立的工具,不管用哪一個GUI實現Panel,大部分代碼都是相同或者相似的,只要稍做修改即可。SCIMPanel模塊的代碼封裝在PanelAgentPanelClient這兩個類中。前者實現所有和麪板相關的socket協議,後者處理所有面板和前端的socket通信,前端用PanelClientPanel後臺進程進行交互。
  • l Helper模塊:SCIM把一些新的輸入法方式,如手寫輸入法等進行特殊處理,通過Helper集成進來。SCIM提供了一個HelperAgent,這個類的功能是把手寫輸入法的結果提交給應用程序。

2.2. 工作原理

SCIM,輸入法有三大功能模塊:前端(FrontEnd),引擎(IMEngine)和後端(BackEnd)。這三大模塊分別實現的功能是:

FrontEnd:主要負責用戶界面的顯示,以及與客戶程序進行交互,將客戶程序的按鍵請求轉發給IMEngine,執行IMEngine發出的各種命令,如繪製預編輯字符串等等。FrontEndBase基類負責管理所有IMEngineInstance實例。

IMEngine:接收FrontEnd發送的按鍵事件,然後向FrontEnd發送相應的命令,如顯示預編輯字符串、向客戶程序提交字符串等等。

BackEnd:管理所有的IMEngine。如全拼、雙拼、五筆、手寫等。

SCIM中最關鍵的部分是FrontEndIMEngine。這兩部分的實現及其之間的通訊方式(本地socketSCIM較其它輸入法平臺最不同的地方。

FrontEnd主要完成用戶界面的繪製、與客戶應用程序交互,FrontEndBase基類負責管理所有IMEngineInstance實例這三方面工作。每個IMEngineInstance 實例用唯一的id進行標識,FrontEndBase類提供的函數和IMEngineInstanceid完成對IMEngineInstance的所有操作。FrontEnd派生類不需直接處理IMEngineInstance實例或者其指針。

IMEngine分爲IMEngineFactoryIMengineInstance兩個接口類。要實現具體的輸入法,比如縱橫漢字輸入法,就必須提供這兩個類的具體實現。IMengineFactory除了負責管理如詞庫等的輸入法涉及的公共數據,還負責創建IMEngineInstance實例。IMEngineInstance類則負責把實際的按鍵轉換爲字符串。

FrontEndIMEngine之間的數據通信採用了一種鬆散的接口形式,signal-slot技術,這樣的方式可以簡化編程接口。輸入法引擎所需的所有動作都經由signal-slot發送給FrontEnd,而輸入法引擎需要處理的事件則直接由FrontEnd調用IMEngineInstance類的相應函數來傳遞。

2.3. 吐槽

參考[4]論文中存在一些文字錯誤,重複以及術語的前後不一致,明顯有整合和拼湊的感覺,看了一下其參考文獻,百度文庫和一篇csdn的博客赫然在列,讓我對該中文期刊的質量表示懷疑,去看了一下引用的源後,果然是整合的,前半截+圖來自文庫,後半截來自博客,對於這種拼接法搞學術,表示強烈的鄙視,雖然我也經常幹這種事情,但是我copy & paste的技術絕對比他們好,感覺有點五十步笑百步。

強烈建立參考原出處,原出處的文章具有一致性和連貫性,不是拼接的,而且更加圖文並茂:

1.SCIM輸入法架構分析(上)http://blog.csdn.net/absurd/article/details/1151404

2.SCIM輸入法架構分析(下)http://blog.csdn.net/absurd/article/details/1151524

3. IBUS

Intelligent Input BUS(iBus)是一個輸入法平臺,可以理解爲是一個已經寫好的與系統交互的庫,各種輸入法運行在iBus上。iBus曾經是Python寫的,現在已經用C++重寫,效率得到很大的提高,兼容性要遠遠強於ScimiBus可以讓程序員專心地編寫輸入法功能的代碼,而不是把過多的精力浪費在與系統交互上,從而增強輸入法的可移植性。

Ibuswiki上的介紹:http://en.wikipedia.org/wiki/Intelligent_Input_Bus (百度百科上的介紹過時太久了)

IbusUbuntu系統上安裝:http://wiki.ubuntu.org.cn/IBus

Ibus項目地址:http://code.google.com/p/ibus/

4. Fcitx

Fcitxwiki介紹:http://en.wikipedia.org/wiki/Fcitx

Fcitx還和搜狗合作開發Linux上的搜狗輸入法,其在Ubuntu(Linux Mint)的安裝參考http://1.techblog.sinaapp.com/?p=283#more-283

Fcitxgoogle項目地址:http://code.google.com/p/fcitx/

FcitxGitHub地址:https://github.com/fcitx/fcitx

Fcitx的安裝:http://wiki.ubuntu.org.cn/Fcitx

5. Yong輸入法

Yong輸入法基於ibus的,但是又和Ibus上的輸入法ibus-pinyin之類的不太一樣。

輸入法論壇及下載:http://yong.dgod.net/

安裝可參考:http://blog.csdn.net/xiajian2010/article/details/9625131 

具體的,我也不是特明白其實現機制,先留給伏筆,等以後我明白了再加。

仔細查看了yong提供的幫助和相關的文檔,發現在當前Home目錄下的.yong中存在這樣的一個文件pinyin.usr,打開後可以看到如下模式的文本:

{0}aihe 愛喝

{-}anquanjiang 安全將

{0}anshenye 安神液

{0}ansong 暗送

{0}aojiao 傲驕

{0}badi 拔地

{0}baiban 白板

{0}bailv 百慮

{0}baishikuai 百十塊

{0}baiyou 柏油

{1}baiyou 柏由

{0}baiyulan 白玉蘭

在看到有一些自己常用的輸入後,想到yong的幫助提到的造詞和刪詞的功能(快捷鍵操作太難用),估計就是通過在文件中設置{}中的數字實現,{-}表示刪除,{0}{1}行爲不太明白,在文件中添加新詞表示造詞。修改該文件後,發現並沒有能禁止,將yong進程殺死,再重啓就起效了,看來yong默認會將該文件加載到內存中去,回想上面介紹的輸入法就是查表操作,這個pinyin.usr就是這樣的表,除了這個表以外,還有個pinyin的主表是安裝目錄yong/mb/下的pinyin.txtpypre.bin,打開pinyin.txt後,其文件內容是:

name=ƴ??

key=abcdefghijklmnopqrstuvwxyz

len=63

wildcard=?

pinyin=1

split='

hint=0

user=pinyin.usr

assist=mb/yong.txt 2

code_a1=p..

[DATA]

a ?? ?? ?? ?? ?? ?? ߹

aba ????

adou ????

aduwu ??????

[DATA]目錄下的字母對應的字符爲不可識別,估計是對怕pypre.bin中的二進制的數據的索引,但又覺得不太像。

根據幫助文檔的,將一些不需要的文件刪除了,只剩下3M了,同樣也能工作,感覺非常好。安裝目錄yong保留的文件如下:

yong目錄下的:libl.so(基礎庫),libmb.so(碼錶庫),yong(主程序),yong.conf(配置文件),yong.ini,yong-tool.sh(安裝卸載腳本),yong.chm(幫助文檔),keyboard.ini(軟件盤配置文件),normal.txt

skin目錄全部保留

mb目錄只保留我需要的拼音輸入法(pinyin.ini,pinyin.txt,pypre.bin)和english.txt

gtk-im目錄下的動態連接庫也需要保留,不然連輸入框都不顯示。

yong-config二進制程序也要保留,這個圖形配置界面的程序。

備註:看到yong官方將輸入法更新到了2.1,不清楚作者怎麼設置版本號的,試用了一段時間,發現很不穩定,常常打字不上屏,害我要將進程殺死再重啓,相當麻煩,我又退回1.7,用了很久,非常穩定。

後記

本來想好好的瞭解一下輸入法,以及我使用的Yong輸入法的,結果只是在蒐集資料,瞭解一些很寬範的東西。在蒐集資料的時候,看到一個關於學習方法的觀點:重基礎勝於技巧,看書勝於看雜誌,看代碼勝於看文章,和朋友討論勝於上論壇,寫BLOG勝於看BLOG,以及學習方法無好壞之分,只有合適不合適之分,所謂天下殊途同歸,一致百慮

二手文獻和原始文獻之間,存在一條加工的溝,而且並不是所有的二手文獻都比原始文獻好。

Linux Mint的界面蠻好看的,有機會嘗試一下。

參考文獻

[1]SCIM輸入法架構分析:http://wenku.baidu.com/view/a33b1484bceb19e8b8f6baea.html

[2]輸入法漫談:http://wenku.baidu.com/view/3d179422bcd126fff7050b9d.html

[3]關於Ibus拼音的開發:https://www.byvoid.com/blog/join-develop-ibus-pinyin/

[4]SCIM輸入法架構及其工作原理,王麗君,李培峯,China Academic Journal Electronic Publishing House 

[5] 我的學習方法:http://blog.csdn.net/absurd/article/details/6475353

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章