Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Руководство программиста для Linux

Sven Goldt, Sven van der Meer, Skott Burkett, Matt Welsh

Перевод: Алексей Паутов,
Russian LDP: http://www.botik.ru/~rldp, ftp://ftp.botik.ru/rented/rldp

8. Символьная графика

Эта глава имеет дело с вводом/выводом символов на экран. Когда мы говорим "символ", то подразумеваем композицию пикселов, которая может меняться в зависимости от таблицы представлений символов (charset). Ваша графическая карта уже предлагает одну или более таких таблиц и по умолчанию работает в текстовом (charset) режиме, потому что текст обрабатывается быстрее, чем пиксельная графика. Терминалы можно использовать лучше, чем как простые и скучные текстовые дисплеи. Рассмотрим, как использовать специальные возможности, которые предлагает терминал Linux-а, особенно консоль Linux-а.

printf, sprintf, fprintf, scanf, sscanf, fscanf

С этими функциями libc вы можете выдавать форматированные строки в stdout (стандартный вывод), с stderr (стандартная ошибка) или другие потоки, определенные как FILE *stream (например, файлы). sscanf обеспечивает подобные возможности для чтения форматированного ввода из stdin.

termcap

База данных TERMinal CAPabilitie - это таблица элементов описания работы с терминалом в ASCII-файле /etc/termcap. Здесь вы можете найти информацию о том, как выводить специальные символы, как осуществлять операции (удаления, вставки символов или строк и т.д.) и как инициализировать терминал. База данных используется, например, редактором vi. Имеются библиотечные функции для чтения и использования возможностей терминала (смотри termcap(3x)). С этой базой данных программы могут работать с различными терминалами одним и тем же кодом. База данных termcap и библиотечные функции предоставляют только низкоуровневый доступ к терминалу. Изменение атрибутов или цветов, параметризованный вывод и оптимизация остаются программисту.

База данных terminfo

База данных TERMinal INFOrmation построена над базой данных termcap и описывает некоторые возможности терминалов на более высоком уровне. С terminfo программа может легко менять атрибуты экрана, используя специальные клавиши, такие как функциональные клавиши и др. Эта база данных может быть найдена в /usr/lib/terminfo/[A-z,0-9]*. Каждый файл описывает один терминал.

curses

Terminfo - хорошая база для работы с терминалом в программе.

Библиотека (BSD-)curses дает вам высокоуровневый доступ к терминалу, базируясь на terminfo. curses позволяет открывать и манипулировать окнами на экране, предоставляет весь необходимый набор функций ввода/вывода и может изменять видеоатрибуты терминально-независимым образом на более чем 150 терминалах. Библиотека находится в /usr/lib/libcurses.a. Это BSD-версия curses.

ncurses

ncurses - это развитие curses. В версии 1.8.6 она должна быть совместима с AT&T curses, как это определено в SYSVR4, и иметь несколько расширений, таких как манипулирование цветами, специальная оптимизация для вывода, оптимизации, зависящие от терминала, и др. ncurses была протестирована на множестве систем, таких как Sun-OS, HP и Linux. Автор рекомендует предпочесть ncurses всему остальному. В SYSV Unix системах (например, Solaris) должна существовать библиотека curses с теми же функциональными возможностями, что и ncurses (на самом деле солярисовская curses имеет немного больше функций и поддержку мыши).

В следующих разделах мы рассмотрим, как пользоваться различными пакетами доступа к терминалу. В Linux-е мы имеем GNU-версию termcap и можем пользоваться ncurses вместо curses.

8.1. Функции ввода/вывода в libc

8.1.1. Форматированный вывод

Функции printf(...) в libc обеспечивают форматированный вывод и позволяют трансформировать аргументы. * int fprintf(FILE *stream, const char *format, ...), преобразует выводимые аргументы в соответствии с шаблоном и записывает его в stream. Формат определяется аргументом format. Функция возвращает число записанных символов или отрицательное число в случае ошибки.

format содержит два типа объектов: обычные символы и информацию, как трансформировать или форматировать аргументы.

Форматная информация должна начинаться с %, за которым следуют значения для формата, дальше идет символ для трансляции (чтобы напечатать знак %, используйте %%). Возможны следующие значения для формата:

  - Флаги
     * -
     Форматированный аргумент будет при печати прижат влево на своем
поле.
     * +
     Каждое число будет напечатано со знаком, например, +12 или -2.32.
  - Пробел
     Если первый символ - не знак, то будет вставлен пробел.
  - 0
     Для чисел ширина поля будет заполнена слева нулями.
  - #

Изменяет вывод в зависимости от трансформации для аргумента:

  • Для o первое число будет 0.
  • Для x или X будет напечатано в конце 0x или 0X соответственно.
  • Для e, E, f, F вывод имеет десятичную точку.
  • Для g или G в конце аргумента будут напечатаны нули.

- Число, указывающее минимальную ширину поля

Трансформированный аргумент печатается в поле, ширина которого не меньше, чем сам аргумент. С этим числом вы можете увеличить ширину поля. Если аргумент меньше, то оставшаяся часть поля заполняется пробелами или нулями. - Точка для отделения ширины поля и точности

- Число для точности

Возможные значения для трансформации смотри в таблице 8.1.

   * int printf(const char *format, ...)
     То же самое, что fprintf(stdout, ...).
   * int sprintf(char *s, const char *format, ...)
     То же, что и printf(...), но вывод будет записан в символьный
указатель s (с последующим \0). (Вы должны захватить достаточно памяти
для s.)
   * vprintf(const char *format, va_list arg)
vfprintf(FILE *stream, const char *format, va_list arg)
vsprintf(char *s, const char *format, va_list arg)

То же, что и для вышеописанных функций, только список аргументов находится в arg.

8.1.2. Форматированный ввод

