5

我想知道如何在我的程序中获取光标位置(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。

4

1 回答 1

4

有几个问题:

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

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

  • read没有读取足够的字符来获得典型的响应

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

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

进一步阅读:

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

    CSI Ps n 设备状态报告 (DSR)。
                Ps = 5 -> 状态报告。
              结果(“OK”)为 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 应用程序中使用光标位置报告。

于 2017-05-21T12:59:00.463 回答