xtermはどうやってフォントを選択しているのか

$Id: xterm-fontsel.html,v 1.3 2015-05-13 13:34:29+09 kabe Exp $


Ctrl右クリックのMediumフォントでは日本語出ないんですけど、なんで?

対応するフォントが無い、からなんですけど、

UTF-8モードの xtermで、 例えば、Ctrl+右クリックの Medium フォント(日本語がでない)を選ぶと、 app-defaults の *VT100.utf8Fonts.font4: -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso10646-1 に沿ってフォントが選択されます。 具体的には以下のフォント名を生成して使おうとします:

このうち最後2つの全角用文字(wide font)は該当フォントがないので、 日本語は出ません。

xterm に Trace-parent.out を吐かせてみると

SetVTFont(which=4, f_n=<null>, f_b=<null>)
set myfonts.f_n from menu_font_names[4][fNorm] -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso10646-1
set myfonts.f_b from menu_font_names[4][fBold] <null>
set myfonts.f_w from menu_font_names[4][fWide] <null>
set myfonts.f_wb from menu_font_names[4][fWBold] <null>
xtermLoadFont #4 normal -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso10646-1
xtermLoadFont #4 bold   <null>
xtermLoadFont #4 wide   <null>
xtermLoadFont #4 w/bold <null>
/* 3項目を"bold"にしたXLFD名を作ってみる */
...derived bold -Misc-Fixed-bold-R-*-*-13-120-75-75-C-80-ISO10646-1
same_font_size height 13/13, min 8/8 max 8/8
...got a matching bold font	←適切な"bold"なフォントが見つかった
caching menu fontname 4.1 -Misc-Fixed-bold-R-*-*-13-120-75-75-C-80-ISO10646-1
/* wide(全角)用に、3項目を"medium", 12項目(平均幅)を通常フォントの倍、最後を"ISO10646-1" にしたXLFD名を作ってみる */
...derived wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-160-ISO10646-1
caching menu fontname 4.2 -Misc-Fixed-medium-R-*-*-13-120-75-75-C-160-ISO10646-1
/* wide用の該当フォントは無いので、フォント読み込みに失敗する */
/* wide-bold用のフォント名も捏造しますが、ログに出てない */
/* wide-bold用の該当フォントは無いので、フォント読み込みに失敗する */
...font server lied (count wide 0 vs wide-bold 0)	←グリフ数の検査に失敗したので、この全角フォントは使わない
...cannot load wide-bold, use wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-160-ISO10646-1	←wide-boldは見つからなかったので、wide用のを使う
		/* のだけど、そもそもwide用のフォントが見つかってないので、結局、全角文字は全部無効 */
same_font_size height 13/13, min 8/8 max 8/8
Will not use internal line-drawing characters
/* 重ね打ちでのboldエミュレーションはしない。boldが見つからなかった場合はする場合もある */
Will not use 1-pixel offset/overstrike to simulate bold

なお、このTrace-parent.outファイルは --enable-trace オプションで xterm を 再コンパイルしないと作られません。普段使いでは邪魔すぎるので通常は --disable になっているはずです。


-fnでフォント指定で起動してから、Ctrl右クリックでのフォント変更すると化けるんですけど?

(k14utfフォントをインストールした状態で) [env LANG=ja_JP.utf8] xterm -fn '-misc-fixed-medium-*-*-*-14-*-*-*-*-*-iso10646-*' で起動するとデフォルト状態では日本語などが出ますが、 Ctrl右クリックの VT Fonts メニューから他のフォントサイズを選ぶと 化けるというか8bit文字しか出ない状況になったりします。

これは、xtermが *vt100.utf8Fonts.font[1-6]リソースを使わず、 *vt100.font[1-6]をそのまま使うからです。

-fnを指定し、そのデフォルトフォントの読み込みで全フォント (normal, bold, wide, wide-bold)が 256文字を越えているフォントを読み込めた場合、 *vt100.utf8Fonts.font[1-6]リソースは使われません。 この後に VT Fontsメニューからフォントサイズ変更すると、 app-defaults/XTerm では *vt100.font3: 6x10などの iso8859フォントになっているので、 XLFDを加工しても対応する iso10646 wideフォントが 見つからず、日本語がことごとく出なくなります。

デフォルトでサイズ変更が効いている場合の動作

