Skip to content

8. Атрибуты

lomaster edited this page Apr 13, 2023 · 1 revision

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

Пример 5 | by Joseph Spainhour [email protected]

#include <ncurses.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int ch, prev, row, col;
  prev = EOF;
  FILE *fp;
  int y, x;
  
  if(argc != 2)
  {
    printf("Использование: %s <a имя файла c>\n", argv[0]);
    exit(1);
  }
  
  fp = fopen(argv[1], "r");
  
  if(fp == NULL)
  {
    perror("Невозможно открыть входной файл");
    exit(1);
  }
  
  initscr();                                /* запускаем режим curses */
  getmaxyx(stdscr, row, col);               /* найти границы экрана */
  while((ch = fgetc(fp)) != EOF)            /* читаем файл до конца */
  getyx(stdscr, y, x);                      /* получаем текущую позицию курсора */
  
  if(y == (row - 1))                        /* мы находимся в конце экрана */
  {
    printw("<Нажмите любую клавишу->");     /* сообщите пользователю о необходимости нажать клавишу */
    getch();
    clear();                                /* очистить экран */
    move(0, 0);                             /* начать с начала экрана */
  }
  
  if(prev == '/' && ch == '*')              /* Если это / и *, тогда только
                                            * включить полужирный шрифт */
  {
    attron(A_BOLD);                         /* включить полужирный шрифт */
    getyx(stdscr, y, x);                    /* получить текущее положение курсора */
    move(y, x - 1);                         /* отступить на один пробел */
    printw("%c%c", '/', ch);                /* Здесь происходит фактическая печать */
  }
  else
    printw("%c", ch);
    
  refresh();
  
  if(prev == '*' && ch == '/')
    attroff(A_BOLD);                        /* Выключите его, как только мы получили *
                                            * и затем / */
    prev = ch;
  }
  
  endwin();                                 /* Завершаем режим curses */
  fclose(fp);
  
  return 0;
}

Не беспокойтесь обо всех этих инициализациях и прочей ерунде. Сосредоточьтесь на цикле while. Он считывает каждый символ в файле и ищет шаблон /*. Как только он находит шаблон, он включает атрибут BOLD с помощью attron(). Когда мы получаем шаблон */, он выключается с помощью attroff(). Приведенная выше программа также знакомит нас с двумя полезными функциями getyx() и move(). Первая функция получает координаты текущего курсора в переменные y, x. Поскольку getyx() является макросом, нам не нужно передавать указатели на переменные. Функция move() перемещает курсор в заданные координаты. Приведенная выше программа на самом деле является простой и не делает многого. На ее основе можно написать более полезную программу, которая читает файл на языке Си, разбирает его и распечатывает разными цветами. Можно даже расширить ее на другие языки.

8.1. Детали

Давайте более подробно разберемся с атрибутами. Функции attron(), attroff(), attrset(), а также родственные им функции attr_get() и т.д. можно использовать для включения/выключения атрибутов, получения атрибутов и создания красочного дисплея.

Функции attron и attroff принимают битовую маску атрибутов и включают или выключают их, соответственно. В эти функции можно передавать следующие видеоатрибуты, определенные в <curses.h>.

A_NORMAL        Нормальное отображение (без подсветки)
A_STANDOUT      Лучший режим подсветки терминала.
A_UNDERLINE     Подчеркивание
A_REVERSE       Обратное видео
A_BLINK         Мигание
A_DIM           Полуяркий
A_BOLD          Очень яркий АКА жирный
A_PROTECT       Защищенный режим
A_INVIS         Невидимый или пустой режим
A_ALTCHARSET    Альтернативный набор символов
A_CHARTEXT      Битовая маска для извлечения символа
COLOR_PAIR(n)   Номер цветовой пары n

Последний - самый красочный :-)

Цвета описаны в следующих разделах. Мы можем использывать ИЛИ [OR] (|) любое количество вышеперечисленных атрибутов, чтобы получить комбинированный эффект. Например если вы хотите получить обратное видео с мигающими символами, вы можете использовать.

attron(A_REVERSE | A_BLINK);

(Комментарий lomaster) думаю вы поняли что символ « | » озночает слово или.

8.2. attron() против attrset()

Тогда в чем разница между attron() и attrset()? attrset устанавливает атрибуты окна, тогда как attron просто включает данный ему атрибут. Таким образом, attrset() полностью отменяет все атрибуты, которые окно имело ранее, и устанавливает новый атрибут(ы). Аналогично attroff() просто выключает атрибут(ы), переданный(ые) ей в качестве аргумента. Это дает нам возможность легко управлять атрибутами, но если использовать их небрежно, то можно потерять представление о том, какие атрибуты есть у окна, и исказить отображение. Это особенно актуально при управлении меню с помощью цветов и подсветки. Поэтому определитесь с последовательной политикой и придерживайтесь ее. Вы всегда можете использовать standend(), что эквивалентно attrset(A_NORMAL), которая отключает все атрибуты и переводит окно в нормальный режим.

8.3. attr_get()

Функция attr_get() получает текущие атрибуты и пару цветов окна. Хотя мы можем использовать ее не так часто, как вышеперечисленные функции, она полезна при сканировании областей экрана. Скажем, мы хотим выполнить какое-то сложное обновление на экране и не уверены, с каким атрибутом связан каждый символ. Тогда эта функция может быть использована вместе с attrset или attron для получения желаемого эффекта.

Мы можем указать -1 (EOF) в качестве количества символов для обновления до конца строки. Если вы хотите изменить атрибуты символов от текущей позиции до конца строки, просто используйте это:

chgat(-1, A_REVERSE, 0, NULL);

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

Другие функции wchgat(), mvchgat(), wchgat() ведут себя аналогично, за исключением того, что функции с w вначале, работают с конкретным окном. Функции с mv вначале, сначала перемещают курсор, а затем выполняют заданную им работу.

На самом деле chgat - это макрос, который заменяется wchgat() с stdscr в качестве окна. Большинство функций "без w" являются макросами.

8.4 Пример 6

#include <ncurses.h>

int main(int argc, char *argv[]){
  initscr();            /* Запуск режима curses */
  start_color();        /* Запуск функциональности цвета */
  
  init_pair(1, COLOR_CYAN, COLOR_BLACK);
  printw("Большая строка, которую я не позаботился напечатать полностью");
  mvchgat(0, 0, -1, A_BLINK, 1, NULL);
  
  /*
  * Первые два параметра задают позицию, с которой нужно начать.
  * Третий параметр задает количество символов для обновления. -1 означает.
  * конец строки
  * Четвертый параметр - это обычный атрибут, который вы хотите придать символу.
  * Пятый параметр - индекс цвета. Это индекс, указанный во время init_pair()
  * Используйте 0, если вам не нужен цвет.
  * Шестой параметр всегда NULL
  */
  
  refresh();
  getch();
  endwin();             /* завершение режима curses */
  
  return 0;
}

Этот пример также знакомит нас с цветовым миром curses. Цвета будут подробно описаны позже. Используйте 0 для отсутствия цвета.