Точно так же, как printf(...) для форматированного вывода, вы можете использовать scanf(...) для форматированного ввода.

   * int fscanf(FILE *stream, const char *format, ...)

fscanf(...) читает из stream и преобразует ввод по правилам, определяемым в format. Результаты помещаются в аргументы, заданные в "..." (эти аргументы должны быть указателями!). Чтение заканчивается, когда в format исчерпаны правила форматирования.

Таблица 8.1: Libc - трансформации printf

   Символ  |         Форматируется в
   --------|-----------------------------------
     d,i   |  int signed, десятиричный
      o    |  int unsigned, восьмеричный, без предваряющего 0
     x,X   |  int unsigned, шестнадцатиричный, без предваряющего 0x
      u    |  int unsigned, десятиричный
      c    |  int (unsigned) одиночный символ
      s    |  char * до \0
      f    |  double как [-]mmm.ddd
     e,E   |  double как [-]m.dddddde+xx, [-]m.dddddde-xx
     g,G   |  double использует %e или %f когда нужно
      p    |  void *
      n    |  int *
      %    |  %

fscanf вернет EOF, при первом достижении конца файла или при возникшей ошибке. Если этого не случится, будет возвращено количество трансформированных аргументов.

format может содержать правила форматирования аргументов (см. табл. 8.2)

Он может также включать:

  • пропуски или табуляции, которые игнорируются;
  • любой нормальный символ, кроме %. Символы должны быть во вводе на соответствующих позициях.
  • правила преобразования, заданные с %, необязательный символ * (позволит fscanf(...) присвоить аргументу), необязательное число, необязательный символ h, l или L (для задания длины считываемой инфомации) и символ трансформации.

* int scanf(const char *format, ...)

То же, что fscanf(stdin,...)

* int sscanf(char *str, const char *format, ...)

То же, что scanf, но ввод производится из строки str.

8.2. Библиотека termcap

8.2.1. Введение

Библиотека termcap - это API для базы данных termcap, которая находится в /etc/termcap/. Библиотечные функции позволяют:

* получить описание текущего терминала: tgetent(...);

Таблица 8.2: libc - трансформации sсanf

  Символ | Вход - тип аргумента
  -------|---------------------------------------------------------------
    d    | десятичный integer - int*
    i    | integer - int* (вход может быть восьме- или шестнадцатиричным)
    o    | восьмеричный integer - int* (с или без предваряющего 0)
    u    | десятичный unsigned - unsigned int*
    x    | шестнадцатиричный integer - int* (с или без предваряющего 0x)
    c    | одна или более литер - char* (без завершающего /0)
  e,f,gf | float - float* (такой как [-]m.dddddde+xx, [-]m.dddddde-xx)
    p    | указатель - void*
    n    | число трансформированных аргументов - int*
  [...]  | непустое множество литер на входе - char*
  [^...] | исключая такие литеры - char*
    %    | %
  -----------------------------------------------------------------------

  перед d,i,n,o,u,x может стоять h, если указатель - short
  то же для l, если указатель - long
  l также может быть перед e,f,g, если указатель - double
  L может стоять перед e,f,g, если указатель - long double

* найти описание для информации: tgetnum(...), tgetflag(...), tgetstr(...);

* вычислить и произвести поточечный вывод: tputs()

Программы, использующие библиотеку termcap должны включать termcap.h и собираться с:

   gcc [flags] files -ltermcap

Функции termcap терминально-независимые программы, но дают программисту только низкоуровневый доступ к терминалу. Для пакета более высокого уровня потребуется curses или ncurses.

8.2.2. Поиск описания терминала

* int tgetent(void *buffer, const char *termtype)

В операционной системе Linux текущее имя терминала содержится в переменой среды TERM. Поэтому termtype есть результат вызова getenv(3). Что касается buffer, то в GNU-версии Linux termcap не нужно захватывать память. В других версиях вам придется выделить 2048 байт (прежде buffer требовал 1024 байта, но сейчас размер удвоился).

tgetent(...) возвращает 1 в случае успеха и 0 когда база данных найдена, но не имеет точки входа для TERM. Другие ошибки возвращают различные значения.

Следующий пример объясняет как использовать getent(...):

#define buffer 0
char *termtype=getenv("TERM");
int ok;
ok=tgetent(buffer,termtype);
if(ok==1)
   /* все нормально, мы имеем вход */
else if(ok==0)
   /* ой, что-то не так с TERM
    * проверим сначала termtype, затем базу данных termcap
    */
else
   /* у-у-у, глобальная ошибка */

По умолчанию termcap использует /etc/termcap/ как базу данных. Если переменная среды TERMCAP установлена, например, в $HOME/mytermcap, то все функции будут пользоваться mytermcap вместо /etc/termcap. Без начального слэша в TERMCAP определенное значение понимается как имя для терминала.

8.2.3. Описание терминала

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

  • Числовой: например, co - число столбцов
  • Логический или флаговый: например, hc - терминал твердой копии (hardcopy terminal)
  • Строковый: например, st - установка табуляции (подробнее см. 8.22.3)

Каждое свойство связано с единственным типом значений (co всегда числовой, hc всегда флаг, а st всегда строка). Три типа значений - и три типа функций, их запрашивающих. char *name - это двухлитерный код свойства.

* int tgetnum(char *name)

Получение свойства с числовым значением, таким как co. Функция tgetnum(...) возвращает числовое значение, если свойство доступно, 1 в противном случае. (Заметьте, что возвращаемое значение всегда неотрицательно.)

* int tgetflag(char *name)

Получение логического свойства. Возвращает 1, если флаг установлен, 0 в противном случае.

* char *tgetstr(char *name, char **area)

