Атрибути

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

Приклад 5. Використання атрибутів

#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("Usage: %s <a c file name>\n", argv[0]);
        exit(1);
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        perror("Cannot open input file");
        exit(1);
    }
    initscr();          /* Розпочинає режим curses     */
    getmaxyx(stdscr, row, col); /* Знаходить межі екрану       */
    while ((ch = fgetc(fp)) != EOF) {   /* Читає файл, до EOF          */
    getyx(stdscr, y, x);    /* Знаходить поточне положення *
                 * курсору                     */
    if (y == (row - 1)) {   /* Якщо ми знаходимося в кінці *
                 * екрану вказує натиснути     */
        printw("<-Press Any Key->");    /* якусь клавішу               */
        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. Він читає кожний знак файлу та шукає послідовності /. Як тільки таку знайдено, вмикає атрибут A_BOLD за допомогою attron(). Коли він доходить до послідовності /, атрибут вимикається функцією attroff().

Вищенаведена програма також ознайомила нас з двома корисними функціями getyx() і move(). Перша функція добуває поточні координати курсору, зберігаючи їх у змінних y і x. Оскільки getyx(), це макрос, ми не можемо передати йому покажчики на змінні. Функція move() переміщає курсор у вказані їй координати.

Вищенаведена програма є досить простою. Її можна розвинути до такої, що читатиме C-файл, оброблятиме прочитане, виводячи його в різних кольорах. Її можна навіть розширити, щоб вона розуміла інші мови.

Подробиці

Давайте ознайомимося з подробицями щодо атрибутів. Функція 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

Останній з них, це найкольоровіший :-) Кольори розглянуто в наступному розділі.

Ми можемо застосувати логічне АБО (|) із будь-якою кількістю вищевказаних атрибутів, щоб добитися комбінованого ефекту. Якщо би вам хотілося інверсне відображення з миготінням, то могли би використати

 attron(A_REVERSE | A_BLINK);

attron() напротивагу attrset()

Яка ж різниця між attron() й attrset()? Функція attrset() встановлює атрибути для певного вікна, тоді як attron() просто вмикає атрибути. Тож, attrset() повністю переважує попередньо встановлені атрибути вікна, задаючи нові. Аналогічно, attroff() просто вимикає, вказані їй атрибути. Це дає нам можливість легкого оперування атрибутами. Але, акщо ви не будете уважними, то легко можете заплутатись і спотворити вивід. Це особливо стосується відображення кольорового меню з підсвіткою. Тож, намагайтеся обрати послідовну тактику і триматися її. Ви завжди можете звернутися до standend(), що рівнозначно attrset(A_NORMAL), що відновить стандарні параметри для атрибутів.

attr_get()

Функція attr_get() отримає поточні атрибути і кольорову пару вікна. Хоч ми й не вживатимемо її настільки часто, як попередні функції, вона може виявитися корисною для перевірки окремих ділянок екрану. Скажімо, ми хочемо здійснити якесь складне оновлення екрану, але не певні, з які встановлено атрибути для окремих символів. Ми можемо використати attr_get() у випадку обох, attrset() і attron(), щоб добитися бажаного ефекту.

Функції attr_

Існує також набір таких функцій як attr_set(), attr_on() тощо. Вони подібні до попередніх за винятком того, що їхні параметри складаються з типу attr_t.

Функції wattr

Для кожної з вищезгаданих функцій, існує відповідна, чия назва починається з 'w', і які діють стосовно вказаного вікна. Дія попередніх розповсюджувалась на stdscr.

Функції chgat()

Функція chgat() згадується наприкінці сторінки посібника curs_attr(3X). Виявляється, вона є корисною. За допомогою цієї функції можна задати атрибути для групи символів, без необхідності пересування. І це правда! Без пересування курсору :-) Вона змінює атрибути заданого числа символів, починаючи з поточної позиції курсору.

Ми можемо вказати -1, як кількість символів, для оновлення атрибутів до кінця рядка. Наприклад

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

Ця функція корисна для зміни атрибутів символів, вже присутніх на екрані. Перейдіть до символу, починаючи з якого ви хочете змінити атрибути і викличте chgat().

Інші функції, wchgat(), mvchgat(), wchgat(), поводяться схожим чином, за винятком того, що вони діють стосовно певного вікна. Функції, що починаються з 'mv', спочатку перемістять курсор до вказаного положення, а потім здійснять вказані їм дії. Насправді, chgat(), це макрос, яке замінюється на wchgat() із аргументом stdscr, як вікно. Більшість функцій, що не включають почткової 'w', являються макросами.

Приклад 6. Використання chgat()

#include <ncurses.h>

int main(int argc, char *argv[])
{       
    initscr();                      /* Розпочати режим curses    */
    start_color();                  /* Вмикає колір              */

    init_pair(1, COLOR_CYAN, COLOR_BLACK);
    printw("A Big string which i didn't care to type fully ");
    mvchgat(0, 0, -1, A_BLINK, 1, NULL);
    /*
     * Перші два параметри вказують положення, з якого розпочати.
     * Третій парамтр - кількісь символів для оновлення. -1 означає
     * до кінця рядка.
     * Четвертий параметр - це атрибут, яки би ви хотіли надати 
     * символу.
     * П'ятий - кольоровий індекс, встановлений init_pair(),
     * вкажіть 0, якщо не хочете жодних кольорів. 
     * Шостий завжди NULL.
     */
    refresh();
    getch();
    endwin();                       /* Завершить режим curses    */
    return 0;
}

Цей приклад, також, знайомить нас з кольоровим світом curses. Кольори буде розглянуто пізніше. Покищо, користуйтеся 0, щоб скасувати колір.