Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading the Device Status Report ANSI escape sequence reply

I'm trying to retrieve the coordinates of cursor in a VT100 terminal using the following code:

void getCursor(int* x, int* y) {
  printf("\033[6n");
   scanf("\033[%d;%dR", x, y);
}

I'm using the following ANSI escape sequence:

Device Status Report - ESC[6n

Reports the cursor position to the application as (as though typed at the keyboard) ESC[n;mR, where n is the row and m is the column.

The code compiles and the ANSI sequence is sent, but, upon receiving it, the terminal prints the ^[[x;yR string to the stdout instead of stdin making it imposible for me to retrieve it from the program:

terminal window

Clearly, the string is designated for the program, though, so I must be doing something incorrectly. Does anybody know what it is?

like image 451
Witiko Avatar asked Apr 16 '13 00:04

Witiko


1 Answers

I ask for the cursor position. If I do not have answer after 100ms (this is arbitrary) I suppose the console is not ansi.

/* This function tries to get the position of the cursor on the terminal. 
It can also be used to detect if the terminal is ANSI.
Return 1 in case of success, 0 otherwise.*/

int console_try_to_get_cursor_position(int* x, int *y)
{
    fd_set readset;
    int success = 0;
    struct timeval time;
    struct termios term, initial_term;

    /*We store the actual properties of the input console and set it as:
    no buffered (~ICANON): avoid blocking 
    no echoing (~ECHO): do not display the result on the console*/
    tcgetattr(STDIN_FILENO, &initial_term);
    term = initial_term;
    term.c_lflag &=~ICANON;
    term.c_lflag &=~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);

    //We request position
    print_escape_command("6n");
    fflush(stdout);

    //We wait 100ms for a terminal answer
    FD_ZERO(&readset);
    FD_SET(STDIN_FILENO, &readset);
    time.tv_sec = 0;
    time.tv_usec = 100000;

    //If it success we try to read the cursor value
    if (select(STDIN_FILENO + 1, &readset, NULL, NULL, &time) == 1) 
      if (scanf("\033[%d;%dR", x, y) == 2) success = 1;

    //We set back the properties of the terminal
    tcsetattr(STDIN_FILENO, TCSADRAIN, &initial_term);

    return success;
}
like image 174
Arnaud B. Avatar answered Sep 19 '22 15:09

Arnaud B.