フォーラム: gnupackフォーラム (スレッド #31403)

menu-treeによる日本語メニューの文字化けを解決 (2012-01-20 11:39 by daregada #61788)

こんにちは。

 少し暇だったので、menu-tree.elでメニューを日本語化した際のNTEmacsの文字化け問題を調べてみました。ちょっと長いので詳細は後で自分のブログに書いておきます。

 問題点は2つあって、

(a) ラジオボタン風の選択項目が最初から文字化けしている
(b) ウィンドウ端をドラッグしてウィンドウサイズを変更していると、メニュー全体が文字化けする

です。

Emacs 23.3のsrc/w32menu.cを追ってみたところ、項目をメニューに追加するadd_menu_item()に問題点を発見しました。

(a) ラジオボタン風の選択項目(BUTTON_TYPE_RADIO)だけ別に処理をしている箇所で、UTF-16-LEに変換していない(UTF-8のままの)項目名を文字列として含む構造体を、SetMenuItemInfoA(ソース内ではset_menu_item_info)の引数に指定しています。SetMenuItemInfoAはマルチバイト対応(日本語だとcp932)のAPIなので、UTF-8のまま文字列を渡したら文字化けするのは当然でした。

 対策としては、UTF-16-LEに変換した文字列を、Unicode対応のSetMenuItemInfoWに渡せばよいことになります。

(b) ラジオボタン風の選択項目以外の項目については、ちゃんとUTF-16-LEに変換された項目名の文字列を、Unicode対応のAppendMenuW(ソース内ではunicode_append_menu)に渡しています。起動直後に日本語が正しく表示されることからもわかるように、この部分は間違っていません。
 ただし、AppendMenuWの返り値が0(エラー発生を示す値)の場合、以後は(マルチバイト対応の)AppendMenuを使って、UTF-8のままの文字列を追加する処理が、その直後にあります。これは、(コメントによると)Windows 9x/MEで、「形だけの(何もしない)AppendMenuW」が存在する場合があるので、それに対応するためらしいです。
 ところが、(Windows XPや7などで)「実際に正しく機能するAppendMenuW」を使っている場合にも、まれに返り値が0になることがあります。テストコードを書いてみたところ、ウインドウサイズをドラッグで変更していると、何度か0が返ってくることを確認しました。上記の9x/Me対応部分により、0が返ってきた後はAppendMenuWが使われなくなり、AppendMenuにUTF-8のままの文字列が追加されるので、(a)と同様に文字化けが発生するわけです。

 対策としては、(実行中のWindowsのバージョンを調べるのはめんどくさいので)、とりあえず9x/ME対応部分を#if 0 ... #endifで囲んで取り除きます。いまどき9x/MEでNTEmacs動かしている人はいるんでしょうかね。

 問題点(a)(b)への対策を行なったw32menu.cのパッチを、
http://daregada.sakuraweb.com/emacs-23.3-fix-unicode-menu-greeking.patch.tar.gz
に置いておきましたので、動作確認していただけると幸いです。

 なお、Emacs 24系列でも、ソースを見た限りでは同じ問題が発生します。上記のパッチは(行がずれてますけど)当たりました。動作は確認していません。

メッセージ #61788 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする

RE: menu-treeによる日本語メニューの文字化けを解決 (2012-01-20 16:44 by ksugita #61792)

Daregadaさん,こんにちわ.

調査結果を提供いただき,誠にありがとうございます.
本プロジェクトは趣味レベルの範囲でしか対応しきれないため,
パッチまで提供いただいて,本当に助かります.

パッチを適用したバイナリは,週末リリース予定で準備中です.

「9x/ME対応部分を#if 0 ... #endif」という修正方法はアリだと思います.
cygwinも 1.7からは Windows95/98/Meを非対応になっていますし,
gnupackで公開するリリース物件も同様の方針にしたいと考えています.
(このことは,これを機にどこかに明記しておきます)


P.S.
別で書き込んでいただいたプロンプトのエスケープシーケンス漏れについて,
gnupack 7.03のリリースで取りもらしてしまいました….
コメントいただいたのに申し訳ないです.次回リリースこそ取り込むようにします.
#61788 への返信

メッセージ #61792 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする

RE: menu-treeによる日本語メニューの文字化けを解決 (2012-01-21 15:43 by daregada #61802)

詳細な解説を以下のブログに書きました。

http://daregada.blogspot.com/2012/01/windowsgnu-emacsmenu-treeel.html

パッチ紹介時のリンク先などにお使いください。
#61788 への返信

メッセージ #61802 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする

RE: menu-treeによる日本語メニューの文字化けを解決 (2012-01-21 16:08 by daregada #61803)

すいません。パッチに一箇所間違いがありました。
末尾付近の、

+ unicode_set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoW");

が、

+ unicode_set_menu_item_info = (SetMenuItemInfoW_Proc) GetProcAddress (user32, "SetMenuItemInfoW");

です。=の後の()の中が1文字違います。元のパッチのままでは文字化けが解消されないと思います。

#61788 への返信

メッセージ #61803 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする

RE: menu-treeによる日本語メニューの文字化けを解決 (2012-01-22 17:49 by ksugita #61814)

こんにちわ,Daregadaさん.

パッチ訂正の件,ご連絡ありがとうございます.
修正したパッチとバイナリは先ほどリリースしました.

また,パッチ内容を詳細に記載されているブログについて,
パッチ引用元として利用させていただきます.
#61803 への返信

メッセージ #61814 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする

RE: menu-treeによる日本語メニューの文字化けを解決 (2012-01-22 19:10 by daregada #61819)

お疲れ様です。

emacs-23.3b-20120122で、menu-tree.elの文字化けが起きないことを確認しました。
#61814 への返信

メッセージ #61819 への返信×

Wiki文法は使えません
ログインしていません。投稿を区別するために投稿者のニックネームをつけてください(ニックネームの一意性は保証されません。全く別の人も同じ名前を利用することが可能ですので本人であることの特定には利用できません。本人であることを保証したい場合にはログインして投稿を行なってください)。 ログインする