Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УПРАВЛЕНИЕ ЦВЕТОМ В СИСТЕМЕ LINUX.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
338.26 Кб
Скачать

Int instr(char *string);

Int innstr(char *string, int number_of_characters);

Функция

inch

должна быть всегда доступна, а функции

instr

и

innstr

не всегда поддерживаются. Функция

inch

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

char

, a

chtype

, в то время как функции

instr

и

innstr

пишут в массивы с элементами типа

char

.

Очистка экрана

Существует четыре основных способа очистки области экрана:

#include <curses.h>

int erase (void);

int clear(void);

int clrtobot(void);

int clrtoeol(void);

Функция

erase

записывает пробелы во все позиции экрана. Функция

clear

, как и

erase

, очищает экран, но вызывает перерисовку экрана с помощью внутреннего вызова низкоуровневой функции clear

o

k, которая выполняет последовательность очистки экрана и новое отображение экрана при следующем вызове

refresh

.

Функция

clear

обычно применяет команду терминала, которая очищает весь экран, а не пытается стереть текущие непробельные символы во всех точках экрана. Это делает функцию

clear

надежным средством очистки экрана. Сочетание функции

clear

с последующей функцией

refresh

может обеспечить удобную команду перерисовки экрана в том случае, когда изображение на экране беспорядочно или испорчено каким-либо образом.

Функция

clrtobot

очищает экран, начиная с текущей позиции курсора и далее до конца экрана, а функция

clrtoeol

очищает экран, начиная с текущей позиции курсора до конца строки, в которой находится курсор.

Перемещение курсора

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

#include <curses.h>

Int move(int new_y, int new_x);

Int leaveok(window *window_ptr, bool leave_flag);

Функция

move

просто переносит позицию логического курсора в заданное место на экране. Напоминаем о том, что начало экранных координат (0, 0) находится в левом верхнем углу экрана. В большинстве версий библиотеки curses две глобальные целочисленные переменные,

LINES

и

COLUMNS

, определяют размер физического экрана и могут применяться для определения максимально допустимых значений параметров

new_y

и

new_x

. Вызов

move

сам по себе не приводит к перемещению физического курсора. Он только изменяет позицию на логическом экране, в которой появится следующий вывод. Если вы хотите, чтобы экранный курсор переместился немедленно после вызова функции move, вставьте следом за ним вызов функции

refresh

.

Функция

leaveok

устанавливает флаг, управляющий положением курсора на физическом экране после его обновления. По умолчанию флаг равен

false

, и после вызова

refresh

аппаратный курсор остается в той же точке экрана, что и логический курсор. Если флаг равен

true

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

Атрибуты символов

У всех символов, обрабатываемых curses, могут быть определенные атрибуты, управляющие способом отображения символа на экране при условии, что оборудование, применяемое для их отображения, поддерживает требуемый атрибут. Определены следующие атрибуты:

A_BLINK

,

A_BOLD

,

A_DIM

,

A_REVERSE

,

A_STANDOUT

и

A_UNDERLINE

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

#include <curses.h>

int attron(chtype attribute);

int attroff(chtype attribute);

int attrset(chtype attribute);

int standout(void);

int standend(void);

Функция

attrset

устанавливает атрибуты curses, функции

attron

и

attroff

включают и отключают заданные атрибуты, не портя остальные, а функции

standout

и

standend

обеспечивают более выразительный режим выделения или "лучший из всех" режим. На большинстве терминалов выбирается инверсия.

Выполните упражнение 6.2.

Упражнение 6.2. Перемещение, вставка и атрибуты

Теперь, когда вы знаете больше об управлении экраном, можно испытать более сложный пример moveadd.c. Вы включите несколько вызовов функций

refresh

и

sleep

в этот пример, чтобы на каждом шаге видеть, как выглядит экран. Обычно программы с использованием библиотеки curses стараются обновлять экран как можно реже, поскольку это не слишком высокопроизводительная операция. Программный код написан с некоторой долей искусственности для обеспечения большей наглядности.

