在ncurses中捕获Control + Key的正确方法 [英] proper way of catching control+key in ncurses

查看:111
本文介绍了在ncurses中捕获Control + Key的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ncurses中捕获Control +键的正确方法是什么? 当前即时通讯正在这样定义控件:

What is the proper way of catching a control+key in ncurses? current im doing it defining control like this:

#define ctl(x) ((x) & 0x1f)

工作正常,但是问题是我无法同时捕获C-j和ENTER,这是因为:

it works ok, but the problem is that i cannot catch C-j and ENTER at the same time, and this is because:

   j = 106 = 1101010
0x1f = 31 = 0011111
1101010 & 0011111 = 0001010 = 10 = ENTER key..

所以..我怎么抓呢? 谢谢!

So.. how shall I catch it? Thanks!

- 如果我尝试下面的代码, 即使在数字键盘中,我也无法正确捕捉Enter键.输入被捕获为ctrl-j.

-- If i try the code below, I am not able to catch the enter key correctly, not even in the numeric keyboard. Enter gets catched as ctrl-j.

#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)

int main(void) {
    initscr();
    int c = getch();
    nonl();
    switch (c) {
        case KEY_ENTER:
            printw("key: %c", c);
            break;
        case ctrl('j'):
            printw("key: ctrl j");
            break;
    }
    getch();
    endwin();
    return;
}

新代码:

#include <stdio.h>
#include <ncurses.h>
#define ctrl(x)           ((x) & 0x1f)

int main(void) {
    initscr();
    int l = -1;
    int c = getch();
    cbreak();
    noecho();
    nonl();
    keypad(stdscr, TRUE);
    switch (c) {
        case KEY_ENTER:
            printw("key: %c", c);
            break;
        case ctrl('j'):
            printw("key: ctrl j");
            break;
    }
    printw("\nnow press a key to end");
    getch();
    endwin();
    return;
}

推荐答案

尝试 nonl :

nl nonl 例程控制是否底层显示设备 将return键转换为输入的换行符,以及是否将换行符转换为return并在输出时换行(无论哪种情况, call addch('\n') 与 虚拟屏幕).最初,确实会发生这些翻译.如果您使用Nonl禁用它们,则curses将能够更好地利用 换行功能,可以更快地移动光标.还有,诅咒 这样便可以检测到返回键.

The nl and nonl routines control whether the underlying display device translates the return key into newline on input, and whether it translates newline into return and line-feed on output (in either case, the call addch('\n') does the equivalent of return and line feed on the virtual screen). Initially, these translations do occur. If you disable them using nonl, curses will be able to make better use of the line-feed capability, resulting in faster cursor motion. Also, curses will then be able to detect the return key.

进一步阅读:的注释部分 getch手册页:

Further reading: the Notes section of the getch manual page:

通常,KEY_ENTER表示由Enter键发送的字符 数字键盘:

Generally, KEY_ENTER denotes the character(s) sent by the Enter key on the numeric keypad:

  • 终端说明中列出了最有用的键,
  • 常规键盘上的Enter键已经由 回车和换行的标准ASCII字符,
  • 取决于是否调用了nl或nonl,请在屏幕上按"Enter" 常规键盘可能会返回回车符或换行符, 最后

  • the terminal description lists the most useful keys,
  • the Enter key on the regular keyboard is already handled by the standard ASCII characters for carriage-return and line-feed,
  • depending on whether nl or nonl was called, pressing "Enter" on the regular keyboard may return either a carriage-return or line-feed, and finally

输入或发送"是此密钥的标准说明.

"Enter or send" is the standard description for this key.

解决了有关换行符/回车符翻译的问题.后续评论提醒我们,该手册页在

That addresses the question about newline/carriage-return translation. A followup comment is a reminder to point out that the manual page gives basic advice in the Initialization section:

一次获取字符而不回显(大多数交互, 面向屏幕的程序需要此),应遵循以下顺序 已使用:

