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

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

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

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

Эта функция дает мне точную позицию курсора (* rows = y, * col = x), но она записывает на экран.

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

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

Существует несколько проблем:

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

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

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

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

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

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

  • Общий интерфейс терминала . Единая спецификация UNIX ®, версия 2

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

  • Последовательности управления XTerm
     CSI Ps n Отчет о состоянии устройства (DSR).
                 Ps = 5 -> Отчет о состоянии.
               Результат («ОК») - CSI 0 n
                 Ps = 6 -> Позиция курсора отчета (CPR) [строка; столбец].
               Результат - CSI r;  c 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.