Заметки о консоли. Украшение её

По мне так текстовая консоль Linux прекрасна сама по себе, в первозданном виде по умолчанию: белые или светло-серые буквы на радикально черном фоне строги, но элегантны. Разумеется, при одном непременном условии — выборе подходящего шрифта.

Кажется, одна из причин того, что многие пользователи пренебрегают консольным режимом, именно в шрифтах и кроется. Действительно, тот, с позволения сказать, шрифт, который обычно устанавливается в консоли по умолчанию при ее кириллизации, — отнюдь не верх эстетического совершенства. Однако ограничиваться “умолчальным” шрифтом никто не заставляет.

Благо, экранных шрифтов для консоли в современных Linux-дистрибутивах обычно много. В этом можно убедиться, просмотрев каталог типа /usr/share/kbd/consolefonts или тот, где они содержатся в конкретном дистрибутиве (точное местоположение легко определить командой find со значением consolefonts для опции -name). Вывод команды ls для этого каталога займет уж точно пару экранов. И шрифтовые файлы, которые в нем можно увидеть, обычно (хотя и не обязательно) имеют вид *.psf.gz (то есть использующие сигнатуру psf и сжатые утилитой компрессии gzip, хотя последнее не всегда применяется). Кроме этого, в последнее время в дистрибутивах встречается все больше шрифтов вида *.psfu (psfu.gz). А иногда можно обнаружить и файлы без всякого суффикса (типа alt8x16).

В чем различие между ними? Файлы без суффикса — это шрифты в т.н. raw-формате, то есть содержащие только собственно данные о шрифте, без всякой дополнительной информации (именно такие шрифты используются в консоли FreeBSD). Файлы же с суффиксом psf, кроме шрифтовых данных, содержат еще т.н. psf-сигнатуру, в которой описываются свойства шрифта. И, наконец, в файлы вида psfu дополнительно вкючается еще и таблица screen font map (sfm), преобразующую внутренние коды символов в коды экранного шрифта.

Почему так сложно? Дело в том, что консольный драйвер Linux (в отличие от syscons той же FreeBSD), способен функционировать в двух режимах — 8- и 16-битном. В первом, как можно догадаться из названия, все символы, как на вводе, так и на выводе, передаются в восьмиразрядном виде — это те самые навязшие в зубах кодировки Великого и Могучего. И, соответственно, каждый вводимый (с клавиатуры или из файла) символ напрямую транслируется в свое экранное представление.

В 16-битном режиме консольный драйвер внутри себя оперирует 16-ти же разрядным представлением символов, то есть кодировкой Unicode. И здесь возможны два варианта: а) 16-битное представление ввода и вывода (т.н. собственно Unicode-режим) и преобразование ввода во внутреннюю кодировку драйвера и вывода — в обратном направлении.

О собственно Unicode-режиме я говорить пока не буду: по ряду причин он только-только начинает приживаться в консоли, и это будет темой одной из ближайших заметок.

Шестнадцатибитный же режим с трансляцией до недавнего времени являлся основным для Linux-консоли (8-битный режим, именуемый иначе trivial, ныне им лишь эмулируется). В этом случае ввод и вывод осуществляются в традиционных 8-битных кодировках. Причем кодировка ввода транслируется во внутреннее 16-битное представление посредством специальных таблиц соответствия, именуемых в kbd таблицами unimap (unicode console map, живут в каталоге /usr/share/kbd/unicode) или, в console-tools, acm (application character map). Выводимые же символы испытывают обратную трансформацию в 8-битное представление с помощью таблицы sfm (screen font map, штатное место для этих таблиц — /usr/share/kbd/consoletrans).

Так вот, именно эта таблица, sfm, и встраивается в шрифтовой файл, которому присваивается суффикс *.psfu (это — правило номенклатуры, имеющее, как обычно, и исключения, о чем скажу чуть ниже). Делается это потому, что, в отличие от кодовых таблиц, порядок символов в шрифтовом файле никем и ничем не регламентируется, и, в общем случае, может быть любым. А значит, для однозначного вывода в заказанной 8-битной кодировке очень желательно, чтобы нужная таблица соответствия была составной частью шрифтового файла.

Тут я хотел бы еще раз поблагодарить вышеупомянутого Kot’а — раньше я как-то не отдавал себе отчета в том, что набор символов в шифтовом файле — штука абсолютно произвольная. Именно это позволяет изготавливать шрифты не только для различных кодировок кириллицы, но и различающиеся наборами вспомогательных символов, начиная с буквы “ё” (как известно, в кодировках DOS и KOI8 ее от природы не было) и кончая специфичными для украинского языка знаками (типа “г с чубом”). А в 16-битном режиме в один шрифтовой файл умудряются втиснуть символы для нескольких национальных алфавитов (например, упомянутое ниже семейство LatArCyrHeb). Правда, использовать все теоретическое богатство 16-битных кодировок не удается даже в чистом Unicode-режиме, так как размер консольного шрифта ограничен 512 символами (это связано с каким-то аппаратными ограничениями — точнее сказать не могу). И потому встречающееся обозначение консольных шрифтов как “юникодовских” (грешен, сам им пользовался до недавнего времени) — не более чем жаргонизм: речь идет о шрифтах с несколькими наборами алфавитных символов и встроенной таблицей sfm.

