如何使用termcap在C程序中获取光标位置,而无需编写字符?

时间:2017-05-19 20:45:15

标签: c terminal termcap

我想知道如何在我的程序中获取光标位置(x,y),而无需在屏幕上写任何内容,也不会一直跟踪它。

我找到了一种方法来获得它在这个功能中的位置(我不会在这里检查读取,写入等的返回,以便在这个主题上编写一个较小的代码,但是我在我的程序中这样做了):< / p>

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。

1 个答案:

答案 0 :(得分:3)

有几个问题:

  • 规范模式缓冲(见下文)

  • 在{em>标准输出的文件描述符上完成了read(这可能会发生 - 有时 - 但不要指望它)

  • read无法读取足够的字符以获得典型回复

  • 响应将有两个十进制整数,以分号分隔 ;

  • 响应将有一个最终字符(如果read实际上要求足够的字符,这将成为一个问题......)

进一步阅读:

  

在规范模式输入处理中,终端输入以行为单位进行处理。一行由换行符(NL),文件结束符(EOF)或行尾(EOL)字符分隔。有关EOFEOL的详细信息,请参阅特殊字符。这意味着read请求将返回,直到输入整行或收到信号为止。此外,无论read()调用中请求了多少字节,最多只返回一行。但是,不必一次读取整行;可以在read()中请求任意数量的字节,甚至一个字节,而不会丢失信息。

    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

也就是说,您的程序应该准备好阅读 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应用程序中使用光标位置报告