|
Так Вам нравится цвет!!! (Таинственные символы ^[[)
Автор: © Pradeep Padala
| ||
|
Пробовали ли вы когда-нибудь перенаправлять вывод программы, использующей библиотеку curses? Удивляли ли вас таинственные символы ^[[ ? Пробовали ли вы получать цвета с помощью команды printf, без использования библиотек curses? Если хотя бы на один из этих вопросов ответ - "да", то эта статья для вас... Статья попытается объяснить загадочные символы, которые можно найти в выводе "curses-программы", работающей с цветами. Потом, мы расширим наши представления, дабы получать цвета с помощью обычной команды printf. Терминальные кодыВ старые времена телетайпных терминалов, последние находились далеко от компьютеров и были связаны с ними последовательными кабелями. Терминалы могли быть настроены с помощью посылки набора байтов к каждому из них. Всеми возможностями терминалов можно было управлять такими наборами байтов, которые обычно назывались эскейп-последовательностями (esc-последовательностями), потому как начинаются они с символа escape(0x1B). Даже в наши дни, работая с эмуляцией терминала vt100, мы можем послать esc-последовательность эмулятору, и это будет иметь тот же эффект, что и на терминале. Наберите на вашей консоли следующее: echo "^[[0;31;40mIn Color" Первый символ является символом escape, и выглядит как два символа ^ и [. Что бы ввести этот символ, вам необходимо нажать CTRL+V а потом клавишу ESC. Все остальные символы являются обычными печатными. Вы увидите строку "В цвете" красного цвета. Консоль так и останется в режиме красного цвета и что бы вернуть обычное состояние, надо ввести теперь: echo "^[[0;37;40m" Как вы можете видеть, достаточно просто устанавливать и сбрасывать цвет. Существует несметное число esc-последовательностей, с помощью которых вы можете выполнять множество вещей, как-то: перемещать курсор, сбрасывать терминал и т.п. Последовательность для установки цветов:
|
#include <stdio.h>
#define RESET 0
#define BRIGHT 1
#define DIM 2
#define UNDERLINE 3
#define BLINK 4
#define REVERSE 7
#define HIDDEN 8
#define BLACK 0
#define RED 1
#define GREEN 2
#define YELLOW 3
#define BLUE 4
#define MAGENTA 5
#define CYAN 6
#define WHITE 7
void textcolor(int attr, int fg, int bg);
int main()
{ textcolor(BRIGHT, RED, BLACK);
printf("В цвете\n");
textcolor(RESET, WHITE, BLACK);
return 0;
}
void textcolor(int attr, int fg, int bg)
{ char command[13];
/* Command - это управляющая команда терминалу */
sprintf(command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40);
printf("%s", command);
}
|
Функция textcolor() - аналог функции API из Turbo C . Вы вызываете функцию для установки цвета, а после выводите информацию командой sprintf() (функция, которая используется в Turbo C для вывода в цвете).
#include <stdio.h>
#define RESET 0
#define BRIGHT 1
#define DIM 2
#define UNDERLINE 3
#define BLINK 4
#define REVERSE 7
#define HIDDEN 8
#define BLACK 0
#define RED 1
#define GREEN 2
#define YELLOW 3
#define BLUE 4
#define MAGENTA 5
#define CYAN 6
#define WHITE 7
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
char *attrs[] = {"NORMAL", "BRIGHT", "DIM", "UNDERLINE", "BLINK",
"REVERSE", "HIDDEN", "EXIT"};
char *colors[] = {"BLACK", "RED", "GREEN", "YELLOW", "BLUE", "MAGENTA",
"CYAN", "WHITE", "EXIT"};
void textcolor(int attr, int fg, int bg);
int print_menu(char *array[], int n_options, char *title);
int main()
{ int attr, fg, bg;
int attr_size, colors_size;
attr_size = ARRAY_SIZE(attrs);
colors_size = ARRAY_SIZE(colors);
while(1)
{ printf("\n");
attr = print_menu(attrs, attr_size, "Выберите атрибут:");
if(attr == attr_size - 1)
break;
fg = print_menu(colors, colors_size, "Выберите цвет символов:");
if(attr == colors_size - 1)
break;
bg = print_menu(colors, colors_size, "Выберите цвет фона:");
if(attr == colors_size - 1)
break;
printf("\n");
textcolor(attr, fg, bg);
printf("Это - пример того, что вы получите, используя комбинацию
атрибута %s, цвета символов %s, и цвета фона - %s", attrs[attr], colors[fg], colors[bg]);
textcolor(RESET, WHITE, BLACK);
system("clear");
}
return 0;
}
int print_menu(char *array[], int n_options, char *title)
{ int choice, i;
for(i = 0;i < n_options; ++i)
printf("%d.%s\n", i, array[i]);
printf("%s", title);
scanf("%d", &choice);
return choice;
}
void textcolor(int attr, int fg, int bg)
{ char command[13];
/* Command - это управляющая команда терминалу */
sprintf(command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40);
printf("%s", command);
}
|
Эта программа получает набор атрибутов от пользователя и выводит текстовую строку с указанными атрибутами и цветами. Обычно, я использую её для нахождения красивых комбинаций цветов для моих программ. Текстовая версия программы находится тут .
В чем же выгода? Если получение цветов так просто, почему люди гробят своё время на написание громоздких программ с помощью curses, которая направляет запрос в базу данных terminfo общим путём? Как мы знаем, существует много типов терминалов с малыми возможностями и терминалов, которые не распознают указанных esc-последовательностей, либо имеют другой набор кодов. Так что, если вы хотите написать портируемую программу, которая работала бы с любым терминалом с аналогичной (или уменьшенной) функциональностью, вы должны использовать библиотеку curses. Она использует базу terminfo для нахождения верных последовательностей, необходимых для корректного выполнения задачи. Terminfo - это большая база, которая содержит информацию о различных возможностях разных терминалов.
Если же вы желаете написать маленькую программу, которая работает с цветами на консоли Linux, либо в окне эмулятора xterm, вы можете преспокойно использовать esc-последовательности. Консоль Linux, в основном, эмулирует vt100, так что она понимает указанные выше последовательности.
Существует, однако, способ сделать запрос к базе данных terminfo и выполнить соответствующие указания. Команда tput посылает запрос и выполняет указанную вами функцию. Две опции setf и setb используются для установки цвета текста и фона. Что бы установить цвет текста в красный, а цвет фона в зелёный, необходимо выполнить следующие команды:
tput setf 4 # tput setf {номер цвета символов }
tput setb 2 # tput setb {номер цвета фона}
Это можно использовать в сценариях shell где угодно. Другие возможности команды tput описаны в руководстве. Руководство по terminfo содержит много информации, касающейся возможностей терминалов - как получить и установить их значения и многое другое. Есть два руководства по terminfo. "man 5 terminfo" описывает базу данных terminfo. "man 3ncurses terminfo" описывает C-функции, которые используют эту базу.
Тут приведены номера цветов, которые нужно передавать в качестве аргументов командам "tput setf" и "tput setb".
0 чёрный 1 красный 2 зелёный 3 жёлтый 4 синий 5 фиолетовый 6 голубой 7 белый
Веселитесь!!!