Когда вы выполните программу, заключительный экран будет выглядеть так, как показано на рис. 6.3. К сожалению, снимок экрана не дает полного впечатления и не показывает курсор, установленный в правом нижнем углу экрана. Эмулятор xterm может быть более подходящей средой для точного отображения программ, чем обычная консоль.
Рис. 6.3
Как
это работает
После инициализации некоторых переменных и экрана с помощью библиотеки curses вы применили функции
move
для перемещения курсора по экрану. Посредством функций
attron
и
attroff
вы управляли атрибутами текста, выводимого в заданную точку экрана. Далее перед закрытием библиотеки curses и завершением программа продемонстрировала, как вставлять символы функцией
insch
.
Клавиатура
Наряду с предоставлением интерфейса, облегчающего управление экраном, библиотека curses также предлагает средства, облегчающие управление клавиатурой.
Режимы клавиатуры
Процедуры считывания с клавиатуры управляются режимами. Режимы устанавливаются с помощью следующих функций:
#include <curses.h>
int echo(void);
int noecho(void);
int cbreak(void);
int nocbreak(void);
int raw(void);
int noraw(void);
Функции
echo
и
noecho
просто включают и отключают отображение символов, набираемых на клавиатуре. Оставшиеся четыре функции управляют тем, как символы, набранные на терминале, становятся доступны программе с применением curses. Для того чтобы понять функцию
cbreak
, необходимо иметь представление о стандартном режиме ввода. Когда программа, использующая библиотеку curses, стартует с вызова функции
initscr
, устанавливается режим ввода, называемый режимом с обработкой (cooked mode). Это означает построчную обработку, т.е. ввод становится доступен программе после нажатия пользователем клавиши <Enter> (или <Return> на некоторых клавиатурах). Специальные символы на клавиатуре включены, поэтому набор соответствующих клавиатурных последовательностей может сгенерировать сигнал в программе. Управление потоком, если терминал запускается с терминала, также включено. Вызывая функцию
cbreak
, программа может установить режим ввода
cbreak
, в котором символы становятся доступными программе сразу после их набора, а не помещаются в буфер и передаются программе только после нажатия клавиши <Enter>. Как и в режиме с обработкой, специальные символы клавиатуры действуют, а простые клавиши, например <Backspace>, передаются для обработки непосредственно в программу, поэтому если вы хотите, чтобы нажатие клавиши <Backspace> приводило к привычным действиям, то вы должны запрограммировать их самостоятельно.
Вызов функции
raw
отключает обработку специальных символов, поэтому становится невозможной генерация сигналов или управление потоком с помощью набранных на клавиатуре специальных символьных последовательностей. Вызов функции
nocbreak
возвращает режим ввода в режим с обработкой символов, но режим обработки специальных символов не изменяет; вызов
noraw
восстанавливает и режим с обработкой, и обработку специальных символов.
Клавиатурный
ввод
Чтение с клавиатуры — очень простая операция. К основным функциям чтения относятся следующие:
#include <curses.h>
int getch(void);
int getstr(char *string);
int getnstr(char *string, int number_of_characters);
int scanw(char *format, ...);
Все они действуют подобно своим аналогам, не входящим в библиотеку curses,
getchar
,
gets
и
scanf
. Обратите внимание на то, что у функции
getstr
нет возможности ограничить длину возвращаемой строки, поэтому применять ее следует с большой осторожностью. Если ваша версия библиотеки curses поддерживает функцию
getnstr
, позволяющую ограничить количество считываемых символов, всегда применяйте ее вместо функции
getstr
. Это очень напоминает поведение функций
gets
и
fgets
, с которыми вы познакомились в главе 3.
В упражнении 6.3 для демонстрации управления клавиатурой приведен пример короткой программы ipmode.c.
Упражнение 6.3. Режим клавиатуры и ввод
1. Наберите программу и включите в нее начальные вызовы библиотеки curses:
#include <unistd.h>
#include <stdlib.h>
#include <curses.h>
#include <string.h>
#define PW_LEN 256
#define NAME_LEN 256
int main {
char name[NAME_LEN];
char password[PW_LEN];
const char *real_password = "xyzzy";
int i = 0;
initscr;
move(5, 10);
printw("%s", "Please login:");
move(7, 10);
printw("%s", "User name: ");
getstr(name);
move(9, 10);
printw("%s", "Password: ");
refresh;
2. Когда пользователь вводит свой пароль, необходимо остановить отображение символов на экране. Далее сравните введенный пароль со строкой xyzzy:
cbreak;
noecho;
memset(password, '\0', sizeof(password));
while (i < PW_LEN) {
password[i] = getch;
if (password[i] == '\n') break;
move(8, 20 + i);
addch('*');
refresh;
i++;
}
3. В заключение восстановите отображение символов и выведите сообщение об успешном или неудачном завершении:
echo;
nocbreak;
move(11, 10);
if (strncmp(real_password, password, strlen(real_password)) == 0)