結合文字が結合せずに表示されるため、スクリーンの表示幅が合わなくなる
手元の環境では再現しませんでした。ウィンドウタイトルや、ログファイルの内容から想像するに、GNU Screenを間に挟んでいませんか?
以下、ログを読んだ結果です。
Tera Termでの表示結果とPuTTYでの表示結果を比べると、Tear Termでは "Middle/Near East" や "South Asia", "South East Asia" などの行の次の行が空行になっています。
この空行が入る事によって全体の行数が増えた結果、上の方の行はスクロールアウトして見えなくなっています。
PuTTYでの表示もよく見ると South East Asiaの次に余計な空行が入っている為、一行目の This is a list of ways ~ という行がスクロールアウトして表示されていません。
背景色を黒以外に変更し、ウィンドウサイズを少し広げた状態でログをcatで表示すると何が起こっているか分かりやすいです。(添付 tt5-cat-log.png)
各行は表示する文字の部分だけではなく、背景色が黒の状態で(元の端末サイズでの)行末までスペースが出力されています。この挙動はおそらくGNU Screenの物だと思います。
その上で、余計な空行が入る前の行(South Asia等)を見ると、他の行より余計にスペースが出力されています。
これはGNU Screenが期待している表示幅とTera Termでの実際の表示幅が違う(Tera Termの方が広い)為、行末スペースを余計に出力している為だと思います。
その結果、余計なスペースで改行が発生して空行が入ってしまっています。
一部の結合文字が結合されずに表示されているように見えます。
例えば South East Asia: の直後ですが、 U+1787 BS U+1787 U+17C6 が出力されています。
この内最初のU+1787 は直後のBSで消える(重ね書きされる)ので無視し、後ろの U+1787 U+17C6 を考えます。
echo -e "\xe1\x9e\x87\xe1\x9f\x86" を実行すると上記2文字をUTF-8で出力されます。
この時PuTTYでは結合されて1桁で表示されますが、Tera Termでは結合されずに2桁として表示されます。
GNU ScreenもPuTTYと同じく1桁だと判断している為、画面での表示幅がずれていると思われます。
他の部分もほぼ結合されていないのが原因のように見えます。Europeの行のみ ¡ や ü ß が2桁として表示されているのが原因です。(これは曖昧文字幅の問題?)
doda への返信
検証ありがとうございます。
まず、ご指摘の通り screen を挟んでいます。screen なしのログを添付します。
途中から表示される理由
桁がはみ出した結果として行数があふれた場合に、下ではなく上に向かってはみ出すというのが私の直感には反したのですが、そういうことがある、ということですね。
結合文字
確かに「点線の○にヒゲのような記号」は結合されるべき文字ですね。Middle/Near East, South Asia, South East Asia の4行はこれが原因に見えます。
ヘブライ語などのLTRが悪さをしているかと思いましたが、Middle/Near Eastの行は1文字ぶんしかはみ出していないのでそれは大丈夫そうな気がしています。
あいまい文字幅
「Setup」「Additional Settings」「coding」「Ambiguous Characters width」を1にすると、Europeの「¡, ü, ß」が1桁で表示されました。
Tera Term を改善できる点としては「結合文字が結合されていない」という理解をしました。
それ以外の部分で、Unicode charsetの行のロシア語のЗдравствуйте!がйとтの間で\で改行されているので emacs は2桁を想定しているように見えます。Europeのために曖昧文字幅を1にすると、キリル文字やギリシャ文字がつぶれることになるのですが、これはフォントの問題になるでしょうか?
桁がはみ出した結果として行数があふれた場合に、下ではなく上に向かってはみ出すというのが私の直感には反したのですが、そういうことがある、ということですね。
上にはみ出すというか、余計な改行が発生した時点では下に行が増えますが、その結果早く画面下端に着くのでそれ以降の表示で画面全体がスクロールしているという事です。
最終的な表示だけからでは分かりづらいですが、描画していく過程が見えると理解しやすいかもしれません。
添付の C-l_5alpha.tty は描画の過程を分かりやすくする為に以下を行ったttyrec形式のログです。
これを見ると何が起きているのか分かりやすいと思います。
Europeのために曖昧文字幅を1にすると、キリル文字やギリシャ文字がつぶれることになるのですが、これはフォントの問題になるでしょうか?
JIS X 0208 にキリル文字やギリシャ文字が収録されている関係で、日本語用のフォントではこれらの文字が全角でデザインされている事が多いです。 これを半角で表示する為、文字の右側が切れて表示されます。
Ricty DiminishedやHackGen Console などのように、半角としてデザインされているフォントを使うと綺麗に表示できます。
全角でデザインされているフォントでも比較的問題なく表示出来るようにする為には、PuTTYのように横方向に圧縮するというのが有ります。特に→は右側が切れるとハイフンに見えてしまうので、圧縮して表示する機能は欲しいですね。
その結果早く画面下端に着くのでそれ以降の表示で画面全体がスクロールしている
描画していく過程が見えると理解しやすいかもしれません。
よくわかりました。1,1 の位置で C-l しているので、頭の中でそこが基準になってしまっていました。
半角としてデザインされているフォント
HackGen Console に設定したら半角になりました。カーソルを進めると2桁ぶん進んだり、表示が右端に到達する桁数がずれるのも、emacs を設定(と、挟んでいれば screen の設定も)すれば解消できるのだろうと理解しました。
emacs の view-hello-file がどのように表示されるのか、端末エミュレータの表示を比べてみました。
Tera Term | PuTTY | RLogin | |
結合文字 | 結合されず次の位置に表示される カーソルは"結合されて1文字"のカウントで進む(行末があわず手前でぶつかる) すべての結合文字に非対応なわけではない? | 結合して表示される カーソルは"結合されて1文字"のカウントで進む(行末があう) | 結合されているようだが、結合された文字は表示されない カーソルは"結合されて1文字"のカウントで進む(行末があう) |
LTR | 「שלום」が正しく並んでいる "East: "から右にカーソルを進めていくと、右端に進んで左に戻ってくる | 「שלום」が逆順に並んでいる ヘブライ語とアラビア語の位置が逆になっている(中立文字のカンマとスペースをRTL扱いしてしまっている?) "East: "から右にカーソルを進めていくと、右端に進んで左に戻ってくる | 「שלום」が逆順に並んでいる "East: "から右にカーソルを進めていくと、右端に進んで左に戻ってくる |
その他 | ベトナム語のbạnのạが半分切れて表示される ヘブライ語の文字が半分切れて表示される C-lで5行スクロールアウトする(Middle/Near East,South Asia(2行),South East Asia, Arabicの行) | ベトナム語のbạnのạが半分切れて表示される C-lで1行スクロールアウトする(South East Asia の行) アラビア語が表示されない | ベトナム語のbạnのạが半分切れて表示される C-lでスクロールアウトしない |
スクロールアウトのせいで、カーソルが見えている行とカーソルが実際にある行がズレていると思いますが、それを脳内で補正して位置を数えています。
上記の動作は、私がアプリやemacsを設定に適切していないためにそうなっている可能性もあります。
結合文字情報の抜けを修正しました。r10098 です。
emacsのHELLOをgithub上のリポジトリ(ミラー)から取ってきてテストしています。
wget https://raw.githubusercontent.com/emacs-mirror/emacs/master/etc/HELLO -O -
修正前の、結合文字がうまく表示されていないのかな? という部分はなくなったと思います。
とても進展がありうれしいです。ありがとうございます。
で確認しました。
South Asia: નમસ્તે, नमस्ते, ನಮಸ್ಕಾರ, നമസ്കാരം, ଶୁଣିବେ, Malayalam: നമസ്കാരം 0x0d28 ന 0x0d2d മ 0x0d38 സ 0x0d4d ് (Nonspacing Mark) 0x0d15 ക 0x0d3e ാ (Spacing Mark) 0x0d30 ര 0x0d02 ം (Spacing Mark) Oriya: ଶୁଣିବେ 0x0b36 ଶ 0x0b41 ୁ (Nonspacing Mark) 0x0b23 ଣ 0x0b3f ି (Nonspacing Mark) 0x0b2c ବ 0x0b47 େ (Spacing Mark)
現在のところ Tera Term 5 は Nonspacing Mark の処理しかしていません。 Spacing Mark でも Nonspacing Mark として扱っています。
Malayalamをベースにした Spacing Markのテスト用スクリプト作りました(r10301)。
Tera Term 5 で表示したものをコピーしてメモ帳などにペーストしてでみると U+0d2f はフォントの幅がなんだか1cellより幅が広いなと思います。 でも East Asian Width でこの文字は Neutral なので、Tera Term 5上では 1cell で ok のはずです。 Tera Term 5 上では縮小などの加工なく1cellの幅で描画するので (フォントによって異なりますが)右が切れた表示になると思います。
U+0d2f U+0d3e では +1 で合計2cellですね。
2cellより大きな文字を作れるのが Spacing Mark では問題になりそうです。 カーソル表示,文字の選択,行末のWrap などが思いつきます。 Tera Trm 5 の内部では今のところ 1文字は1か2cell(全角/半角) しか考慮していません。
3cell以上になる(たすけてみたいな面白文字ではなく)普通の文字が存在するなら対応が必要です。 とりあえずは、2cellに収めて表示するように実装したらどうかなと思っています。
U+0D4D の結合がどのような仕様かわからなかったです。 https://www.unicode.org/charts/PDF/U0D00.pdf 特に書いてないようです。ZWJ みたいに文字と文字の間に入れると結合するのかな?
ほかにも、wikipediaによると 「独自の規則」というという説明があります。どんな規則だろう・・
1cellの幅で描画するので (フォントによって異なりますが)右が切れた表示に
上で書いたヘブライ語とかベトナム語の「ạ」と同じですね。
など考えられるかもしれませんが、それはまた別の話だと思います。
3cell以上になる
マラヤーラム語には ൈ とか ൊ ോ ൌ なんて文字もありますね。組み合わさったら3文字の幅を取りそうです。
ベンガル語には ো という文字があって、組み合わせると কোになりますが、この幅は2文字のように見えます。
UnicodeData.txt には Spacing Mark であるかどうかはありますが、幅をいくつとるかという定義はなさそうですね。
とりあえずは、2cellに収めて表示するように
私としては「多言語を表示するテストとして view-hello-file は比較的メジャーなものだと思うので、あまり崩れてほしくない」という感じで、実用で困っているわけではないので、ひとまず +1 の width で表示されてくれればよいかなと思います。
+0D4D の結合がどのような仕様
もしかして独自の規則の一つ上にある「ヴィラーマ」というものでしょうか。
セルにとらわれないデザインのフォント(多分 East Asian Width の Neutral)を どうやって圧縮表示してきれいに表示するか、難しそうです。
また別の話
そうですね、別チケットで。
Spacing Mark であるかどうかはありますが、幅をいくつとるかという定義はなさそう
どこかに定義してあるのかな。他のソフトは1cellにしているようなのでならっています。
手もとである程度実装しました。次の出力を添付します
$ wget https://raw.githubusercontent.com/emacs-mirror/emacs/master/etc/HELLO -O - --quiet | grep MalayaHELLO_1012.png
出力はよさそうです。
今のところ、0x0d3e, 0x0d02 の2文字だけ Nonspacing mark としてハードコードしていますが、 コード全体からNonspacing Markのテーブルを作ってしらべることができればよさそうです。
സ്കാ| U+0d38 U+0d4d(Nonspacing Mark) U+0d15 U+0d3e(Spacing Mark) 2cell??
unicodebuf-combining-spacing_mark.pl
U+0d15は普通の文字らしいので、U+0d4dがU+0d15を前の文字と結合させる作用 があるようです。このルールがわかっていません。
とりあえず、U+0d4dがあれば次の文字と結合するようにハードコードして 正しいかなと思う出力を得ています。もう少し調べます。
ありがとうございます。
ヴィラーマ
マラヤーラム語は6文字の幅になっているので大丈夫そうです。
Devanagari と Kannada の、今まで見えていた部分が見えなくなってしまっているようです。
Spacing Mark
マラヤーラム語の最後の文字「ം」が見えていますし、オリヤー語の最後の「 େ」が基底文字の左に見えていますので、大丈夫そうです。
South Asia: નમસ્તે, नमस्ते, ನಮಸ್ಕಾರ, നമസ്കാരം, ଶୁଣିବେ, Gujarati: 3文字の幅(足りない?) 1 ન 2 મ 3 સ ્ GUJARATI SIGN VIRAMA ત 幅が足りなくて見えない ે Devanagari: 3文字の幅(足りない?) 1 न 2 म 3 स ् DEVANAGARI SIGN VIRAMA त 幅が足りなくて見えない े Kannada: 5文字の幅(OK) 1 ನ 2 ಮ 34 ಸ ್ KANNADA SIGN VIRAMA ಕ 4の右下に小さく存在する(幅が足りなくて見えない) ಾ 3の次に見えている 5 ರ Malayalam: 6文字の幅(OK) 1 ന 2 മ 34 സ ് MALAYALAM SIGN VIRAMA ക 右下に小さく表示されている ാ സの幅が広いので幅が足りなくて見えない 56 ര ം Oriya: 4文字の幅(OK) 1 ଶ ୁ 2 ଣ ି 34 ବ େ
Virama の前後は結合する、というルールだけだと問題があるようです。
emacs の view-hello-file で問題がある文字をピックアップした perlスクリプトです。
Tamilは"("が消えてしまいます。
# Virama + Spacing mark test use utf8; binmode STDOUT, ":utf8"; local $| = 1; # Devanagari # wget https://raw.githubusercontent.com/emacs-mirror/emacs/master/etc/HELLO -O - --quiet | grep Devanagari # name prop width print "\N{U+0938}"; # DEVANAGARI LETTER SA +1 print "\N{U+094d}"; # DEVANAGARI SIGN VIRAMA Virama +0 print "\N{U+0924}"; # DEVANAGARI LETTER TA +0 print "\N{U+0947}"; # DEVANAGARI VOWEL SIGN E Nonspacing mark +0 print "\n"; # Gujarati # wget https://raw.githubusercontent.com/emacs-mirror/emacs/master/etc/HELLO -O - --quiet | grep Gujarati # name prop width print "\N{U+0ab8}"; # GUJARATI LETTER SA +1 print "\N{U+0acd}"; # GUJARATI SIGN VIRAMA Virama +0 print "\N{U+0aa4}"; # GUJARATI LETTER TA +0 print "\N{U+0ac7}"; # GUJARATI VOWEL SIGN E Nonspacing mark +0 print "\n"; # Tamil # wget https://raw.githubusercontent.com/emacs-mirror/emacs/master/etc/HELLO -O - --quiet | grep Tamil # name prop width print "\N{U+0bb4}"; # TAMIL LETTER LLLA +1 print "\N{U+0bcd}"; # TAMIL SIGN VIRAMA Virama +0 print "\N{U+0029}"; # RIGHT PARENTHESIS +0 print "\n";
Virama の前後は結合する、というルールだけだと問題があるようです。
「Virama の前後は結合し、追加幅は+0」となっているようですね。
Virama結合をしていい場合とそうでない場合があり、Tamil の「Virama+)」は結合すべきではない場合に見えます。「行末がVirama」のとき(これはおかしくなっていない)のように、結合しないことができればよいのでしょうか。「結合するのは同じ言語の範囲内」みたいな条件が必要なのかもしれません。
Virama の後の文字が「Nonspacing Markのように下に表示され、追加幅が+0」の場合と、「Spacing Markと同様に次のcellに表示され、追加幅が+1」の場合があるように見えます。文字の種類は同じ Lo なのにこの違いがあるので、もしかしたら「どの言語か」で判定しなければいけないのかもしれません。
Gujarati: 1 ન / U+0AA8 / GUJARATI LETTER NA / Lo / +1 2 મ / U+0AAE / GUJARATI LETTER MA / Lo / +1 3 સ / U+0AB8 / GUJARATI LETTER SA / Lo / +1 ્ / U+0ACD / UJARATI SIGN VIRAMA / Mn / +0 ત / U+0AA4 / GUJARATI LETTER TA / Lo / +0 ... この Lo は +1 であるべき ે / U+0AC7 / GUJARATI VOWEL SIGN E / Mn / +0 Devanagari: 1 न / U+0928 / DEVANAGARI LETTER NA / Lo / +1 2 म / U+092E/ DEVANAGARI LETTER MA / Lo / +1 3 स / U+0938 / DEVANAGARI LETTER SA / Lo / +1 ् / U+094D / DEVANAGARI SIGN VIRAMA / Mn / +0 त / U+0924 / DEVANAGARI LETTER TA / Lo / +0 ... この Lo は +1 であるべき े / U+0947 / DEVANAGARI VOWEL SIGN E / Mn / +0 Kannada: 1 ನ / U+0CA8 / KANNADA LETTER NA / Lo / +1 2 ಮ / U+0CAE / KANNADA LETTER MA / Lo / +1 3 ಸ / U+0CB8 / KANNADA LETTER SA / Lo / +1 ್ / U+0CCD / KANNADA SIGN VIRAMA / Mn / +0 ಕ / U+0C95 / KANNADA LETTER KA / Lo / +0 ... この Lo は +0 でよい?下に小さく表示 4 ಾ / U+0CBE / KANNADA VOWEL SIGN AA / Mc / +1 5 ರ / U+0CB0 / KANNADA LETTER RA / Lo / +1 Malayalam: 1 ന / U+0D28 / MALAYALAM LETTER NA / Lo / +1 2 മ / U+0D2E / MALAYALAM LETTER MA / Lo / +1 3 സ / U+0D38 / MALAYALAM LETTER SA / Lo / +1 ് / U+0D4D / MALAYALAM SIGN VIRAMA / Mn / +0 ക / U+0D15 / MALAYALAM LETTER KA / Lo / +0 ... この Lo は +0 でよい?下に小さく表示 4 ാ / U+0D3E / MALAYALAM VOWEL SIGN AA / Mc / +1 5 ര / U+0D30 / MALAYALAM LETTER RA / Lo / +1 6 ം / U+0D02 / MALAYALAM SIGN ANUSVARA / Mc / +1 Tamil: 1 த / U+0BA4 / TAMIL LETTER TA / Lo / +1 2 ம / U+0BAE / TAMIL LETTER MA / Lo / +1 3 ி / U+0BBF / TAMIL VOWEL SIGN I / Mc / +1 4 ழ / U+0BB4 / TAMIL LETTER LLLA / Lo / +1 ் / U+0BCD / TAMIL SIGN VIRAMA / Mn / +0 ) / U+0029 / RIGHT PARENTHESIS / Pe / +0 ... 結合すべきではない 1 வ / U+0BB5 / TAMIL LETTER VA / Lo / +1 2 ண / U+0BA3 / TAMIL LETTER NNA / Lo / +1 3 க / U+0B95 / TAMIL LETTER KA / Lo / +1 ் / U+0BCD / TAMIL SIGN VIRAMA / Mn / +0 க / U+0B95 / TAMIL LETTER KA / Lo / +0 ... この Lo は +1 であるべき 4 ம / U+0BAE / TAMIL LETTER MA / Lo / +1 ் / U+0BCD / TAMIL SIGN VIRAMA / Mn / +0 ... この次が改行で、結合されていない Javanese: 1 ꦲ / U+A9B2 / JAVANESE LETTER HA / Lo / +1 2 ꦭ / U+A9AD / JAVANESE LETTER LA / Lo / +1 3 ꦺ / U+A9BA / JAVANESE VOWEL SIGN TALING / Mc / +1 4 ꦴ / U+A9B4 / JAVANESE VOWEL SIGN TARUNG / Mc / +1 "2" の文字に2つの Spacing Mark が結合して 3cell になっている
Virama の後ろの文字分の幅を+1するようにしました。r10319です。
表示を見た感じはよさそうです。 Tamilのときの Virama の次に ")" が来た場合でも+1されてうまく表示されます。
ありがとうございます。emacs で行末まで移動したときのカーソル位置も大丈夫そうです。
しかし、grep したり emacs で view-hello-file したときに、いままで表示されていた部分が表示されなくなってしまったようです。cat したときには表示されるようなのですが…
手もとでフォントがうまく表示されない不具合再現しました。
assert()することもあるようです。
もう少し調べます。
r10325 で、ヴィラーマで結合する条件を追加しました。
文字のセルへの収まりが考えていた通りになりました。 ありがとうございました。
Virama について調べていて次の資料を見つけました。
http://unicode.org/faq/indic.html#17
実装していないルールが残っていそうです。 でも表示には問題ない状態になっているのかなと思います。
いったんクローズしてはと思いますがどうでしょうか?
Emacs の HELLO を表示し、C-l すると、1行目からではなく途中から表示されます。
「記号を幅1で表示するか2で表示するの違いがあり、ひとつの行が端末の次の行まで続いて表示された結果、何行目まで表示されるかが変わる」というなら理解できます。しかし、最後に表示される行が異なるのではなく、最初に表示される行が異なるのには違和感を覚えます。
Tera Term 4 からの挙動なので、Tera Term 5 の開発で内部を Unicode 化したことによる問題ではなく、以前からある何らかの原因によるものと思われます。