Как легко догадаться, далеко не все шрифты из штатного комплекта любого дистрибутива содержат символы кириллицы. Однако и таких обычно обнаружится десятка три. Если нет — их можно позаимствовать (прямым копирование в должный каталог) из какого-либо Linux-дистрибутива отечественного производства (типа Altlinux или ASPLinux). Или — из пакета console-tools-cyrillic, собранного и периодически обновляемого Виктором Вагнером.

Полная коллекция кириллических экранных шрифтов включает наборы для всех традиционных кодировок Великого и Могучего, получивших распространение на родных просторах — DOS, Windows, KOI8, ISO8859-5, которые опознаются по именам шрифтовых файлов. Шрифты в DOS-кодировке имеют имена типа alt*, Cyr*, cp866* или просто 866* (имена одних и тех же шрифтов в разных дистрибутивах могут варьировать; хотя в принципе шрифты с префиксами alt и Cyr несколько различаются по наборам символов). Шрифты KOI8 (как R, так и U) именуются прозрачно — koi8r и koi8u, соответственно. Шрифты для Win-кодировки имеют в своем имени слово win или цифры 1251. ISO’шные шрифты опознаются по символам iso5 или слову sun (поскольку именно на Sparc’ах главным образом и используются).

По причинам, которые будут рассмотрены в заметке о русификации, практическое значение для экранного вывода в наших условиях имеют почти исключительно шрифты для кодировки DOS. Вне зависимости от того, как их называют, в любом дистрибутиве Linux (за исключением уж совсем американских) можно обнаружить минимум три таких “гарнитуры” (если этот термин в данном случае уместен), именуемые как-нибудь вроде cp866*, cp866-b* и cp866-c*. Они несколько отличаются своим обликом и расположением некоторых редко используемых специальных символов. Впрочем, все три внешне выглядят вполне скверно (особенно при плотности символов, отличной от стандартной).

В отечественных дистрибутивах (и в пакете console-tools-cyrillic) можно найти еще несколько кириллических шрифтов для DOS-кодировки. Например, alt-antiq, стилизованный под старину, или t866, имеющий как бы рукописный облик. Однако и они не вполне подходят для постоянного использования (хотя могут придать вашей консоли вполне оригинальный вид).

И потому очень рекомендую обратить внимание на семейство шрифтов UniCyr*.psf(.gz). Вопреки приведенному выше правилу, эти шрифты содержат в себе таблицу sfm — то самое исключение, поминаемое выше. Среди них можно обнаружить как курьерообразные разновидности, так и вполне честные шрифты Sans Serife (а на мой взгляд, именно шрифты без засечек наиболее подходят для экранного вывода в консоли). Таковых — два, UniCyr-lenta-8x16 и UniCyr-sans-8x16. Их дополнительное достоинство — слабая подверженность деформации при нестандартной плотности символов (напомню, что в консоли мы всегда имеем дело с растровыми шрифтами, и потому их искажение при масштабировании неизбежно). Впрочем, на вкус и цвет товарищей нет, и потому подходящий шрифт каждый может выбрать для себя методом ползучего эпмиризма.

Как уже упоминалось, с некоторого времени в дистрибутивах Linux, претендующих на интернациональность, можно видеть шрифты вида *.psfu.gz или *.psfu. Например, семейство гарнитур, именуемое LatArCyrHeb-* (с высотами матрицы 8, 14, 16 и 19 пикселей). Как легко понять из названия, любой из них пригоден для вывода на экран символов латиницы, кириллицы, арабского и еврейского алфавитов, нужно только указать, какого точно (как — скажу чуть ниже).

Для смены экранного шрифта в текущем сеансе работы служит команда setfont из пакета kbd (в пакете console-tools ей соответствует команда consolechars). Дается она с указанием имени шрифта в качестве аргумента, например:

$ setfont UniCyr-sans

что приводит к мгновенной смене экранного шрифта на всех виртуальных консолях. Если шрифты расположены в стандартном для данного дистрибутива каталоге (например, /usr/share/kbd/consolefonts), не требуется ни указания полного пути к имени шрифтового файла, ни его суффикса (вида *.psf.gz). Необходимость и в том, и в другом возникнет, если шрифты берутся из необычного места (например, домашнего каталога пользователя).

В команде consolechars загружаемый шрифт определяется значением опции -f, каковое подчиняется тем же правилам, что и аргумент команды setfont.