Получение строкового свойства. Возвращает указатель на строку или NULL в случае отсутствия. В GNU-версии, если area есть NULL, termcap выделит память сам. termcap больше не позаботится об этом указателе, если вы не освободите name перед выходом из программы. Такой метод предпочтителен, поскольку вы не знаете сколько памяти потребуется для указателя, поэтому позвольте termcap сделать все за вас.

char *clstr, *cmstr;
int lines, cols;
void term_caps()
{
char *tmp;
 clstr=tgetstr("cl",0); /* очистка экрана */
 cmstr=tgetstr("cm",0); /* перемещение y,x */
 lines=tgetnum("li"); /* полосы терминала */
 cols=tgetnum("co"); /* колонки терминала */
 tmp=tgetstr("pc",0); /* символ дозаполнения */
 PC=tmp ? *tmp : 0;
 BC=tgetstr("le",0); /* сдвиг курсора на символ влево */
 UP=tgetstr("up",0); /* сдвиг курсора на линию вверх */
}

8.2.4. Свойства termcap

Логические свойства
5iпринтер не имеет эха на экране
amавтоматические границы, что означает автоматическое форматирование строки
bsCrtl-H представляет backspace
bwbackspace на левой границе переносит строку на правую границу предыдущей
daвывести сохраненное над текущим экраном
dbвывести сохраненное под текущим экраном
eoпробел стирает литеру на позиции курсора
esesc-последовательности и специальные символы работают в строке состояния
gnродовое устройство
hcэто терминал твердой копии (hardcopy terminal)
HCкурсор плохо видно, когда он не на последней линии
hsприсутствует линия статуса
hzтерминал не может напечатать тильды (tilde characters)
inтерминал вставляет нули вместо пробелов на пустые места
kmтерминал имеет мета клавишу
miрежим вставки для курсора
msрежим стандартного вывода / подчеркивания для курсора
NPнет символов-заполнителей
NRti не обращает teos терминал может забивать ошибки
ulтерминал подчеркивает, но ошибки забивать не может
xbсбой, вызванный столпотворением, F1 посылает ESCAPE, F2 посылает ^C
xnсбой новой линии / соединения строк
xoтерминал использует xon/xoff протокол
xsтекст, напечатанный поверх выделенного, будет выделен
xtсбой телевизионного луча, неверная табуляция и странный режим выделения

Числовые свойства
coчисло столбцов
dBприостановка на милисекунды для возврата на терминалах твердой копии
dCприостановка на милисекунды для перевода каретки на терминалах твердой копии
dFприостановка на милисекунды для заполнения страницы на терминалах твердой копии
dNприостановка на милисекунды для новой линии на терминалах твердой копии
dTприостановка на милисекунды для табуляции на терминалах твердой копии
dVприостановка на милисекунды для вертикальной табуляции на терминалах твердой копии
itраница между позициями табуляции
lhвысота мягких меток
lmлинии памяти
lwширина
liчисло линий
Nlчисло мягких меток
pbнаименьшая граница, когда требуется дозаполнение
sgсбой режима выделения
ugсбой режима подчеркивания
vtномер виртуального терминала
wsширина линии статуса, если она отлична от ширины экрана