何も -fn を指定しないで起動すると、デフォルトの fixed フォント (-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO8859-1) を元にして各フォントを読もうとしますが、

normal: fixed (-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO8859-1) 255セル
bold: -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO8859-1 255セル
wide: -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1 65536セル
wide-bold: 該当なし、なのでwide流用 65536セル
が選択されます。 255セルしかないフォントが含まれるので、 "current fonts are not all wide" と判定します。 よって、*vt100.utf8Fonts.font[1-6]サブリソースを読み込みます。 (xtermのマニュアルで load-vt-fonts(utf8Fonts, Utf8Fonts) どうたら というのは要するにこの処理)

単にxterm -en utf8した際の Trace-parent.out の出力:

...
VTRealize
xtermLoadFont #0 normal fixed
xtermLoadFont #0 bold   <null>
xtermLoadFont #0 wide   <null>
xtermLoadFont #0 w/bold <null>
...derived bold -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO8859-1
same_font_size height 13/13, min 6/6 max 6/6
...got a matching bold font
caching menu fontname 0.1 -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO8859-1
...derived wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1
caching menu fontname 0.2 -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1
...font server lied (count wide 65536 vs wide-bold 0)
...cannot load wide-bold, use wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1

...

check if this is a wide font, if not try again
isWideFont(wide) found 65536 cells
isWideFont(wide-bold) found 65536 cells
isWideFont(normal) found 255 cells
current fonts are not all wide
/* 全部がwide フォントではないので、utf8Fonts サブリソースを併合する */
xtermLoadVTFonts saving original
COPY_MENU_FONTS w->screen to original
xtermLoadVTFonts(utf8Fonts, Utf8Fonts)
MERGE_SUBFONT subresourceRec.default_font.f_n found -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1
MERGE_SUBFONT subresourceRec.default_font.f_b merge <null>
MERGE_SUBFONT subresourceRec.default_font.f_w merge <null>
MERGE_SUBFONT subresourceRec.default_font.f_wb merge <null>
MERGE_SUBFONT subresourceRec.MenuFontName(n) merge nil2
MERGE_SUBFONT subresourceRec.MenuFontName(n) found -misc-fixed-medium-r-normal--8-80-75-75-c-50-iso10646-1
MERGE_SUBFONT subresourceRec.MenuFontName(n) found -misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1
MERGE_SUBFONT subresourceRec.MenuFontName(n) found -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso10646-1
MERGE_SUBFONT subresourceRec.MenuFontName(n) found -misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1
MERGE_SUBFONT subresourceRec.MenuFontName(n) found -misc-fixed-medium-r-normal--20-200-75-75-c-100-iso10646-1
COPY_MENU_FONTS subresourceRec to w->screen
xtermLoadWideFonts:1

utf8Fonts サブリソースを併合後は、再度フォントを探した結果、 以下のようなフォントを使うよう変更されます。 *VT100.utf8Fonts.font: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1を元にして探すので、 iso10646フォントに変更され、日本語や特殊文字が出ます。

normal: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1 65536セル
bold: -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO10646-1 65536セル
wide: -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1 65536セル
wide-bold: 該当なし、なのでwide流用 65536セル
/* utf8Fonts サブリソースを読み込んだので、フォントを再度探す */
SetVTFont(which=0, f_n=<null>, f_b=<null>)
set myfonts.f_n from menu_font_names[0][fNorm] -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1
set myfonts.f_b from menu_font_names[0][fBold] <null>
set myfonts.f_w from menu_font_names[0][fWide] <null>
set myfonts.f_wb from menu_font_names[0][fWBold] <null>
xtermLoadFont #0 normal -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-io10646-1
xtermLoadFont #0 bold   <null>
xtermLoadFont #0 wide   <null>
xtermLoadFont #0 w/bold <null>
...derived bold -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO10646-1
same_font_size height 13/13, min 6/6 max 6/6
...got a matching bold font
caching menu fontname 0.1 -Misc-Fixed-bold-R-*-*-13-120-75-75-C-60-ISO10646-1
...derived wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1
caching menu fontname 0.2 -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1
...font server lied (count wide 65536 vs wide-bold 0)
...cannot load wide-bold, use wide -Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1

