Выбрать главу

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, за исключением нескольких специализированных встроенных приложений, никогда не разрешается напрямую обращаться к физической памяти. Приложению может казаться, что у него есть такая возможность, но самом деле это тщательно управляемая иллюзия.