Čeština na Linuxové konzoli

Ano, vidíte správně, toto je další z mnoha WWW-stránek zabývajících se češtinou pod Linuxem. Na tomto místě se samozřejmě nabízí spousty všetečných otázek, proč že jsem to vlastně dělal a co jsem tím sledoval, když už mnozí jiní učinili na poli lokalizačním spousty práce (za což jsem jim ostatně náležitě vděčný; viz též linky níže).

Leč jak už to bývá, u mnoha věcí mne napadlo, jak je vyřešit úplně jinak a dle mého vlastního názoru lépe (přivedl mne na to vlastně Vojta Pavlík), a tak vznikla tato stránka.

Zatím jediné, čím jsem se pořádně zabýval, je starý známý problém "české znaky kontra Linuxová konzole". Problémy s X-Window zde nejsou ani diskutovány, natož pak řešeny, neboť na okénka si nepotrpím.

Veškeré připomínky jsou samozřejmě vítány.

Kompletní archiv obsahující všechny zmiňované soubory je ke stažení zde. Všechny programy i datové soubory je možno distribuovat při dodržení podmínek GNU General Public License - tedy přesně stejně, jako Linux samotný.

Obsah:

Bylo, nebylo

Aneb jak vlastně v Linuxu funguje konzole.

Znakové sady

Již od malička Linux podporuje vyměnitelnou znakovou sadu pro konzoli. A od nepaměti to mělo nějaké háčky: hlavní problém je v tom, ze když panove od IBM (Institute of Black Magic?) vyvíjeli svoji VGA kartu, rozhodli se, že implementují 9-pixelový font, který by vypadal o něco estetičtěji než původní 8-pixelový, co měla EGA, nicméně nechtělo se jim ukládat někam onen devátý bit. Vyřešili to tedy velice šalamounsky: do devátého pixelu dávali hardwarově barvu pozadí, ovšem aby to nerozbořilo rámečkové znaky, u znaků s kódy 0xb0 až 0xdf se použije barva pixelu předchozího.

Aby se Linux mohl s tímto šílenstvím vyrovnat (uznejte, že většina kódování znaků používaných v nedosovském světě - jako například ISO-8859-cokoliv - má v této zóně normální znaky a případnou grafiku má zcela jinde), musely být zavedeny mapovací tabulky konvertující kódy znaků na jejich pozice ve fontu (viz příkaz mapscrn).

Ovšem Linuxová implementace VT100 podporuje hned několik různých mapování - například VT100-grafiku, IBM-grafiku apod., přičemž před chvílí popsané překódovávání se děje pouze pro jeden z těchto módů. Tudíž aby fungovala grafika, musí se poměrně nechutným způsobem modifikovat termcap, terminfo a kdo ví, co ještě všechno, a přemapovat grafické znaky ve všech těchto souborech. I to ovsem občas nepřinese kýžené ovoce (tedy ono přinese, ale poněkud zkažené), jelikož se tak grafika většinou přemapuje do oblasti 0x80 až 0x9f, již vetšina programů považuje za znaky řídící, a tudíž nezobrazitelné.

Naštestí se během vývoje Linuxu 1.3.X objevilo řešení nové všech těchto problémů prosté: kernel začal podporovat mapování znaků přes 16-bitový kód UniCode. Zkrátka a dobře, pro každý z popisovaných módů konzole existuje převodní tabulka do UniCode, plus ještě jedna definovatelná uživatelem (tu ostatně nakonec pro češtinu využijeme) a pak je ještě definována konverzní tabulka z UniCode do kódování fontu, čímž se všechny konverze dají provést jednoduše a docela rychle.

Keymapy

O tom, jak funguje mapování klávesnice pod Linuxem, byla již popsána spousta papíru, jakož i spousta elektronů. Spokojme se tedy s odkazem na příslušnou manuálovou stránku od programu loadkeys.

A jak tedy?

Před chvílí jsme dospěli k názoru, že UniCodový mechanismus bude pro řešení češtiny to pravé (nyní pomlčme o tom, že žádná ze standardních utilit neumí příslušne mapování do UniCode nastavovat, takže musela vzniknout ještě utilita další).

Jediným problémem bylo vybrat kódováni fontu. Vzhledem k mírně šíleným požadavkům, které jsou na jeho obsah kladeny, se asi nikomu nepodaří najít žádné standardní kódování tyto požadavky splňující. Nuž vydejme se cestou objevitelů...

