问题
I would like to know how to get the cursor position (x, y) in my program, without writing anything on the screen neither tracking it all the time.
I found out a way to get its position with this function (I don't check the return of read, write, etc here to write a smaller code on this subject 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 cursor position (*rows = y, *col = x), but it writes on the screen.
How can I get the cursor position without writting anything on the screen ? (because if the cursor is on one of the printed characters, it will overwrite it).
This is a school project, so I only can use termcap, I can't use ncurses functions, the only allowed functions are tputs, tgoto, tgetstr, tgetnum, tgetflag.
回答1:
There are several problems:
canonical mode is buffered (see below)
the
read
is done on the file-descriptor for standard output (that may happen to work — sometimes — but don't count on it)the
read
does not read enough characters to get a typical responsethe response would have two decimal integers, separated by semicolon
;
the response would have a final character (which would become an issue if the
read
actually asked for enough characters...)
Further reading:
- General Terminal Interface The Single UNIX ® Specification, Version 2
In canonical mode input processing, terminal input is processed in units of lines. A line is delimited by a newline character (
NL
), an end-of-file character (EOF
), or an end-of-line (EOL
) character. See Special Characters for more information onEOF
andEOL
. This means that aread
request will not return until an entire line has been typed or a signal has been received. Also, no matter how many bytes are requested in the read() call, at most one line will be returned. It is not, however, necessary to read a whole line at once; any number of bytes, even one, may be requested in a read() without losing information.
- XTerm Control Sequences
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
That is, your program should be prepared to read Escape[
followed by two decimal integers (with no fixed limit on their length), and two other characters ;
and R
.
By the way, termcap by itself will do little for your solution. While ncurses has some relevant 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)
few programs use those, and in any case you would find it difficult to use the cursor position report in a termcap application.
来源:https://stackoverflow.com/questions/44078725/how-to-get-the-cursor-position-in-a-c-program-using-termcap-without-writing-a-c