Строковые свойства
!1клавиша сохранения в верхнем регистре
!2клавиша подвешивания в верхнем регистре
!3клавиша undo в верхнем регистре
#1клавиша помощи в верхнем регистре
#2клавиша home в верхнем регистре
#3клавиша ввода в верхнем регистре
#4клавиша курсор - влево в верхнем регистре
%0клавиша redo
%1клавиша помощи
%2клавиша пометки
%3клавиша сообщения
%4клавиша перемещения
%5клавиша следующего объекта
%6клавиша открытия
%7клавиша опций
%8клавиша предыдущего объекта
%9клавиша печати
%aклавиша сообщения в верхнем регистре
%bклавиша перемещения в верхнем регистре
%cклавиша следующего объекта в верхнем регистре
%dклавиша опций в верхнем регистре
%eклавиша предыдущего объекта в верхнем регистре
%fклавиша печати в верхнем регистре
%gклавиша redo в верхнем регистре
%hклавиша перестановки в верхнем регистре
%iклавиша курсор-вправо в верхнем регистре
%jклавиша продолжения в верхнем регистре
&0клавиша cancel в верхнем регистре
&1клавиша ссылки
&2клавиша обновления
&3клавиша перестановки
&4клавиша перезапуска
&5клавиша продолжения
&6клавиша сохранения
&7клавиша подвешивания
&8клавиша undo
&9клавиша начала в верхнем регистре
*0клавиша поиска в верхнем регистре
*1клавиша команды в верхнем регистре
*2клавиша копирования в верхнем регистре
*3клавиша создания в верхнем регистре
*4клавиша удаления символа в верхнем регистре
*5клавиша удаления строки в верхнем регистре
*6клавиша выделения
*7клавиша конца в верхнем регистре
*8клавиша очистки линии в верхнем регистре
*9клавиша выхода в верхнем регистре
0клавиша поиска1 клавиша начала
2клавиша cancel
3клавиша закрытия
4клавиша команды
5клавиша копирования
6клавиша создания
7клавиша конца
8клавиша ввода/посылки
9клавиша выхода
alклавиша вставки одной линии
ALклавиша вставки %1 линий
acцвет блока символов, отображаемых в другой таблице символов
aeконец множества символов из альтернативной таблицы
asначало блока символов в альтернативной таблице
bcbackspace, если не ^H
blсимвол звонка
btпереход к предыдущему месту табуляции
cbочистка от начала линии до курсора
ccстранный командный символ
cdочистка до конца экрана
ceочистка до конца линии
chперемещение курсора горизонтально до столбца %1
clочистка экрана, курсор помещается в начало
cmкурсор перемещается на полосу %1 и колонку %2 (на экране)
CMкурсор перемещается на линию %1 и колонку %2 (в памяти)
crвозврат каретки
csобласть прокрутки от линии %1 до линии %2
ctочистка табуляций
cvвертикальное движение курсора до линии %1
dcудаление 1 символа
DCудаление %1 символов
dlудаление 1 линии
DLудаление %1 линий
dmначало режима удаления
doкурсор на 1 линию вниз
DOкурсор на %1 линию вниз
dsубрать линию статуса
eAактивирование альтернативной символьной таблицы
ecудаление %1 символов начиная с позиции курсора
edконец режима удаления
eiконец режима вставки
ffсимвол дозаполнения экрана на терминалах твердой копии
fsвозврат символа на его позицию перед переходом на линию статуса
F1строка послана функциональной клавишей F11
... ...
F9строка послана функциональной клавишей F19
FAстрока послана функциональной клавишей F20
... ...
FZстрока послана функциональной клавишей F45
Faстрока послана функциональной клавишей F46
... ...
Frстрока послана функциональной клавишей F63
hdперемещение курсора на пол-линии вниз
hoкурсор в начало
huперемещение курсора на пол-линии вверх
i1инициализация строки 1 в начале сеанса
i3инициализация строки 3 в начале сеанса
isинициализация строки 2 в начале сеанса
icвставка 1 символа
ICвставка %1 символов
ifфайл инициализации
imначало режима вставки
ipвставка времени и необходимых специальных символов после вставки
iPпрограмма инициализации
K1верхняя левая клавиша на keypad
K2центральная клавиша на keypad
K3верхняя правая клавиша на keypad
K4нижняя левая клавиша на keypad
K5нижняя правая клавиша на keypad
k0функциональная клавиша 0
... ...
k9функциональная клавиша 9
k;функциональная клавиша 10
kaклавиша очистки всех табуляций
kAклавиша вставки линии
kbклавиша backspace
kBклавиша возврата к предыдущему месту табуляции
kCклавиша очистки экрана
kdклавиша down
kDклавиша удаления символа под курсором
keотключение keypad
kEклавиша очистки до конца линии
khклавиша курсор - home
kHклавиша курсор home + down
kIвставка символа / клавиша режима вставки
klклавиша курсор - left
kLклавиша удаления линии
kMMклавиша выхода из режима вставки
kNклавиша следующей страницы
kPклавиша предыдущей страницы
krклавиша курсор - right
kRклавиша прокрутки назад/вверх
ksвключение keypad
kSклавиша очистки до конца экрана
ktклавиша очистки данной табуляции
kTклавиша установки табуляции на этом месте
kuклавиша курсор - up
l0метка для нулевой функциональной клавиши, если не f0
l1метка для первой функциональной клавиши, если не f1
l2метка для второй функциональной клавиши, если не f2
...
laметка для десятой функциональной клавиши, если не f10
leкурсор влево на 1 символ
llперемещение курсора в нижний левый угол
LEкурсор влево на %1 символов
LFотключение мягких меток
LOвключение мягких меток
mbначало мерцания
MCочистка мягких границ
mdначало режима верхнего регистра
meконец всех режимов типа so, us, mb, md, mr
mhначало полуяркого режима
mkначало темного режима (символы не видны)
MLустановка левой мягкой границы
mmвход терминала в метарежим
moвыход терминала из метарежима
mpвключение защищенного атрибута
mrначало режима обращения (reverse mode)
MRустановка правой мягкой границы
ndкурсор на 1 символ влево
nwкоманда возврата каретки
pcсимвол-заполнитель
pfотключение принтера
pkпрограммная клавиша %1 для посылки строки %2, если нажата пользователем
plпрограммная клавиша %1 для исполнения строки %2 в локальном режиме
pnпрограммная мягкая метка %1 для отображения строки %2
poподключение принтера
pOподключение принтера для %1 (<256) байт
psпечать содержимого экрана на принтере
pxпрограммная клавиша %1 для посылки строки %2 в компьютер
r1сброс строки 1, установка нормальных режимов
r2сброс строки 2, установка нормальных режимов
r3сброс строки 3, установка нормальных режимов
RAотключение автоматических границ
rcвосстановление сохраненной позиции курсора
rfсброс строки имени файла
RFтребование ввода с терминала
RIкурсор вправо на %1 символов
rpповторение символа %1 %2 раз
rPзаполнение после присланного символа в режиме замены
rsсброс строки
RXвыключение XON/XOFF управления
saустановка атрибутов %1 %2 %3 %4 %5 %6 %7 %8 %9
SAвключение автоматических границ
scсохранение позиции курсора
seконец режима стандартного вывода
sfнормальная прокрутка на одну линию
SFнормальная прокрутка на %1 линию
soначало режима стандартного вывода
srобратная прокрутка
SRпрокрутка назад на %1 линию
stустановка табуляции во всех линиях в данной колонке
SXвключение XON/XOFF управления
taперемещение к следующей табуляции физического устройства
tcчтение в описании терминала с другой точки входа
teконец программы, использующей движение курсора
tiначало программы, использующей движение курсора
tsперемещение курсора на столбец %1 линии статуса
ucподчеркивание символа под курсором и движение курсора вправо
ueконец подчеркивания
upкурсор на 1 линию вверх
UPкурсор на %1 линию вверх
usначало подчеркивания
vbвидимый звонок
veнормальный видимый курсор
viневидимый курсор
vsкурсор стандартного вывода
wiустановка окна с линии %1 до линии %2 и столбцов с %3 до %4
XFсимвол XOFF, если не ^S

8.3. Введение в ncurses

