RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
YandexMoney: 
41001198119846 
E-gold:
5128052

Вперед: 9 Программирование портов ввода/вывода Оглавление: Оглавление Назад: 7 Программирование звук а

 

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 database
    База данных 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 содержит два типа объектов:

    1. обычные символы и
    2. информацию, как трансформировать или форматировать аргументы.

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

    • Параметры:
      • -
        Форматированный аргумент будет при печати прижат влево на своем поле.
      • +
        Каждое число будет напечатано со знаком, например, +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.
СимволФорматируется в
d,iint signed, десятиричный
oint unsigned, восьмеричный, без предваряющего 0
x,Xint unsigned, шестнадцатиричный, без предваряющего 0x
uint unsigned, десятиричный
cint (unsigned) одиночный символ
schar * до \0
fdouble как [-]mmm.ddd
e,Edouble как [-]m.dddddde+xx, [-]m.dddddde-xx
g,Gdouble использует %e или %f когда нужно
pvoid *
nint *
%%

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

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

 

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

  • int fscanf(FILE *stream, const char *format, ...)  
    fscanf(...) читает из stream и преобразует ввод по правилам, определяемым в format. Результаты помещаются в аргументы, заданные в "..." (эти аргументы должны быть указателями!). Чтение заканчивается, когда в format исчерпаны правила форматирования. 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.
СимволВход: тип аргумента
dдесятичный integer: int*
iinteger: int* (вход может быть восьми или шестнадцатиричным)
oвосьмеричный integer: int* (с или без предваряющего 0)
uдесятичный unsigned: unsigned int*
xшестнадцатиричный integer: int* (с или без предваряющего 0x)
cодин или более символов: char* (без завершающего /0)
e,f,gffloat: float* (такой как [-]m.dddddde+xx, [-]m.dddddde-xx)
pуказатель: void*
nчисло трансформированных аргументов: int*
[...]непустое множество символов на входе: char*
[^...]исключая такие символы: char*
%%

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

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

8.2.1 Введение

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

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

gcc [flags] files -ltermcap

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

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

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

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

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

8.2.4 Свойства termcap

Boolean

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сбой телевизионного луча, неверная табуляция и странный режим выделения

Numeric

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

String

!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

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

Обычно программа, использующая 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 скажет gcc произвести некоторую оптимизацию; -ansi: для ANSI си-кода; -Wall выведет все предупреждения; -m486 оптимизирует код для Intel 486 (можно и для Intel 386).

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

Структуры данных для экрана называются 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/ сохранятся ваши определения.

Текущей версией ncurses является (на момент написания книги) 1.8.6.

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

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

8.5 Окна

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

8.6 Вывод

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

8.6.2 Вставка символов и строк

8.6.3 Удаление символов и строк

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

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

Код символаПозиция По умолчанию
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.3: Ограничительные символы Ncurses

Рисунок 8.2: Символы бокса в ncurses.

tl      ts    tt     ts      tr
  |------------|------------|
  |                         |
ls|            |            |rs
  |                         |
  |            |            |
lt|- - - - - - - - - - - - -|rt
  |            |            |
  |                         |
ls|            |            |rs
  |                         |
  |------------|------------|
bl      bs    bt     bs      br

8.7 Ввод

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

8.8 Опции

Опции вывода

8.8.1 Опции ввода

8.8.2 Атрибуты терминала

8.8.3 Использование опций

Поговорим об использовании опций окна и режимов терминала.

Прежде всего, под Linux следует подключить keypad. Это позволит пользоваться цифровым блоком и клавишами перемещения курсора на клавиатуре ПК.

Теперь имеется 2 основных типа ввода:

  1. Программа ожидает нажатия клавиши, чтобы вызвать соответствующую функцию (например, что-нибудь вроде "press 'q' for quit" и ждет q);
  2. Ожидается, что пользователь введет строку символов в маску на экране (например, каталог или адрес в базе данных).

Для первого случая мы установим следующие опции и режимы, и цикл while сработает корректно:

char c;

noecho();
timeout(-1);
nonl();
cbreak();
keypad(stdscr,TRUE);
while(c=getch()){
  switch(c){
    case 'q': your_quit_function();
    default: break;
  }
}

Эта программа повиснет до нажатия клавиши. Если нажата q, мы вызываем your_quit_function(), иначе ждем другого ввода.

Выражение switch может быть расширено по нашему желанию. Макросы KEY_* служат для учета специальных клавиш. Например,

KEY_UP     KEY_RIGHT   KEY_A1   KEY_B2   KEY_C1
KEY_DOWN   KEY_LEFT    KEY_A3            KEY_C3
для клавиш перемещения курсора. Для просмотра файла цикл может выглядеть примерно так:
int loop=TRUE;
char c;
enum{UP,DOWN,RIGHT,LEFT};

noecho();
timeout(-1);
nonl();
cbreak();
keypad(stdscr,TRUE);
while(loop==TRUE){
   c=getch();
   switch(c){
      case KEY_UP:
      case 'u':
      case 'U': scroll_s(UP);
                break;
      case KEY_DOWN:
      case 'd':
      case 'D': scroll_s(DOWN);
                break;
      case KEY_LEFT:
      case 'l':
      case 'L': scroll_s(LEFT);
                break;
      case KEY_RIGHT:
      case 'r':
      case 'R': scroll_s(RIGHT);
                break;
      case 'q':
      case 'Q': loop=FALSE;
      default: break;
   }
}

Для второго случая, нам достаточно установить echo(), и символы, набираемые пользователем, будут напечатаны на экране. Место печати задается функциями move(...) или wmove(...).

Или вы можете открыть окно с маской (выделяемой другими цветами) и попросить пользователя ввести строку:

WINDOW *maskwin;
WINDOW *mainwin;
char *ptr=(char *)malloc(255);
...
   mainwin=newwin(3,37,9,21);
   maskwin=newwin(1,21,10,35);
   ...
   werase(mainwin);
   werase(maskwin);
   ...
   box(mainwin,0,0)
   mvwaddstr(mainwin,1,2,"Inputstring:");
   ...
   wnoutrefresh(mainwin);
   wnoutrefresh(maskwin);
   doupdate();
   ...
   mvwgetstr(maskwin,0,0,ptr);
   ...
   delwin(maskwin);
   delwin(mainwin);
   endwin();
   free(ptr);

Более подробно см. input.c в каталоге примеров.

8.9 Очистка окна и линий

8.10 Обновление терминала

Как написано в обзоре, окна ncurses есть отображения в памяти. Это означает, что любое изменение окна не отражается на физическом экране до тех пор, пока не будет произведено обновление. Это оптимизирует вывод на экран, поскольку вы получаете возможность совершать множество действий, а затем лишь единожды вызвать обновление, чтобы напечатать его на экране. В противном случае на терминале отражалось бы каждое изменение, что ухудшало бы исполнение ваших программ.

8.11 Видеоатрибуты и цвет

Атрибуты это специальные возможности терминала, применяемые во время печати символов на экран. Символы могут быть напечататы жирно, могут быть подчеркнуты, могут мигать и т.д. В ncurses вы имеете возможность включать или отключать атрибуты для достижения наилучшего внешнего вида вывода. Возможные атрибуты перечислены в нижеследующей таблице.

ОпределениеАтрибут
A_ATTRIBUTESмаска для атрибутов (chtype)
A_NORMALнормальный, переустановка всего остального
A_STANDOUTнаиболее яркий режим
A_UNDERLINEподчеркивание
A_REVERSEобратное изображение
A_BLINKмигание
A_DIMтусклый или полуяркий режим
A_BOLDчеткий или очень яркий режим
A_ALTCHARSETиспользование альтернативной символьной таблицы
A_INVISневидимый режим
A_PROTECTне понял
A_CHARTEXTмаска для действующих символов (chtype)
A_COLORмаска для цвета
COLOR_PAIR(n)установка цветовой пары n
PAIR_NUMBER(a)получение цветовой пары, лежащей в атрибуте a

  
Таблица 8.4: Ncurses-атрибуты

Ncurses определяет 8 цветов, которыми вы можете пользоваться на терминале с цветовой поддержкой. Сначала проинициализируйте цветовые структуры данных посредством start_color(), затем проверьте возможности терминала при помощи has_colors(). start_color() будет инициализировать COLORS, наибольшее количество цветов, поддерживаемых терминалом, и COLOR_PAIR, максимальное число цветовых пар, которые вы можете определить.

ОпределениеЦвет
COLOR_BLACKчерный
COLOR_REDкрасный
COLOR_GREENзеленый
COLOR_YELLOWжелтый
COLOR_BLUEсиний
COLOR_MAGENTAпурпурный
COLOR_CYANголубой
COLOR_WHITEбелый

  
Таблица 8.5: Цвета в Ncurses

Атрибуты могут быть совмещены '|' (OR), поэтому вы можете получить четкий мерцающий вывод при помощи A_BOLD|A_BLINK

Если вы установите окно с атрибутом attr, все символы, напечатанные в этом окне, приобретут это свойство и будут его сохранять до изменения вами атрибута. Это не будет утеряно при прокрутке или движении окна и т.п.

Будьте осторожны с цветами, если вы пишете программы для ncurses и BSD curses, так как BSD curses не имеет цветовой поддержки. (Точно так же не имеют цветовой поддержки старые версии SYS V). Поэтому, если вы компилируете для обеих библиотек, придется использовать операции #ifdef.

Как комбинировать атрибуты и цвета? Некоторые терминалы, как консоли в Linux, имеют цвета, а некоторые нет (xterm, vs100 и т.д.). Следующий код решит эту проблему:

void CheckColor(WINDOW *win1, WINDOW *win2)
{
  start_color();
  if (has_colors()){
     /* Хорошо, у нас есть цвета, определяем цветовые пары для
      * цветов переднего и заднего плана
      */
     init_pair(1,COLOR_BLUE,COLOR_WHITE);
     init_pair(2,COLOR_WHITE,COLOR_RED);
     /* теперь используем уже определенные цветовые пары для окон */
     wattrset(win1,COLOR_PAIR(2));
     wattrset(win2,COLOR_PAIR(1));
  }
else
  {
    /* Нет цвета (может быть vt100 или xterm). Ладно, будем
     * пользоваться вместо этого черно-белыми атрибутами.
     */
    wattrset(win1,A_REVERSE);
    wattrset(win2,A_BOLD);
  }
  return;
}

Прежде всего, функция CheckColor проинициализирует цвета при помощи start_color(). Затем has_colors() вернет TRUE, если текущий терминал имеет цвета. После этого вызывается ini_tpair(...) для соединения цветов переднего и заднего плана, и wattrset(...) для установки этих цветов в данном окне. Впрочем, чтобы установить атрибуты для черно-белого терминала, мы можем использовать только wattrset(...).

Чтобы получить цвета на xterm, лучший способ, найденный автором, это использовать ansi_xterm с надерганными элементами terminfo из Midnight Commander. Просто добудьте исходники ansi_xterm и Midnight Commander (mc-x.x.tar.gz). Потом скомпилируйте ansi_xterm и используйте tic с xterm.ti и vt100.ti из архива mc-x.x.tar.gz. Запустите ansi_xterm и протестируйте его.

8.12 Координаты курсора и окна