Skip to content

Commit

Permalink
term: work around Cygwin-console bug of bottom IL/DL
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Feb 22, 2021
1 parent 6ca0b8c commit 5dce0b8
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 37 deletions.
1 change: 1 addition & 0 deletions memo/ChangeLog.md
Expand Up @@ -60,6 +60,7 @@

- term: work around quirks of Solaris xpg4 awk `#D1481` 0000000
- term: support key sequences and control sequences of Solaris console `#D1481` 0000000
- term: work around Cygwin-console bug of bottom `IL`/`DL` `#D1482` 000000

## Internal changes and fixes

Expand Down
195 changes: 195 additions & 0 deletions note.txt
Expand Up @@ -1204,6 +1204,18 @@ bash_tips
ToDo
-------------------------------------------------------------------------------

2021-02-22

* cygwin: 下部での IL が動かない旨を報告する?

後 DA2 応答をしてくれないか頼みたい。

$ printf 'Line %s\n' {0..100}; /bin/sleep 1; printf '\e[L'; /bin/sleep 1

最下部で DL を実行した時にも何か変な事が起こる。

$ printf 'Line %s\n' {0..100}; /bin/sleep 1; printf '\e[M'; /bin/sleep 1

2021-01-28

* progcolor: ble/syntax/progcolor/eval-word を着色を跨いでキャッシュできないか
Expand Down Expand Up @@ -3811,6 +3823,189 @@ bash_tips

2021-02-20

