Следующий параметр отвечает за включение и отключение управления потоком. Управляя потоком на уровне терминала, пользователь может приостанавливать процесс вывода данных на терминал, не допуская прокрутки, а затем возобновлять его. Обычно для приостановления процесса вывода данных на экран используется <Ctrl+S> и <Ctrl+Q> — для возобновления этого процесса. Хотя эта особенность удобна для некоторых утилит, ориентированных на работу со строками, программы, работающие с библиотекой S-Lang, обычно ориентированы на работу с экраном, поэтому она может оказаться излишней. S-Lang позволяет приложениям отключать эту функциональность, в результате чего программа сможет назначить нажатия клавиш Stop (Стоп) и Start (Пуск) для других команд. Чтобы включить управление потоками, функции SLang_init_tty()
необходимо передать ненулевое значение в качестве второго параметра.
Последний параметр разрешает заключительную обработку вывода на терминале. Любой механизм ядра, связанный с заключительной обработкой, будет включен, если последний параметр будет иметь ненулевое значение. Информацию об обработке выходных данных можно найти в главе 16.
24.1.2. Восстановление состояния терминала
После того как состояние терминала было изменено с помощью функции SLang_init_tty()
, программа, прежде чем завершить свою работу, должна явным образом восстановить первоначальное состояние терминала. Если этого не сделать, то вряд ли можно будет работать с терминалом после завершения программы. Функция SLang_init_tty()
не принимает и не возвращает никаких аргументов.
Если вы пишете программу, работу которой нужно будет приостановить (обычно посредством нажатия <Ctrl+Z>), то эту функцию также необходимо вызывать после получения сигнала SIGTSTP
. Более подробно об обработке сигнала SIGTSTP
можно прочитать в главе 15.
Не исключено, что в процессе разработки программ с помощью библиотеки S-Lang в них будут неоднократно происходить сбои, после которых терминал будет находиться в нестандартном состоянии. С этой проблемой можно справиться, если выполнить команду stty sane
.
24.1.3. Чтение символов с терминала
После правильной инициализации терминала чтение одиночных нажатий клавиш не составит труда. Функция SLang_getkey()
возвращает одиночный символ из терминала. Однако это не означает, что функция возвращает одиночное нажатие клавиши, ведь в системе Unix после многих нажатий клавиш может быть возвращено несколько символов. Например, на терминале VT100 (а также на многих других терминалах, включая консоль Linux) при нажатии клавиши <F1> на экран посылается четыре символа — ESC [ [ А
(попробуйте запустить slecho
, нажать клавишу <F1> и посмотрите, что получится). Чтобы установить соответствие между подобными многосимвольными последовательностями и нажатиями клавиш, можно использовать базу данных terminfo
[37].
Функция SLang_get_key()
, прежде чем вернуть результат, в течение неопределенного периода времени ожидает нажатие символа, который необходимо представить. В случае возникновения ошибки вместо действительного символа эта функция возвращает значение 0xFFFF
[169].
24.1.4. Проверка ожидающего ввода
Во многих случаях вам нужно будет проверять доступные символы, не прибегая при этом к блокировке. Это удобно делать тогда, когда программе необходимо перейти к фоновой обработке, а пользователю в этот момент посылается запрос на ввод данных (особенно в видеоиграх). Функция SLang_input_pending()
определена следующим образом:
int SLang_input_pending(int timeout);
Функция SLang_input_pending()
возвращает true
, если символы стали доступными в течение n десятых долей секунды. Она возвращает результат, как только символы становятся доступными, и false
, если ни один из символов не окажется доступным в течение определенного периода времени. Если задать нулевой период времени, то функция SLang_input_pending()
сообщит о доступных в данный момент символах.
Это поведение легко пронаблюдать. Для этого в программе slecho.с
достаточно изменить проверку в цикле while
:
while (ch != 'q' && SLang_input_pending(20))
Теперь программа будет ожидать ввода дополнительных данных не более двух секунд. По истечении двух секунд, если никакие данные не будут введены, работа программы будет завершена.
24.2. Обработка вывода
Функции библиотеки S-Lang, предназначенные для вывода данных на терминал, бывают двух разновидностей: функции управления терминалом (семейство SLtt
) и функции высокого уровня для управления экраном (семейство SLsmg
).
Функции, принадлежащие семейству SLtt
, работают напрямую с терминалом; к ним принадлежат функции, осуществляющие отображение данных в строгом соответствии с возможностями, определенными в терминальной базе данных. Это семейство также включает набор подпрограмм для определения пар цветов переднего плана и фона, а также включения и выключения курсора. Разработчики приложений обычно используют только некоторые из этих функций, а остальные вызываются внутри самой библиотеки S-Lang.
Семейство SLsmg
предлагает высокий уровень абстракции терминала. Хотя эти функции используют функции семейства SLtt
для управления терминалом, они предлагают разработчикам приложений интерфейс с более широкими возможностями.
Эти функции отвечают за вывод строк, рисование линий и отправку запросов к экрану. Чтобы не допустить снижения производительности, эти подпрограммы осуществляют запись во внутренний буфер, а не напрямую на терминал. Когда приложение посылает библиотеке S-Lang запрос на обновление физического терминала, она сравнивает новое содержимое с исходным и соответствующим образом оптимизирует последовательность выходных данных.
24.2.1. Инициализация управления экраном
Прежде чем использовать функции библиотеки S-Lang для вывода данных на терминал, программа должна послать S-Lang запрос на поиск текущего терминала (как это определено в переменной окружения TERM
) в терминальной базе данных. Это осуществляется следующим образом:
void SLtt_get_terminfo(void);
Одной из главных задач функции SLtt_get_terminfo()
является установка физического размера экрана в соответствии с размером, указанным в базе данных терминала. Информация о количестве строк и колонок в терминале хранится, соответственно, в SLtt_Screen_Rows
и SLtt_Screen_Cols
. Хотя данные в терминальной базе данных обычно корректны, в настоящее время широкую популярность приобрели терминалы с изменяемыми размерами (например, xterms
). После того как размер такого терминала будет изменен по отношению к размеру, принятому по умолчанию, терминальная база данных не будет содержать корректной информации о размерах терминала. Для компенсации этой неточности библиотека S-Lang позволяет программам восстанавливать исходные значения SLtt_Screen_Rows
и SLtt_Screen_Cols
после вызова функции SLtt_get_terminfo()
. В системе Unix текущие размеры терминала всегда можно узнать с помощью команды TIOCGWINSZ
управления вводом-выводом, которая подробно описана в главе 16.
Инициализировать уровень управления экраном в S-Lang можно очень просто:
void SLsmg_init_smg(void);
SLsmg_init_smg()
169
Ошибка возникает, если получение сигнала происходит в тот момент, когда S-Lang ожидает нажатие клавиши.