Terminals

来自osdev
Zhang3讨论 | 贡献2022年1月12日 (三) 07:45的版本 (创建页面,内容为“This page is about the very essentials of how to implement video terminal functionality. Terminals are connected to the OS over serial port, but could use network too with the telnet and ssh protocols. ==History== 200px|thumb|A real terminal 200px|thumb|PuTTY with serial port option 200px|thumb|Minicom running in xterm Originally terminals were line print…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

This page is about the very essentials of how to implement video terminal functionality. Terminals are connected to the OS over serial port, but could use network too with the telnet and ssh protocols.

History

文件:VT220 Irssi.jpg
A real terminal
文件:PuTTY Ubuntu.png
PuTTY with serial port option
文件:Minicom cs xterm.png
Minicom running in xterm

Originally terminals were line printers. The user typed in a command, pressed enter, and the computer executed that command and printed the results line by line. This is where command line interface originates. It understood the basic ASCII control characters, like ASCII 8 (backspace), ASCII 10 (line feed), ASCII 13 (carriage return) etc. but nothing else.

Although this input and output method works for simple programs, it is very complicated to implement a text editor for example. Many editors kept the line terminal heritage, like Vi, but to provide a more comfortable interface, the printer was replaced with a screen. With it come the need to position the cursor on the screen, hence video terminal and video terminal sequences was born.

There were many more or less successful terminals (most notably the VT52), but finally Digital Equipment Corporation's VT100 got widespread and its codes got standardized. The VT100 codes (also called ANSI escape codes) are the most widely emulated sequences, ever.

Communication

When your OS is communicating over the serial like, it is very likely that on the other end there's a terminal. Either a real one, or a terminal emulator, like PuTTY or minicom. It is the terminal's duty to handle the keyboard, the key modifier keys (like Shift, Control, Alt), and send terminal key sequences. It is also the terminal's duty to interpret the received terminal codes (sometimes also called escape sequences) and visualize them properly. These sequences always start with the ASCII 27 (escape) character, "\033" in C literals, and terminated by a latin uppercase or lowercase letter or tilde ("~"). In between there might be numeric parameters (0-9) separated by comma ("," and ";") but such arguments are always prefixed by "[". This two bytes start sequence "\033[" also called Control Sequence Introducer, or CSI.

Receiving Keys

This section is about the bytes your OS might receive from a terminal. It is important to know that terminals are different, some are configurable, so they might send different codes. For a comprehensive list of all possible key codes, consult the termcap database.

Code Name Meaning
ASCII 3 Break (^C) the Break signal
ASCII 7 Bell (^G) makes a beep
ASCII 8 BS (^H) Backspace, moves the cursor left and delete, some terminals send ASCII 127 instead
ASCII 9 Tab (^I) Tabulator, moves to cursor to the next multiple of 8 coloumn on the right
ASCII 10 Line Feed (^J) move the cursor down (on modern machines line feed and carriage return is combined and called newline)
ASCII 13 Carriage Return (^M) Return or Enter key, move the cursor to the left most coloumn
ASCII 27 Escape (^[) start the command sequences
ASCII 32 - 126 keys "normal" keys
ASCII 127 or \033[3~ Delete delete without moving the cursor, some terminals send ASCII 127 instead of ASCII 8, but \033[3~ is standard
\033[A Up up arrow key
\033[B Down down arrow key
\033[C Right right arrow key
\033[D Left left arrow key
\033[5~ or \033[S PgUp the Page Up key
\033[6~ or \033[T PgDn the Page Down key
\033[7~ or \033[H Home the Home key
\033[8~ End the End key
\033[11~ to \033[21~ F1 - F10 function keys
\033[row;colR Status report answer to the \033[6n code

Note that cursor keys are standard, but there might be differences with the Home, End, PgUp, PgDn and Fn keys depending on the terminal. Key modifiers (like Shift, Caps Lock, Control, Alt, Compose etc.) are always interpreted by the terminal, and have no codes.

Sending Sequences

These are the bytes that your OS might send to a terminal. Terminals and terminal emulators are different, they usually understand different codes. However there's a subset of codes that all guaranteed to understand, and those are the VT100 codes. Modern terminal emulators usually support more, the VT220 subset is the smallest common denominator. Everything above that requires exact terminal type detection and differentiated codes.

Code Name Meaning
\033[nA CUU move the cursor up n rows
\033[nB CUD move the cursor down n rows
\033[nC CUF move the cursor right n coloumns
\033[nD CUB move the cursor left n coloumns
\033[nE CNL move the cursor to the beginning of line n down
\033[nF CPL move the cursor to the beginning of line n up
\033[nG CHA move the cursor to coloumn n
\033[H CUP move the cursor to the top left corner of screen
\033[row;colH CUP move the cursor
\033[row;colf HVP move the cursor
\033[J or \033[0J ED clear the screen from cursor to the end
\033[1J ED clear the screen from beginning to the cursor
\033[2J ED clear the entire screen
\033[K or \033[0K EL clear the line from cursor to the end
\033[1K EL clear the line from beginning to the cursor
\033[2K EL clear the entire line
\033[S SU scroll up one page
\033[T SD scroll down one page
\033[m SGR reset color attributes
\033[1m SGR select bold or intensive color
\033[30-37m SGR select foreground color
\033[40-47m SGR select background color

The Select Graphic Rendition (or SGR) codes are often concatenated into one command, for example to select bright white on blue background \033[1;37;0;44m. Some terminals understands color codes 90 - 97 (same as 1;30 - 1;37) and 100 - 107 (same as 1;40 - 1;47).

For the foreground and background color codes, these are as follows:

FG BG Name RGB (VGA colors)
30 40 Black 0,0,0
31 41 Red 170,0,0
32 42 Green 0,170,0
33 43 Yellow 170,85,0
34 44 Blue 0,0,170
35 45 Magenta 170,0,170
36 46 Cyan 0,170,170
37 47 White 170,170,170
1;30 1;40 Bright Black (Gray) 85,85,85
1;31 1;41 Bright Red 255,85,85
1;32 1;42 Bright Green 85,255,85
1;33 1;43 Bright Yellow 255,255,85
1;34 1;44 Bright Blue 85,85,255
1;35 1;45 Bright Magenta 255,85,255
1;36 1;46 Bright Cyan 85,255,255
1;37 1;47 Bright White 255,255,255

Detecting Terminal

First and most, you should detect the size of the screen. This is done by moving the cursor over the screen, and then query the position.

\033[999;999H\033[6n\033[H = your OS to the terminal

\033[row;colR = the terminal's answer, screen size

To detect the exact terminal type to determine if you can use advanced codes (like \033[38;2;r;g;bm RGB foreground color), well, not possible, as there's no commonly supported identify command. Each terminal has a special command with a specific answer that you can use. Or simply leave it to the user, many OS use the TERM environment variable to select a code set from the termcap database.

Implementing A Terminal

Once your OS is sufficiently advanced, you'll probably want to implement a terminal emulator on your OS too so that you can receive connections. For that, you must interpret these sequences, display them on screen accordingly, and convert the keyboard scancodes into ASCII sequences. Under DOS, this exactly what ANSI.SYS does. For Linux, take a look at minicom's source code.

See Also

External Links