В этом разделе будем пользоваться следующей терминологией.

  • окно (window) - внутреннее представление, содержащее изображение части экрана. WINDOW определен в ncurses.h.
  • экран (screen) - это окно размером в целый экран (с верхнего левого до нижнего правого угла). Экранами являются stdscr и curscr.
  • терминал (terminal) - специальный экран с информацией о том, как выглядит экран на данный момент.
  • переменные - следующие переменные и константы, определенные в ncurses.h:
    • WINDOW *curscr - текущий экран
    • WINDOW *stdscr - стандартный экран
    • int LINES - полосы на терминале
    • int COLS - колонки на терминале
    • bool TRUE - флаг истины, 1
    • bool FALSE - флаг лжи, 0
    • int ERR - флаг ошибки, -1
    • int OK - флаг ok, 0
  • функции - в описаниях функций аргументы будут следующих типов:
    • win - WINDOW*
    • bf - bool
    • ch - chtype
    • str - char*
    • chstr - chtype*
    • fmt - char*
    • иначе int

Обычно программа, использующая ncurses, выглядит так:

#include
...
main()
{
   ...
   initscr();
   /* вызов функции ncurses */
   endwin();
   ...
}

Подключение ncurses.h определит переменные и типы для ncurses, такие как WINDOW, и прототипы функций. Автоматически подключатся stdio.h, stdarg.h, termios.h, unctrl.h.

initscr() используется для инициализации структур данных ncurses и для чтения файла terminfo. Будет захвачена память под stdscr и curscr. Если произойдет ошибка, то initscr вернет ERR. В противном случае возвращается указатель на stdscr. Кроме этого, экран будет очищен и будут проинициализированы LINES и COLS.

endwin() очистит все выделенные ресурсы ncurses и восстановит режимы tty, какими они были до вызова initscr(). Функция endwin() должна вызываться перед любой другой функцией из библиотеки ncurses и перед выходом из вашей программы. Если вы хотите использовать для вывода более чем один терминал, используйте newterm(...) вместо initscr().

Компилируйте программу посредством:

gcc [flags] files -lncurses

Вы можете устанавливать любые флаги (см. gcc(1)). Если путь к ncurses.h изменился, вы должны включить следующую строку, иначе ncurses.h, nterm.h, termcap.h и unctrl.h не будут найдены:

-I/usr/include/ncurses

Другие возможные в Linux-е флаги: -O2 -ansi -Wall -m486. O2 скажет gcc произвести некоторую оптимизацию; -ansi - для ANSI си-кода; -Wall выведет все предупреждения; -m486 оптимизирует код для Intel 486 (можно и для Intel 386).

Библиотека ncurses находится в /usr/lib/. Существует 3 версии библиотеки:

  1. libncurses.a - обычная ncurses
  2. libdcurses.a - ncurses для отладки
  3. libpcurses.a - ncurses для профилирования (существует ли что-нибудь после 1.8.6libcurses.a?)
  4. libcurses.a - не четвертая версия, это первоначальная BSD curses

Структуры данных для экрана называются windows и определены в ncurses.h. Окно - это нечто типа литерного массива в памяти, которым программист может манипулировать без вывода на терминал. При помощи newwin(...) вы можете создать другие окна.

Чтобы оптимально обновить физический терминал, ncurses имеет другое окно, curscr. Это изображение, реально выводимое на экран. Для отображения stdscr на экране используется функция refresh(). После этого ncurses обновит curscr и физический терминал содержимым stdscr. Библиотечные функции произведут внутреннюю оптимизацию для процесса обновления, поэтому вы можете менять различные окна и затем обновлять экран сразу самым оптимальным способом.

Функциями ncurses вы можете работать со структурой данных window. Функции, начинающиеся с w, позволяют назначать окно window, тогда как остальные обычно имеют дело с stdscr. Функции, начинающиеся с mv, прежде всего переместят курсор на позицию y,x.

Символы имеют тип chtype, который является long unsigned int, чтобы сохранять дополнительную информацию о себе (атрибуты и т.д.).

Библиотека ncurses использует базу данных terminfo. Обычно она находится в usr/lib/terminfo/, и ncurses обращается туда за локальными определениями терминала. Если вы хотите проверить некоторые другие определения для терминала, не исправляя первоначальную terminfo, установите соответственно переменную среды TERMINFO. Эта переменная будет протестирована ncurses, и вместо usr/lib/terminfo/ сохранятся ваши определения.

Tекущей версией ncurses является 1.8.6.

В конце этого раздела вы найдете обзорную таблицу для BSD-Curses, ncurses и Sun-OS 5.4 curses.

8.4. Инициализация

* WINDOW *initscr()

Обычно это первая функция, вызываемая из программы, использующей ncurses. В некоторых случаях полезно вызывать slk_init(int), filter(), ripoffline(...) или use_env(bf) перед initscr(). Для работы с несколькими терминалами (или тестирования возможностей системы) вы можете использовать newterm(...) вместо initscr(). initscr() прочитает terminfo файл и установит структуры данных ncurses, выделит память для curscr и stdscr и проинициализирует переменные LINES и COLS значениями, соответствующими вашему терминалу. Будет возвращен указатель на stdscr или ERR в случае ошибки. Вам НЕ нужно инициализировать указатель. stdscr=initscr(); поскольку initscr() сделает это за вас. Если возвращен ERR, ваша программа должна завершиться, поскольку ни одна функция ncurses не будет работать:

if(!(initscr())){
   fprintf(stderr,"type: initscr() failed\n\n");
   exit (1);
}

* SCREEN *newterm(char *type, FILE *outfd, FILE *infd)

Работая в ncurses с несколькими терминалами, вы должны вызвать для каждого из них newterm(...) вместо initscr(). type - это имя терминала как оно содержится в $TERM (ansi, xterm, vt100, например); outfd - это указатель для вывода, infd - указатель для ввода. Для каждого терминала, открытого newterm(...), следует вызывать endwin().

* SCREEN *set_term(SCREEN *new)

При помощи set_term(SCREEN) вы можете переключать текущий терминал. Все функции будут работать с текущим терминалом, установленным set_term(SCREEN).

