24.2.8. Рисование линий и прямоугольников
Хотя функция SLsmg_set_char_set() предлагает весь спектр функциональных возможностей, необходимых для рисования простой линейной графики на терминале, в библиотеке S-Lang для этого предусмотрено несколько простых функций.
void SLsmg_draw_hline(int row);
void SLsmg_draw_vline(int column);
void SLsmg_draw_box(int row, int column, int height, int width);
Функция SLsmg_draw_hline() рисует одну горизонтальную линию в строке row, а функция SLsmg_draw_vline() — одну вертикальную линию в колонке col.
Функция SLsmg_draw_box() рисует прямоугольник, начиная с row и col, который простирается на height строк и width колонок. Функция SLsmg_draw_box() подобна комбинации функций SLsmg_draw_hline() и SLsmg_draw_vline(), однако вдобавок она получает информацию о вершинах.
Далее представлен пример программы, которая рисует экран, отображающий обычный и альтернативный наборы символов. В программе также демонстрируется простое использование функции SLsmg_draw_box().
1: /* slcharset.с */
2:
3: #include <slang/slang.h>
4: #include <stdio.h>
5: #include <sys/ioctl.h>
6: #include <termios.h>
7:
8: /* отображает таблицу, содержащую 256 символов из одного набора символов,
9: начиная со столбца col. Поверх таблицы отображается метка 'label',
10: а альтернативный набор символов будет отображаться в том случае,
11: если isAlternate будет иметь ненулевое значение */
12: static void drawCharSet(int col, int isAlternate, char * label) {
13: int i, j;
14: int n = 0;
15:
16: /* нарисовать прямоугольник */
17: SLsmg_draw_box(0, col, 20, 38);
18:
19: /* центрировать надпись */
20: SLsmg_gotorc(0, col + 2);
21: SLsmg_write_string(label);
22:
23:
24: /* нарисовать горизонтальную линию */
25: SLsmg_gotorc(2, col + 4);
26: SLsmg_write_string("0123456789ABCDEF");
27:
28: /* задать используемый набор символов */
29: SLsmg_set_char_set(isAlternate);
30:
31: /* итерация по 4 самым старшим битам */
32: for (i = 0; i < 16; i++) {
33: SLsmg_gotorc(3 + i, 2 + col);
34: SLsmg_write_char(i < 10 ? i + '0' : (i - 10) + 'A');
35:
36: /* итерация по 4 самым младшим битам */
37: for (j = 0; j < 16; j++) {
38: SLsmg_gotorc(3 + i, col + 4 + (j * 2));
39: SLsmg_write_char(n++);
40: }
41: }
42:
43: SLsmg_set_char_set(0);
44: }
45:
46: int main (void) {
47: struct winsize ws;
48:
49: /* получить размеры терминала, подключенного к stdout */
50: if (ioctl(1, TIOCGWINSZ, &ws)) {
51: perror("сбой при получении размеров окна");
52: return 1;
53: }
54:
55: SLtt_get_terminfо();
56:
57: SLtt_Screen_Rows = ws.ws_row;
58: SLtt_Screen_Cols = ws.ws_col;
59:
60: SLsmg_init_smg();
61: SLang_init_tty(-1, 0, 1);
62:
63: drawCharSet(0, 0, "Normal Character Set");
64: drawCharSet(40, 1, "Alternate Character Set");
65:
66: SLsmg_refresh();
67: SLang_getkey();
68:
69: SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
70: SLsmg_refresh();
71: SLsmg_reset_smg();
72: SLang_reset_tty();
73:
74: return 0;
75: }
24.2.9. Использование цвета
Библиотека S-Lang упрощает процесс добавления цветов в приложения. Она позволяет использовать палитру, состоящую из 256 элементов[171], каждый из которых определяет цвет переднего плана и фона. В большинстве приложений используется элемент палитры для одного визуализируемого объекта, например, рамки окна или пункта списка. Настроить цвета палитры можно с помощью функции SLtt_set_color().
void SLtt_set_color(int entry, char * name, char * fg, char * bg);
Первый параметр определяет модифицируемый элемент палитры. Параметр name в настоящий момент игнорируется и должен быть равен NULL. Два последних элемента задают новые цвета переднего плана и фона для данного элемента палитры. В табл. 24.2 приведен список цветов, которые поддерживает библиотека S-Lang; fg и bg должны представлять строки, содержащие имя используемого цвета. Все цвета в левой колонке таблицы могут использоваться как для переднего плана, так и для фона. Цвета в правой колонке таблицы могут служить только в качестве цветов переднего плана. Попытка использования этих цветов для фона может привести к непредсказуемым результатам[172].
Таблица 24.2. Цвета в S-Lang
Передний план и фон Передний план black gray red brightred green brightgreen brown yellow blue brightblue magenta brightmagenta cyan brightcyan lightgray white
Запись на экран осуществляется с применением текущего элемента палитры, который можно задать с помощью функции Slsmg_set_color().
void SLsmg_set_color(int entry);
Эта функция задает текущий элемент палитры по определенному элементу. Цвета, определяемые этим элементом, будут использоваться при последующих записях на экран.
Хотя приложение может вызывать функции для работы с цветом на терминале любого типа, возможность отображения того или иного цвета будет определяться некоторыми факторами. Глобальная переменная SLtt_Use_Ansi_Colors контролирует отображение цветов. Если эта переменная будет иметь нулевое значение, цвета не используются, а если любое другое значение — то используются.
Функция SLtt_get_terminfo() пытается предположить, будет ли цвет доступен на текущем терминале. К сожалению, многие базы данных termcap и terminfo в этом отношении несовершенны. Если будет задана переменная среды COLORTERM, то S-Lang установит переменную SLtt_Use_Ansi_Colors независимо от того, что отражено в базе данных терминала.
Большинство приложений, обеспечивающих поддержку цветов, также предлагают опцию командной строки, позволяя избирательно разрешать поддержку цветов. Указание этой опции приводит к явной установке переменной SLtt_Use_Ansi_Colors в приложении.
Глава 25
Библиотека хешированных баз данных
Приложениям часто необходимо хранить некоторую разновидность бинарных данных в файлах. Хранение таких данных, когда во главу угла ставится задача эффективного их извлечения, отличается сложностью и слабой устойчивостью к ошибкам. Существует несколько библиотек, которые предлагают простые API-интерфейсы для хранения информации в файлах. В системах семейства Unix одной из первых использовалась библиотека dbm (впоследствии она была повторно реализована как ndbm), что привело затем к появлению библиотек Berkley db и gdbm проекта GNU. Все эти библиотеки обеспечивали простой доступ к файлам, организованным в виде хеш-таблиц, с двоичным ключом, который обеспечивал доступ к области бинарных данных[173].
Несмотря на то что gdbm и Berkley db широко доступны в системах Linux, лицензии, сопровождаемые их, снижают удобство их коммерческого использования[174]. Библиотека gdbm во многом похожа на другие библиотеки, но подпадает под действие лицензии LGPL, что делает ее более привлекательной для большинства разработчиков. Базовый API-интерфейс каждой из этих библиотек похож на остальные, поэтому переносить код между библиотеками несложно.
Полный исходный код и документацию по библиотеке gdbm можно найти на Web-сайте по адресу http://qdbm.sourceforge.net. В этой главе будут описаны все функции, которые большинство приложений должны использовать для qdbm (каждая из них имеет близкие аналоги в Berkley db, adbm и ndbm). Доступны также и другие функции API, описание которых можно найти на Web-сайте qdbm.
25.1. Обзор
qdbm предлагает несколько различных API-интерфейсов. Самый основной из них, Depot, является низкоуровневым API, который мы и рассмотрим в этой главе. Интерфейс Curia позволяет разбивать базу данных на несколько файлов (для повышения масштабируемости или с целью работы в файловой системе с ограничениями), а функции Villa предлагают две модели: модель B-деревьев и модель транзакций. API-интерфейс Odeon позволяет работать с инвертированными индексами[175]. Два последних API, Relic и Hovel, предлагают реализацию таких интерфейсов, как ndbm и qdbm.