2

Lately, I've been wondering how vim's user interface works, that when you start it, it occupies the entire terminal window, instead of just printing text and maybe requiring you to input something and when it's done printing another command line below.

How does this work, just out of curiosity?

2 Answers 2

3

The terminal window is simply an emulation of a "Dumb terminal - Wikipedia" which can do nothing but display lines of characters, traditionally 24 lines of 80 ASCII characters, with new characters being added only at the end of the last line. (Think of a typewriter.)

Terminals gradually got "smarter", adding the ability to move the cursor to a specific location, insert lines, display the next character in colour, etc.

But every manufacturer did it in their own way, and there was no single standard, so every program would have built into it the knowledge of the specific hardware it was being used with. (I remember being shown a database interface program at a trade show in the early 1980s. The presenter gave a list of a dozen or so common terminal types that it knew how to work with, and said that for only $X they could teach it to handle whatever other type we had at our company.)

Meanwhile, BSD had developed the Termcap - Wikipedia library for their UNIX system. It specified a text-based database that defined a set of standard capabilities for each type of terminal, and provided a C library that used this database to determine the appropriate format of the string to send to the terminal based on the TERM environment variable. Not all terminals supported all capabilities of course, but that was okay, programs would know to use only those capabilities that were available (e.g. if a terminal didn't have direct addressing, it might have move up/down one line and move left/right one position).

termcap.small · freebsd/freebsd · GitHub shows a sample termcap entry for a vt100 terminal:

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:

Later, a curses - Wikipedia library was developed to simplify the process, providing functions to generate the appropriate codes with specified values. Any program could simply say something like tgoto(capabilities, column, row), and the library would find the terminal type in the TERM environment variable, look up the capabilities for that specific type in the termcap database, and generate a string containing the appropriate terminal commands for moving the cursor to the specified position.

termcap(3) - OpenBSD manual pages shows declarations of a few libcurses functions:

#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));

Programs, such as vi - Wikipedia, used these libraries to provide an editor that would work on any terminal with an addressable screen. A new type of terminal required only defining its termcap entry, and it would automatically, and instantly, work with vi and any other program based on that library.

Eventually termcap was replaced by an improved version called terminfo, and curses was replaced by a new version ncurses, but the underlying principles remained the same.

Note that this all relies on UNIX's ability to read a character entered from the keyboard without automatically displaying it on the terminal. Many operating systems at the time could not do this. Some wouldn't even accept input from the terminal until an entire line (or even screen) had been entered.

1

Programs with a full-screen textual user interface (TUI) on Unix-like operating systems use a cursor-positioning library called curses.

This library initially used a terminal-capabilties database known as termcap which was later replaced by a system known as terminfo .

TUI apps windowed in a GUI desktop make use of window resizing signals such as sigwinch

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .