21.4. Direct Screen Writing
There are some cases in which being able to write characters to the screen is simply insufficient, partially because it is impossible to determine the current state of the screen. Although standard Unix practice is to ignore the state of the screen to set it up as you need it, make changes to it as you have changes to make, and to redraw it completely any time the user requests it (usually by pressing ^L) you may have other applications in mind.
In particular, screen capture and restore programs and functions need access to the current contents of the screen. Linux provides this through two interfaces. One provides only the text contents of the screen, and one contains attributes (color and so forth), as well.
The simple text device is called vcs, which presumably stands for virtual console screen. The /dev/vcs0 device when read produces the contents of the current virtual console as it is being viewed at the time it is read. If the screen is currently scrolled back (the Control-PageUp and Control-PageDown keys are set up to control console scrolling by default), /dev/vcs0 contains the scrolled-back contents that are being viewed. The rest of the vcs devices, /dev/vcs n, each represent the current state of the virtual console n, normally accessed through /dev/ttyn.
 This section belongs logically to Chapter 20 because it is related to virtual consoles, but it belongs in this chapter in a practical sense you would not know to look in Chapter 20 unless you did not need to read this book in the first place.
When you read /dev/vcs*, you are given no indication of new lines or of console size other than an EOF at the end of the screen. If you read 2,000 bytes and then receive an EOF, there is no indication whether the screen is 80 columns and 25 lines or 40 columns and 50 lines. No newline characters are produced to mark the ends of lines, and every empty character cell, whether or not it was ever written to, is denoted by a space character. There are several popular screen configurations, and there is no guarantee that each of them has a unique number of lines and columns. The vcs device provides an easy way for a savvy sysadmin or developer to see what is on any virtual console, but it is not very useful from a programmer's standpoint, at least alone.
One useful way to use vcs is from within X. XFree86, by default, starts the X server on the first free virtual console, not on the console that the program was started from. If you start XFree86 from virtual console 1, you do not need to change back to virtual console 1 to see the detection messages that XFree86 left on the screen; bring up a terminal window the same size as the console (normally 80 columns by 25 lines), become superuser (in order to gain access to the vcs device), and run cat /dev/vcs1. The contents of the first virtual console will fill your terminal window.
In order to write reliable programs, however, you need some basic knowledge about the state of the screen that a vcs device does not provide
The vcsa device (which presumably stands for virtual console screen with attributes) provides all this. The first four bytes of /dev/vcsan (for the same n as vcs devices) contain a header that gives the current cursor position and screen configuration. The first byte contains the number of rows, the second the number of columns, the third the cursor's current column, and the fourth the cursor's current row. The rest of the file contains alternating bytes that represent the text and text attribute bytes of the console in question.
So, if you need to know only the size of the console and its textual contents, you can read the first two bytes of the appropriate vcsa device and from then on use only the vcs device. If you want to set the current cursor position, write to the third and fourth bytes of the vcsa device (the first two bytes are read-only, so the first two characters are placeholders; we prefer to use spaces or some other similar character to make this more obvious). As an example, to move the cursor on the fourth virtual console to the eighth row and the twentieth column (counting from zero):
echo -n -e '..\023\007' > /dev/vcsa4
The -n keeps echo from adding a newline character to the end, and the -e makes it interpret escape codes, so that \nnn is interpreted as octal character nnn.
The attributes and character contents are represented as alternating bytes, the first containing the character and the second containing the attributes to apply to the character. The attribute byte is normally defined like the attribute byte used on VGA hardware. Other kinds of hardware, including the TGA cards used on many Linux/Alpha machines and the SPARC console driver, emulate the VGA attribute handling. On video hardware without color support but with underline support, it can be read slightly differently; it is designed in such a way that you can pretend that it is all VGA hardware, and all other hardware will behave somewhat reasonably.
For each attribute byte, the bits are interpreted as documented in Table 21.12. That is the VGA representation; some color hardware replaces blink by a bright background. The monochrome representation uses bit 0 of the foreground color to indicate underline.
Table 21.12. Attributes