Указанной команды достаточно, если мы работаем в режиме trivial, и притом только с одной и той же кодировкой ввода и вывода. На практике же в наших условиях такого почти не бывает — для вывода используется кодировка DOS, для ввода — обычно KOI8-R (или CP1251). И потому необходимо обеспечить загрузку так называемой карты соответствия (mapscreen, то есть таблицы перекодирования набора символов клавиатурного ввода в таковой экранного вывода). Что достигается указанием опции -m, значением которой и выступает имя файла таблицы (они произрастают в том же каталоге /usr/share/kbd/consoletrans, что и sfm-таблицы, хотя вещи это разные). Подробнее об этом будет говориться в заметке о русификации, пока же — лишь несколько соображений рецептурного характера.

Первое — если после исполнения команды setfont имя_шрифта вместо русского текста на экране наблюдаются всякого рода безобразия, команду следует повторит в виде

$ setfont UniCyr-sans -m koi2alt

где значение опции -m указывает на имя mapscreen. В особо тяжелых случаях (при нерусифицированной системе, или при открытии новой виртуальной консоли в соответствии с ранее описанными методами), возможно, придется этот самый mapscreen еще и активизировать вручную вводом т.н. “магической последовательности”

$ echo -ne '(K'

Без этого русские буквы будут видны только на той консоли, с которой была дана команда setfont (она автоматически активизирует нужную кодировку, но только — на текущей консоли).

Если принято решение использовать для вывода шрифты в кодировке KOI8, отпадает требование не только вывода “магической последовательности”, но и опции -m в команде setfont. Оно и понятно — ведь при этом в случае 8-битного режима и для ввода, и для вывода используется один и тот же набор символов.

В 16-битном режиме необходимо выполнить две трансляции символов — сначала из кодировки ввода в Unicode-представление, а затем — в кодировку вывода. Первая осуществляется той же опцией -m, которая теперь приобретает значение имени unimap-файла, вторая же — опцией -u, в качестве значения которой задается имя sfm-таблицы:

$ setfont cp866-8x16 -m koi8-r_to_uni -u cp866

Если загружаемый шрифт уже содержит встроенную sfm-таблицу, опцию -u задавать не нужно (точнее — нельзя), опция же -m потребуется в любом случае, например:

$ setfont LatArCyrHeb-16 -m koi8-r_to_uni

Подчеркну, что в этом случае, в отличие от 8-разрядного режима, опция -m обеспечивает перекодирование символов ввода не прямо в их экранное воплощение (то есть кодировку шрифта), а во внутреннюю кодировку Unicode.

Режим с 16-битным внутренним представлением теоретически является более гибким и более прогрессивным (особенно — в Unicode-варианте). Однако 8-битный режим отнюдь не потерял своего значения — и не только обратной совместимости ради. Дело в том, что, как будет показано в соответствующей заметке, русификация консоли в нем осуществляется простым, отработанным и абсолютно предсказуемым комплексом мер, применимых к любому произвольному дистрибутиву Linux. Тогда как русификация 16-битного режима более дистрибутиво-зависима и не всегда предсказуема. По крайней мере, до недавнего времени было именно так. Нынче, с активным внедрением UTF-8 (и ее поддержкой терминальными библиотеками и консольными приложениями), ситуация, видимо, упростится.

Рано или поздно упражнения со шрифтами заканчиваются достижением идеального (или, по меньшей мере, оптимального) варианта. Который хотелось бы увековечить как загружаемый по умолчанию при старте системы. Сделать это не очень-то и трудно, сложнее дать однозначные рекомендации, как именно. Поскольку метод загрузки “умолчального” шрифта очень зависит от системы инициализации, принятой в конкретном дистрибутиве.

В клонах Red Hat, насколько я помню, это достигается изменением значения строки SYSFONT в конфигурационном файле /etc/sysconfig/i18n. В других дистрибутивах “умолчальный” шрифт может изменяться в других конфигах из каталога /etc и его подкаталогов — сверяйтесь с документацией. А в почти любых неясных случаях самое место для подгрузки шрифта — файл /etc/rc.local, куда можно поместить строку вида

setfont UniCyr-sans -m koi2alt

Не забыв сопроводить ее сценарием инициализации mapscreen на всех открываемых при старте виртуальных консолях, о чем подробно будет сказано в заметке по русификации.

Теоретически рассуждая, шрифт, загружаемый по умолчанию, можно вкомпилировать в ядро системы (во FreeBSD такая возможность предусмотрена в штатной документации). Преимущество этого метода — доступ к кириллическим шрифтам при всякого рода аварийных загрузках (например, при подмене штатного процесса init командной оболочкой путем передачи ядру параметра init=/bin/shell_name). Это позволит для исполнения ремонтно-спасательных действий прибегнуть к подсказкам из русскоязычной документации. Однако сам я такую процедуру не проделывал. Могу только предполагать, что она потребует изменения исходников файлов типа /usr/src/linux/drivers/char/console*. За любые соображения по сему предмету буду благодарен.


Содержание . .

. .