I am writing a program that changes the color of the characters based on their position in the terminal. I need to get the cursor position at least once in order to do this. I do not need the row, only the column is of interest.
I looked it up and I found the ANSI escape sequence ESC[6n
which is supposed to return the current position of the cursor in stdin
, in the following format: ESC[<row>;<col>R
.
I wrote a small test program (largely inspired by this answer) through which I tried to isolate the behavior of this escape sequence, and it is able to get the row number correctly, but for some reason, the column is always 1.
Here's a piece of relevant C code:
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
int main() {
// This will shift the cursor right a few places
printf("some text");
struct termios restore;
tcgetattr(0, &restore);
// Disable flags in order to read the response
struct termios term;
tcgetattr(0, &term);
term.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &term);
// Write ANSI escape sequence for cursor position
write(1, "\033[6n", 4);
// Read back response
char buffer[16] = { 0 };
int idx = 0;
char ch;
while (ch != 'R') {
read(0, &ch, 1);
buffer[idx] = ch;
++idx;
}
buffer[idx] = '\0';
// Restore original settings
tcsetattr(0, TCSANOW, &restore);
// +1 because the first character is ESC
puts(buffer + 1);
return 0;
}
On my terminal (mintty), this code has the following output:
$ ./main
some text[3;1R
The row was, indeed, 3. However, the column should have been 10, not 1, because of the text it printed earlier. What is the reason for this behavior? Is there something wrong with my code, or could the problem be with the terminal? Alternatively, is there another standard/more correct way of getting the column of the cursor?
Thanks in advance.