XIM協議的原理及其實現

引言

 

1.輸入法

世 界上大多數語言是基於字母表的,一些字母的集合組成了單詞,當在計算機中輸入這些語言時,用戶通常是在鍵盤上鍵入相應的字符或一些組合鍵來實現。但表意文 字(如中,日,韓等)卻不能在鍵盤上找到相應的鍵,如果想在計算機中輸入這些文字,就需要相應的輸入法。輸入法有很多種,如拼音,五筆等,但這些輸入法的 一個共同的特徵是用戶敲多個鍵來組成一個文字(或一組文字),統稱爲編碼輸入。

2.XIM協議

XIM(X Input Method)是X-Window系統下的符合國際化標準的輸入法協議,只要應用程序和系統都支持這種輸入協議,應用程序就不必具體考慮在不同語言環境下的輸入問題,系統可以根據相應的locale去尋找相應的輸入法,從而達到國際化的要求。

 




 

 

XIM的原理

 

1.體系結構

  • 1.1 實現模型 在X-Window 系統環境下,XIM的實現有以下兩種典型的體系結構:

    1)Client/Server模型:

    IM服務器是一個獨立的進程,由它來處理輸入、預編輯、轉換和確認。IM庫存在於應用程序中,就象IM服務器的一個客戶,它只是簡單的從IM服務器接收確認字符串。

    2)Library模型:

    所有的輸入都由應用程序中的IM庫來處理。事件處理在IM庫中就被關閉了,所以就不再需要一個獨立的IM服務器。

    大多數語言,如亞洲語言一般都有複雜的預編輯,所以都採用Client/Server模型來實現,其他的只有一些死鍵或組合鍵的語言,如歐洲語言一般都採用Library模型來實現。

    下面主要都討論Client/Server模型,如圖1所示:

  • 客戶程序通過連接IM服務器來實現XIM輸入,它們之間的通訊是利用XIM的協議來實現的。IM子系統完成文字查找和文本的組合。

  • 1.2 IM結構 當客戶程序向服務器發出連接或斷開請求時,在客戶和服務器之間會產生打開和關閉操作。

    函數XopenIM()設置或修改客戶的locale,IM是根據相應的locale來指定的。另外,客戶支持的IM類型可以通過函數XGetIMValues()來獲得。

    一 個客戶程序通常有多個輸入域,Xlib提供了一個結構“Input Context”(IC)來管理每個輸入域。函數XCreateIC()可以指定XIM並創建一個相應的IC,函數XDestroyIC()用來刪除此 IC。許多重要的信息,比如確認字符串都通過IC來從IM服務器送到客戶程序。每一個IC與一個輸入域相關,函數XSetICFocus()用來通知IM 服務器當前IC獲得了焦點(XUnSetICFocus()表示失去焦點)。

  • 1.3 事件處理模型 現存的輸入法都支持前端輸入法和後端輸入法或其中的一種。XIM把後端輸入法作爲一種默認的輸入法,但也支持前端輸入法。

    1)後端輸入法:

    在後端輸入法中,客戶窗口的輸入事件總是送到IM庫中,然後IM庫把此事件送到IM服務器中。事件以傳送的順序來處理,因此在IM庫和IM服務器中沒有需要同步的問題。

    2)前端輸入法:

    在 前端輸入法中,客戶窗口的輸入事件由XServer直接傳送到IM庫和IM服務器中。因此這種方法提供了更好的接口性能(尤其在IM服務器運行在一臺工作 站而客戶程序運行在另一臺工作站上,且網絡又相對較慢時)。而,前端模型在處理鍵的時候有同步問題,時會引起事件丟失或時間重複。因此後端輸入法是由核心 輸入法支持的,前端輸入法是從擴展性能的目的出發的。

  • 1.4 事件流控制

    XIM協議在IM庫和IM服務器之間的通訊支持兩種事件流:靜態和動態。

    1)靜態事件流是客戶程序的輸入事件總是發送到IM服務器。

    2) 動態事件流是輸入事件中需要處理的事件發送到IM服務器。例如,在即輸入ASCII字符又輸入中文字符的時候,ASCII字符就不必送到IM服務器了。因 此,採用動態事件流後,在XServer、客戶和IM服務器之間的需求事件大大減少了,從而性能有所提高。IM服務器發送 XIM_REGISTER_TRIGGERKEYS事件來切換動態事件流。

2.簡單協議處理模型

下圖2是一個最簡單的協議流的例子:

當 應用程序發生按鍵事件時,它調用Xlib API的XNextEvent函數,對於後端輸入法模型,事件都由IM庫來處理,IM庫先發出XIM_FORWARD_EVENT作爲同步請求,IM服務 器接收到此協議後發出XIM_FORWARD_EVENT或XIM_COMMIT作爲同步應答,雙方完成同步。然後,IM服務器阻塞從IM庫接收到的 XIM_FORWARD_EVENT消息,進行處理,結束後把結果返回到應用程序。

 


   

 

XIM開發工具IMdkit簡介

IMdkit(IMServer Develops Kit)是X11R6的Xi18n執行工作組發佈的XIM服務器開發工具,它提供了一個低級的C語言接口,把每個IM協議操作都綁定到了簡單的C語言接 口,這樣用戶就可以很容易的使你的IM服務器與XIM客戶程序很容易的通訊,而不用直接處理複雜的IM協議。XIM客戶程序是指利用在X11R6中定義的 XIM API國際化過的應用程序。IMdkit封裝了實際的IM協議操作,這樣用戶自己就不必處理實際包,可以利用它提供的數據結構,簡化了許多細節麻煩;封裝 了不同的傳輸機制(包括X協議,TCP/IP,DECNET),這些協議用來在IM庫和IM服務器之間傳輸數據包;封裝了多種IM協議模型,包括Ximp 和Xi18n。

IMdkit定義了一個不透明的數據結構XIMS,用來抽象輸入法服務器的結構。它由函數IMOpenIM返回,函數IMOpenIM如果成功的話,返回一個XIMS結構,否則返回NULL。

對於每一個XIM協議輸入,在IMdkit的頭文件中都定義了一些相應的結構,對於R6標準的IM協議模型,中定義了所有的IM協議結構。

1)IM協議的通用數據結構

在R6的標準IM協議模型中,所有的事件結構有如下的通用成員:

	typedef	struct{

int major_code;

int minor_code;

CARD16 connect_id;

}

 

major_code和minor_code指定了唯一鑑別這個IM協議類型本身的常量名。connect_id指定了連接的客戶ID。

2)協議處理

一些由IM庫發送的IM協議請求由IMdkit內部處理了,不需要發送到IM服務器。因爲IMdkit會根據你在XIMS結構中設置的值來決定對這個IM協議請求的應答。需要處理的一些IM協議請求參看下面介紹的XIM的實現。

 

XIM的實現

以下討論的具體實現是利用IMdkit開發的XIM服務器。

1.初始化輸入法服務

	ims = IMOpenIM(display,IMModifiers,”Xi18n”,IMServerWindow,window,

IMServerName,imname,IMLocale,DEFAULT_LOCALE,

IMServerTransport,transport,IMInputStyles,input_styles,

IMProtocolHandler,MyProtoHandler,IMEncodingList,encodings,NULL);

 

函數IMOpenIM初始化輸入法服務的連接,並設置一個或多個由變長的參數列表指定的IM的屬性。

下面簡介上面函數中的參數:

Display是當前的屏幕顯示。

IMModifiers定義XIM的協議模型,有兩種:

“Xi18n”指定R6標準的IM協議模型。
“XIMP”指定R5標準的Ximp模型。

IMServerWindow指定IM服務器的窗口以便於與XIM客戶程序進行通訊。

IMServerName指定IM服務器的名字。

IMLocale指定IM服務器支持的locale列表。

IMServerTransport指定IM服務器用來與客戶程序間的通訊技術。

IMIputStyles指定IM服務器支持的輸入風格列表。如:XIMPeeditPosition|XIMStatusNothing爲光標跟隨,不需要狀態顯示風格。下面的具體協議處理就是根據這種風格來介紹的。

IMProtocolHandler指定當IM主循環接收到客戶程序的協議時的時間處理函數。

IMEncodingList指定IM服務器支持的傳輸編碼列表。

2.協議處理函數

下面函數用於處理整個客戶協議,由於篇幅原因,本文只列出了相應的協議,而沒有具體的處理函數,實際應用中,每一個分支都由一個相應的函數來處理。

MyProtoHandler(XIMS ims,IMProtocol *call_data)

{

switch(call_data->major_code){

case XIM_OPEN:

case XIM_CLOSE:

case XIM_CREATE_IC:

case XIM_DESTROY_IC:

case XIM_SET_IC_VALUES:

case XIM_GET_IC_VALUES:

case XIM_FORWARD_EVENT:

case XIM_SET_IC_FOCUS:

case XIM_UNSET_IC_FOCUS:

case XIM_RESET_IC:

case XIM_TRIGGER_NOTIFY:

}

}

 