* int endwin()

endwin() произведет очистку, восстановит режимы терминала, сохраненные перед вызовом initscr(), и поставит курсор в левый верхний угол экрана. Не забудьте закрыть все окна перед тем, как вызвать endwin(), перед выходом из вашей программы. Дополнительный вызов refresh() после endwin() восстановит содержимое терминала, отображавшееся до вызова initscr() (visual-mode), в противном случае экран будет очищен (non-visual-mode).

* int isendwin()

Возвращает TRUE, если после endwin() была вызвана refresh(), иначе - FALSE.

* void delscreen(SCREEN *sp)

Вызывается после endwin() для высвобождения всех занятых ресурсов, когда SCREEN больше не нужен. (Пока не реализована.)

8.5. Окна

Окна могут быть созданы, уничтожены, перемещены, скопированы, задублированы и т.д.

* WINDOW *newwin(nlines, ncols, begy, begx)

begy и begx - координаты верхнего левого угла окна. nlines - это число линий (integer); ncols - число колонок (integer).

WINDOW *mywin;
mywin=newwin(10,60,10,10);

Верхний левый угол нашего окна находится на линии 10 в колонке 10; окно имеет 10 линий и 60 колонок. Если nlines равна нулю, окно будет иметь (LINES - begy) полос. Точно так же, если ncols равна нулю, то окно будет иметь (COLS - begx) колонок. Когда мы вызываем newwin(...) с нулевыми аргументами:

WINDOW *mywin;
mywin=newwin(0,0,0,0);

открытое окно получает размеры экрана.

При помощи LINES и COLS мы можем открыть окно на середине экрана, какую бы размерность оно ни имело:

      0      begx
       |       |
0      |       |                            COLS
- - - - -------|-------------------------|------->
       |       |     ncols               |
 begy  |       |<. . . . . . . . . . . .>|
- - - -|- - - -|-------------------------|
       |      ^|                         |
       |      .|                         |
       |      .|                         |
       |nlines.| newwin(nlines, ncols,   |
       |      .|        begy, begx)      |
       |      v|                         |
       |- - - -|-------------------------|
 LINES |
       v
#define MYLINE (int) ((LINES-22)/2)
#define MYCOL ((COLS-70)/2)
#define MYLINES 22
#define MYCOLS 70
...
WINDOW *win;
...
if(!(initscr())){
   fprintf(stderr, "type: iniscr() failed\n\n");
   exit(1);
}
...
if ((LINES<22)||(COLS<70)){
   fprintf(stderr, "screen too small\n\n");
   endwin(); exit (1);
}
win=newwin(MYLINES,MYCOLS,MYLINE,MYCOL);
...

Откроется окно с 22 линиями и 70 колонками в середине экрана. Проверьте размер экрана перед тем, как открывать окно. Консоль Linux-а имеет не менее 25 линий и 80 колонок, но на x-терминалах это может не выполняться (их размеры изменяемы).

С другой стороны, используйте LINES и COLS, чтобы поместить два окна в один экран:

#define MYROWS   (int) (LINES/2+LINES/4)
#define MYCOLS   (int) (COLS/2+COLS/4)
#define LEFTROW  (int) ((LINES-MYROWS)/2)
#define LEFTCOL  (int) (((COLS-2)-MYCOLS)/2)
#define RIGHTROW (int) (LEFTROW)
#define RIGHTCOL (int) (LEFTROW+2+MYCOLS)
#define WCOLS    (int) (MYCOLS/2)
...
WINDOW *leftwin, *rightwin;
...
leftwin=newwin(MYROWS, WCOLS, LEFTROW, LEFTCOL);
rightwin=newwin(MYROWS, WCOLS, RIGHTROW, RIGHTCOL);
...

Подробнее смотрите screen.c в директории с примерами.

*int delwin(win)

Удаляет окно win. Подокна win удаляются перед win. Будут освобождены все ресурсы, занятые win. Удаляйте все открытые вами окна перед вызовом endwin().

*int mvwin(win, by, bx)

Перемещает окно на координаты by,bx. Если это означает выход за пределы экрана, то ничего не произойдет и будет возвращен ERR.

* WINDOW *subwin(origwin, nlines, ncols, begy, begx)

Возвращает подокно в середине origwin-а. Когда вы изменяете одно из двух окон (origwin или новое), это изменение отразится на обоих окнах. Вызывайте touchwin(origwin) перед следующим refresh(). begx и begy относятся не к origwin, а к экрану.

* WINDOW *derwin(origwin, nlines, ncols, begy, begx)

То же, что subwin(), begx и begy относятся не к экрану, а к origwin.

* int mvderwin(win, y, x)

Перенесет win за пределы родительского окна. (Пока не реализована.)

* WINDOW *dupwin(win)

Дублирует окно win.

* int syncok(win, bf)
void wsyncup(win)
void wcursyncup(win)
void wsyncdown(win)

(Пока не реализованы.)

* int overlay(win1, win2)

int overwrite(win1, win2)

overlay(...) скопирует весь текст из win1 в win2, игнорируя пропуски. overwrite(...) делает то же самое, но копирует вместе с пропусками.

* int copywin(win1, win2, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, overlay)

То же, что overlay(...) и overwrite(...), но позволяет контролировать область окна для копирования.

8.6. Вывод

   * int addch(ch)
     int waddch(win, ch)
     int mvaddch(y, x, ch)
     int mvwaddch(win, y, x, ch)

Эти функции выводят символ в окно. Они работают с окном; вам нужно вызвать refresh(), чтобы поместить окно на экран. Функции addch(...) и waddch(...) помещают символ ch в окно stdscr или win. mvaddch(...) и mvwaddch(...) предварительно ставят курсор на позицию y,x.

   * int addstr(str)
     int addnstr(str, n)
     int waddstr(win, str)
     int waddnstr(win, str, n)
     int mvaddstr(y, x, str)
     int mvaddnstr(y, x, str, n)
     int mvwaddstr(win, y, x, str)
     int mvwaddnstr(win, y, x, str, n)

