В последнее время я задавался вопросом, как работает пользовательский интерфейс vim: когда вы его запускаете, он занимает все окно терминала, вместо того чтобы просто печатать текст и, возможно, требовать от вас ввода чего-либо, а затем выводить ниже еще одну командную строку.
Как это работает, просто из любопытства?
решение1
Окно терминала — это просто эмуляция «Тупой терминал - Википедия", который не может ничего делать, кроме как отображать строки символов, традиционно 24 строки по 80 символов ASCII, причем новые символы добавляются только в конце последней строки. (Представьте себе пишущую машинку.)
Терминалы постепенно становились «умнее», добавляя возможность перемещать курсор в определенное место, вставлять строки, отображать следующий символ цветом и т. д.
Но каждый производитель делал это по-своему, и не было единого стандарта, поэтому каждая программа встраивала в себя знания о конкретном оборудовании, с которым она использовалась. (Я помню, как мне показали программу интерфейса базы данных на торговой выставке в начале 1980-х годов. Докладчик дал список из примерно дюжины распространенных типов терминалов, с которыми она умела работать, и сказал, что всего за X долларов они могут научить ее работать с любым другим типом, который был в нашей компании.)
Тем временем BSD разработалаTermcap - Википедиябиблиотека для их системы UNIX. Она указала текстовую базу данных, которая определила набор стандартных возможностей для каждого типа терминала, и предоставила библиотеку C, которая использовала эту базу данных для определения соответствующего формата строки для отправки на терминал на основе переменной среды TERM
. Конечно, не все терминалы поддерживали все возможности, но это было нормально, программы знали, что нужно использовать только те возможности, которые были доступны (например, если терминал не имел прямой адресации, он мог перемещаться вверх/вниз на одну строку и перемещаться влево/вправо на одну позицию).
termcap.small · freebsd/freebsd · GitHubпоказывает пример записи termcap для терминала vt100:
vt100|dec-vt100|vt100-am|vt100am|dec vt100:\
:do=2\E[B:co#80:li#24:cl=50\E[H\E[J:sf=2*\ED:\
:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:\
:is=\E>\E[?1;3;4;5l\E[?7;8h\E[1;24r\E[24;1H:\
:if=/usr/share/tabset/vt100:nw=2\EE:ho=\E[H:\
:as=2\E(0:ae=2\E(B:\
:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||:\
:rs=\E>\E[?1;3;4;5l\E[?7;8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=\177:\
:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOt:\
:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:@8=\EOM:\
:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:pt:sr=2*\EM:xn:\
:sc=2\E7:rc=2\E8:cs=5\E[%i%d;%dr:UP=2\E[%dA:DO=2\E[%dB:RI=2\E[%dC:\
:LE=2\E[%dD:ct=2\E[3g:st=2\EH:ta=^I:ms:bl=^G:cr=^M:eo:it#8:\
:RA=\E[?7l:SA=\E[?7h:po=\E[5i:pf=\E[4i:
Позже,проклятия - ВикипедияБиблиотека была разработана для упрощения процесса, предоставляя функции для генерации соответствующих кодов с указанными значениями. Любая программа могла просто сказать что-то вроде tgoto(capabilities, column, row)
, и библиотека нашла бы тип терминала в TERM
переменной среды, нашла бы возможности для этого конкретного типа в базе данных termcap и сгенерировала бы строку, содержащую соответствующие команды терминала для перемещения курсора в указанную позицию.
termcap(3) - страницы руководства OpenBSDпоказывает объявления нескольких функций libcurses:
#include <curses.h>
#include <term.h>
extern char PC;
extern char * UP;
extern char * BC;
extern short ospeed;
int tgetent(char *bp, const char *name);
int tgetflag(char *id);
int tgetnum(char *id);
char *tgetstr(char *id, char **area);
char *tgoto(const char *cap, int col, int row);
int tputs(const char *str, int affcnt, int (*putc)(int));
Программы, такие какvi - Википедия, использовал эти библиотеки для создания редактора, который работал бы на любом терминале с адресуемым экраном. Для нового типа терминала требовалось только определить его запись termcap, и он автоматически и мгновенно работал бы с vi
любой другой программой, основанной на этой библиотеке.
В конце концов termcap
была заменена улучшенной версией под названием terminfo
, а затем curses
была заменена новой версией ncurses
, но основные принципы остались прежними.
Обратите внимание, что все это основано на способности UNIX считывать символы, введенные с клавиатуры.безавтоматически отображая его на терминале. Многие операционные системы того времени не могли этого сделать. Некоторые даже не принимали ввод с терминала, пока не была введена вся строка (или даже экран).
решение2
Программы с полноэкранным текстовым пользовательским интерфейсом (TUI) в Unix-подобных операционных системах используют библиотеку позиционирования курсора, называемую curses
.
Первоначально эта библиотека использовала базу данных возможностей терминала, известную как , termcap
которая позже была заменена системой, известной как terminfo
.
Приложения TUI, отображаемые в окнах графического рабочего стола, используют сигналы изменения размера окна, такие какsigwinch