函數MyProtoHandler是由 IMOpenIM登記的處理客戶程序發送到IM服務器的協議的函數,在參數call_data中有相應的協議。上面列出了一些主要的協議,對於不同的情況 (主要是根據不同的輸入法風格),有一些協議不必處理,或根本不會發生。下面簡介一些主要的協議處理過程。

XIM_OPEN:XIM客戶程序啓動時,要在IM庫和IM服務器之間建立邏輯連接。

XIM_CLOSE:關閉在IM庫和IM服務器之間建立 的邏輯連接。

XIM_CREATE_IC:當客戶程序創建了一個輸入法上下文(IC)時,發送此協議到IM服務器,這時在IM服務器中爲此IC申請了一個相應的結構,用於記錄一些必要的信息,包括字體、位置、前背景色等等。

XIM_DESTROY_IC:當客戶程序退出時,刪除相應的IC,釋放一些與IC相關的存儲空間。

XIM_SET_IC_VALUES:設置當前連接IM服務器的IC的屬性。實際XIM服務器定期發送此協議來修改IC的屬性值。

XIM_GET_IC_VALUES:取得當前連接IM服務器的IC的屬性。

XIM_FORWARD_EVENT: 當有按鍵發生時,客戶程序發送此協議到IM服務器,此按鍵事件放在call_data的event結構中。在相應的處理函數中,讀出相應的鍵值,如果是一 些控制鍵,就作相應的操作,如輸入法的開啓,不同輸入法之間的切換等;如果是輸入法不需要處理的鍵,就直接送回客戶程序,如一些功能鍵,組合鍵等;否則調 用輸入法的處理程序,輸入法處理程序對這個字符進行處理,此時在預編輯區和選擇區會有相應的變化,如果有結果字符串生成,輸入法服務器會按照開始時確定的 編碼方式把這個字符串發送到客戶程序,這樣就完成了一次輸入過程。

XIM_SET_IC_FOCUS:當在不同的應用程序間進行切換時,當前的IC會發生變化,此時新的應用程序會發送此協議到IM服務器,輸入法服務器會改變當前的焦點,當前的一些與IC有關的屬性和全局變量也要有相應的變化。

XIM_UNSET_IC_FOCUS:當前IC失去焦點。在此處可以釋放一些與當前IC相關的資源。

XIM_RESET_IC:重置在IM服務器中的IC的狀態。

XIM_TRIGGER_NOTIFY:IM庫通知IM服務器匹配啓動(on-keys)和關閉(off-keys)的事件發生了。

3.主事件循環

在主程序中要用XselectInput選擇輸入法窗口要處理的所有X事件,

	XSelectInput(display,window,ExposureMask|ButtonPressMask|ButtonReleaseMask|

ButtonMotionMask|VisibilityChangeMask);

 

然後在主循環中要處理所有這些事件,如下由函數MyXEventHandler完成。

	for(::){

XNext event;

XNextEvent(display,&event);

if (XFilterEvent(&event,NULL)= =True) continue;

MyXEventHandler(&event);

}

 

函數MyEventHandler要處理輸入法窗口的事件。包括在屏幕上的顯示,窗口的改變,拖動窗口,及與其他窗口進行通訊等消息。通過此函數,可以使程序達到對用戶友好的目的。

以上三點是一個XIM服務器的必須要處理的,我們還需要包含以下頭文件:X11/Xlib.h、IMdkit.h和Xi18n.h,後面兩個頭文件是IMdkit提供的面向R6標準的一些結構定義。另外連接的時候要連接IMdkit的libXimd.so。

五、小結

以 前的X Window下的輸入法的實現大都是通過截取X的通訊函數的方法來實現在X下的應用程序中進行文本輸入。具體方法是修改libX11.so.6裏面的 XNextEvent函數,當時按鍵事件時,如果此是在中文狀態,就把按鍵消息發送到輸入法去處理,並等待輸入法的迴應。相應的要修改 XlookupString函數,和一些顯示函數。這種方法屬於非標準的方法,在實際應用中如果有一些應用程序通過其它方法接收輸入時,輸入法就會起不到 作用,爲了達到目的需要修改很多應用程序,另外對於其他語言不兼容,每一種語言都要有不同的輸入法,給程序的開發者和應用者帶來了很多困難。採用了XIM 協議後,完全符合國際化標準,這樣X下的應用程序根本不必過多的考慮輸入問題,就可以達到國際化的要求,在不同的語言環境下可以自由的應用,減少了應用程 序開發者的麻煩。

 

參考資料

  • 參考文獻
    • [1] Open Software Foundation:X Window System Version 11 Input Method Secifications,November 1990
    • [2] X11R6 Xi18n Implementation Group:IM Server Developers Kit-C Language Interface,May 15 1994
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章