V archivu obsažené soubory layout/*.uni obsahují kompletní tabulky rozložení jednotlivých kódování, jejichž znaky by font měl obsahovat - v prvním sloupci kód, ve druhém UniCode glyph number, ve třetím pak standardní UniCodové jméno znaku.

Jistým kompromisem mezi všemi těmito znakovými sadami je pak kódování popsané v souboru ucw.uni - obsahuje ASCII ve standardních pozicích, dále pak běžné IBMovské rámečky mezi 0xb0 a 0xdf, písmena s akcenty mezi 0x7f a 0xaf, jakož i mezi 0xe0 a 0xff a konečně "všehochuť" mezi 0x00 a 0x1f (ani znak nazmar!). Toto kódování obsahuje všechny znaky Latin-2, část Latin-1, většinu IBMovské grafiky (všechny rámečky a pár doplňujících znaků jako např. šipky) a vetšinu VT-100 grafiky.

Balíček

Vymyslet řešení by ještě nebylo tak zajímavé a hlavně tak užitečné jako ho realizovat. Výsledky mého snažení (doplněné o to, co poskytli ostatní) jsou k nalezení v archivu ucw-cs-1.1.tar.gz, který obsahuje:

Fonty

Dosud nejsou k dispozici fonty pro všechny používané velikosti znaků, nicméně doufejme, že časem je někdo (možná já) dokreslí. Zatím máme:

Všechny tyto fonty jsou ve formátu PSF se zakompilovanou UniCodovou tabulkou, takže je stačí naloadovat příkazem setfont a vše začne fungovat. Při tvorbě vlastních fontů můžete využít samostatnou UniCodovou tabulku (setfont font -u unimap).

Pokud vytvoříte jakýkoliv nový font, prosím o jeho zaslání, abych jej mohl zařadit do nové verze této distribuce.

Mapy klávesnice

Na rozdíl od klasických balíků pro podporu češtiny jsem nedodal mnoho různých kompetních keymap, nýbrž systém modulů, ze kterých se dají různé keymapy skládat (využívám toho, že příkaz loadkeys si umí nechat zadat několik jmen souborů, které "slepí" dohromady).

Pro všechny české i slovenské klávesnice jsou určeny následující moduly:

K těmto modulům se pak přidává jeden z následujících určující konkrétní typ klávesnice:

Tedy například českou standardní klávesnici lze nahrát pomocí příkazu loadkeys cs-head.map cz-type.map cs-compose.map.

Program mapscrnuni

Jelikož žádná ze standardních utilit dodávaných v balíku kbd neumí nastavovat jádru mapování uživatelského kódování do UniCode, vytvořil jsem jednoduchý prográmek mapscrnuni, který toto mapování nastavuje. Na standardním vstupu očekává soubor typu latin2.table toto kódování popisující (první sloupec obsahuje pozici ve fontu, druhý pak příslušné UniCodové číslo znaku).

Emacs

Emacsu je nutno trochu domluvit, aby byl ochoten akceptovat z klávesnice a zobrazovat znaky z ISO-8859-2. Tento problém řeší inicializační soubor ucw-cz.el (pro Emacs 19.34), případně ucw-cz-old.el (pro Emacsy starší), který správně nastaví osmibitový vstup i výstup, jakož i charakteristiky jednotlivých znaků.

Readline a Bash

I Bash (respektive readline library) potřebují trochu domluvit, aby pracovali s osmibitovými znaky. Stačí jim podstrčit správný soubor .inputrc, ve kterém je nedefinováno, že vše je osmibitové a ještě nádavkem namapovány některé klávesy (tudíž pak v Bashi chodí i klávesy jako Home a End).

Standardní Bash bohužel dosud neumí pracovat s globálním inputrc. Napsal jsem patch pro Bash 2.01, který v případě absence uživatelského ~/.inputrc hledá /etc/inputrc a totéž ještě pro /etc/bashrc, nicméně ve standardní distribuci Bashe dosud není. Snad brzy bude...

HowTo

A kterak tento skromný balíček nainstalovat?

  1. Zkopírovat fonty do /usr/lib/kbd/consolefonts, keymapy do /usr/lib/kbd/keytables, mapscrnuni do /usr/bin a latin2.table do /usr/lib/kbd/consoletrans.
  2. Do startup-scriptů přidat příkazy (se správným jménem fontu a keymapy):
    		setfont ucw16.psf
    		mapscrnuni </usr/lib/kbd/consoletrans/latin2.table
    		loadkeys cs-head.map cs-ucw.map cs-compose.map
    
    
  3. Do /etc/issue či /etc/profile přidat, aby se v případě loginu na konzoli vypisovala řídící sekvence pro přepnutí na uživatelské mapování (které jsme nastavili na Latin-2), konkrétně ESC(K (například příkazem echo -en "\033(K").

Možná někdy někdo napíše instalační script či vyrobí RPM...

Credits

Rád bych poděkoval všem, kdož přispěli k vývoji tohoto balíčku, zejména pak těmto:

Vojtěch Pavlík
Přivedl mne na myšlenku něco takového napsat.
Milan Vančura
Nakreslil krásné 11-bodové fonty.
Ladislav Lhotka
Od něj pochází syntax table pro ISO-8859-2 použitá v ucw-cz-old.el.
Michael Gschwind
Vyrobil syntax and case table v ucw-cz.el.

Linky


Změna kódování češtiny

Last modification 13. 12. 1997 by Martin Mares