top page > L'Internationale > here

UTF-8 環境における mwm


概要

UTF-8 環境において生じる mwm (Motif Window Manager) のフォントの問題を検討します.

  1. Open Motif (x11-toolkits/openmotif) の version は 2.3.8 です.
  2. mwm の version は "Motif 2.3.4" とあります. (これは Open Motif として一括の version だと思います.)
    ちなみに,すべてのソースファイルの日付が 2017.8.17 です.

とりあえず,解決することができたと思います.

(2021.7.27) FreeBSD の ports/packages においては,firefox 90 あたりから,Window の title bar に閲覧先の <title> tag を表示するのをやめたようです. title bar には "Mozilla Firefox" と表示されるだけです. なので,ここに記した修正は不要になりました.


目次

1. はじめに
2. 原因の分析
3. 対策 (その 1)
4. 対策 (その 2)
5. 補足

1. はじめに

Window Manager mwm (x11-toolkits/motif) を UTF-8 の環境にて使うと,Window の title bar に表示される文字が化けることがあります.[1][2]

具体的には,~/.Xresources にて "Mwm*fontList" によりフォントを設定しようとすると,iso8859-1 と iso10646-1 の両方を同時に設定することができません.[3] そのくせ,片方だけ設定した場合にはうまく動作しません. すなわち,

以下でその原因を分析し,対策も二通り考えました. とりあえずは問題なく動作しております. ただし,これらを十分に試用したわけではないので,ご注意下さい.

なお,これらの対策を施した mwmLANG=ja_JP.eucJP の環境で用いても不具合は生じておりません.

[1] 私は積極的に title bar に漢字を表示したいわけではありません. firefox は閲覧先の <title> tag の内容を title bar に表示します. したがって,ここに漢字が使われている場合にはそれを表示してしまうのです. むしろ,可能ならば,この表示をやめるように firefox の設定をしたいです.
(2021.7.27) 概要にも書きましたが,最近の firefox はこのような表示を行なうのをやめたようです.

[2] OS は Linux ですが,同じ問題に遭遇した方がいらっしゃいます. ただ,その方の質問に対して回答がなされていないのが悩ましいです. (ここからの link は設定しておりません.)

https://motif.ics.com/forum/general-questions/mwm-font-setting-window-title

[3] LANG=ja_JP.eucJP の環境では,以下のように設定すればうまく行きます.

Mwm*fontList:\
-misc-fixed-medium-r-normal--14-*-*-*-*-*-iso8859-1; \
-misc-fixed-medium-r-normal--14-*-*-*-*-*-jisx0201.1976-0; \
-misc-fixed-medium-r-normal--14-*-*-*-*-*-jisx0208.1983-0:

LANG=ja_JP.UTF-8 の環境では,このように複数のファイルを設定するとエラーになります.

[4] こちらで遭遇した不具合をそのまま表わして「半角英数字」「漢字」という呼称を使いましたが,正確には「8 bit 文字」と「16 bit 文字」です.

[5] 他の Window Manager は iso10646-1 だけでちゃんと表示されるものが多いです. これには半角英数字のフォントも入っているので,本来そうなるはずです.

(1) twm ではこの問題は生じません. .twmrc を雛型から cp し,

% cp /usr/local/share/X11/twm/system.twmrc ~/.twmrc

以下の部分を,日本語のフォントを含みエンコードが iso10646 であるようなファイルを指すように書き換えれば,title bar に日本語が表示されます.

TitleFont "-gnu-unifont-medium-r-normal-sans-16-160-75-75-c-80-iso10646-1"

(2) fvwm2 (x11-wm/fvwm2) でもこの問題は生じません. .fvwm2rc を雛型から cp し,

% cp /usr/local/etc/system.fvwm2rc ~/.fvwm2rc

以下の部分を書き換えれば,title bar に日本語が表示されます.

Style *           Font -gnu-unifont-medium-r-normal-sans-16-160-75-75-c-80-iso10646-1

(3) xfce (x11-wm/xfce4-wm), mate (x11/mate) でもこの問題は生じません.

(4) lesstif (x11-toolkits/lesstif) の mwm は日本語が表示されませんでした.文字化けでなく空白になります. (これは当方の設定が不適切である可能性もあります.)

2. 原因の分析

先ず,探るべきは「両方のフォントを設定できない原因」なのか,「iso10646-1 フォントで半角英数字を表示しない原因」なのか迷いました.

