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.

+3


source to share


1 answer


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:

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 on EOF

and EOL

see Special Characters. This means that the query read

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.

+2


source







All Articles