While researching this problem, in the comments I found someone mentioning ANSI escape codes to get the terminal size. Since I will be using ANSI escape sequences, I thought this would be a much more elegant way to get the terminal size than ioctl()
or getenv()
.
Here is a very good post about ioctl(), and here is the comment that piqued my interest.
Now, I did find some posts (1, 2) about ANSI, but none answer the specific question I have - how to actually do it?
Using this chart, I deduced that in order to move the cursor to the extreme right and down position, I would need the CUP
(CSI n ; m H
) "Cursor Position" command, which would probably translate to something like \x1b[9999;9999H
. This is the easy part since it is a command.
The second part is where I have a big problem. Even if I could deduce that I need the DSR
(CSI 6n
) "Device Status Report" command, and that it goes \x1b[6n
, I still don't know how this querying works and where the data is stored and how can I take the data and store it in a variable, preferrably without disrupting the other data that is being displayed on the terminal.
Please help me figure out how to do it.
Thank you!
CodePudding user response:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <ctype.h>
#define SIZE 100
int main ( void) {
char in[SIZE] = "";
int each = 0;
int ch = 0;
int rows = 0;
int cols = 0;
struct termios original, changed;
// change terminal settings
tcgetattr( STDIN_FILENO, &original);
changed = original;
changed.c_lflag &= ~( ICANON | ECHO);
changed.c_cc[VMIN] = 1;
changed.c_cc[VTIME] = 0;
tcsetattr( STDIN_FILENO, TCSANOW, &changed);
printf ( "\033[2J"); //clear screen
printf ( "\033[9999;9999H"); // cursor should move as far as it can
printf ( "\033[6n"); // ask for cursor position
while ( ( ch = getchar ()) != 'R') { // R terminates the response
if ( EOF == ch) {
break;
}
if ( isprint ( ch)) {
if ( each 1 < SIZE) {
in[each] = ch;
each ;
in[each] = '\0';
}
}
}
printf ( "\033[1;1H"); // move to upper left corner
if ( 2 == sscanf ( in, "[%d;%d", &rows, &cols)) {
printf ( "%d rows\n", rows);
printf ( "%d cols\n", cols);
}
// restore terminal settings
tcsetattr( STDIN_FILENO, TCSANOW, &original);
return 0;
}