前者ですが,~/.Xresources がどこでどう処理されるのか理解していないこと,Motif ではフォントの標準的な扱い方が XmFontList から XmRenderTable に代わっているのに mwm では前者を使い続けているので動作を追いにくいことから,頓挫しました. (ついでながら,私は XmRenderTable に関しては知識が追い付いていないのです.)

後者ですが,他の Window Manager は iso10646-1 フォントだけで問題が生じていないことから,こちらを追求すべきと考えました.[1] それで,title bar に表示される内容のデータの流れを追ってみました.

[1] 二つの対策ができた後で試したのですが,Motif を使った自作のプログラムにて,Label 等には iso10646-1 フォントだけで問題は生じないのです. なので,後者を追求して正解だったのだと思います.

以後,current directory を以下のところに移します.

# cd /usr/ports/x11-toolkits/open-motif/work/motif-2.3.8/clients/mwm/

WmWinInfo.c の関連部分を要約します. indent は関数の呼び出し関係を表わします.

GetClientInfo()
   ProcessWmWindowTitle()
      XGetWMName(&wmNameProp)    [1]

      title_xms = WmICCCMToXmString(&wmNameProp)   [2]
         XmCvtTextPropertyToXmStringTable()

      pCD->clientTitle = title_xms

      DrawWindowTitle(pCD)   [3]

[1] ここで Window の title bar に表示する文字列やその encode 等を取得し,XTextProperty 形式の変数 wmNameProp に格納します. encode は.文字列が半角英数のみならば 8 bit 文字,漢字のみまたは混在の場合には 16 bit 文字とされます.
[2] XTextProperty 形式の情報を XmString 形式の変数 title_xms に書き換えます.
  ここで 8 bit 文字は COMPONENT_TEXT として,16 bit 文字は COMPONENT_LOCALE_TEXT として分類されます.
[3] 描画のための関数が呼ばれます,

次に WmCDecor.c の関連部分を要約します.

DrawWindowTitle(pcd)   [3]

     if (DECOUPLE_TITLE_APPEARANCE(pcd))   [4]
     {
        fontList = CLIENT_TITLE_APPEARANCE(pcd).fontList;
     }
     else
     {
        fontList = CLIENT_APPEARANCE(pcd).fontList;
     }

     WmDrawXmString(fontList,pcd->clientTitle)   [5]
        XmStringDraw()

[4] ~/.Xresources で設定したフォント (この段階では XmFontList 形式) を fontList に設定します.
  COMPONENT_TEXT に対しては iso8859-1COMPONENT_LOCALE_TEXT に対しては iso10646-1 を設定すべきです.
  しかし,両方のフォントを同時に設定できないので,どちらかの表示がうまく行きません.
  (iso10646-1 には半角英数字の情報もあります. それにも関わらず文字が化けるのは,半角二文字を漢字一文字と解釈してしまうからです.)
[5] タイトルを描画します. WmDrawXmString() (WmGraphics.c) は実質,標準関数である XmStringDraw() を呼ぶだけなので勝手に中をいじれません. 対策はこの前にしておく必要があります.

3. 対策 (その 1)

WmWinInfo.c の関連部分を次のように変更します.
すなわち,半角英数字のみの場合においても encoding を 16 bit の文字列に変更します. こうすれば WmICCCMToXmString() はこの文字列を COMPONENT_LOCALE_TEXT にしてくれます.

不安なのは,この 294 という数字が何であるのかが分からないことです. 十分な普遍性があれば良いのですが.

この変更の「あり」「なし」を切り換え易いように #ifndef AAA#endif で囲みました.