この utf8Fonts サブリソース読み込みは、最初のデフォルトフォントの 読み込みの時だけ起動されます。 あとからCtrl右クリックの VT Fonts メニューで フォントサイズ変更しても適用されません。

xterm -fnでフォント明示した際の動作

xterm -en utf8 -fn '-misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1' でデフォルトフォントで日本語が出る設定にしてみると、
normal: -misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1 65536セル
bold: -Misc-Fixed-bold-R-*-*-18-120-100-100-C-90-ISO10646-1 65536セル
wide: -Misc-Fixed-medium-R-*-*-18-120-100-100-C-180-ISO10646-1 65536セル
wide-bold: 該当なし、なのでwide流用 65536セル
となり、全フォントがwideである、と判定され、 *vt100.utf8Fonts.font[1-6]リソースは使われません。
VTRealize
xtermLoadFont #0 normal -misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1
xtermLoadFont #0 bold   <null>
xtermLoadFont #0 wide   <null>
xtermLoadFont #0 w/bold <null>
...derived bold -Misc-Fixed-bold-R-*-*-18-120-100-100-C-90-ISO10646-1
same_font_size height 18/18, min 9/9 max 9/9
...got a matching bold font
caching menu fontname 0.1 -Misc-Fixed-bold-R-*-*-18-120-100-100-C-90-ISO10646-1
...derived wide -Misc-Fixed-medium-R-*-*-18-120-100-100-C-180-ISO10646-1
caching menu fontname 0.2 -Misc-Fixed-medium-R-*-*-18-120-100-100-C-180-ISO10646-1
...font server lied (count wide 65536 vs wide-bold 0)
...cannot load wide-bold, use wide -Misc-Fixed-medium-R-*-*-18-120-100-100-C-180-ISO10646-1

...

check if this is a wide font, if not try again
isWideFont(wide) found 65536 cells
isWideFont(wide-bold) found 65536 cells
isWideFont(normal) found 65536 cells
isWideFont(bold) found 65536 cells
/* xtermLoadVTFonts(utf8Fonts, Utf8Fonts) を行わない */
xtermLoadWideFonts:1

この後で、Ctrl+右クリックでフォントサイズ変更を行っても、 utf8Fontsリソースの併合が行われていないので、生の *VT100.font3: 6x10リソースが使われ、 wideフォントの読み込みに失敗します。

Smallフォントを選んでみた際の Trace-parent.out の部分:

SetVTFont(which=3, f_n=<null>, f_b=<null>)
set myfonts.f_n from menu_font_names[3][fNorm] 6x10
set myfonts.f_b from menu_font_names[3][fBold] <null>
set myfonts.f_w from menu_font_names[3][fWide] <null>
set myfonts.f_wb from menu_font_names[3][fWBold] <null>
xtermLoadFont #3 normal 6x10
xtermLoadFont #3 bold   <null>
xtermLoadFont #3 wide   <null>
xtermLoadFont #3 w/bold <null>
...derived bold -Misc-Fixed-bold-R-*-*-10-100-75-75-C-60-ISO8859-1
same_font_size height 10/13, min 6/6 max 6/6
...did not get a matching bold font
...derived wide -Misc-Fixed-medium-R-*-*-10-100-75-75-C-120-ISO10646-1
caching menu fontname 3.2 -Misc-Fixed-medium-R-*-*-10-100-75-75-C-120-ISO10646-1
/* wideフォントの読み込みに失敗。日本語は出ない */
...font server lied (count wide 0 vs wide-bold 0)
...cannot load wide-bold, use wide -Misc-Fixed-medium-R-*-*-10-100-75-75-C-120-ISO10646-1

解決法1

UXtermのリソースでは

*VT100.font3:   -misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1
などと定義されているので、 uxterm もしくは xterm -class UXTerm で起動するようにする。


▼付録

kterm には行間にすき間をあける -lsp (KTerm*lineSpace)オプション がありましたが、 xtermには Patch #274以降についている -sh (XTerm*scaleHeight) オプションで似たようなことができます。

xterm -sh 1.2 とすれば行送りが1.2行分になるのですき間があきます。 全角文字のところにカーソルを持っていくと段つきの反転表示になりますが。 (アンダーバー型カーソルをサポートするようになったため?)


▼リンク


かべ@sra-tohoku.co.jp