puttyのコンソールでIMEの切り替え時カーソル色を変更するパッチを書いた(初めてのOSS活動)

※追記:コンパイルしたexeファイル

1年くらい前に、人力はてなでこんな質問をしました。
question:1164473105

putty(vim)でカーソルの色を変更する方法を教えてください。

kaoriya版gvimではwindowsIMEを使うので、『has('multi_byte_ime')』でIMEの状態を取得し、IMEのON/OFFでカーソル色を変更できます。

puttyなどの仮想端末を使った場合は、vimは接続先のソフトを使い、
インプットメソッドは仮想端末からWindowsIMEを使って入力するので、
IMEの状態を取得することができないようです。

四苦八苦してもvimのみでは解決できそうにもなかったので、
putty自体にvimrcにこれと同じ機能を実装すれば良いのでは?と思って、初めてのOSS活動をしました。

if has('multi_byte_ime') || has('xim')
" 日本語入力ON時のカーソルの色を設定
highlight CursorIM guibg=dodgerblue guifg=NONE
endif


その時に自分で書いたパッチを公開していなかったので、今まで色んなソフトを使わせて頂いているので、
私も少しでもフィードバックできればと思い、パッチを公開します。

どこを編集したらいいのかもわからず、taglist.vim*1を使ってじっくりソースを解析したり、ソースの相談をさせて他方にさせて頂いたり*2C言語は全く使った事がなかったので、C特有の事に関しては周りのC言語経験者に相談して書きました。


なので色々とご指摘やレビューなどして頂けるとうれしいです。


問題がなければ、近々ごった煮の「蛭子屋」さんにパッチを送ってみたいと思います。

手順

  1. ソースとパッチを取得する
  2. コンパイル環境を揃える
  3. パッチをあてる

パッチファイルを取得する

【putty0.60のソースを取得する】
http://the.earth.li/~sgtatham/putty/0.60/putty-0.60.tar.gz
puttyのごった煮パッチを取得する】
http://yebisuya.dip.jp/DL/putty-0.60-JP_Y-2007-08-06.zip

私が書いた、パッチを保存する

diff -urN config.c config.c
--- config.c	2008-03-23 22:33:27.468750000 +0900
+++ config.c	2008-03-23 22:33:25.843750000 +0900
@@ -616,7 +616,7 @@
 static const char *const colours[] = {
     "Default Foreground", "Default Bold Foreground",
     "Default Background", "Default Bold Background",
-    "Cursor Text", "Cursor Colour",
+    "Cursor Text", "Cursor Colour", "IME Cursor colour",
     "ANSI Black", "ANSI Black Bold",
     "ANSI Red", "ANSI Red Bold",
     "ANSI Green", "ANSI Green Bold",
diff -urN settings.c settings.c
--- settings.c	2008-03-23 22:33:28.296875000 +0900
+++ settings.c	2008-03-23 22:33:26.531250000 +0900
@@ -687,10 +687,10 @@
     gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour);
     gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
 
