From a8fbc3f557483978bbce0a42a8e2146270510813 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 20 Sep 2026 18:38:54 +0200 Subject: [PATCH] NCURSES_NO_UTF8_ACS: ncurses zu Unicode-Rahmen zwingen Die Diagnose auf dem betroffenen Terminal war eindeutig: Zeile A (echte UTF-8-Rahmenzeichen) zeichnete Linien, Zeile B (VT100-Umschaltung ESC(0) nicht. Locale war bereits C.UTF-8, dialog war installiert - und die Oberflaeche sah trotzdem falsch aus. Grund: ncurses benutzt die VT100-Umschaltung AUCH mit UTF-8-Locale, solange das terminfo sie anbietet - bei TERM=xterm der Fall. Die Locale-Korrektur allein reichte deshalb nicht, und der Wechsel von whiptail zu dialog machte es sogar schlechter, weil whiptail (slang) bei UTF-8-Locale von sich aus Unicode zeichnet, ncurses aber nicht. Abhilfe ist NCURSES_NO_UTF8_ACS=1. Mit dialog unter LANG=C.UTF-8 und TERM=xterm gemessen: ohne Schalter : 38 ESC(0, 0 Rahmenbytes, 182 rohe q mit Schalter : 0 ESC(0, 220 Rahmenbytes, 0 rohe q ui_init setzt den Schalter jetzt, sobald eine UTF-8-Locale gilt. CMK_TUI_ACS=1 stellt das alte Verhalten wieder her - fuer Terminals, die ESC(0 beherrschen, aber kein UTF-8. tui-check zeigt den Stand des Schalters an und erklaert bei "A Linien, B Buchstaben" jetzt, dass genau dieser Fall abgefangen wird und die Oberflaeche trotzdem sauber aussehen muss. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 21 +++++++++++++++++++-- README_en.md | 21 +++++++++++++++++++-- scripts/cmk-manage.sh | 11 +++++++++-- scripts/lib/common.sh | 24 +++++++++++++++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 417689d..2974672 100644 --- a/README.md +++ b/README.md @@ -1798,11 +1798,28 @@ und zeigen stattdessen die rohen Buchstaben. Nachgemessen: bei `LC_ALL=C` schickt `whiptail` eine `ESC(0`-Umschaltung und **91 rohe `q`**; mit UTF-8-Locale keine einzige. -**Das Skript behebt das selbst.** Beim Start der Oberfläche setzt es +**Das Skript behebt das auf zwei Wegen selbst.** + +**1. UTF-8-Locale.** Beim Start der Oberfläche setzt es `LC_CTYPE` auf die erste verfügbare UTF-8-Locale (`C.UTF-8`, `en_US.UTF-8`, …). Nur `LC_CTYPE`, damit Sortierung und Zahlenformat unberührt bleiben. Ist `LC_ALL` auf einen Nicht-UTF-8-Wert gesetzt, wird es dabei entfernt – sonst -würde es `LC_CTYPE` aushebeln. Prüfen lässt sich das mit: +würde es `LC_CTYPE` aushebeln. **2. Unicode statt VT100.** Das allein genügt nicht: **ncurses benutzt die +VT100-Umschaltung auch mit UTF-8-Locale**, solange das terminfo sie anbietet – +bei `TERM=xterm` der Fall. Deshalb wird zusätzlich `NCURSES_NO_UTF8_ACS=1` +gesetzt, womit ncurses echte Unicode-Rahmenzeichen zeichnet. Mit `dialog` unter +`LANG=C.UTF-8` und `TERM=xterm` gemessen: + +| | `ESC(0` | UTF-8-Rahmenbytes | rohe `q` | +|---|---|---|---| +| ohne Schalter | 38 | 0 | **182** | +| **mit Schalter** | **0** | **220** | **0** | + +`whiptail` braucht das nicht – es zeichnet bei UTF-8-Locale von sich aus +Unicode. Wer den umgekehrten Fall hat – ein Terminal, das `ESC(0` beherrscht, +aber kein UTF-8 – stellt mit `CMK_TUI_ACS=1` das alte Verhalten wieder her. + +Prüfen lässt sich das mit: ```bash ./scripts/cmk-manage.sh selftest # Abschnitt "Zeichensatz fuer die Oberflaeche" diff --git a/README_en.md b/README_en.md index 767ea48..d417d6d 100644 --- a/README_en.md +++ b/README_en.md @@ -1799,11 +1799,28 @@ instead. Measured: with `LC_ALL=C`, `whiptail` emits one `ESC(0` switch and **91 raw `q`** characters; with a UTF-8 locale, none at all. -**The script fixes this itself.** When starting the interface it sets +**The script fixes this in two ways.** + +**1. UTF-8 locale.** When starting the interface it sets `LC_CTYPE` to the first available UTF-8 locale (`C.UTF-8`, `en_US.UTF-8`, …) – only `LC_CTYPE`, so sorting and number formats stay untouched. If `LC_ALL` is set to a non-UTF-8 value it is removed, since it would otherwise override -`LC_CTYPE`. Verify with: +`LC_CTYPE`. **2. Unicode instead of VT100.** That alone is not enough: **ncurses uses the +VT100 switch even with a UTF-8 locale** as long as the terminfo offers it – +which it does for `TERM=xterm`. So `NCURSES_NO_UTF8_ACS=1` is set as well, +making ncurses draw real Unicode box-drawing characters. Measured with +`dialog` under `LANG=C.UTF-8` and `TERM=xterm`: + +| | `ESC(0` | UTF-8 box bytes | raw `q` | +|---|---|---|---| +| without the switch | 38 | 0 | **182** | +| **with the switch** | **0** | **220** | **0** | + +`whiptail` does not need this – with a UTF-8 locale it draws Unicode by itself. +For the opposite case – a terminal that handles `ESC(0` but not UTF-8 – +`CMK_TUI_ACS=1` restores the old behaviour. + +Verify with: ```bash ./scripts/cmk-manage.sh selftest # section "Zeichensatz fuer die Oberflaeche" diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 2434dff..c0feccb 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -4692,6 +4692,8 @@ cmd_tui_check() { printf ' LC_CTYPE : %s\n' "${LC_CTYPE:-}" printf ' Zeichensatz : %s\n' "$(locale charmap 2>/dev/null || echo unbekannt)" printf ' Programm : %s\n' "${UI_BIN:-keines (dialog/whiptail fehlt)}" + printf ' Unicode-ACS : %s\n' \ + "$([ -n "${NCURSES_NO_UTF8_ACS:-}" ] && echo 'ein (ncurses zeichnet Unicode)' || echo 'aus (ncurses nutzt ESC(0)')" [ -n "${UI_LOCALE_NOTE:-}" ] && printf ' Angepasst : %s\n' "$UI_LOCALE_NOTE" printf '\n%sZeile A - echte UTF-8-Rahmenzeichen%s\n' "$C_BLD" "$C_RST" @@ -4711,8 +4713,13 @@ ${C_BLD}Auswertung${C_RST} Alles in Ordnung - die Oberflaeche muss sauber aussehen. A zeigt Linien, B zeigt lqqqk / x / mqqj - Das Terminal macht die VT100-Umschaltung nicht mit. - Genau das ist der PuTTY-Fall. Abhilfe in PuTTY: + Das Terminal macht die VT100-Umschaltung nicht mit - der + PuTTY-Fall. Das Skript faengt das ab: es setzt + NCURSES_NO_UTF8_ACS=1, womit ncurses (und damit dialog) + dieselben Zeichen wie in Zeile A verwendet. Die Oberflaeche + muss dadurch sauber aussehen, obwohl Zeile B es nicht tut. + + Sieht sie trotzdem falsch aus, hilft in PuTTY: Window -> Translation -> Remote character set: UTF-8 Window -> Translation -> Handling of line drawing characters: "Use Unicode line drawing code points" diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh index 54b6ea2..c709848 100644 --- a/scripts/lib/common.sh +++ b/scripts/lib/common.sh @@ -308,12 +308,33 @@ ui_calc_text() { # text zusatzzeilen # Nachgemessen: bei LC_ALL=C schickt whiptail eine ESC(0-Umschaltung und # 91 rohe "q"; mit UTF-8-Locale keine einzige. Es genuegt, LC_CTYPE zu # setzen - Sortierung und Zahlenformat bleiben damit unberuehrt. +# Zwingt ncurses zu echten Unicode-Rahmenzeichen. +# +# Auch mit UTF-8-Locale benutzt ncurses die VT100-Umschaltung ESC(0, +# solange das terminfo sie anbietet (bei TERM=xterm der Fall). Terminals +# im UTF-8-Modus - PuTTY - machen die nicht mit und zeigen q, x, l, m. +# Gemessen mit dialog unter LANG=C.UTF-8, TERM=xterm: +# ohne Schalter : 38 ESC(0, 0 Rahmenbytes, 182 rohe q +# mit Schalter : 0 ESC(0, 220 Rahmenbytes, 0 rohe q +# whiptail (slang) braucht ihn nicht, es zeichnet bei UTF-8-Locale schon +# von sich aus Unicode. +ui_use_unicode_acs() { + # CMK_TUI_ACS=1 erzwingt umgekehrt das alte Verhalten - fuer + # Terminals, die ESC(0 koennen, aber kein UTF-8. + if [ -n "${CMK_TUI_ACS:-}" ]; then + unset NCURSES_NO_UTF8_ACS 2>/dev/null || true + return 0 + fi + export NCURSES_NO_UTF8_ACS=1 + return 0 +} + ui_fix_locale() { [ -n "${UI_LOCALE_DONE:-}" ] && return 0 UI_LOCALE_DONE=1 UI_LOCALE_NOTE="" case "${LC_ALL:-${LC_CTYPE:-${LANG:-}}}" in - *UTF-8*|*utf-8*|*UTF8*|*utf8*) return 0 ;; + *UTF-8*|*utf-8*|*UTF8*|*utf8*) ui_use_unicode_acs; return 0 ;; esac local l for l in C.UTF-8 C.utf8 en_US.UTF-8 en_US.utf8 de_DE.UTF-8 de_DE.utf8; do @@ -323,6 +344,7 @@ ui_fix_locale() { if [ -n "${LC_ALL:-}" ]; then unset LC_ALL; fi export LC_CTYPE="$l" UI_LOCALE_NOTE="LC_CTYPE auf $l gesetzt (war nicht UTF-8)" + ui_use_unicode_acs return 0 fi done