人気ブログランキング | 話題のタグを見る

メニュートリガー

メニュートリガー_a0011820_040189.jpg

図の一番上に示したのは BeOS を日本語で使っているとときどき見かける
「ファイル(F) 」というメニューです。ここで注目してほしいのは最後になんかゴミのような点があるところ。実はこの点、メニュー項目をキーで選択する際のトリガーである F の下に引かれるべき下線が別のところに出ているんです。

その下に示した 2 つのメニューは、BeOS R5 と Haiku で次のように作成した 4 つのメニュー項目を表示させてみたものです。

menuItem = new BMenuItem("Haiku BEOS beos rebirth", new BMessage('MNU1'));
menuItem->SetTrigger('B');
popupMenu->AddItem(menuItem);

menuItem = new BMenuItem("Haiku BEOS beos rebirth", new BMessage('MNU2'));
menuItem->SetTrigger('e');
popupMenu->AddItem(menuItem);

menuItem = new BMenuItem("はいく BEOS beos rebirth", new BMessage('MNU3'));
menuItem->SetTrigger('O');
popupMenu->AddItem(menuItem);

menuItem = new BMenuItem("はいく BEOS beos rebirth", new BMessage('MNU4'));
menuItem->SetTrigger('s');
popupMenu->AddItem(menuItem);

まずは BeOS R5 の方で上の 2 つのメニュー項目に注目。トリガーに大文字を指定しても小文字を指定しても、その区別なく、その文字が前から見つかったところに下線が引かれます。ところが、大文字で指定した方は実はキーでは操作できません。いや、もしかしたらキーに大文字が割り当てられている Keymap で試せば操作できるのかもしれませんが、そこまでは試していません。通常は小文字が割り当てられていると思うので、基本的にトリガーは小文字で指定すると考えていいでしょう。

次に BeOS R5 の残り 2 つのメニュー項目に注目。こっちは O と s を設定してあるのにとんでもないところに下線が引かれてます。どうもこれ、UTF-8 のバイト数で割り出したインデックスを文字数として計算しているようなのです。
UTF-8では「はいく BEOS beos rebirth」は「E3 81 AF E3 81 84 E3 81 8F 20 42 45 4F 53 20 62 65 6F 73 20 72 65 62 69 72 74 68」というコード列になります。「は」が「E3 81 AF」という 3 バイトで表されるわけです。
このコード列から「O」(4F あるいは 6F)を探すと前から 13 バイト目に見つかります。これは文字数で言えば前から 7 文字目になるのですが、実際に下線が引かれているのは 13 文字目ですね。マルチバイト圏のことが考慮されていないバグでしょう。

さて、このバグ、Haiku では治っているのかな~?と思って実験してみたのが図の一番下のもの。
Haiku の方でも注目して欲しいのが上の 2 つ。BeOS R5 と異なり、トリガーに指定した文字の大文字・小文字を区別して下線が引かれています。これは微妙に困ります。例えば「File」とメニューに「f」のトリガーを与える場合を考えてください。BeOS R5 では小文字を指定しないと実質動かないのですが、Haiku で小文字を指定すると(「f」はラベルに見つからないので)トリガーの下線が引かれません。BeOS R5 と Haiku の両方でうまく行くようなプログラムは作れないのです。ちなみに、Haiku、このバージョンではキーによるトリガー操作は大文字も小文字も効きませんでした。

それはそうと、残り 2 つのメニュー項目が今回の実験のメインです。結論から言うと、BeOS R5 と全く同じ不具合を持ってます。そんなところは再現しなくていいんだってば。

Haiku の BMenuItem のソースを見てみた感じでは、strchr で得たインデックスを BFont::GetEscapements() に渡しているのが悪いみたい。GetEscapements() の第 2 引数はバイト数じゃなくて文字数ですからね。
あと、ソースレベルでしか確認してませんが、BMenuItem::SetTrigger() を呼んだあとで BMenuItem::SetLabel() でラベルを変えてもトリガーの下線位置が更新されないように見えます。これもおかしいんじゃないのかな?

ある程度予想はしていたことですが Haiku も細かいところで完成度がまだまだのようです。

(2007-09-29 13:47追記
みなさんの励ましと Google 言語ツールのおかげで、なんとか Haiku プロジェクトへバグ報告しました。
http://dev.haiku-os.org/ticket/1506
)
by hironytic | 2007-09-21 00:46 | 情報
<< [CoveredCalc] キ... [CoveredCalc] ダ... >>