В предыдущей статье мы создали несколько простых слов,
управляющих терминалом с помощью команд ANSI (Escape-последовательностей).
В этой статье мы продолжим рассказывать о программировании команд управления текстовым терминалом.
"Затем я напечатал GOTO 500 - и вот он я!". Рисунок Лео Броуди.
Напомним определенные в прошлой статье слова.
Константа управляющего кода Escape:
27 CONSTANT ESC
Специальное слово, выводящее последовательность символов Escape и [ (начало команд ANSI) в текстовую консоль:
: ESC[ ESC EMIT [CHAR] [ EMIT ;
Слово для очистки экрана терминала:
: CLRSCR ESC[ ." 2J" ;
Последнее слово, которое мы создали, перемещает курсор в верхний левый угол экрана (он имеет координаты 1;1):
: CRSHOME ESC[ ." 1;1H" ;
На самом деле, эта Escape-последовательность предназначена для перемещения курсора в любую символьную позицию текстового экрана. Достаточно указать номер строки вместо первой единицы и номер столбца вместо второй.
Некоторое затруднение заключается в том, что координаты должны быть представлены текстом. Если мы хотим извлекать X и Y из стека, мы должны выводить их в текстовую консоль так, как это делает слово "точка". Но "точка" выводит после текстового представления числа дополнительный пробел. Это очень удобно при распечатке содержимого стека, но не подходит для управляющих команд.
Создадим простое слово, которое преобразует число на вершине стека в его текстовое представление и выводит на терминал (не добавляя ничего лишнего). Мы назвали слово ASC-TYPE от ASCII и TYPE (печатать):
: ASC-TYPE U>D <# #S #> TYPE ;
Разберем определение. Первое слово, U>D , преобразует число на вершине стека в двойное число без знака. Двойное число, как следует из названия, занимает в два раза больше места, то есть две ячейки на вершине стека. Двойные числа, или пары ячеек, довольно часто используются в Форте.
Такое преобразование потребовалось потому, что дальше следуют три мощных слова Форта, отвечающие за преобразование чисел в текст: <# , #S , #> . Эти слова работают с двойными числами.
Первое слово, <# , инициализирует специальный буфер в памяти данных программы, предназначенный для преобразования числа в строку.
Второе слово, #S , преобразует число с вершины стека в эквивалентную текстовую строку.
Третье слово, #> , возвращает на вершине стека длину полученной строки, а в следующей ячейке – адрес первого символа строки в памяти данных программы.
Об этих и других словах, преобразующих числа в текст, мы подробно поговорим в одной из следующих статей.
Слово TYPE выводит в текстовую консоль строку символов. На вершине стека должна находиться длина строки, а ниже – адрес первого символа строки (то есть именно то, что возвращает слово #> ).
Проверим, как работает новое слово. Введем число и посмотрим, что будет выведено на экран:
Именно такой результат нам и нужен, чтобы определить следующее слово. Это новое слово должно получать координаты X и Y в стеке (причем Y на вершине, так удобнее) и перемещать курсор в заданную позицию на экране терминала. В отличие от ANSI-команды, наши координаты будут начинаться с 0, так намного удобнее (позже вы увидите, почему).
Небольшое отступление. В Форте, как и в других языках, есть возможность оставлять комментарии в тексте программы. В Advanced Forth комментарии оформляются двумя способами. Если в начале строки стоит слово \\ , то весь текст до конца строки игнорируется Форт-системой:
\\ Вся эта строка – комментарий
Второй способ больше подходит для внедрения комментариев в определение слова. Комментарий начинается словом \ и продолжается до первого символа \ (который является частью комментария):
\ Это комментарий \
(В классическом Форте комментарии оформляются несколько иначе).
Особое значение имеют комментарии, показывающие, что должно находиться в стеке до начала выполнения слова, и что будет в стеке после. Такая запись называется стековой диаграммой.
Если мы хотим определить слово, которое получает в стеке два числа, координаты X и Y, и удаляет их из стека в процессе работы, комментарий со стековой диаграммой будет таким:
\ x y -- \
Два символа -- разделяют состояние стека до и после выполнения слова.
Теперь опишем слово GO-XY , перемещающее курсор текстового терминала в заданную позицию:
: GO-XY \ x y -- \
ESC[ 1+ ASC-TYPE [CHAR] ; EMIT 1+ ASC-TYPE [CHAR] H EMIT ;
Пройдем по тексту определения (со второй строки). Созданное ранее слово ESC[ выводит в консоль символы начала команды ANSI.
Следующее слово, 1+ , увеличивает на 1 число на вершине стека (инкрементирует его). На вершине стека находится значение Y. Мы решили, что у нас верхний левый угол экрана имеет координаты 0;0, а не 1;1, как в ANSI. Таким образом, инкремент осуществляет преобразование систем координат.
Слово ASC-TYPE выводит преобразованное значение Y в консоль. На вершине стека остается X.
Слова [CHAR] ; EMIT выводят символ ; , разделяющий координаты в команде.
Аналогичным образом инкрементируется и выводится текстовое представление координаты X.
Завершает команду ANSI вывод в консоль символа H .
Вы можете исследовать работу слова GO-XY , передавая в стеке координаты на экране. Координата X может иметь значение от 0 до 79, а координата Y – от 0 до 24 (если вы используете стандартные настройки терминала):
Подведем итоги наших экпериментов. В двух статьях мы определили следующие слова:
27 CONSTANT ESC
: ESC[ ESC EMIT [CHAR] [ EMIT ;
: CLRSCR ESC[ ." 2J" ;
: ASC-TYPE U>D <# #S #> TYPE ;
: GO-XY \ x y -- \
ESC[ 1+ ASC-TYPE [CHAR] ; EMIT 1+ ASC-TYPE [CHAR] H EMIT ;
Эти шесть строк – начало большой программы, которую мы продолжим разрабатывать в следующих статьях. Рекомендуем сохранить их в текстовом файле для удобства дальнейшего использования.
Спасибо за внимание.