--- WmWinInfo.c.orig    2017-08-17 09:38:43.000000000 +0900
+++ WmWinInfo.c 2020-02-18 22:18:15.580177000 +0900
@@ -2316,6 +2316,13 @@
 #endif /* WSM */
        XGetWMName(DISPLAY, pCD->client, &wmNameProp))
     {
+#ifndef AAA
+/*  XA_STRING  (= 31  defined in X11/Xatom.h) : 8 bit string  */
+/*  294 : 16 bit string (depend on font and/or environment ?)  */
+
+      if ( wmNameProp.encoding == XA_STRING )  wmNameProp.encoding = (Atom)294;
+#endif
+
       title_xms = WmICCCMToXmString(&wmNameProp);
       if (wmNameProp.value)
        XFree ((char*)wmNameProp.value);

この変更の後,openmotif 全体を make し直す必要はありません. この directory にて make, make install すれば良いです.

~/.Xresources は次のようにします.

Mwm*fontList:-gnu-unifont-medium-r-normal-sans-16-160-75-75-c-80-iso10646-1
Mwm*client.fontList:-gnu-unifont-medium-r-normal-sans-16-160-75-75-c-80-iso10646-1
Mwm*icon.fontList:-sony-fixed-medium-r-normal--16-120-100-100-c-80-iso8859-1

iconiso8859-1 であることにご注意下さい. ここも iso10646-1 にしたければ,icon に関しても同様の変更をすれば良いです. ただ,icon で表示されるのはプログラム名であり,絶対に半角英数字であることと,以下の「対策 (その 2)」との共用 (単なる試用の便宜) も考えてこのようにしております.

4. 対策 (その 2)

WmCDecor.c を以下のように変更します.
~/.Xresources にて icon 用のフォントを iso8859-1 に設定することにして,タイトルの文字列が半角英数字である場合にはそちらを使うようにします.

この変更の「あり」「なし」を切り換え易いように #ifndef AAA#endif で囲みました.

--- WmCDecor.c.orig     2017-08-17 09:38:43.000000000 +0900
+++ WmCDecor.c  2020-02-18 22:02:47.418784000 +0900
@@ -1215,6 +1215,17 @@
     Window win;
     XmFontList  fontList;
 
+#ifndef AAA
+    char *text;
+    int c;
+    unsigned char     *unknown_value;
+    XmStringCharSet   charset;
+    XmStringDirection direction;
+    XmStringContext   context;
+    XmStringComponentType component_type, peek_comp_type, unknown_tag;
+    unsigned short unknown_length;
+#endif
+
     /* make sure there is a title bar first */
     if (!(decoration & MWM_DECOR_TITLE))
        return;
@@ -1254,6 +1265,28 @@
        win = pcd->clientFrameWin;
        fontList = CLIENT_APPEARANCE(pcd).fontList;
     }
+
+#ifndef AAA
+        c = 0;
+        if ( XmStringInitContext(&context,pcd->clientTitle) )  {
+           while ( (component_type=
+               XmStringGetNextComponent(context,&text,&charset,
+               &direction,&unknown_tag,&unknown_length,
+               &unknown_value)) != XmSTRING_COMPONENT_END )  {
+
+              if ( (int)component_type == XmSTRING_COMPONENT_CHARSET )  {
+                 c = 1;  break;
+              }
+              else if ( (int)component_type == XmSTRING_COMPONENT_TEXT )  {
+                 c = 1;  break;
+              }
+           }
+        }
+
+        if ( c == 1 )  {/*  if ISO8859-1, exchange fontList for ICON  */
+          fontList = ICON_APPEARANCE(pcd).fontList;
+        }
+#endif  /*  AAA  */
 
     if (eraseFirst)
     {

5. 補足

UTF-8 対応の日本語フォントですが,pcf 形式に限定すれば,標準では次のものがあります.

-misc-fixed-medium-r-normal-ja-13-120-75-75-c-120-iso10646-1
-misc-fixed-medium-r-normal-ja-18-120-100-100-c-180-iso10646-1

ただし,xfd (x11/xfd) で表示すればわかるように,これらのフォントは半角英数字の幅が全角と同じになっています.
(このことを知らないと,設定を間違えたのかと勘違いしてしまうんですよね.)

% xfd -fn "-misc-fixed-medium-r-normal-ja-13-120-75-75-c-120-iso10646-1"

そこで GNU Unifont を試してみます.これを ports から導入します.

# cd /usr/ports/x11-fonts/gnu-unifont
# make install

これを使える状態にするために,xorg.conf にて以下のように FontPath を設定します.

Section "Files"
   FontPath   "/usr/local/share/fonts/gnu-unifont/"
EndSection

「使える状態」かどうかは xlsfonts (x11-fonts/xlsfonts) を使えば確認することができます.

% xlsfonts | grep gnu

として,次のように出力されれば大丈夫です.

-gnu-unifont-medium-r-normal-sans-0-0-75-75-c-0-iso10646-1
-gnu-unifont-medium-r-normal-sans-16-160-75-75-c-80-iso10646-1

UTF-8 対応の日本語フォントは種々配布されておりますので,お気に入りのものを探すのも一興でしょう.