To get character-at-a-time input without echoing (most interactive, screen oriented programs want this), the following sequence should be used:

     initscr(); cbreak(); noecho();

,并且该OP的示例程序未使用cbreak(或raw). cbreak 的手册页说

and that OP's sample program did not use cbreak (or raw). The manual page for cbreak says

通常,tty驱动程序会缓冲输入的字符,直到换行符或 输入回车符. cbreak 例程禁用行缓冲 和擦除/杀死字符处理(中断和流控制字符不受影响),使用户立即键入字符 该程序可用. nocbreak 例程将终端返回到 正常(煮熟)模式.

Normally, the tty driver buffers typed characters until a newline or carriage return is typed. The cbreak routine disables line buffering and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately available to the program. The nocbreak routine returns the terminal to normal (cooked) mode.

最初,终端可能处于或不处于cbreak模式,因为该模式是 遗传;因此,程序应显式调用 cbreak nocbreak . 大多数使用curses的交互式程序都会设置cbreak模式. 请注意, cbreak 会覆盖 raw . (有关讨论,请参见 curs_getch(3x) 这些例程如何与 echo noecho 进行交互.)

Initially the terminal may or may not be in cbreak mode, as the mode is inherited; therefore, a program should call cbreak or nocbreak explicitly. Most interactive programs using curses set the cbreak mode. Note that cbreak overrides raw. (See curs_getch(3x) for a discussion of how these routines interact with echo and noecho.)

此外,在 curs_getch 您可以阅读

Also, in curs_getch you may read

如果 keypad 为TRUE,并按下功能键,该标记为 返回功能键,而不是原始字符:

If keypad is TRUE, and a function key is pressed, the token for that function key is returned instead of the raw characters:

  • 预定义的功能键在<curses.h>中作为宏列出 值在8位字符范围之外.他们的名字以 KEY_ 开头.
  • The predefined function keys are listed in <curses.h> as macros with values outside the range of 8-bit characters. Their names begin with KEY_.

也就是说,如果程序调用keypad,则curses仅返回KEY_ENTER:

That is, curses will only return KEY_ENTER if the program calls keypad:

keypad(stdscr, TRUE);

为了便于讨论,下面是一个示例,该示例修复了截至5月17日的示例程序中的一些问题:

For the sake of discussion, here is an example fixing some of the problems with your sample program as of May 17:

#include <stdio.h>
#include <ncurses.h>
#define ctrl(x)           ((x) & 0x1f)

int
main(void)
{
    int c;
    initscr();
    keypad(stdscr, TRUE);
    cbreak();
    noecho();
    nonl();
    c = getch();
    switch (c) {
    case KEY_ENTER:
        printw("\nkey_enter: %d", c);
        break;
    case ctrl('j'):
        printw("\nkey: ctrl j");
        break;
    default:
        printw("\nkeyname: %d = %s\n", c, keyname(c));
        break;
    }
    printw("\nnow press a key to end");
    getch();
    endwin();
    return 0;
}

也就是说,您必须在getch之前调用keypad,并且 KEY_ENTER 返回的值不是字符(不能用%c打印).

That is, you have to call keypad before getch, and the value returned for KEY_ENTER is not a character (it cannot be printed with %c).

在具有常规终端说明的Linux控制台上运行,您将仅看到数字小键盘 Enter 的回车,因为该说明不使用 application模式. Linux控制台确实支持应用程序模式,并且可以编写相应的描述.快速检查(有差异...),您可以设置TERM=vt100以查看 KEY_ENTER .

Running on the Linux console with the usual terminal description, you will see only carriage return for the numeric keypad Enter, because that description does not use application mode. Linux console does support application mode, and a corresponding description could be written. As a quick check (there are differences...) you could set TERM=vt100 to see the KEY_ENTER.

这篇关于在ncurses中捕获Control + Key的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