【问题标题】:How do you read the arrow keys?你怎么读箭头键?
【发布时间】:2016-04-21 20:18:08
【问题描述】:

通过 termios 和 xterm 对 raw 模式的使用进行广泛搜索,导致大量引用了区分 escape-sequence 和单独出现的 escape 所需的“计时技巧” 字符。

那么你是怎么做到的呢?

我不想使用诅咒,因为我不想清除屏幕。这是一个计算器风格的程序,所以保留“ticker-tape”界面很重要。

【问题讨论】:

  • 咳嗽 ncurses 咳嗽
  • 使用ncurses
  • 像@AshishAhuja 所说的那样使用ncurses
  • 仅当终端被设计为发送不同的 ESC 代码时...叹息;我想他们这样做是为了手动输入缺失的序列
  • 我不知道为什么三个评论者建议 ncurses 显然不符合 OP 的要求。 ncurses 控制整个屏幕。大多数现代 shell 都可以在不强制全屏 UI 的情况下读取箭头键。

标签: c unix xterm termios


【解决方案1】:

终于在old usenet thread 中找到了一个很好的详细描述。我完整引用了相关信息。

路径:utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!usenet.ins.cwru.edu!ncoast!allbery 来自:所有...@NCoast.ORG (Brandon S. Allbery KB8JRR) 新闻组:comp.unix.programmer 主题: Re: 你是怎么看方向键的? 消息 ID: 日期:格林威治标准时间 91 年 1 月 1 日 03:56:56 参考: 回复:所有...@ncoast.ORG (Brandon S. Allbery KB8JRR) 后续行动:comp.unix.programmer 组织:北海岸计算机资源(ncoast) 行数:68 引自 brn...@kramden.acf.nyu.edu (Dan Bernstein): +--------------- |这真的是终端的错,而不是程序员的错。代码 |来自终端的应该是唯一可解码为非定时字节 |流。在最好的情况下,没有代码是另一个代码的前缀。 +---------------

AT&T 有一个很好的解决方案来解决这个问题;不幸的是,这取决于 AT&T termio(或 POSIX termios),因此在 BSD 变体下实现它是 难的。虽然可以想象使用 select 想出一个 hack, 它不会那么可靠。我知道的至少一种商业产品 使用此方法(termio,而不是 select),但它至少记录在一个 程序员手册我也看过。

Termio(s) 并没有真正的“原始”模式;它有一个“数据包”模式。最多 常见的用途是数据包大小为 1,超时时间为 1(被视为 “没有超时”)。但是,可以将其设置为其他组合。最多 在这种情况下有用的是将数据包大小设置为最长的大小 功能键序列和超时所需的最长时间 作为功能键发送。假设(通常是正确的)是,如果 用户键入它,它需要更长的时间。

完成此操作后,您将尝试 read() 最长的字符数 同时。 read() 返回之前读取的实际字符数 超时,在收到数据包的第一个字符后开始。 因此,像 ESC 这样的单个击键被这样读取,但给出了类似 VT100, PF1 会返回 3 个字符 --- ESC O P (ESC [ P if, like me, you 讨厌应用程序的光标和键盘模式)。

struct termio tbuf; /* POSIX: struct termios */
int maxlen = 3, len;
char buf[3];

ioctl(0, TCGETA, &tbuf); /* POSIX: tcgetattr(0, &tbuf); */
tbuf.c_lflags &= ~(ICANON|ECHO);
tbuf.c_cc[VMIN] = maxlen;
tbuf.c_cc[VTIME] = 2; /* 2/10 sec, good at 9600 baud and up */
ioctl(0, TCSETAW, &tbuf); /* POSIX: tcsetattr(0, X???WAIT, &tbuf); */
              /* I forget the exact flag */

len = read(0, buf, maxlen);
if (len == 1)
{
    /* single character */
}
else
{
    /* function key sequence */
}

为各种波特率获取正确的 VTIME 可能很棘手;但它也是一个 一次性任务。我在自己的程序中使用了这个技巧;它运作良好。 我相信 SVR3 诅咒中的功能键支持可以强制执行 如果启用了 halfdelay() 并在您的端口中工作,则此操作。

对于 BSD,我最多只能检查您的版本(例如 Ultrix 3.x 或 SunOS 4.x 等)支持 termio 接口,或等待 BSD4.4 哪个 据说会有POSIX termios。 (因为 BSD4.4 要么出来要么将会 很快——我已经与它脱节了——毫无疑问有人会插话 并告诉我们。)请注意,早期的 Ultrix 版本声称有 termio 支持,但是没用。

我已经删掉了这个作者的签名栏,因为他承认自己不是原作者。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
  • 2010-09-24
  • 2010-09-05
  • 2013-10-21
相关资源
最近更新 更多