Linux版Scratch1.4で日本語入力

  • 4
    Like
  • 0
    Comment

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が使えるようになっていますので試しに「あいうえお」と日本語を入力してみます。

16-06-30 scratch.png

めでたく?化け文字が入力できました!「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-vmhttp://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
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を起動して日本語が入力できることを確認します。