* term: Cygwin console で最終行で IL/DL すると画面消去されるバグ [#D1482]

Solaris に加えて Cygwin console も何だか変な振る舞いをしている。
どうも一番下の行で .insert-newline をすると画面の内容が全て消える。
分かった。どうやら一番下の行で IL すると問答無用で画面クリアされる。
これは明らかにバグである。Cygwin をアップデートしてみる事にする。

→cygwin を update して見たが修正されていない。なので、結局 ble.sh の側で対
策をしなければならない。この様な壊れた IL に対して対策を実行する事は可能な
のだろうか。

* 取り敢えず現在位置が分かっていれば対応は可能である様に思われる。一番下の行
にいる時には IL の代わりに CSI 2K を実行すれば良い。それ以外の行にいる時に
は特に問題は起こらない様だ。

うーん。最下部にいるかどうかで振る舞いを変えるのは難しい気がする。取り敢
えず複数行の IL, DL の時にはちゃんと計算ができていれば最下行になる事はな
い。問題は単一行の IL 及び DL で以下に最下行での IL/DL を避けるかという事。

最下行にいない時には以降の内容を下に一行ずらす役割がある。うーん。それよ
り下に内容があると分かっている場合には IL/DL を実行し、それより下に内容が
ないという場合には DL を実行するというのが可能な対策方法である。

うーん。かなり面倒臭い。というより CYGWIN の側で修正してもらえばこの様な
面倒な事はしなくても良い筈なのである。取り敢えずこの workaround の為に本
体の描画アルゴリズムを変更する事はしない事にする。

IL/DL の中だけで対策可能であればそれを実施する。そうでなければ何もしない。

例えば IND CUU を実行して一番下の行にダミー行を挿入して、その上で DL/IL
を実行してから、RI かスクロールを実行してまた元に戻すという実装は可能だろ
うか。→ SD,SU を実行してみたが消えてしまった行は戻ってこない様である。RI
も同様に一度消えた内容が戻って来る物ではない。うーん。現在最下行にいるか
どうかを判定して動作を切り替えるしかないのか。

| a 結局 DSR(6) で現在位置を問い合わせて一番下の行にいる時には CSI 2K で行
| 消去する事にした。
|
| x これで以前よりも全画面消去が起こる場面は減ったが、それでもやはり全画面消
| 去が依然として発生している。何故だろうか。IL/DL を実行している箇所は既に
| 全て抑えてある。とすれば IL/DL とは別に未だ全画面消去を引き起こす物が存在
| しているという事。
|
| 問題が発生している場所での出力内容を確認すると
|
| ^[(B^[[m^[[1B^M^[[2K^[[1M^[(B^[[m^[[1A^[[31C^[(B^[[m
|
| printf '\e(B\e[m\e[1B\r\e[2K\e[1M\e(B\e[m\e[1A\e[31C\e(B\e[m'
|
| うーん。全消去が起きそうな気配は何処にもない気がする。と思ったが、よく見
| たら DL(1) が含まれている。これは一体何処から現れたのだろう…。あー。分かっ
| た。。DSR(6) で問い合わせする前に flush しないと駄目だ。
|
| そして各スタックにある DRAW_BUFF にアクセスして出力予定の内容を全て集めて
| flush しなければならない。然し、DRAW_BUFF の中には取り敢えず内容を構築し
| て保存する為の物だったり、後で再解釈する為の物だったりする可能性もあり、
| 一律に出力して良い内容7日どうかも分からない。という事を考えると put-il,
| put-dl の中で現在位置を検出して出力するという対策は全然駄目である。
|
| | if ((_ble_bash>=40000)) && [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $TERM == xterm-256color ]]; then
| | # Cygwin console (pcon) では最終行で IL/DL すると画面全体がクリアされる。
| | function ble/canvas/.put-il.workaround {
| | local count=$1
| | ((count==1)) || return 1
| |
| | # Cygwin console 以外なら対策不要
| | [[ ! $_ble_term_DA2R ]] || return 1
| |
| | # 現在のカーソル位置の取得
| | local reply=
| | printf '\e[6n' >/dev/tty
| | IFS= read -r -d R -t 0.1 reply </dev/tty
| | local rex='([0-9]*);([0-9]*)'
| | [[ $reply =~ $rex ]] || return 1
| | local l=$((10#${BASH_REMATCH[1]}))
| | local c=$((10#${BASH_REMATCH[2]}))
| |
| | ((l==LINES)) || return 1
| |
| | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2
| | return 0
| | }
| | function ble/canvas/put-il.draw {
| | local value=${1-1}
| | ((value>0)) || return 0
| | ble/canvas/.put-il.workaround "$value" && return 0
| | DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_il//'%d'/$value}
| | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux
| | }
| | function ble/canvas/put-dl.draw {
| | local value=${1-1}
| | ((value>0)) || return 0
| | ble/canvas/.put-il.workaround "$value" && return 0
| | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux
| | DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_dl//'%d'/$value}
| | }
| | fi
|
| b 別の手段を考える。一番上の行を犠牲にする事になるが SU/SD を組み合わせる。
|
| DRAW_BUFF[${#DRAW_BUFF[*]}]=$'\e[S\e[A\e[M\e[B\e[T'
|
| うーん。一応動いている様な気がするが、この対策法の問題点は DA2 を返さない
| 端末で SU/SD に対応してない物があると描画がずれてしまうという事である。
|
| あとちらつきが激しく出ているという事。やはり対策を実施するのは最
| 低限にしたい。
|
| c また別の手法。一番下の行は諦めて DL/IL をする前に必ず IND/CUU を実行して
| 一番下の行は使わない様にするという作戦。これは実際に試してみた所レイアウ
| ト崩れるので使えない。

改めてそれぞれの方法の問題点について整理する

a DSR(6) で問い合わせて判定する方法。

o この方法は出力をキャッシュしていなければ確実に最終行を判定できる。

x 然し実際にはカーソル移動なども含めて出力内容を複雑にキャッシュしている
ので、その場で現在位置を取得したとしても全く意味がない。キャッシュを
flush するにしても、それぞれのキャッシュがその場で画面に出力する事を想
定した物でない場合もあり困難。

b SU/SD の組み合わせを用いる。

x 一番上の行の内容が犠牲になる。
x 画面がちらつく。

o これについては panel 内部で動作している限りは panel の最終行にいる時
にだけ対策をする。これでちらつきはある程度抑える事ができる。それでも、
panel の最終行にいる時にはちらつきが出るが、そもそも本当に最終行にい
る時のちらつきは抑える事ができないので、我慢する。

x Cygwin console であると誤判定した時に、その端末が SD/SU に対応していな
いと悲惨な事になる。

c 一番下の行は常に空になる様にしておく。

x 使える領域が一行減ってしまう。
x 今までの座標計算が狂ってしまうので注意深く全体を書き直す必要がある。

d panel で一番下の行にいると分かっている時は単に EL(2) で良い。

panel で一番下の行にいるという事が分かっている場合には、IL を一番下の行
で実行する代わりに単に端末の最上部で DL をすれば良いのではないだろうか。
と思ったが全然違う結果になるので駄目だ。

或いは panel で一番下の行にいるという事が分かっているのであれば何処か別
の行で IL/DL すれば良いのではないか。と思ったが、それだと端末最終行にい
なかった時にずれるべき内容がずれずに残るのではないか。と思ったが、そも
そも panel 外の内容に関しては関知しなくて良い。

整理すると panel で一番下の行にいる時、panel の最上部で IL/DL を実行す
る。その上で panel の最下部で EL(2) を実行すれば良い。うーん。実は最下
部で EL(2) を実行するだけで良い気がしてきた。

結局 b に d を組み合わせて実装した。どうも既存の IL/DL は全て panel 管理下
にある様だ。という事なので実は実質的に d だけでうまく行くという事。

x fixed: と思ったがどうも SU/SD の対策がコマンドを実行する度に発動している
様子だ。と思ったがこれは単純ミスだった。opts=$2 を忘れて opts を使ってい
た。

? IND を \n にして見たが微妙かもしれない。端末によっては現在の x の位置をずらしてしまうから。
然し、現在の設計では ind によって位置がずれてしまう事も想定しているのではなかったか。

と思ったが IND に対応していない物も沢山ある様だ。なのでやはり \n に頼るべきなのだろう。

IND を使っている箇所について改めて確認する必要がある。ちゃんと x=0 にしているか?

→どうも _ble_term_ind の使用は canvas.sh の中で閉じている様子である。
put-ind.draw も内部でしか使われていない。殆どの箇所で既に対策済みか或いは
元から column 0 にいる状態で使っている。

問題に成るのは ble/canvas/put-move-y.draw の内部での使用で、mc の中で動作
している時には CUU の代わりに IND を使っている。put-move.draw が何処で使
われているか確認すると相対移動・noscrc で使っている。_ble_term_{sc,rc} も
使えないし、相対移動なので後で絶対位置を指定して補正というのも使えない。
ここは IND/LF で col が移動しない状況で使われていると期待するしかない。

→うーん。現在の init-term だと LF が優先されてしまう。IND に端末が対応し
ている事を期待して $'\eD' を使った方が安全に思われる。

* term: sum (Solaris console) IND/RI が使えない。他色々動いていない [#D1481]

* RI が使えない時にどの様にすれば良いか。
Expand Down

0 comments on commit 5dce0b8

Please sign in to comment.