-    for (i = 0; i < 22; i++) {
+    for (i = 0; i < 23; i++) {
 	static const char *const defaults[] = {
 	    "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
-	    "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
+	    "0,255,0", "0,0,255", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
 	    "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
 	    "85,85,255", "187,0,187", "255,85,255", "0,187,187",
 	    "85,255,255", "187,187,187", "255,255,255"
diff -urN windows/putty.lng windows/putty.lng
--- windows/putty.lng	2008-03-23 22:33:28.921875000 +0900
+++ windows/putty.lng	2008-03-23 22:33:27.156250000 +0900
@@ -192,7 +192,8 @@
 Default Background=標準の背景
 Default Bold Background=標準の強調背景
 Cursor Text=カーソル上の文字
-Cursor Colour=カーソルの色
+Cursor Colour=IME_OFF時カーソルの色
+IME Cursor Colour=IME_ON時カーソルの色
 ANSI Black=ANSI 黒
 ANSI Black Bold=ANSI 黒 太字
 ANSI Red=ANSI 赤
diff -urN windows/window.c windows/window.c
--- windows/window.c	2008-03-23 22:33:29.000000000 +0900
+++ windows/window.c	2008-03-23 22:33:27.265625000 +0900
@@ -1409,12 +1409,12 @@
 {
     int i;
     static const int ww[] = {
-	256, 257, 258, 259, 260, 261,
+	256, 257, 258, 259, 260, 261, 262,
 	0, 8, 1, 9, 2, 10, 3, 11,
 	4, 12, 5, 13, 6, 14, 7, 15
     };
 
-    for (i = 0; i < 22; i++) {
+    for (i = 0; i < 23; i++) {
 	int w = ww[i];
 	defpal[w].rgbtRed = cfg.colours[i][0];
 	defpal[w].rgbtGreen = cfg.colours[i][1];
@@ -1454,6 +1454,7 @@
 	{ COLOR_WINDOW,		258, 259 }, /* Default Background */
 	{ COLOR_HIGHLIGHTTEXT,	260, 260 }, /* Cursor Text */
 	{ COLOR_HIGHLIGHT,	261, 261 }, /* Cursor Colour */
+	{ COLOR_HIGHLIGHT,	262, 262 }, /* IME Cursor Colour */
     };
 
     for (i = 0; i < (sizeof(or)/sizeof(or[0])); i++) {
@@ -2387,12 +2388,48 @@
 				WPARAM wParam, LPARAM lParam)
 {
     HDC hdc;
+    HIMC hImc = NULL ;
+    BOOL bIMEOpen = FALSE ;
     static int ignore_clip = FALSE;
     static int need_backend_resize = FALSE;
     static int fullscr_on_max = FALSE;
     static UINT last_mousemove = 0;
+    static BYTE defCursorPal[3] ;
 
     switch (message) {
+        case WM_IME_NOTIFY :                   /* IME_Notify_Message */
+			if(wParam == IMN_SETOPENSTATUS){
+				hImc = ImmGetContext(hwnd);
+				if(hImc){
+					BOOL bIMEOpen = ImmGetOpenStatus(hImc);
+					if(bIMEOpen){
+						/* default cursor color setting */
+						defCursorPal[0] = defpal[261].rgbtRed ;
+						defCursorPal[1] = defpal[261].rgbtGreen ;
+						defCursorPal[2] = defpal[261].rgbtBlue ;
+
+						/* IME_ON cursor color setting */
+						defpal[261].rgbtRed = defpal[262].rgbtRed;
+						defpal[261].rgbtGreen = defpal[262].rgbtGreen;
+						defpal[261].rgbtBlue = defpal[262].rgbtBlue;
+
+						init_palette();
+						InvalidateRect(hwnd,NULL,FALSE);
+						UpdateWindow(hwnd);
+					}
+					else {
+						/* IME_OFF cursor color setting */
+						defpal[261].rgbtRed = defCursorPal[0] ;
+						defpal[261].rgbtGreen = defCursorPal[1] ;
+						defpal[261].rgbtBlue = defCursorPal[2]  ;
+
+						init_palette();
+						InvalidateRect(hwnd,NULL,FALSE);
+						UpdateWindow(hwnd);
+					}
+				}
+			}
+			break ;
       case WM_TIMER:
 	if ((UINT_PTR)wParam == TIMING_TIMER_ID) {
 	    long next;

コンパイル環境を整える

コンパイルCygwinでの説明を書きます。が、『VisualC』『BorlandC』などのMakefileもあるので、Cygwin以外でも全然問題ありません。※追記2008/3/25:Visual C++でビルドしてみましたが、パッチを当てるとエラーが発生する事を確認しました。私のパッチ手順が間違っているか、ソースに手を加える必要がでてきます。確認を怠っていい加減な事書いてしまって、すいませんでした。

cygwinのsetup時に下記パッケージをインストールする。

他にもなにかインストールしかもしれないですが、必要なコマンドが足りなければインストールしてください。

パッチをあてる

まずは、cygwinでワークディレクトリでも作っておき

【例】

~/work/

puttyのソースファイル「putty-0.60.tar.gz」を配置し、cygwin上でファイルを展開します。

tar zxf putty-0.60.tar.gz

次にごった煮パッチを展開し、パッチファイルをputtyソースディレクトリに移動します。(putty-0.60-JP_Y.patchとputtyd.icoのみ使用)
ここでは、まだicoファイルは移動しません。

unzip putty-0.60-JP_Y-2007-02-06.zip
mv ./putty-0.60-JP_Y-2007-08-06/putty-0.60-JP_Y.patch ./putty-0.60/

次に、ごった煮パッチを当てます。(パッチを置く階層が間違っているとファイル名を聞かれます。パッチ実行後は問い合わせないなしで完了します)

cd ./putty-0.60
patch -Np0 < putty-0.60-JP_Y.patch

次に、IMEカーソル色パッチを当てます。同じくputty-0.60のソースディレクトリにIMEパッチファイルを配置し、パッチを実行します。

patch -Np0 < putty-0.60-JP_Y_IME.patch

次に、Makeファイルを作成する為に「mkfiles.pl」を実行します。

perl ~/work/putty-0.60/mkfiles.pl


次に、ごった煮パッチのzipで解凍したファイルに含まれていたicoファイルをwindowsディレクトリに配置します。*3

~/work/putty-0.60/windows/puttyd.ico

次に、Makeを実行します。

make -f ~/work/putty-0.60/windows/Makefile.cyg

コンパイルが開始されるので、暫く待ちます。
完了したらwindowsディレクトリに、putty.exeができてているはずです。
必要なファイルは「ごった煮版パッチ」のzipファイルに入っていたファイルだけですので、後で移動させてあげるといいと思います。

これで完了です。

動作確認は、コンパイルしたputty.exeを起動し、『ウインドウ』→『色』に「IME_OFF時カーソルの色」と「IME_ON時カーソルの色」が入っている事を確認します。
次に、puttyを起動してコンソールを表示させ、IMEの切り替えで色が変わる事を確認します。

*1:便利ですねctags。(^^

*2:その際は本当にお世話になりました。

*3:順序が間違っていました。mkfiles.pl実行後にコピーする必要があります。※2009/2/24修正