How to get the cursor position in a C program using termcap without writing a character?
I would like to know how to get the position of the cursor (x, y) in my program without writing anything to the screen, without tracking it all the time.
I found out a way to get my position using this function (I don't check the return of read, write, etc. here to write less code on this topic, but I do it in my program):
void get_cursor_position(int *col, int *rows)
{
int a = 0;
int i = 0;
char buf[4]
write(1, "\033[6n", 4); // string asking for the cursor position
read(1, buf, 4);
while (buf[i])
{
if (buf[i] >= 48 && buf[i] <= 57)
{
if (a == 0)
*rows = atoi(&buf[i]) - 1;
else
*col = atoi(&(buf[i]) - 1;
a++;
}
i++;
}
}
This function gives me the exact position of the cursor (* rows = y, * col = x), but it writes to the screen.
How can I get the cursor position without clicking anything on the screen? (because if the cursor is on one of the printable characters it will overwrite it).
This is a school project so I can use termcap, I cannot use ncurses functions, the only valid functions are tputs, tgoto, tgetstr, tgetnum, tgetflag.
source to share
There are several problems:
-
canonical mode is buffered (see below)
-
read
is executed on the file descriptor for stdout (it may happen that you are working but not counting on it) -
read
doesn't read enough characters to get a typical answer -
the answer will have two decimal integers separated by semicolons
;
-
the response will have a trailing character (which would be a problem if you
read
actually requested enough characters ...)
Further reading:
- Common Terminal Interface UNIX® Unified Specification Version 2
In canonical mode input mode, terminal input is processed in line units. The line is separated by a newline character (
NL
), an end of file character ( ),EOF
or an end of line character (EOL
). For more information onEOF
andEOL
see Special Characters. This means that the queryread
will not return until the whole line is printed or a signal is received. Also, no matter how many bytes are requested when calling read (), at most one line will be returned. However, it is not necessary to read the entire line at once; any number of bytes, even one, can be requested in read () without loss of information.
CSI Ps n Device Status Report (DSR). Ps = 5 -> Status Report. Result ("OK") is CSI 0 n Ps = 6 -> Report Cursor Position (CPR) [row; column]. Result is CSI r; c R
Thus, your program should be ready to read , followed by two decimal integers (with no fixed limit on their length) and two other characters and .Escape [
;
R
By the way, termcap by itself will do little for your solution. Although ncurses has some related capabilities defined in the terminal database:
# u9 terminal enquire string (equiv. to ANSI/ECMA-48 DA)
# u8 terminal answerback description
# u7 cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
# u6 cursor position report (equiv. to ANSI/ECMA-48 CPR)
several programs use them, and you will find it difficult to use the cursor position report in termcap anyway.
source to share