Cursor Appearance in the Linux Console
Escape sequences to control the cursor appearance in the Linux console (text, no X11) are yet to be included in the manpage on console_codes, but they are tentatively documented in the file
This article is mainly an interpreted version of the file above, with examples added. The file was written in 1999; if you read it, you'll understand why it needs interpretation.
The following files are also relevant:
the first of which is, unfortunately, quite tough to digest.
(1) Hardware vs. Software Cursor
The Linux cursor is, by default, the normal PC text-mode cursor. It looks like a short blinking underscore, whitish on black, with weak contrast in daylight. This is the hardware cursor, i.e., it is generated by the hardware.
However, Linux has the ability to manipulate the cursor appearance using, e.g., a software-generated non-blinking full block cursor. This is done with the escape sequence
where \e is the escape character, and p1, p2 and p3 are parameters. The last semi-colon is optional. It is used here to tell the sequence closing letter 'c' from the parameters. If you omit any of the parameters, they will default to zero. Only decimals are accepted, and you will never get an error: your input is going to be restrained to the valid range.
Each console can have its own custom softcursor.
Parameter 3 sets the colour bits in the VGA adapter's register, parameter 2 toggles the colour bits, and setting goes before toggling. What that means in practice we'll have to find out.
Parameter 1 specifies cursor size as follows:
0 default 1 invisible 2 underscore 3 lower_third 4 lower_half 5 two_thirds 6 full block
The size refers to the character cell at the cursor. As an example, issuing
echo -e "\e[?3c"
from the command line will turn the cursor into a thick underscore, reclaiming one third of the character cell.
Values 7-15 are also accepted, but they give the same as 6. The cursor default is defined in console-struct.h as the underscore, so, by default, value 0 is same as value 2.
If the first parameter is less than 16, parameters 2 and 3 will be set to 0, and you get the hardware cursor, whitish on black. If visible, it will blink.
As for size, the good news is that parameter 1 really works. The bad news is that parameter 2 and 3 depend in part on VGA peculiarities likely to be implemented differently from graphic adapter to graphic adapter. It can be assumed that the kernel contributors were coding according to the official VGA standard, but that rarely used VGA specifications are implemented in a non-standard way.
A softcursor is obtained setting parameter 1 to 16. Values 17-31 are same as 16. A softcursor is a non-blinking full block in some colour.
For instance, let's try
echo -e "\e[?16c"
We see nothing. How come? Very simple - the cursor is now a block of one full character cell. Parameter 2 and 3 are missing, so they default to 0. That block uses colour 0, which is black. Black on black, gives what? That's what you are seeing.
Lesson learnt: if we want to see the softcursor, we must specify parameter 2 and 3 in a suitable way. Let's try again:
echo -e "\e[?16;0;16c"
You can go through the entire range of colours (0-7), leaving the second parameter at 0 and setting the third parameter to a multiple of 16, or rather a multiple with factor 1-7. Factor 0 already taught us a lesson. Only dim colours will obtain.
So far, so good. We can get a blinking cursor in differing sizes; its colour will be the foreground colour in the console. We can get a non-blinking cursor in (dim) colours, independently of foreground and background colours in the console.
The values you enter for parameter 1 are reduced modulo 32. That means 0-31, 32-63, 64-95 ... are the same. However:
48-63 (range 16-31 plus 32) gives a softcursor using the console foreground colour, making the character at the cursor invisible 112-127 (range 16-31 plus 32 plus 64) gives a softcursor using the console foreground colour but allowing the character at the cursor to be read
Try the following:
(i) echo -e "\e[?48c" (ii) echo -e "\e[?112c"
Note that you are not specifying parameters 2 and 3. If you do, the parameters will apply.
Also note that a bold foreground colour will be dimmed when used as background by the softcursor. So if you changed the console default to bold white on black, both (i) and (ii) will give a dim white non-blinking block.
If you try to get some interesting cursor just firing off wild parameters, be assured that your options are limited, and you will be wasting plenty of time for nothing. Essentially, what you have got to remember is:
parameter 3 determines the softcursor background,
parameter 2 determines the softcursor foreground.
This rule, however, is not 100% correct, since parameter 3 does affect the dim/bold status of the foreground. For instance, let's try the range 64-79 with parameter 2 fixed at 0. The softcursor background is in this case red. What changes when the parameter runs through the range 64-79 is how the character at the cursor shows up.
We are starting from the defaults dim white on black and issue
echo -e "\e[?16;0;64c"
The cursor background is red; the character at the cursor is dim white. We go up from 64 to 71, and the result is the same. However, for 72-79, the character at the cursor is turned bold; we have bold white on red.
The result is simple: with parameter 2 fixed at 0, parameter 3 will have
dim foreground for 16*k + l (l is 0-7) bold foreground for 16*k + l (l is 8-15)
where k runs from 1-7.
Fine, but what if we keep parameter 3 fixed and let parameter 2 run? In our example, we keep parameter 3 at 64, and let parameter 2 go through 1-15. The result is cursor foreground in different colours, while the background does not change.
This is the maximum you can aspire to. The softcursor's own foreground and background can be different from foreground and background in the console, showing you four colours at all times.
You have dutifully read VGA-softcursor.txt, and something caught your attention. Apparently, with the softcursor you can
[ ... ] highbright the cursor character and still keep the original hardware cursor visible.
Well, no - or at least, it depends. The authors were not aware that their hardware was behaving its own way. Compare with the following, where the author clearly warns that what he is saying applies to his ATI Mach 64 card:
echo -e '\033[?18;255;8c' -- .... if this doesn't get your attention, I don't know what will... (nonblinking 'transparent' block... blinking the character it's over - over an underline that blinks at twice the rate....)
Are we done yet? That would seem to be the case, but for a crash I experienced recently.
A small text-mode application crashed, and left behind a console with white on black and a blinking cursor underscore. That blinking underscore was red; yes, it was red!
Now, there is absolutely no trace on the Web of a hardware cursor with its own very private colour. Of course, I cannot prove it, but, after a couple of hours googling, I would take any bet. Furthermore, the official wisdom states:
On the standard VGA, the [hardware] cursor color is obtained from the foreground color of the character that the cursor is superimposing. On the standard VGA, there is no way to modify this behavior.
Source: FreeVGA Project
So here is my request for support:
- - Has anybody ever seen a console (text, no X11) with a hardware underscore blinking in its own distinct colour?
- - If so, were you able to reproduce it?
Please write to The Answer Gang at the Linux Gazette ('Talkback' link, below).
A. N. Onymous has been writing for LG since the early days - generally by sneaking in at night and leaving a variety of articles on the Editor's desk. A man (woman?) of mystery, claiming no credit and hiding in darkness... probably something to do with large amounts of treasure in an ancient Mayan temple and a beautiful dark-eyed woman with a snake tattoo winding down from her left hip. Or maybe he just treasures his privacy. In any case, we're grateful for his contribution.
-- Editor, Linux Gazette