Linux版のScratch1.4で日本語入力日本語入力をできるようにした時のメモです。Ubuntu12とRaspberry Piで動くRaspbianで動くことを確認しています。※RaspbianについてはQEMU上で検証なので実機では検証していないのですが、実機でもできたというような話は聞いています。
どうやって実現する?
ScratchはソースコードはScratch 1.4 Source Codeで公開されていますがScratchという名前やロゴが使えなかったり、Scratchのサイトにアップロードできないなどの条件がありますので、今回はScratch自体に変更を加えるのではなくVMの方に変更を加えてみようと思います。
以前どこかのMLでScratchはutf32を期待しているというのを読んだ事がありますので、Scratchの期待するutf32をVMがScratchに渡してあげるように変更してみます。
Scratchの設定と起動
まずはScratchをインストールします。
$ sudo apt-get install scratch
素のままではIMEが起動すらしませんので、Scratchの起動ファイル中のVMOPTIONS
に-compositioninput
を追加します。
$ sudo vi /usr/bin/scratch
@@ -7,7 +7,7 @@
VM_VERSION=`find /usr/lib/squeak/ -name "squeakvm" -type f|cut -f5 -d"/"`
SQ_DIR=/usr/lib/squeak/$VM_VERSION
VM="$SQ_DIR/squeakvm"
-VMOPTIONS="-encoding UTF-8 -vm-display-x11 -plugins /usr/lib/scratch/plugins/:$SQ_DIR/"
+VMOPTIONS="-encoding UTF-8 -vm-display-x11 -plugins /usr/lib/scratch/plugins/:$SQ_DIR/ -compositioninput"
IMAGE="/usr/share/scratch/Scratch.image"
IMOPTIONS=""
DOCUMENT=""
Scratchはを起動してみます。-compositioninput
オプションを指定したことによってIMEが使えるようになっていますので試しに「あいうえお」と日本語を入力してみます。
めでたく?化け文字が入力できました!「0081」「0082」あたりからutf8らしい事が分かります。ここでutf8ぽい雰囲気が確認できないと大変そうだったんですが、ちょっとひと安心です。
VMの変更
まずはVMのコンパイルに必要なパッケージをインストールします。
$ sudo apt-get install cmake g++ xorg-dev
つづけてVMのソースコードをダウンロードするために今使っているVMのバージョンを調べます。バージョンを調べるにはls -Al /usr/lib/squeak/
を実行します。私の環境では4.4.7-2357である事が分かります。
$ ls -Al /usr/lib/squeak/
total 4
drwxr-xr-x 2 root root 4096 6月 8 21:26 4.4.7-2357
https://packages.debian.org/ja/wheezy/squeak-vm や http://ftp.de.debian.org/debian/pool/main/s/squeak-vm/ あたりから近いバージョンを探します。今回は同じバージョンがありましたのでsqueak-vm_4.4.7.2357.orig.tar.gz
をダウンロードしますが、もし同じバージョンがない場合は近いものをダウンロードして試してみるという事になります。
解凍します。
$ tar xvfz squeak-vm_4.4.7.2357.orig.tar.gz
ソースコードを変更します。検証コードという事で力技で書いたので長いコードになってしまいましたが、中身はutf8をutf32に変換するだけのものです。探せば普通に関数とかあるのかもしれません…
$ cd squeak-vm-4.4.7.2357.orig
$ vi unix/vm-display-X11/sqUnixX11.c
@@ -1699,29 +1699,64 @@ static unsigned char *lookupKeys(int (*l
static int recordPendingKeys(void)
{
- if (inputCount > 0)
- {
- int i= iebOut - iebIn;
- for (i= (i > 0 ? i : IEB_SIZE + i) / 4; i > 0; -- i)
- {
-# if defined(DEBUG_XIM)
- fprintf(stderr, "%3d pending key %2d=0x%02x\n", inputCount, i, *pendingKey);
-# endif
- recordKeyboardEvent(*pendingKey, EventKeyDown, modifierState, 0);
- recordKeyboardEvent(*pendingKey, EventKeyChar, modifierState, 0);
- recordKeystroke(*pendingKey); /* DEPRECATED */
- ++pendingKey;
- if (--inputCount == 0) break;
- }
- return 1;
- }
- /* inputBuf is allocated by lookupKeys */
- if (inputBuf != inputString)
- {
+ if (inputCount <= 0) {
+ if (inputBuf != inputString) {
free(inputBuf);
inputBuf= inputString;
}
- return 0;
+ return 0;
+ }
+
+ int utf32 = 0;
+ while (inputCount > 0) {
+ //110x xxxx 10xx xxxx
+ if(inputCount >= 2 &&
+ pendingKey[0] >= 0xc0 && pendingKey[0] <= 0xdf &&
+ pendingKey[1] >= 0x80 && pendingKey[1] <= 0xbf)
+ {
+ utf32 = ((pendingKey[0] & 0x1f) << 6) |
+ (pendingKey[1] & 0x3f);
+ recordKeyboardEvent(0, EventKeyDown, modifierState, utf32);
+ recordKeyboardEvent(0, EventKeyChar, modifierState, utf32);
+ pendingKey+=2;
+ inputCount-=2;
+ //1110 xxxx 10xx xxxx 10xx xxxx
+ } else if(inputCount >= 3 &&
+ pendingKey[0] >= 0xe0 && pendingKey[0] <= 0xef &&
+ pendingKey[1] >= 0x80 && pendingKey[1] <= 0xbf &&
+ pendingKey[2] >= 0x80 && pendingKey[2] <= 0xbf)
+ {
+ utf32 = ((pendingKey[0] & 0x0f) << 12) |
+ ((pendingKey[1] & 0x3f) << 6) |
+ (pendingKey[2] & 0x3f);
+ recordKeyboardEvent(0, EventKeyDown, modifierState, utf32);
+ recordKeyboardEvent(0, EventKeyChar, modifierState, utf32);
+ pendingKey+=3;
+ inputCount-=3;
+ //1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ } else if(inputCount >= 4 &&
+ pendingKey[0] >= 0xf0 && pendingKey[0] <= 0xf7 &&
+ pendingKey[1] >= 0x80 && pendingKey[1] <= 0xbf &&
+ pendingKey[2] >= 0x80 && pendingKey[2] <= 0xbf &&
+ pendingKey[3] >= 0x80 && pendingKey[3] <= 0xbf)
+ {
+ utf32 = ((pendingKey[0] & 0x07) << 18) |
+ ((pendingKey[1] & 0x3f) << 12) |
+ ((pendingKey[2] & 0x3f) << 6) |
+ (pendingKey[3] & 0x3f);
+ recordKeyboardEvent(0, EventKeyDown, modifierState, utf32);
+ recordKeyboardEvent(0, EventKeyChar, modifierState, utf32);
+ pendingKey+=4;
+ inputCount-=4;
+ } else {
+ recordKeyboardEvent(*pendingKey, EventKeyDown, modifierState, 0);
+ recordKeyboardEvent(*pendingKey, EventKeyChar, modifierState, 0);
+ recordKeystroke(*pendingKey); /* DEPRECATED */
+ pendingKey++;
+ inputCount--;
+ }
+ }
+ return 1;
}
static int xkeysym2ucs4(KeySym keysym);
コンパイルします。PCがゆっくり目なので、今回はvm-display-X11のみをコンパイルしてインストールしてみます。インストールはちょっと強引かもしれませんが既存のso.vm-display-X11を新しいso.vm-display-X11に差し替える事で行います。
$ mkdir bld
$ cd bld
$ ../unix/cmake/configure
$ make vm-display-X11
$ sudo mv /usr/lib/squeak/4.4.7-2357/so.vm-display-X11 /usr/lib/squeak/4.4.7-2357/so.vm-display-X11.orig
$ sudo cp vm-display-X11/so.vm-display-X11 /usr/lib/squeak/4.4.7-2357/
オリジナルのso.vm-display-X11と新しいfileso.vm-display-X11を比較するとかなり大きくなってしまいましたが、とりあえずは気にしないでおきます。
$ ls -Al /usr/lib/squeak/4.4.7-2357/so.vm-display-X11*
-rwxr-xr-x 1 root root 279934 7月 2 12:26 so.vm-display-X11
-rw-r--r-- 1 root root 96860 4月 25 2012 so.vm-display-X11.orig
Scratchを起動して日本語が入力できることを確認します。