Специальные клавиши определены аналогичным образом. Например, функциональная клавиша Esc, O, P
, которая определяется как kf1=\EOP
.
Все несколько усложняется, если escape-последовательности требуются какие-либо параметры. Большинство терминалов могут перемещать курсор в заданные строку и столбец. Ясно, что неразумно хранить отдельную характеристику для каждой точки экрана, в которую можно переместить курсор, поэтому применяется общая строковая характеристика с параметрами, определяющими значения, которые вставляются при использовании характеристики. Например, терминал VT100 использует последовательность Esc, [,
для перемещения курсора в заданную позицию. В исходном формате terminfo это записывается довольно устрашающе: cup=\E[%i%p1%d;%p2%dH$<5>
.
Эта строка означает следующее:
\E
— послать escape-символ;
[
— послать символ [
;
%i
— дать приращение аргументам;
%p1
— поместить первый аргумент в стек;
%d
— вывести число из стека как десятичное;
;
— послать символ ;
;
%р2
— поместить второй аргумент в стек;
%d
— вывести число из стека как десятичное;
H
—послать символ H
.
Данная запись кажется сложной, но позволяет задавать параметры в строгом порядке, не зависящем от порядка, в котором терминал ожидает их появления в финальной escape-последовательности. Приращение аргументов %i
необходимо, поскольку стандартная адресация курсора задается, начиная от верхнего левого угла экрана (0, 0), а терминал VT100 обозначает начальную позицию курсора как (1, 1). Заключительные символы $<5>
означают, что для обработки терминалом перемещения курсора требуется задержка, эквивалентная времени вывода пяти символов.
Мы могли бы описывать огромное множество характеристик, но, к счастью, в основном системы UNIX и Linux приходят с большинством предопределенных терминалов. Если нужно добавить новую модель терминала, вы можете найти полный список характеристик на странице интерактивного справочного руководства, посвященной terminfo. Лучше всего начать с поиска включенного в базу данных терминала, похожего на ваш новый, и затем создания описания новой модели как вариации существующего, т. е. осуществить последовательный просмотр характеристик, одну за другой, и исправление нуждающихся в корректировке.
Применение характеристик terminfo
Теперь, когда вы знаете, как определить характеристики терминала, нужно научиться обращаться к ним. Когда используется terminfo, прежде всего вам нужно задать тип терминала, вызвав функцию setupterm
. Она инициализирует структуру TERMINAL
для текущего типа терминала. После этого вы сможете запрашивать характеристики терминала и применять его функциональные возможности. Делается это с помощью вызова setupterm
, подобного приведенному далее:
#include
int setupterm(char *term, int fd, int *errret);
Библиотечная функция setupterm
задает текущий тип терминала в соответствии с заданным параметром term
. Если term
— пустой указатель, применяется переменная окружения TERM
. Открытый дескриптор файла, предназначенный для записи на терминал, должен передаваться в параметре fd
. Результат функции хранится в целой переменной, на которую указывает errret
, если это не пустой указатель. Могут быть записаны следующие значения:
-1 — нет базы данных terminfo;
0 — нет совпадающего элемента в базе данных terminfo;
1 — успешное завершение.
Функция setupterm
возвращает константу OK
в случае успешного завершения и ERR
в случае сбоя. Если на параметр errret
установлен как пустой указатель, setupterm
выведет диагностическое сообщение и завершит программу в случае своего аварийного завершения, как в следующем примере:
#include
#include
#include
#include
int main {
setupterm("unlisted", fileno(stdout), (int *)0);
printf("Done.\n");
exit(0);
}
Результат выполнения этой программы в вашей системе может не быть точной копией приведенного далее, но его смысл будет вполне понятен. "Done.
" не выводится, поскольку функция setupterm
после своего аварийного завершения вызвала завершение программы: