【发布时间】:2014-12-24 06:05:37
【问题描述】:
所以我有以下代码,它基本上只是读取用户输入的字符并打印它们,直到输入“q”。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<termios.h>
int main(void) {
char c;
static struct termios oldtio, newtio;
tcgetattr(0, &oldtio);
newtio = oldtio;
newtio.c_lflag &= ~ICANON;
newtio.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &newtio);
printf("Give text: ");
fflush(stdout);
while (1) {
read(0, &c, 1);
printf("%c", c);
fflush(stdout);
if (c == 'q') { break; }
}
printf("\n");
tcsetattr(0, TCSANOW, &oldtio);
return 0;
}
在 main 函数的开头,我关闭了规范模式,以便用户在输入时能够看到他的输入。我还关闭了回声,例如,当按下向上箭头键时,不会弹出诸如“^[[A”之类的东西。这可行,但我也可以将光标移动到终端窗口的上排,这并不好。有没有办法解决这个问题,让用户只能在当前行内移动?
另一个问题是退格。当我按下它时,程序会打印一个奇怪的符号(我假设它是 0x7f),而不是擦除光标当前位置左侧的字符。我应该以某种方式适当地处理程序中的退格键输出,但我不知道该怎么做,因为它是这个奇怪的十六进制数字。有什么建议吗?
我也一直在考虑使这项工作的一个选项是使用规范模式,以便自动使用箭头键和退格功能。但是,规范模式逐行工作,因此在用户点击“Enter”之前不会出现文本。到目前为止,我还没有想出任何方法让用户在打字时看到他的输入。这甚至可能吗?
请不要使用 ncurses 或 readline 建议。我想使用 termios.h 来做到这一点。
【问题讨论】:
-
您关闭回显,然后自己回显所有内容。这不是一个成功的策略。回显普通可打印字符,处理和解释控制序列。您需要知道您的控制序列是什么以及它们的含义。为此,您需要一个等效的 terminfo 数据库。由于 terminfo 与 ncurses 密切相关,而您不需要 ncurses,我只能祝您好运。
-
所以你是说如果没有 ncurses 这甚至不可能?
-
如果您从头开始重新实现所有内容的一部分并且不介意放弃其他部分的功能,那么没有一切一切皆有可能。您可以将自己限制在一个流行的终端系列中,例如 VT100 和后代,编译您自己的控制序列列表并使用它。否则,您几乎必须至少使用 terminfo(技术上是 (n)curses 的一部分)。
-
@n.m.如何实现另一个依赖 UTF8 编码的 ncurses? UTF8 现在是标准字符集,每个终端仿真器都支持它。这会使新库(以取代 ncurses)更轻吗?我们也不需要 terminfo,对吧?