Эти функции заносят строку в окно и эквивалентны сериям вызовов addch(...). str - это строка, заканчивающаяся символом с кодом 0 ("кукареку\0"). Функции, начинающиеся с w, заносят str в окно win, остальные - в stdscr. Функции с n пишут n символов строки str. Если n равен -1, будет записана вся строка.

   * int addchstr(chstr)
     int addchnstr(chstr, n)
     int waddchstr(win, chstr)
     int waddchnstr(win, chstr, n)
     int mvaddchstr(y, x, chstr)
     int mvaddchnstr(y, x, chstr, n)
     int mvwaddchstr(win, y, x, chstr)
     int mvwaddchnstr(win, y, x, chstr, n)

Эти функции копируют chstr в окно stdscr или win. Начальной позицией является позиция курсора. Функции с n пишут n символов строки chstr. Если n равен -1, будет записана вся строка. Курсор не двигается и символы не контролируются. Эти функции быстрее, чем addstr(...). chstr является указателем на массив элементов chtype.

   * int echochar(ch)
     int wechochar(win, ch)

То же, что addch(...), waddch(win), с последующим refresh(), wrefresh(win).

8.6.1. Форматированный вывод

   * int printw(fmt, ...)
     int wprintw(win, fmt, ...)
     int mvprintw(y, x, fmt, ...)
     int mvwprintw(win, y, x, fmt, ...)
     int vwprintw(win, fmt, va_list)

Эти функции соответствуют printf(...) и подобным ей функциям libc. В libc printf(...) используется для форматированного вывода. Вы можете определять выводимую строку и включать в нее переменные различных типов. Подробнее смотрите раздел 8.1.1. vwprintw(...) требует подключения varargs.h.

8.6.2. Вставка символов и линий

   * int insch(c)
     int winsch(win, c)
     int mvinsch(y, x, c)
     int mvwinsch(win, y, x, c)

Символ ch вставляется слева от курсора, и все символы сдвигаются на одну позицию вправо. Самый правый символ строки может быть потерян.

   * int insertln()
     int winsertln(win)

Вставляет чистую строку над текущей. Нижняя строка будет потеряна.

   * int insdelln(n)
     int winsdelln(win, n)

Для положительного n эти функции вставляют n линий в соответствующем окне (n нижних линий будут потеряны). Для отрицательных n будут удалены n линий под курсором, оставшиеся сдвинутся вверх.

   * int insstr(str)
     int insnstr(str, n)
     int winsstr(win, str)
     int winsnstr(win, str, n)
     int mvinsstr(y, x, str)
     int mvinsnstr(y, x, str, n)
     int mvwinsstr(win, y, x, str)
     int mvwinsnstr(win, y, x, str, n)

Эти функции занесут str в текущую строку слева от курсора (сколько возможно до конца строки). Символы справа от курсора сдвигаются вправо и удаляются достигнув конца строки. Курсор остается на месте. y и x - координаты, на которые переместится курсор перед вставкой str; n - это число вставляемых символов (n=0 вводит чистую строку).

8.6.3. Удаление символов и линий

   * int delch()
     int wdelch(win)
     int mvdelch(y, x)
     int mvwdelch(win, y, x)

Удаление символа под курсором и сдвиг оставшейся справа от курсора строки на одну позицию влево.

y и x - координаты, на которые курсор переместится перед удалением.

   * int deleteln()
     int wdeleteln(win)

Удаление строки под курсором и перемещение нижележащих линий на одну позицию вверх. Последняя линия окна будет очищена.

8.6.4. Боксы и линии

   * int border(ls, rs, ts, bs, tl, tr, bl, br)
     int wborder(win, ls, rs, ts, bs, tl, tr, bl, br)
     int box(win, vert, hor)

Очерчивают соответствующее окно (stdscr или win). В таблице 8.3 вы увидите символы и их значения по умолчанию для box(...). На картинке вы увидите позиции символов для бокса.

   * int vline(ch, n)
     int wvline(win, ch, n)
     int hline(ch, n)
     int whline(win, ch, n)

Эти функции вычерчивают вертикальную или горизонтальную прямую начиная с позиции курсора. ch - это используемый символ, n - число таких символов. Позиция курсора не изменяется.

8.6.5. Фоновый (background) символ

   * void bkgdset(ch)
     void wbkgdset(win, ch)

Устанавливает фоновый символ и атрибут для экрана или окна. Атрибут в ch будет OR-нут с каждым непробельным символом окна. Фон становится частью окна и не изменяется при прокрутке и вводе/выводе.

Таблица 8.3: ncurses - ограничительные символы

Литера |      Позиция         | По умолчанию
-------|----------------------|----------------------
  tl   | левая верхняя        | ACS_ULCORNER
  ts   | верхняя сторона      | ACS_HLINE
  tr   | правая верхняя       | ACS_URCORNER
  ls   | левая сторона        | ACS_VLINE
  rs   | правая сторона       | ACS_VLINE
  bl   | левая нижняя         | ACS_LLCORNER
  bs   | нижняя сторона       | ACS_HLINE
  br   | правая нижняя        | ACS_LRCORNER
  rt   | правая средняя       | ACS_RTEE
  lt   | левая средняя        | ACS_LTEE
  tt   | верхняя средняя      | ACS_TTEE
  bt   | нижняя средняя       | ACS_BTEE
              Рисунок 8.2: ncurses - символы бокса
         tl      ts    tt     ts      tr
           |------------|------------|
           |                         |
         ls|            |            |rs
           |                         |
           |            |            |
         lt|- - - - - - - - - - - - -|rt
           |            |            |
           |                         |
         ls|            |            |rs
           |                         |
           |------------|------------|
         bl      bs    bt     bs      br
   * int bkgd(ch)
     int wbkgd(win, ch)

