Алексей Федорчук
[email protected]
Как уже говорилось, экранную часть виртуальной консоли можно сравнить с окном, через которою мы наблюдаем за процессами в системе. Подобно окну экран консоли не только дает возможность видеть происходящее, но и ограничивает кругозор. Потому что реально оперировать можно только той информацией, которая в текущий момент выведена на экран.
Чтобы убедиться в справедливости сравнения экрана с окном (не в смысле оконной системы Икс, и тем более не в понимании MS Windows), представим себе выделение мышью блока текста, например, в редакторе. Подробностям мышиной темы я собираюсь посвятить отдельную заметку. Пока же заметим, что при этом происходит автоматическое копирование выделенного экранного блока в буфер обмена. Подчеркиваю - именно экранного блока, а не текстового фрагмента: если строка выходит за пределы экрана, невидимая в данный момент ее часть в буфер обмена не попадет. Также не будет скопирована и часть абзаца, уходящая вниз. То есть экранному буферу консоли глубоко безразлична разметка текста.
В то же время, если блоки для копирования и вставки выделять средствами текстового редактора (в joe, например, этой цели служат команды Control+K-B для начала и Control+K-K - для конца выделения блока. В этом случае мы, действуя клавишами управления курсором (или такими командами Joe, как Control+F, Control+B, Control+P, Control+N), как бы протаскиваем наш текст через прорезь экрана. Подобно тому, как детский диафильм стародавних времен для своего воспроизведения протаскивалася через соответствующий агрегат (кто не помнит - назвался он диапроектором). Правда, в случае с экранным буфером такое протаскивание возможно как по вертикали, так и по горизонтали.
И так, "призрачно все в этом мире бушующем, есть только миг", запечатленный в экранном буфере текущей виртуальной консоли. И потому возникает естественное желание продлить мгновение. Или, вспомнив, что миг этит мы видим в окне экрана, - прорубить окно пошире. И способы для этого имеются.
Поскольку сам по себе размер экрана - объективная реальность, данная нам в дюймах его диагонали (да и то, в случае CRT-мониторов, с обманом), напрашивается решение - поместить на экран как можно больше информации. То есть - увеличить разрешение.
Термин "разрешение" применительно к текстовому режиму используется в несколько ином смысле, чем в графических системах типа Иксов или MS Windows. Ведь в качестве единицы измерения ширины и высоты экрана здесь выступает не пиксель, а их набор (матрица), составляющий единичный символ. И потому правильнее говорить не о разрешении экрана текстовой консоли, а о плотности символов на ней.
Это повелось со стародавних времен чисто текстовых мониторов и видеоадаптеров, когда на экране могли воспроизводиться только цельные символы, выдаваемые знакогенератором видеоподсистемы из неких фиксированных их наборов, как бы "вшитых" в нее. Однако уже давно видеокарты приобрели способность подгружать (и выводить на экран) и разные другие наборы символов, считываемые из соответствующих шрифтовых файлов. Вот этим-то свойством мы и воспользуемся для расширения нашего поля зрения.
Стандартная плотность символов текстовой консоли в Linux, устанавливаемая по умолчанию, составляет 80 колонок на 25 строк (80x25). И обеспечивается она использованием шрифта с матрицей 8 на 16 пикселей (в имени такого шрифтового файла, вне зависимости от кодировки, присуствуют эти цифры - 8x16). То есть, казалось бы, для увеличения "разрешения" текстовой консоли достаточно было бы подгрузить шрифт с иной матрицей символов. Однако это не совсем так.
Начать с того, все консольные шрифты, говоря типографскими терминами, не пропорциональные, а моноширинные (то есть ширина буквы "л" в пикселях точно такая же, как и ширина буквы "щ". Далее, ширина символьной матрицы - фиксированная для любых шрифтов, и составляет 8 пикселей. Это обусловлено аппаратными особенностями видеосистемы тех компьютеров, которые в старое время называли IBM PC-совместимыми (а нынче кличут просто PC или писюками - это те самые машины, за которыми мы с вами и сидим). В них под ширину символа отведено 9 пикселей, причем последний, 9-й, зарезервирован на тот случай, чтобы между символами на экране всегда оставались пробелы, даже между буквами типа "н" и "м" (то есть теми, у которых полностью заняты первая и посленяя колонки матрицы). И, следовательно, заменяя шрифт с матрицей 8x16 на более мелкий (а стандартно в любом дистрибутиве можно найти еше и шрифты с матрицами 8x14 и 8x8 для любых кодировок, для некоторых же наборов символов доступны высоты матрицы 12, 10, 9, 7 и 6 пикселей), мы увеличиваем лишь количество строк, отображаемых на экране, при сохранении количества символов в строке.
Забегая вперед, отмечу, что в Linux-консоли возможно использование шрифтов с количеством строк матрицы, отличным от 8. Но - только в режиме графической консоли, который будет предметом одной из финальных заметок цикла.
Тем не менее, в некоторых случаях этого может оказаться достаточно. И на сей предмет к пакете kbd есть специальная команда - setfont (в console-tools ей соответствует consolechars; длина последней - одна из причин моей нелюбви к этому пакету)). Она требует единственного обязательного аргумента - имени подгружаемого шрифтового файла. То есть в форме
$ setfont cp866-8x8
мы загрузим шрифт в кодировке CP866 и с матрицей символов 8x8, в результате чего плотность строк у нас возрастет более чем вдвое (до примерно 55-56) по сравнению с "умолчальной". Вид экрана, правда, при этом будет вполне отвратительным. И потому "расширение окна" таким образом - лишь временное решение проблемы.
Второй вариант увеличения плотности символов на экране консоли - команда resizecons из все того же пакета kbd (есть она, кажется, и в пакете console-tools). Смысл ее понятен из название - это именно масштабирование консольного дисплея, то бишь изменение количества отображаемых строк и колонок. Она может быть использована в трех формах:
$ resizecons COLSxLINES
или
$ resizecons COLS LINES
а также
$ resizecons -l LINES
где под COLS и LINES понимается количество знаков в строке и количество строк, соответственно.
Использование команды resizecons сопряжено с рядом ограничений. Во-первых, ни количество строк, ни количество колонок не могут быть произвольными числами. Они должны соответствовать фиксированным сочетаниям, поддерживаемым, с одной стороны, ядром Linux, с другой - наличной видеокартой. Теоретически (то есть ядром) поддерживаются значения плотности строк - 25, 28, 30, 34, 36, 40, 44, 50, 60, и плотности знаков в строке - 80, 100, 132 (детали можно посмотреть в файле документации к ядру - /usr/src/linux/Documentation/svga.txt. Однако практически достижимы лишь некоторые сочетания этих значений. Далее в этой заметке я расскажу, как определить значения плотности символов, пригодные именно для данной системы.
Второе ограничение связано с используемыми шрифтов. Дело в том, что команда resizecons, если так можно выразиться, синтетическая, и выполняет несколько последовательных действий. Из которых финальным является смена текущего экранного шрифта тем, который имеет соответствующую плотности строк высоту матрицы (обычно 12 пикселей для 28-30 строк и 8 или 9 - для большего их числа). А имя этого шрифта, как нетрудно догадаться - default, и ни малейшей кириллицы он не содержит. То есть при необходимости работы с русскими текстами вслед за изменением "разрешения" экрана необходимо и переопределить шрифт на соответствующий кириллический.
И наконец (хотя, вероятно, с этого следовало бы начать), в некоторых системах команда resizecons просто отказывается работать, выдавая сообщение о невозможности найти файл указанного видеорежима.
Честно говоря, я разбирался с resizecons довольно давно, и детали уже забыл (так что буду признателен за любые дополнения по этому вопросу). И если пишу здесь о ней - так только ради полноты картины. Потому что есть наиболее эффектвиный способ установки желательной плотности знаков в консоли - передача соответствующих параметров ядру при старте системы.
Для выполнения этого действа неолбходимо, во-первых, иметь должным образом собранное ядро. То есть в пункте его конфигурации Console drivers (при использовании make menuconfig), кроме опции VGA text console (она обязательна в любом случае, кроме встраивания в ядро поддержки Frame Buffer, о чем пойдет речь в заключительных заметках цикла), необходимо включить и опцию Video mode selection support.
Далее, необходимо на стадии загрузки передать ядру параметр vga=значение. Это можно сделать вручную в ответ на приглашение boot при использовании Lilo или включив режим редактирования загрузочной записи, если в качестве загрузчика выступает GRUB. А можно и назначить какой-либо видеорежим загружаемым по умолчанию. В GRUB для этого следует дописать в строку его конфигурационного файла /boot/grub/menu.lst, определяющуюю образ ядра и устройство корневой файловой системы
kernel /bzImage root=/dev/hda?
параметр vga=значение. Например, если придать этой строке вид
kernel /bzImage root=/dev/hda? vga=5
по умолчанию будет загружаться видеорежим с плотностью знаков 80x34. В Lilo той же цели послужит строка
vga=5
добавленная в любое место Linux-секции файла /lilo.conf после строки, определяющей загрузочное устройство (детали - в документации по Lilo, я его основательно подзабыл).
В третьих, и это главное, следует выяснить, какие видеорежимы практически доступны в конкретной системе (напомню, что теоретически доступные режимы перечислены в файле /usr/src/linux/Documentation/svga.txt), и какие из них выглядят подходящими с точки зрения информативности и читабельности. Для этого нужно провести небольшое исследование с помощью передачи ядру параметра vga=ask (любым из упомянутых выше способов). В этом случае перед загрузкой ядра Linux будет выведено предложение просмотреть (нажав клавишу Enter) список доступных видеорежимов в виде вроде следующего:
0 0F00 80x25 1 0F01 80x50 ...
и так далее. Чтобы убедиться, что список этот полон, можно дать команду scan, которая проведет повторный мониторинг возможностей видеокарты (при этом может создасться впечатление, что система пошла на перезагрузку; впрочем, и мертвое зависание в этой ситуации случается) и выведет тот же (или расширенный) список повторно. Чтобы загрузиться в любом из доступных режимов, нужно ввести его номер, шестнадцатеричный (из первой колонки) или восьмеричный (из второй). А перепробовав все режимы, которые кажутся разумными, увековечить его вышеописанным способом в конфигурационном файле Lilo или GRUB.
Параметр vga может принимать и другие значения, например, normal (режим 80x25, что эквивалентно отсутствию параметра vga) или extended (в этом случае загружается какой-нибудь из режимов с большей плотностью строк, какой именно - предсказывать не берусь, скорее всего - 80x50). А при использовании Frame Buffer к списку добавится еще много режимов для графической консоли, но об этом речь впереди.
Загрузка ядра в выбранном видеорежиме через параметр vga никак не влияет на определение экранного шрифта по умолчанию, так как последний будет загружен далее по ходу старта машины при обработке одного из сценариев инициализации (например, /etc/rc.local). Изменение шрифта с "умолчального" на переопределенный можно зримо наблюдать на последней стадии загрузки, почти прямо перед появлением приглашения к авторизации (или - приглашения командной строки, если был выбран описанный ранее способ автоидентификации пользователя). И потому установка видеорежима через параметр ядра не накладывает на выбранный шрифт никаких ограничений. Так, даже использование плотности символов 132x60 ничуть не препятствует назначению умолчальным шрифта с матрицей 8x16. Впрочем, о шрифтах - в следующей заметке.
Но прежде - несколько слов о еще одном способе доступа через виртуальную консоль, осуществляемом через экранную память консоли (console screen memory), которая во FreeBSD удачно называется буфером истории (history buffer - не путать с историей команд, доступ к которой осуществляется средствами шелла). Это - расширение стандартного экранного буфера, позволяющее (по нажатию комбинации Shift+PgUp/PgDown) "пролистать" назад (и вперед - вплоть до текущего) несколько экранов и при помощи мыши вытащить на текущий экран (или другую виртуальную консоль) экранный блок из любого.
Правда, в Linux доступ к буферу экранной истории более ограничен, чем во FreeBSD. Поскольку первое же переключение на другую виртуальную консоль подменяет его содержимое, и при обратном переключении доступ к истории именно этой консоли становится невозможным (во FreeBSD каждая из виртуальных консолей имеет собственный буфер истории, и получиьть к нему доступ можно в любой момент, нажав клавишу ScrollLock, после чего клавиши типа PgUp/PgDown и управления курсором уже не перемещают курсор по текущему экрану, а служат для перемещения по экранам и строкам из буфера истории).
И еще о буфере экрана. Как и всякое историческое явление, текущее его содеражние можно сохранить для потомков. В виде, принятом в Unix - то есть в виде файла. Делается это командой setterm из пакета util-linux (запомним ее, она применяется и для других целей, о которых будет говориться в следующей заметке). Из-за своего многоцелевого назначения команда эта имеет множество опций, с которыми можно ознакомиться через man (1) setterm. Однако в сегодняшнем контексте нас интересуют следующие: dump, append и file.
Команда
$ setterm -dump
создает "слепок" буфера текущей виртуальной консоли в виде простого текстового файла с именем по умолчанию - screen.dump. В качестве ее аргумента можно использовать номер консоли, для которой требуется сделать дамп. А добавление опции --file имя_файла перенаправит этот дамп в файл с указанным именем. Опция же -append присоединит новый дамп к уже существующему файлу - "умолчальному" screen.dump или поименованному опцией -file.
Примечание для крутых программеров. К сожалению, в Linux'е нет инструмента для изготовления истинных скриншотов текстовых консолей (по крайней мере, мне такое не известно). Конечно, при использовании фреймбуфера сделать снимок графической консоли возможно (и об этом мы со временем поговорим), однако графическая консоль - это не чито текстовая.
И тут поневоле приходит на память FreeBSD, где существует утилита scr2png, именно для этой цели и предназначенная. Она принимает на ввод текстовый экранный дамп (создаваемый во Free командой vidcontrol) и преобразует его в графический файл формата PNG, используя информацию об экранном шрифте, данную в виде соответствующей опции. То есть в результате мы получаем графический снимок именно текстовой консоли, идентичный наблюдаемому, причем - очень высокого качества. Не взялся ли кто-нибудь за написание аналогичной программы для Linux'а?
А пока Linux-программеры размышляют на эту тему, мы перейдем к следующему вопросу - украшению консоли, что будет темой следующей заметки.