Как получить позицию курсора в программе на C, используя termcap, без написания символа?

Я хотел бы знать, как получить положение курсора (x, y) в моей программе, не записывая ничего на экране и не отслеживая его все время.

Я нашел способ получить свою позицию с помощью этой функции (я не проверяю возвращение read, write и т. Д. Здесь, чтобы написать меньший код на эту тему, но я делаю это в своей программе):

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++;
    }
}

Эта функция дает мне точное положение курсора (*row = y, *col = x), но она пишет на экране.

Как я могу получить положение курсора, не записывая ничего на экране? (потому что, если курсор находится на одном из напечатанных символов, он будет перезаписан).

Это школьный проект, поэтому я могу использовать только termcap, я не могу использовать функции ncurses, разрешены только функции tputs, tgoto, tgetstr, tgetnum, tgetflag.

1 ответ

Решение

Есть несколько проблем:

  • канонический режим буферизован (см. ниже)

  • read делается на дескриптор файла для стандартного вывода (это может случиться, иногда - но не рассчитывайте на это)

  • read не читает достаточно символов, чтобы получить типичный ответ

  • ответ будет иметь два десятичных целых числа, разделенных точкой с запятой ;

  • ответ будет иметь окончательный характер (который станет проблемой, если read на самом деле просят достаточно символов...)

Дальнейшее чтение:

В обработке ввода в каноническом режиме ввод терминала обрабатывается в единицах строк. Строка ограничена символом новой строки (NL), символ конца файла (EOF) или конец строки (EOL) персонаж. См. Специальные символы для получения дополнительной информации о EOF а также EOL, Это означает, что read запрос не вернется, пока не будет введена вся строка или не будет получен сигнал. Кроме того, независимо от того, сколько байтов запрашивается в вызове read (), будет возвращено не более одной строки. Однако нет необходимости читать всю строку сразу; Любое количество байтов, даже один, может быть запрошено в read () без потери информации.

    CSI Ps n Отчет о состоянии устройства (DSR).
                Ps = 5  -> Отчет о состоянии.
              Результат ("ОК") - CSI 0 n
                Ps = 6  -> Положение курсора отчета (CPR) [строка; столбец].
              Результат - CSI r; с R

То есть ваша программа должна быть готова прочитать Escape [ за которыми следуют два десятичных целых числа (без фиксированного ограничения их длины) и два других символа ; а также R,

Кстати, termcap сам по себе мало что даст для вашего решения. В то время как ncurses имеет некоторые соответствующие возможности, определенные в базе данных терминала:

#       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)

немногие программы используют их, и в любом случае вам будет трудно использовать отчет о положении курсора в приложении termcap.

Другие вопросы по тегам