void list_tracks() {
FILE *tracks_fp;
char entry[MAX_ENTRY];
int cat_length;
int lines_op = 0;
WINDOW *track_pad_ptr;
int tracks = 0;
int key;
int first_line = 0;
if (current_cd[0] == '\0') {
mvprintw(ERROR_LINE, 0, "You must select a CD first. ");
get_return();
return;
}
clear_all_screen();
cat_length = strlen(current_cat);
/* Сначала считает количество дорожек у текущего CD */
tracks_fp = fopen(tracks_file, "r");
if (!tracks_fp) return;
while (fgets(entry, MAX_ENTRY, tracks_fp)) {
if (strncmp(current_cat, entry, cat_length) == 0) tracks++;
}
fclose(tracks_fp);
/* Создает новую панель, гарантируя, что даже при наличии одной
дорожки панель достаточна большая, поэтому последующий вызов
prefresh() всегда будет допустим. */
track_pad_ptr = newpad(tracks + 1 + ВОХЕD_LINES, BOXED_ROWS + 1);
if (!track_pad_ptr) return;
tracks_fp = fopen(tracks_file, "r");
if (!tracks_fp) return;
mvprintw(4, 0, "CD Track Listing\n");
/* Записывает сведения о дорожке на панель */
while (fgets(entry, MAX_ENTRY, tracks_fp)) {
/* Сравнивает номер каталога и оставшийся вывод элемента */
if (strncmp(current_cat, entry, cat_length) == 0) {
mvwprintw(track_pad_ptr, lines_op++, 0, "%s", entry + cat_length + 1);
}
}
fclose(tracks_fp);
if (lines_op > BOXED_LINES) {
mvprintw(MESSAGE_LINE, 0,
"Cursor keys to scroll, RETURN or q to exit");
} else {
mvprintw(MESSAGE_LINE, 0, "RETURN or q to exit");
}
wrefresh(stdscr);
keypad(stdscr, TRUE);
cbreak();
noecho();
key = 0;
while (key != "q" && key != KEY_ENTER && key != '\n') {
if (key == KEY_UP) {
if (first_line > 0) first_line--;
}
if (key == KEY_DOWN) {
if (first_line + BOXED_LINES + 1 < tracks) first_line++;
}
/* Теперь рисует соответствующую часть панели на экране */
prefresh(track_pad_ptr, first_line, 0, BOX_LINE_POS, BOX_ROW_POS,
BOX_LINE_POS + BOXED_LINES, BOX_ROW_POS + BOXED_ROWS);
key = getch();
}
delwin(track_pad_ptr);
keypad(stdsсr, FALSE);
nocbreak();
echo();
}
4. В последних двух функциях вызывается функция get_return, которая приглашает к вводу и считывает символ возврата каретки, игнорируя другие символы.
void get_return() {
int ch;
mvprintw(23, 0, "is", " Press return ");
refresh();
while ((ch = getchar()) != '\n' && ch != EOF);
}
Если вы выполните эту программу, то увидите на экране нечто похожее на рис. 6.10.
Рис. 6.10
Резюме
В этой главе вы изучили библиотеку curses. Она предлагает текстовым программам удобный способ управления экраном и считывания данных с клавиатуры. Хотя библиотека curses не обеспечивает такого уровня управления, как общий терминальный интерфейс (GTI) и прямой доступ к структуре terminfo, ею гораздо легче пользоваться. Если вы пишете полноэкранное текстовое приложение, стоит рассмотреть возможность применения в нем библиотеки curses для управления экраном и чтения данных с клавиатуры.
Глава 7
Управление данными
В предыдущих главах мы касались темы ограниченности ресурсов. В этой главе мы собираемся рассмотреть сначала способы управления распределением ресурсов, затем методы обработки файлов, к которым обращается много пользователей примерно в одно и то же время, и наконец, одно средство, предоставляемое в системах Linux и позволяющее преодолеть ограничения простых файлов как среды хранения данных.
Мы можем представить все эти темы как три способа управления данными:
□ управление динамической памятью: что делать и что Linux не разрешит делать;
□ блокировка файлов: совместная блокировка, блокируемые области совместно используемых файлов и обход взаимоблокировок;
□ база данных dbm: базовая, основанная не на запросах SQL библиотека базы данных, присутствующая в большинстве систем Linux.
Управляемая память
Во всех компьютерных системах память — дефицитный ресурс. Не важно, сколько памяти доступно, ее всегда не хватает. Кажется, совсем недавно считалось, что 256 Мбайт RAM вполне достаточно, а сейчас распространено мнение о том, что 2 Гбайт RAM — это обоснованное минимальное требование даже для настольных систем, а серверам полезно было бы иметь значительно больше.
У всех UNIX-подобных операционных систем, начиная с самых первых версий, был ясный подход к управлению памятью, который унаследовала ОС Linux, воплощающая стандарт X/Open. Приложениям в ОС Linux, за исключением нескольких специализированных встроенных приложений, никогда не разрешается напрямую обращаться к физической памяти. Приложению может казаться, что у него есть такая возможность, но самом деле это тщательно управляемая иллюзия.