1. Для начала вставьте несколько заголовочных файлов, определите несколько символьных массивов и указатель на них, а затем инициализируйте структуры библиотеки curses:

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <string.h>

#include <curses.h>

int main() {

 const char witch_one[] = " First Witch ";

 const char witch_two[] = " Second Witch ";

 const char *scan_ptr;

 initscr();

2. Теперь для трех начальных текстовых фрагментов, которые появляются на экране через определенные интервалы, включите и отключите соответствующие флаги атрибутов;

 move(5, 15);

 attron(A_BOLD);

 printw("%s", "Macbeth");

 attroff(A_BOLD);

 refresh();

 sleep(1);

 move(8, 15);

 attron(A_STANDOUT);

 printw("%s", "Thunder and Lightning");

 attroff(A_STANDOUT);

 refresh();

 sleep(1);

 move(10, 10);

 printw("%s", "When shall we three meet again");

 move(11, 23);

 printw("%s", "In thunder, lightning, or in rain ?");

 move(13, 10);

 printw("%s", "When the hurlyburly's done, ");

 move(14, 23);

 printw("%s", "When the battle's lost and won.");

 refresh();

 sleep(1);

3. Действующие лица идентифицированы, и их имена выводятся посимвольно:

 attron(A_DIM);

 scan_ptr = witch_one + strlen(witch_one) - 1;

 while (scan_ptr != witch_one) {

  move(10, 10);

  insch(*scan_ptr--);

 }

 scan_ptr = witch_two + strlen(witch_two) - 1;

 while (scan_ptr != witch_two) {

  move(13, 10);

  insch(*scan_ptr--);

 }

 attroff(A_DIM);

 refresh();

 sleep(1);

4. В заключение переместите курсор в правый нижний угол экрана, а затем подготовьте и выполните завершение:

 move(LINES - 1, COLS - 1);

 refresh();

 sleep(1);

 endwin();

 exit(EXIT_SUCCESS);

}

Когда вы выполните программу, заключительный экран будет выглядеть так, как показано на рис. 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)

   printw("%s", "Correct");

 else printw("%s", "Wrong");

 printw("%s", " password");

 refresh();

 sleep(2);

 endwin();

 exit(EXIT_SUCCESS);

}

Как это работает

Остановив отображение клавиатурного ввода и установив режим

cbreak

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

*

в следующей позиции курсора. Вам необходимо каждый раз обновлять экран и сравнивать с помощью функции

strcmp

две строки: введенный и реальный пароли.

Примечание

Если вы пользуетесь очень старой версией библиотеки curses, вам, возможно, понадобится выполнить дополнительный вызов функции

refresh

перед вызовом функции

getstr

. В библиотеке ncurses вызов

getstr

обновляет экран автоматически.

Окна

До сих пор вы использовали терминал как средство полноэкранного вывода. Это вполне подходит для маленьких простых программ, но библиотека curses идет гораздо дальше. Вы можете на физическом экране одновременно отображать множество окон разных размеров. Многие из описанных в этом разделе функций поддерживаются в терминах стандарта X/Open так называемой "расширенной" версией curses. Но поскольку они поддерживаются библиотекой ncurses, не велика проблема сделать их доступными на большинстве платформ. Пора идти дальше и применить множественные окна. Вы увидите, как обобщаются до сих пор использовавшиеся команды и применяются в сценариях с множественными окнами.

Структура WINDOW

Несмотря на то, что мы уже упоминали стандартный экран

stdscr

, пока у вас не было необходимости в его применении, поскольку почти все рассматриваемые до сих пор функции полагали, что они работают на экране

stdscr

, и не требовалось передавать его как параметр.

stdscr

— это специальный случай структуры

WINDOW

, как stdout — специальный случай файлового потока. Обычно структура

WINDOW

объявляется в файле curses.h и, несмотря на то, что ее просмотр может быть очень поучителен, программы никогда не используют эту структуру напрямую, т.к. она может различаться в разных реализациях.

Вы можете создать и уничтожить окно с помощью вызовов функций newwin и delwin:

#include <curses.h>

WINDOW *newwin(int num_of_lines, int num_of_cols, int start_y, int start_x);