Terminál FAQ programozók számára

K: Mi a smacs és a rmacs?
V: Terminvezérlő szekvenciák, 'start alternate character set' és 'end alternate character set'. Ezeket lehet használni a 'grafikus' karakterek előcsalogatására, amilyeneket a Midnight Commander használ. Például 'linux' terminálon: smacs=ESC[11m, rmacs=ESC[10m; 'rxvt' terminálon: smacs=^N, rmacs=^O.

K: Honnan is lehet ezeket tudni?
V: Az infocmp <termináltípus> válaszából.

K: És ez mindig működik?
V: Hát, például az rxvt esetében az enacs szekvenciát is használni kell előtte.
Vagy megerőszakolni az rxvt forrásprogramját (screen.c):
volt: MEMSET(charsets, 'B', sizeof(charsets));
lett: MEMSET(charsets, 'B', sizeof(charsets)); charsets[1]= '0';
Vagy megerőszakolni az rxvt termináltípus definícióját:
# infocmp rxvt >rxvt.ti
volt: smacs=^N
lett: smacs=\E)0^N
# tic rxvt.ti
K: És ha mindent jól beállítottam, működni fog a karaktergrafika az emulátoromban?
V: Ez nincsen kizárva, de lehetnek buktatók, például PuTTY-ban UTF8 esetén kell egy külön beállítás, hogy működjön:
Window / Translation / Enable VT100 line drawing even in UTF-8

K: Kezdem úgy érezni, hogy az egész nem is annyira egzakt tudomány, mint amilyennek látni szeretnénk... Van erre egy kipróbálóprogram?
V: Itt van: shchars.c

K: És a tput-tal hogy van ez?
V: A smacs és rmacs paraméterekkel dolgozhatsz:
$ tput smacs
<olvasható vagy olvashatatlan szöveg>
$ tput rmacs
<normál állapot>
K: És még milyen paramétereket használhatok a tput-tal, amik a manuáljában nincsenek?
V: A terminfo(5) manualban lévőket, itt van néhány lehetőség az ESC-szekvenciával együtt:
hatás       bekapcs   kódnév kikapcs kódnév  megjegyzés
alternatív  ?         smacs  ?       rmacs   emulátorfüggő, esetleg enacs is kell hozzá
betűkészlet
előtérszín  ESC[30+nm -	     -	     -	     n=szín sorszáma (0..7;9=alapértelmezés)
háttérszín  ESC[40+nm -	     -	     -	     n=szín sorszáma (0..7;9=alapértelmezés)
aláhúzás    ESC[4m    smul   ESC[24m rmul
inverz      ESC[7m    smso   ESC[27m rmso
vastag betű ESC[1m    bold   ESC[21m -       hatása emulátorfüggő
villogás    ESC[5m    blink  ESC[25m -       hatása emulátorfüggő
alaphelyzet ESC[0m    sgr0   -       -       színek alaphelyzetbe, spec. hatások kikapcsolása
K: Ha egy ilyen szekvenciában egy %p1%d-szerű részt látok, annak van valamilyen speciális jelentése?
V: Igen, oda változó paramétert kell beilleszteni (esetünkben az első változó paramétert, decimális számként). Programban erre használható a tparm vagy a tiparm függvény.
K: Ha esetleg egy $<100/> szerű szekvencia jelenik meg a képernyőmön, akkor annak is lehet köze a terminfóhoz?
V: Ez előfordulhat, ugyanis terminfo-nyelven ezek a szekcenciák várakozást jelentenek (a szám ezredmásodpercben értendő). Ha történetesen egy program erről nem tud, és a szekvenciát egyben kiküldi a terminálnak, akkor persze joggal csodálkozol, hogy mit is látsz.
K: Mikor lenne szükség ilyen várakozásra?
V: Itt van például a flash művelet: ez először inverzre állítja a képet, aztán vár, aztán visszaállítja a normál képet:
$ infocmp xterm | grep flash
  flash=\E[?5h$<100/>\E[?5l
$ tput flash | od -tx1
  1b  5b 3f 35 68 1b  5b 3f 35 6c  # a várakozás itt nem látszik!
  ESC [  ?  5  h  ESC [  ?  5  l
K: Ha én programban a tigetstr-vel kiolvasok egy ilyen szekvenciát, és azt ki akarom iratni, akkor az abban esetleg benne lévő várakozásokat nekem kell kezelnem?
V: Megteheted, de van rá kész függvény is, putp illetve tputs néven.
K: Még valami hasznos funkció a tput-tal?
V: Például a LINES és a COLUMNS változók beállítása, ha valamiért nem történt meg automatikusan:
$ export COLUMNS=$(tput cols); export LINES=$(tput lines)
K: Ezt vajon hogy csinálja a tput?
V: A kerneltől kérdezi meg, a TIOCGWINSZ nevű ioctl-vel. Ugyanezt teszi a stty size parancs is. Ennek párja a TIOCSWINSZ, amivel átállítod a kernel által ismert méretet.
K: Milyen paranccsal használhatom ezt a TIOCSWINSZ ioctl-t?
V: A stty(1) való erre: stty rows <sorok> columns <oszlopok>
Ne felejtsd el, ennek semmi hatása nincs a terminál(emulátor)ra, csak a kernel által tárolt méretekre. Továbbá nem állítja a COLUMNS/LINES változókat sem.
K: Ez azt jelenti, hogy a kernel számon tartja az emulált terminálokat?
V: Igen, minden (valós vagy emulált) terminálnak nyilvántartja a beállításait, hogy a tiéd melyik, azt a tty(1) vagy a ttyname(3) adja meg. Próbáld ki:
$ tty
/dev/pts/9
$ ls -l $(tty)
crw--w---- 1 user tty 136, 9 Aug 30 15:59 /dev/pts/9
K: Hogyan 'születik' egy ilyen virtuális terminál?
V: Programból lehet létrehozni (a részletekért lásd a pty(7) manualt), példa ezt használó programokra: xterm, telnetd, sshd, script, expect, ttyrec.
K: Hogyan lehet azt megoldani, hogy a kernel értesítsen, ha átméretezték az ablakomat?
V: A kernel SIGWINCH signalt küld azoknak a folyamatoknak, akiknek a terminál a 'controlling terminal'-ja, és van signal-handlerük erre a signal-ra (az alapértelmezés az ignore).
K: És még mire jó ez a stty?
V: Minden helyi beállítást ezzel szabályozhatsz, számtalan opciója van, például:
$ savestty=$(stty -g) # minden beállítás elmentése
$ stty $savestty # elmentett beállítások visszaállítása
$ stty -a # minden beállítás kiírása (human-readable formátumban)
K: Közvetlenül a terminál(emulátor)tól is meg lehet kérdezni az ablakméretet?
V: Lehet, a következő ESC-szekvenciákkal:
kérdés: ESC[18t
válasz: ESC[8;<sorok>;<oszlopok>;t
kérdés: ESC[14t
válasz: ESC[4;<pixelsorok>;<pixeloszlopok>;t
K: Átméretezni is lehet így?
V: Terminálfüggő, ha lehet, akkor ezek valamelyikével:
ESC[8;<sorok>;<oszlopok>;t
ESC[4;<pixelsorok>;<pixeloszlopok>;t
K: Van erre a célra program is?
V: A neve resize a neve, használata:
# lekérdezés:
$ resize -s
# beállítás; egyszerű meghívás, univerzális:
$ resize -s <oszlopok> <sorok>
# "trükkös" meghívás, egyes shell-ek esetén COLUMNS+LINES is állítódik
$ eval $(resize -s <oszlopok> <sorok>)
K: Mindezekből a részletekből hogy lehetne valami komplett funkciót kihozni?
V: Például egy ilyen shell-függvényt lehetne írni:
termsize () {
    if [ $# -eq 2 ]; then
        eval $(resize -s "$1" "$2")
    else
        eval $(resize -s)
    fi;
    stty rows "$LINES" columns "$COLUMNS"
}
— Karaktergrafika —
K: Fentebb volt szó smacs / rmacs szekvenciákról. Kicsit pontosabban mit is csinálnak ezek?
V: Átváltják a terminált pszeudografikus karakterkészletre és vissza. Ez kétféleképpen történhet: vagy a G0 és G1 között kapcsolnak oda-vissza, vagy a G0-t állítják át a normál és a grafikus karkaterkészlet között.
K: Mi lenne a G0 és G1?
V: Először is a terminál/emulátor több karakterkészletet ismer(het):
kód jelentés
 0  pszeudografikus karakterkészlet
 A  ASCII/UK (módosított ASCII)
 B  ASCII
stb Különféle módosított ASCII változatok
A gyakorlatban elég a 'B'-t és a '0'-t megjegyezni (a többinek akkor volt jelentősége, amikor csak a 7-bites ASCII kód egyéni módosításaival lehetett a nemzeti karaktereket előállítani). Ezeknek a kódoknak az alábbi ESC-szekvenciákban van jelentősége:
ESC ( C  G0 beállítása, pl. ESC(B -> G0=ASCII (ez a szokásos beállítás G0-ra)
ESC ) C  G1 beállítása, pl. ESC)0 -> G1=grafikus (ez meg G1-re a szokásos beállítás)
A teljesség kedvéért említsük meg, hogy egyes terminálok ismernek G2 és G3 készleteket is.
K: Tehát akkor mi is lenne a G0 és G1?
V: Tekintsük őket egy indirekciós szintnek: a fenti szekvenciákkal beállítjuk, hogy mit jelentsen a G0 és G1, utána beállítjuk a terminált, hogy G0-t vagy G1-et használja:
SO (0x0e)	Váltás G1-re (DEC)
SI (0x0f)	Váltás G0-ra (DEC)
ESC[10m		Váltás G0-ra (csak 'linux' terminál)
ESC[11m		Váltás G1-ra (csak 'linux' terminál)
K: És akkor mik is ezek a grafikus karakterek?
V: Például olyasféle grafikus karakterek, amiket a Midnight Commander használ a keretek kirajzolásához.
Ilyesmi lenne a listájuk:
kód  graf.char  hely.   név
2b +	→	>	ACS_RARROW
2c ,	←	<	ACS_LARROW
2d -	↑	^	ACS_UARROW
2e .	↓	v	ACS_DARROW
30 0	█	#	ACS_BLOCK
60 `	♦	+	ACS_DIAMOND
61 a	░	:	ACS_CKBOARD
66 f	°	'	ACS_DEGREE
67 g	±	#	ACS_PLMINUS
68 h	▒	#	ACS_BOARD
69 i	¤ v §	#	ACS_LANTERN
6a j	┘	+	ACS_LRCORNER
6b k	┐	+	ACS_URCORNER
6c l	┌	+	ACS_ULCORNER
6d m	└	+	ACS_LLCORNER
6e n	┼	+	ACS_PLUS
6f o	⎺	~	ACS_S1
70 p	⎻	-	ACS_S3
71 q	─	-	ACS_HLINE
72 r	⎼	-	ACS_S7
73 s	⎽	-	ACS_S9
74 t	├	+	ACS_LTEE
75 u	┤	+	ACS_RTEE
76 v	┴	+	ACS_BTEE
77 w	┬	+	ACS_TTEE
78 x	│	|	ACS_VLINE
79 y	≤	<	ACS_LEQUAL
7a z	≥	>	ACS_GEQUAL
7b {	π	*	ACS_PI
7c |	≠	!	ACS_NEQUAL
7d }	£	f	ACS_STERLING
7e ~	∙	o	ACS_BULLET
A lista tartalmaz egy úgynevezett helyettesítő karaktert is, ezt akkor látjuk, ha a terminál nem tudja a grafikus karaktert megjeleníteni.
Megj: Természetesen az is lehet, hogy a böngésződ sem tudja ezek egyikét-másikát megjeleníteni, például a ACS_S1, ACS_S3, ACS_S7, ACS_S9 nem szokott megjelenni (bár az Unicode-ban benne vannak: U+23BA..U+23BD).
Megj: Az ACS_LANTERN jelentése nem egészen tiszta, maga a szó lámpást jelent, szerintem a '¤' (U+A4) vagy a '§' (U+A7) jelre utalhat, a ncurses szerint viszont az U+2603 kódú ☃ karaktert (hóember).
K: Ezek a karakterek fixen ezeken a kódokon vannak?
V: Természetesen nem, linux termináltípus esetén más pozíciókon vannak (az IBM CP437 kódkészletéhez igazodva).
K: És ezt hogyan kezeljem a programomból?!
V: Lekérdezheted a terminfo-ból acsc, illetve termcap-ból ac néven. Ekkor egy karakterpárokból álló listát kapsz, amivel szabványos kódról terminál-specifikusra fordíthatsz.
K: Ez most komoly, vagy itt van valahol egy kandi kamera?
V: Általában nem neked kell ezt csinálnod, hanem rábízhatod a ncurses nevű komponensre, pl:
addch (ACS_ULCORNER);
— Egérkezelés —
K: A terminál(emulátor) az egérkattintást is elküldi a szervernek?
V: Igen, ha a szerver ezt kéri tőle:
ESC[?9h    -- X10 protokoll szerinti jelentés
	      (csak az 1-3 gombok lenyomása küld szekvenciát)
ESC[?1000h -- X11 protokoll szerinti jelentés
ESC[?1002h -- mint az előbbi,
	      de a 'vonszolás' (gombnyomás+mozgás) is küld szekvenciát
ESC[?1003h -- mint az előbbiek,
	      de a 'síma' mozgás is küld szekvenciát
ESC[?<n>l -- kikapcsolás (az előbb számok bármelyike használható)
Ennek hatására a terminál a következő szekvenciát küldi gombnyomás/felengedéskor:
ESC[M<kód><xpos><ypos>
<kód>: <valami> + 0x20 + <módosítók> + <gombsorszám>

módosítók (csak X11 protokoll esetén, emulátorfüggő):
    0x04: Shift
    0x08: Alt (vagy Meta)
    0x10: Control

gombsorszám (a <valami> értékétől is függően):
       0: bal
       1: középső
       2: jobb
       3: felengedés
    0x40: 4. gomb / görgő fel
    0x41: 5. gomb / görgő le
    0x42: 6. gomb / görgő-2 balra
    0x43: 7. gomb / görgő-2 jobbra

valami:
    0x00: (alapeset) 1-3 gomb lenyomás/felengedés
    0x20: vonszolás (mozgás gomblenyomással) / mozgás

xpos,ypos:
    0x20 + koordináta (1..223)
Persze ez csak egy kivonatos részlet, ennél sokkal több és bonyolultabb lehetőség is van (ez persze az emulátorunktól is függ).
Arra is jó esély van, hogy pl a Shift-et az emulátor arra használja, hogy mégse küldje a szervernek az egérszekvenciákat, hanem kijelölésre szolgáljon az egér.
Megj: Látható, hogy a gombok felengedéséről csak korlátozottan értesülünk: csak X11 protokoll esetén, csak az első három gomb esetén, és még akkor sem jön az az információ, hogy melyik gombot engedték fel.
K: Az rxvt-2.6.4 nem jól kezeli az egérgörgőt!
V: Frissíts rxvt-2.7.10-re, vagy urxvt-re.
K: Nincs olyan továbbfejlesztett üzemmód, ami nem korlátozza a képméretet 226x226-ra?
V: Hogyne lenne?! Három lehetőség is van, ezek közül az emulátorod nullát vagy többet ismer.
kódnév bekapcsolás korlát
EXT    ESC[?1005h  2015
SGR    ESC[?1006h  nincs
URXVT  ESC[?1015h  nincs
— Scrolling region —
K: Mi az a scrolling region?
V: Egy sortartomány a terminálon, amely legalább két sorból áll, de lehet a terminál egésze is, amelyen kívül semmilyen scrollozás nem történik.
K: Miféle scrollozás?
V: Például ha a line-wrap funkció a scrolling region utolsó sorában történik, akkor az egész scrolling régió felfelé léptet, a legfelső sora elvész, legalul pedig új (üres) sor keletkezik. Azután van néhány ESC-szekvencia, pl:
Insert Line (IL)   ESC [ n L    Sor(ok) beszúrása
Delete Line (DL)   ESC [ n M    Sor(ok) törlése
Index (IND)        ESC D	Kurzor le / scroll fel
Reverse Index (RI) ESC M	Kurzor fel / scroll le
Next Line (NEL)    ESC E        Kurzor a következő sor elejére / scroll fel
Linefeed (LF)      LF		Soremelés / scroll fel
Reverse Linefeed   ESC I        Kurzor fel / scroll le     
Megj: A 'reverse linefeed' meg a 'reverse index' nagyon egyformának tűnik; a 'linefeed' működése egyes beállítások esetén megegyezik a 'next line'-éval.
K: Egyéb érdekesség a scrolling regionról?
V: Például, hogy relatív kurzorpozícionálással (pl. ESC[A, ESC[B, ESC[C, ESC[D) csak belemenni lehet, kilépni belőle nem; sőt van olyan üzemmód, amelyben abszolút pozícionálással (ESC[r;cH) sem, (ebben a módban az első sor scrolling region első sorát jelenti).
K: Hogyan kell kijelölni a scrolling regiont?
V: Ezek a szekvenciák a barátaid:
ESC [ firstrow;lastrow r  s.r. kijelölése
ESC [ r 		  s.r. a teljes képernyő
ESC c			  terminál alapállapotba (s.r. a teljes képernyő) 
ESC [ ? 6 h               kurzor bezárása a s.r.-be
ESC [ ? 6 l               az előbbi ellenkezője
K: És mire is jó ez a scrolling region?
V: Képzeljünk el egy olyan alkalmazást (mondjuk egy szövegszerkesztőt vagy kalandjátékot), ahol a kép tetején és/vagy alján fix információs sorok vannak, középen pedig egy scrollozódó adatrész.
— Távoli elérés (telnet) —
K: Mi a különbség a unixos és Windows-os telnet-kliens között?
V: Számos különbség lehet, de a legnyilvánvalóbb az, hogy a unixos kliens egy terminál(emulátor)on belül fut, a Windows-os pedig egybe van építve a terminálemulátorral. Rendszerint több különböző termináltípust képes emulálni (részben vagy egészben), de az is lehetséges, hogy több különböző terminál ESC-szekvenciáinak az unióját kezeli (már ahol ezek nem mondanak ellent egymásnak).
K: Igaz, hogy a telnet kliens és szerver metainformációkat is küldözgetnek egymásnak, amit a felhasználó nem lát?
V: Hogyne, vegyük például ismét az átméretezést: amikor átméretezed a kliens ablakát, az egy ilyen üzenetet küld a szervernek:
byte kódnév
---- ------
 FF  IAC  (interpret as command)
 FA  SB   (subnegotiation)
 1F  NAWS (window size)
 xh	  width (msb)
 xl	  width (lsb)
 yh	  height (msb)
 yl	  height (lsb)
 FF  IAC  (interpret as command)
 F0  SE   (subnegotiation end)
— Színek —
K: Honnan tudom meg, hogy hány színt lehet használni az emulált terminálon?
K: A tput colors paranccsal.
K: Ami megkérdezi a termináltól...
K: Nem, a TERM változóból és terminfo adatbázisból dolgozik, pl:
$ TERM=rxvt tput colors
8
$ TERM=rxvt-256color tput colors
256
$ TERM=vt102 tput colors
-1
Megjegyzés: az a nyolc szín lehet éppen 16 is, mivel egyes emulátorok a 'bold' (vastag betűs) módot fényes tintaszínnel helyettesítik, és/vagy a 'blink' (villogó) módot fényes papírszínnel.
— Programok és terminálok —
K: A programok ugyebár a TERM változó és a terminfo adatbázis alapján működnek, így nagyon flexibilisen alkalmazkodnak az aktuális helyzethez.
V: Abszolúte. De hogy egy kicsit árnyaljam a dolgot, bizony néha behardkódolt szekvenciák és saját konfigfájlok is szerepelnek a történetben.
K: Például a Midnight Commander esetében?
V: Igen, a Midnight Commander a 'Learn Keys' funkcióval megtanított szekvenciákat egy konfigfájlban tárolja (pl. ~/.config/mc/ini), ezeknek prioritása van a terminfóból származó értékek felett.
K: Vagy a bash.
V: Igen, a bash, és általában a readline-t használó programok a ~/.inputrc és /etc/inputrc fájlokból tájékozódnak, ezek kibővíthetik/felülbírálhatják a terminfo adatait.
Bash-ban próbáljuk ki a bind -P parancsot az aktuális állapot lekérdezésére.
Megj: Egy kis inputrc-részlet, csak kedvcsinálónak:
# allow the use of the Home/End keys -- linux/vt100/xterm/rxvt

"\e[1~": beginning-of-line
"\e[7~": beginning-of-line
"\e[H":  beginning-of-line
"\eOH":  beginning-of-line

"\e[4~": end-of-line
"\e[8~": end-of-line
"\e[F":  end-of-line
"\eOF":  end-of-line
K: Mi szükség lehet ilyen trükkökre?
V: Például: a TERM rosszul van beállítva; a terminfo adatbázis hibás; az emulátor rosszul emulál; esetleg a terminál(emuláció) működése a történelem folyán inkompatibilisen változott, és nem világos, hogy melyik fél melyiket használja. Ha például kiváncsi vagy, hogy hány xterm-szerű/xterm-alapú termináldefiníció van a rendszerben, akkor próbáld ki ezt:
find /usr/share/terminfo/x/ -name 'xterm*'
(És az még a jobbik eset, amikor az új működés új nevet kap, a rosszabb az, amikor ez névváltozás nélkül történik.)
K: Ha már a bash-ról és a terminfo-ról esik szó: ha a bash-ban nem működik a Ctrl+L és/vagy a hosszú parancsosorok nem több képernyősorban, hanem egy sorban, vízszintesen scrollozva jelennek meg, az is terminfo-probléma lehet?
V: Igen: lehet, hogy a terminfo adatbázisod nem tartalmazza a terminálod (helyes) leírását, esetleg a rendszeredben egynél több terminfo van, és azok nem binárisan kompatibilisek egymással (ilyet csak AIX-on tapasztaltam).
K: Igaz, hogy a terminfo meg a termcap ugyanaz?
V: Majdnem: a termcap elavult (kezdve azzal a koncepcióval, hogy az összes ismert termináltípus leírása egy szöveges fájlban (/etc/termcap) legyen benne), de a kompatibilitás megtartására a terminfo biztosít termcap-kompatibilis függvényeket. Programozói szempontból a két rendszer hasonló, pl:
Függvények

terminfo  termcap jelentés
setupterm tgetent Inicializálás 
tigetstr  tgetstr string-típusú terminál-adat lekérdezése
tigetnum  tgetnum numerikus terminál-adat lekérdezése

Funkcióazonosító stringek

terminfo  termcap jelentés
clear     cl      képernyőtörlés
kmous     Km      egérjelentés engedélyezése
kbs	  kb	  backspace billentyű (terminál küldi)
kcuf1     kr	  kurzor jobbra billentyű (terminál küldi)
K: És ha nem használ terminfo-t, nem hívja a libreadline-t, hanem csak síma gets/fgets van benne, akkor azzal azért van valamilyen szerkesztési lehetősége a felhasználónak?
V: Használható pl. a BackSpace (visszatörlés) gomb.
K: Láttam már olyat, hogy mégsem volt használható, csak egy ^? vagy ^H jelent meg...
V: Ilyenkor a kernel említett adattartalma nincs szikronban a terminállal. Egészen pontosan a stty erase (avagy termios.c_cc[V_ERASE]) beállítás hibás.
Például ilyesmivel lehetne probálkozni (valamilyen profile scriptben):
case $TERM in
linux|putty*)
    stty erase ^?
    ;;
xterm*|rxvt*)
    stty erase ^H
    ;;
esac
Egy flexibilisebb megoldás:
if [ -n "$TERM" ]; then
    X=$(tput kbs) && stty erase "$X"
fi
Megj: egyes linux-változatok olyan meghaxolt terminfo adatbázist használnak, amiben egyes termináltípusoknál (pl. rxvt) a BackSpace beállítása eltér a szokásostól, hogy jobban idomuljon a linux-os alapértelmezéshez (ami a ^?) .
K: És kinek kellett volna ezt a stty-beállítást megtennie?
V: Tippem szerint annak a programnak, aki a virtuális terminált létrehozta, ez például távoli belépés esetén a telnetd/sshd.
K: Programból ugyanez hogyan állítható?
V: A termios(3) használatával. A beállítások lekérdezése a tcgetattr függvénnyel történik, a módosítás a tcsetattr függvénnyel, az adatok egy termios nevű struktúrába kerülnek. Pl:
struct termios t;
tcgettr (0, &t);
printf ("a kernel szerint a backspace kódja 0x%x", (unsigned char)t.c_cc[VERASE]);
— Üzemmódok, módosítók —
K: Addig értem, hogy a különböző terminálok és emulációk más-más szekvenciákat fogadnak, illetve küldenek; de vannak-e további bonyolító tényezők?
V: Természetesen, itt van például a Cursor Key Mode (DECCKM), ez egy kétállású kapcsolót jelent, aminek állásától függően más-más szekvenciát küldenek a nyíl-billentyűk:
bekapcs: ESC [ ? 1 h           kikapcs: ESC [ ? 1 l
Up:      ESC O A			ESC [ A
Down:    ESC O B			ESC [ B
Right:   ESC O C			ESC [ C
Left:    ESC O D			ESC [ D
Home:    ESC O H			ESC [ H
End:	 ESC O F			ESC [ F
Num5:    ESC O E			ESC [ E

Megjegyzés: az utóbbi három csak az xterm-re igaz, másoknál (pl rxvt) a szekvencia nem ez (és nem is függ a CKM-től)
K: Valamint?
V: Van olyan is, hogy Application Key Mode (DECKPAM), ennek 'Application' és 'Numeric' állásai vannak, a numerikus billentyűzet működését befolyásolja (emulátortól függ, hogy csak a NumLock kikapcsolt állapotában-e, illetve, hogy NumLock működik-e egyáltalán az 'Application' üzemmódban, esetleg csak Shift-tel együtt működik, stb.)
         Application Numeric (NumLock-tól függően)
kapcs:   ESC =       ESC >
vagy:    ESC[?66h    ESC[?66l		(ugyanaz, másképp)
0	 ESC O p     0	|  Insert
1	 ESC O q     1  |  End
2	 ESC O r     2  |  Down
3	 ESC O s     3  |  PgDn
4	 ESC O t     4  |  Left
5	 ESC O u     5  |  'kb2'
6	 ESC O v     6  |  Right
7	 ESC O w     7  |  Home
8	 ESC O x     8  |  Up
9	 ESC O y     9  |  PgUp
NumLock (ESC O P)    (működik)
/	 ESC O Q     /
*	 ESC O R     *
-	 ESC O S     -
+	 ESC O l     +
Enter	 ESC O M     ^M
.,	 ESC O n     .,
— Funkcióbillentyűk —
K: Igaz, hogy a funkcióbillentyűk éppolyan összevissza vannak, mint minden más a terminálokkal kapcsolatban?
V: Igaz.
K: Például egyes leírások húsz, vagy annál is több funkcióbillentyűről vélnek tudni. Ez hogy jön ki?
V: Ha pl. Shift-tel együtt nyomsz le egy funkcióbillentyűt, akkor az olyan, mintha 10-et hozzáadnál a billentyű sorszámához. Vagy 12-t. Programtól függ. Pl a ncurses-hez van egy tesztprogram, annak a kimenete alapján:
billentyű	ncurses				xterm-szekvencia	rxvt-szekvencia
F1		Key pressed: 0411 KEY_F(1)	ESC O P			ESC [ 11 ~
Shift+F1	Key pressed: 0425 KEY_F(13)	ESC [ 1 ; 2 P		ESC [ 23 ~
Ctrl+F1		Key pressed: 0441 KEY_F(25)	ESC [ 1 ; 5 P		ESC [ 11 ^
Ctrl+Shift+F1	Key pressed: 0455 KEY_F(37)	ESC [ 1 ; 6 P		ESC [ 23 ^
Az érdekesség kevéért a sorok végén feltüntettem két terminál-emulátor, az xterm és az rxvt által generált ESC-szekvenciákat is.
K: Szóval itt 12-t adott hozzá a Shift a funkció-billentyű sorszámához. És mikor van olyan, hogy 10-et ad hozzá?
V: Például a Midnight Commander használatáház praktikusabb, ha Shift+F5=F15, Shift+F7=F17 stb.
K: És ezt hogyan lehet elérni?
V: A derék mc saját erőből igyekszik alkalmazkodni a leggyakoribb termináltípusokhoz, (ehhez lásd a /usr[/local]/share/mc/mc.lib fájlban a [terminal:] bejegyzéseket), illetve a 'Learn Keys' funkcionalitással mi is segíthetünk neki.
— Egyéb —
K: Azt még értem, hogy mik azok az ESC-szekvenciák, de mi az hogy CSI, SS3, ST meg a többi?
V: Vezérlőkarakterek 0x80 és 0x9f között, gyakran (általában) kétbájtos szekvenciával helyettesítjük őket, pl:
Név Kód  Helyette Utf8
SS3 8F   ESC O    C2 8F
DCS 90   ESC P    C2 90
CSI 9B   ESC [    C2 9B
ST  9C   ESC \    C2 9C
OSC 9D   ESC ]    C2 9D
Megj: ha UTF-8-at használunk, akkor ezeket a vezérlőkódokat kétbájtos szekvenciaként kell továbbítani, ezt a táblázat utolsó oszlopában láthatjuk.
Q: In X Window, I wish to deactivate key NumLock.
A: Before xkb extension you could do this:
numlockx on|off # pick the preferred value
xmodmap -e 'keycode 77 = '
With xkb, I suggest swapping keycodes with a non-used key, eg:
numlockx on|off # pick the preferred value
/usr/bin/xkbcomp "$DISPLAY" /tmp/kbmap.xkb
sed -i.bak 's/<NMLK> = 77;/<NMLK> = 98;/
            s/<KATA> = 98;/<KATA> = 77;/' /tmp/kbmap.xkb
/usr/bin/xkbcomp /tmp/kbmap.xkb "$DISPLAY"
Q: In Midnight Commander, if I press ESC key once, it acts as if I pressed it twice. How can I deactivate this behaviour?
A: In menu Options / Configuration / Esc key mode uncheck Single press.
— rxvt —
K: Mit kell tudni az rxvt-ről?
V: Kicsi, gyors, fapados. Fejlesztése abbamaradt, a legfrisebb verzió itt van: http://sourceforge.net/projects/rxvt/files/rxvt-dev/2.7.10/
Saját termináltípusa(i): rxvt és rxvt-256color
K: Milyen opciókkal érdemes fordítani?
V: Az én beállításaim:
./configure			\
	--prefix=/usr/local	\
	--enable-frills		\
	--enable-rxvt-scroll	\
	--enable-mousewheel	\
	--enable-256-color	\
	--with-term=rxvt-256color
— urxvt —
K: Mit kell tudni az urxvt-ről?
V: Az rxvt egyik folytatása, itt található: http://software.schmorp.de/pkg/rxvt-unicode.html
Saját termináltípusa(i): rxvt-unicode és rxvt-unicode-256color; illetve használhatjuk a rxvt és rxvt-256color, típusokat is, de vigyázzunk, mert a BackSpace terminfo-kódja különböző: rxvt: ^H, rxvt-unicode: ^?
K: Ha mondjuk rxvt-256color típussal akarok repülni, mit állítsak be?
V: Pl. ilyesmit tegyél a ~/.Xdefaults fájlodba:
Rxvt.termName: rxvt-256color
Rxvt.backspacekey: \010
Megj: Ennek persze kell egy xrdb ~/.Xdefaults, hogy érvényre jusson.
K: Milyen opciókkal érdemes fordítani?
V: Az én beállításaim:
./configure			\
    --prefix=/usr/local		\
    --enable-frills		\
    --enable-rxvt-scroll	\
    --enable-mousewheel		\
    --enable-256-color		\
    --with-term=rxvt-256color	\
    --disable-perl
— gnome-terminal —
K: Mit kell tudni a gnome-terminal-ról?
V: Kényelmesnek látszik, tab-okat kezel, UTF-8-képes; idegesítő tulajdonsága, hogy lenyúlja az F1 és F10 gombokat; korlátozottan konfigurálható (X11-resource-ökkel nem, XML-konfig fájljai vannak); van hozzá egy gnome termináltípus, de a TERM változót nem arra állítja be, hanem xterm-re (amellyel nem egészen kompatibilis).
Ezt úgy fixálhatjuk meg, ha az 'Edit / Profile Preferences / Title and Command' menüben a Custom command-ot ilyesmire állítjuk:
sh -c 'TERM=gnome exec /bin/bash'
— PuTTY —
K: Mit kell tudni az PuTTY-ról?
V: Ingyenes, elterjedt, jól használható, flexibilisen konfigurálható, ssh-t is tudó program Windows-ra.
Honlapja: http://www.chiark.greenend.org.uk/~sgtatham/putty/
Saját termináltípusa(i): putty és putty-256color a 'linux' típusra hasonlítanak legjobban
A beállításai közül érdekes lehet:
Window / Translation a távoli rendszer által használt kódolást állíthatjuk be, összhangban a következő ponttal; ha a partner támogatja az UTF8-at, válasszuk azt.
Connection / Data / Environment variables a LC_CTYPE-ot az előző ponttal összhangban állítsuk be, pl. hu_HU.UTF-8. Más gyakran használt változókat is beállíthatunk itt, pl. NLS_LANG, LESSCHARSET, TZ. (Vö: /etc/ssh/sshd_config-ban AcceptEnv)
Terminal / Keyboard / TheHomeAndEndKeys: a 'standard' állást érdemes választani, ugyanis abban a 'putty' termináltípussal kompatibilis, az 'rxvt' állásban viszont semmivel (legkevésbé azt rxvt-vel: Home: ESC[H End: ESC[0w).
Terminal / Keyboard / TheFunctionKeysAndKeypad:
K: Ha a mc-ben nem menne az egérgörgő TERM=putty esetén, mit tegyünk?
V: Természetesen a mc forrását kell megpecselni, pl. 4.8.11 esetén valahogy így:
cd lib/tty
cat >tty.patch <<DONE
111a112
>         || strncmp (termvalue, "putty", 5) == 0
DONE
patch -i tty.patch tty.c
— Vegyes problémák —
K: Valamiért a TERM változó értéke csupa nagybetű (pl PUTTY-256COLOR), emiatt persze nem működik semmi!
V: Úgy tudom, hogy a kliensnek nagybetűt is kell küldenie, és a szervernek lekicsinyítenie – de ha ez valamiért nem történik meg, akkor megpróbálhatsz szervert cserélni, vagy protokollt cserélni (telnet helyett ssh), vagy klienst cserélni, vagy olyan termináltípust beállítani, amiben nincs kötőjel.
K: A TERM-változóm jó, van is hozzá terminfo-bejegyzés (különben 'Unknown terminal' üzenetet kapnék), de mégsem mennek a grafikus karakterek (például a mc-ben)!
V: Lehet, hogy a terminfo-bejegyzés hiányos (mert pl az őskorszakból származó egzotikus rendszered van), szerezz be egy újabbat (egy működő rendszerről az infocmp(1) programmal), és telepítsd a tic(1) programmal.
K: Egzotikus rendszeremen (AIX) a bash (vagy más, readline-t használó program) átméretezésnél lefagy!
V: A readline-t ne shared lib-ként fordítsd/telepítsd.
K: Mi lehet az oka annak, hogy a mc-ben a keretrajzoló karakterek (avagy grafikus karakterek) nem működnek?
V: Számos lehetőség van, pl:
* a TERM változó hibás, pl putty esetén a TERM=putty (vagy TERM=putty-256color) használandó
* a terminfo adatbázis hibás/hiányos, szerezzünk be egy új definíciót a termináltipusunkhoz, és a tic(1) programmal telepítsük.
* a LC_CTYPE nincs beállítva, vagy nincs összhangban az emulátor beállításával; putty esetén a Window/Translation/RemoteCharacterSet beállítással összhangban lévő LC_TYPE-ot a Connection/Data/EnvironmentVariables menüpontban definiálhatunk.
* a terminálunk kíván egy enacs szekvenciát. Adjunk neki:
$ tput enacs
K: Ez a LC_CTYPE hogyan viszonyul az ssh-hoz?
V: Akkor működik legjobban, ha a /etc/ssh/sshd_config fájlban van egy ilyen sor (bejövő kapcsolatokhoz):
AcceptEnv LANG LC_*
a /etc/ssh/ssh_config fájlban pedig egy ilyen (kimenő kapcsolatokhoz):
SendEnv LANG LC_*
— Nagy összehasonlító táblázat —
keyterminfo(5)
kódnév
xterm
sco
xterm
new
xterm
old
rxvt,
Eterm
puttylinuxvt100
Inskich1 ESC[LESC[2~
Delkdch1 ^?ESC[3~
Homekhome ESC[H ESC[7~ESC[1~ESC[7~
Endkend ESC[F ESC[8~ESC[4~ESC[8~
PgUpkpp ESC[IESC[5~
PgDnknp ESC[GESC[6~
Upkcuu1 ESC[A
Downkcud1 ESC[B
Rightkcuf1 ESC[C
Leftkcub1 ESC[D
Shift+Upsr   ESC[1;2A   ESC[a ESCOA  
Shift+Downsf   ESC[1;2B   ESC[b ESCOB  
Shift+RightkRIT   ESC[1;2C   ESC[c ESCOC  
Shift+LeftkLFT   ESC[1;2D   ESC[d ESCOD  
Ctrl+Up    ESC[1;5A   ESCOa ESCOA  
Ctrl+Down    ESC[1;5B   ESCOb ESCOB  
Ctrl+Right    ESC[1;5C   ESCOc ESCOC  
Ctrl+Left    ESC[1;5D   ESCOd ESCOD  
BkSpckbs ^H^?
Num5kb2  ESC[E ESCOuESC[GESCOu
Back-Tabkcbt  ESC[Z ESC[Z 
F1kf1 ESC[MESCOPESC[11~ESC[[AESCOP
F2kf2 ESC[NESCOQESC[12~ESC[[BESCOQ
F3kf3 ESC[OESCORESC[13~ESC[[CESCOR
F4kf4 ESC[PESCOSESC[14~ESC[[DESCOS
F5kf5 ESC[QESC[15~ESC[[EESCOt
F6kf6 ESC[RESC[17~ESCOu
F7kf7 ESC[SESC[18~ESCOv
F8kf8 ESC[TESC[19~ESCOl
F9kf9 ESC[UESC[20~ESCOw
F10kf10 ESC[VESC[21~ESCOx
F11kf11 ESC[WESC[23~ 
F12kf12 ESC[XESC[24~ 
F13kf13 ESC[YESC[1;2PESC[25~ 
F14kf14 ESC[ZESC[1;2QESC[26~ 
F15kf15 ESC[aESC[1;2RESC[28~ 
F16kf16 ESC[bESC[1;2SESC[29~ 
F17kf17 ESC[cESC[15;2~ESC[31~ 
F18kf18 ESC[dESC[17;2~ESC[32~ 
F19kf19 ESC[eESC[18;2~ESC[33~ 
F20kf20 ESC[fESC[19;2~ESC[34~ 
Megjegyzések:
— PC és VT billentyűzet —
VT (részlet)
+--------+-----------------+    +----+----+----+----+
| Help   | Do              |    |F17 |F18 |F19 |F20 |
+--------+-----------------+    +----+----+----+----+

+--------+--------+--------+    +----+----+----+----+
| Find   | Insert | Re-    |    |PF1 |PF2 |PF3 |PF4 |
|        | Here   | move   |	|    |    |    |    |
+--------+--------+--------+    +----+----+----+----+
| Select | Prev   | Next   |	| 7  | 8  | 9  | -  |
|        | Screen | Screen |	|    |    |    |    |
+--------+--------+--------+    +----+----+----+----+
         | Up     |		| 4  | 5  | 6  | '  |
+--------+--------+--------+	+----+----+----+----+
| Left   | Down   | Right  |	| 1  | 2  | 3  |Entr|
+--------+--------+--------+	+----+----+----+    |
				| 0       | .  |    |
				+---------+----+----+
Generált szekvenciák (Különféle üzemmódoktól függően)
Billentyű    Szekvencia(szekvenciák)  terminfo PC-ekvivalens
Help:        CSI 28 ~                 kf15     F15(?)
Do:          CSI 29 ~                 kf16     F16(?)
Find:        CSI 1 ~                  khome    Home(?)
Insert Here: CSI 2 ~                  kich1    Insert
Remove:      CSI 3 ~                  kdch1    Delete
Select:      CSI 4 ~                  kslt     End(?)
Prev Screen: CSI 5 ~                  kpp      PageUp
Next Screen: CSI 6 ~                  knp      PageDn
Up:          CSI A   SS3 A   ESC A    kcuu1    Up
Down:        CSI B   SS3 B   ESC B    kcud1    Down
Right:       CSI C   SS3 C   ESC C    kcuf1    Right
Left:        CSI D   SS3 D   ESC D    kcub1    Left
PC (részlet)
	+----+----+----+
	|SyRq|ScLk|Brk |
	+----+----+----+

	+----+----+----+    +----+----+----+----+
	|Insr|Home|PgUp|    |NmLk| /  | *  | -  |
	+----+----+----+    +----+----+----+----+
	|Del |End |PgDn|    | 7  | 8  | 9  | +  |
	+----+----+----+    +----+----+----+    +
			    | 4  | 5  | 6  |    |
	     +----+	    +----+----+----+----+ 
	     | Up |	    | 1  | 2  | 3  |Entr|
	+----+----+----+    +----+----+----+    |
	|Left|Down|Rght|    | 0       | .  |    |
	+----+----+----+    +---------+----+----+ 
— További olvasmány —