Установит в ch фоновый символ и атрибут.

8.7. Ввод

   * int getch()
     int wgetch(win)
     int mvgetch(y, x)
     int mvwgetch(win, y, x)
     getch()

прочитает ввод с терминала. Если режим паузы установлен, getch() будет ждать нажатия клавиши. Если нет - вернет клавишу из буфера ввода или ERR, если буфер пуст. mvgetch(...) и mvwgetch(...) сначала установят курсор на позицию y,x. w-функции читают ввод с терминала, связанного с окном win, getch() и mvgetch(...) - с stdscr.

Со включенной keypad(...) при нажатии функциональной клавиши getch() вернет код, определенный в ncurses.h как макрос KEY_*. При нажатии ESCAPE (который может быть началом функциональной клавиши) ncurses запустит односекундный таймер. Если остаток не получен в течение этой секунды, то возвращается ESCAPE, иначе - значение функциональной клавиши. При необходимости секундный таймер можно отключить через notimeout().

   * int ungetch(ch)
     Вернет ch в буфер ввода.
   * int getstr(str)
     int wgetstr(win, str)
     int mvgetstr(y, x, str)
     int mvwgetstr(win, y, x, str)
     int wgetnstr(win, str, n)

Эти функции проделают серию вызовов getch(), пока не будет получена новая линия. Символы помещаются в str, поэтому не забывайте захватывать память для вашего символьного указателя перед вызовом getstr(...). Если включено эхо, то строка отображается (используйте noecho(), чтобы его отключить) и пользовательские символы удаления будут проинтерпретированы.

   * chtype inch()
     chtype winch(win)
     chtype mvinch(y, x)
     chtype mvwinch(win, y, x)

Эти функции возвращают литеру с экрана или окна. Поскольку возвращается тип chtype, возвращается и атрибут. Информация об атрибуте может быть получена с помощью констант A_* (см. таблицу 8.4).

   * int instr(str)
     int innstr(str, n)
     int winstr(win, str)
     int winnstr(win, str, n)
     int mvinstr(y, x, str)
     int mvinnstr(y, x, str, n)
     int mvwinstr(win, y, x, str)
     int mvwinnstr(win, y, x, str, n)

Возвращает символьную строку из экрана или окна. (Пока не реализована.)

   * int inchstr(chstr)
     int inchnstr(chstr, n)
     int winchstr(win, chstr)
     int winchnstr(win, chstr, n)
     int mvinchstr(y, x, chstr)
     int mvinchnstr(y, x, chstr, n)
     int mvwinchstr(win, y, x, chstr)
     int mvwinchnstr(win, y, x, chstr, n)

Возвращает строку типа chtype из экрана или окна вместе с атрибутом для каждого символа. (Пока не реализована; lib_inchstr не включена в библиотеку ncurses.)

8.7.1. Форматированный ввод

   * int scanw(fmt, ...)
     int wscanw(win, fmt, ...)
     int mvscanw(y, x, fmt, ...)
     int mvwscanw(win, y, x, fmt, ...)
     int vwscanw(win, fmt, va_list)

Функции эквивалентны scanf(...) из libc (см. раздел 8.1.2). Входом для сканирования служит вызов wgetstr(...).

8.8. Опции

Опции вывода

   * int idlok(win, bf)
     void idcok(win, bf)

Включение и отключение возможностей вставки/удаления для окна терминала (idlok(...) для линий, idcok(...) - для символов). (idcok(...) пока не реализована.)

   * void immedok(win, bf)

Если устанавливается TRUE, то каждое изменение в окне вызывает физическое обновление экрана. Это может ухудшить характеристики программы, поэтому значение по умолчанию - FALSE. (Пока не реализована.)

   |-------|-------|-------|         |-------|-------|-------|-------|
   |  ???  | KEY_  | KEY_  |         |  NUM  |   /   |   *   |   -   |
   |       | HOME  | PPAGE |         |       |       |       |       |
   |-------|-------|-------|         |-------|-------|-------|-------|
   | CTRL  | KEY_  | KEY_  |         | KEY_  | KEY_  | KEY_  |       |
   |  +D   | END   | NPAGE |         | HOME  | UP    | PPAGE |       |
   |-------|-------|-------|         |-------|-------|-------|   +   |
                                     | KEY_  |  ???  | KEY_  |       |
                                     | LEFT  |       | RIGHT |       |
           |-------|                 |-------|-------|-------|-------|
           | KEY_  |                 | KEY_  | KEY_  | KEY_  |       |
           | UP    |                 | END   | DOWN  | NPAGE | CTRL  |
   |-------|-------|-------|         |-------|-------|-------|  +M   |
   | KEY_  | KEY_  | KEY_  |         |      ???      | KEY_  |       |
   | LEFT  | DOWN  | RIGHT |         |               | DC    |       |
   |-------|-------|-------|         |-------|-------|-------|-------|
   * int clearok(win, bf) 

Если bf равен TRUE, то следующий вызов wrefresh(win) очистит экран и полностью его перерисует (Ctrl+L в редакторе vi).

* int leaveok(win, bf)

По умолчанию ncurses ставит курсор там, где он был при последнем обновлении окна. Программы, не использующие курсор, могут установить leaveok(...) TRUE и сэкономить время, требующееся движения курсора. Кроме того, ncurses попытается сделать курсор терминала невидимым.

   * int nl()
     nonl()

Управление переходом на новую строку. После nl() произойдетт возврат каретки и дозаполнение; nonl() отключает контроль. В последнем случае ncurses может ускорить перемещение курсора.

Назад | Содержание | Вперед

 

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...