在 ncurses 中捕获 control+key 的正确方法
proper way of catching control+key in ncurses
在 ncurses 中捕获 control+key 的正确方法是什么?
目前我正在做这样定义控制:
#define ctl(x) ((x) & 0x1f)
它工作正常,但问题是我不能同时捕获 C-j 和 ENTER,这是因为:
j = 106 = 1101010
0x1f = 31 = 0011111
1101010 & 0011111 = 0001010 = 10 = ENTER key..
所以..我该如何捕捉它?
谢谢!
--
编辑:
如果我尝试下面的代码,
我无法正确捕捉回车键,即使在数字键盘中也是如此。 Enter 被捕获为 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
:
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
手册页的 Notes section:
Generally, KEY_ENTER denotes the character(s) sent by the Enter key on
the numeric keypad:
- 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.
这解决了有关 newline/carriage-return 翻译的问题。后续评论提醒您指出手册页在 Initialization 部分提供了基本建议:
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
的手册页说
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.
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
中您可以阅读
If keypad
is TRUE, and a function key is pressed, the token for that
function key is returned instead of the raw characters:
- 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 只会 return KEY_ENTER
keypad(stdscr, TRUE);
为了便于讨论,这里有一个示例,用于解决截至 5 月 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
,returned for KEY_ENTER
的值是不是字符(不能用 %c
打印)。
运行 在带有通常终端描述的 Linux 控制台上,您只会看到数字键盘的回车 return Enter,因为那个描述没有使用应用模式。 Linux控制台支持应用模式,可以写相应的说明。作为快速检查(存在差异...),您可以设置 TERM=vt100
以查看 KEY_ENTER
.
在 ncurses 中捕获 control+key 的正确方法是什么? 目前我正在做这样定义控制:
#define ctl(x) ((x) & 0x1f)
它工作正常,但问题是我不能同时捕获 C-j 和 ENTER,这是因为:
j = 106 = 1101010
0x1f = 31 = 0011111
1101010 & 0011111 = 0001010 = 10 = ENTER key..
所以..我该如何捕捉它? 谢谢!
-- 编辑: 如果我尝试下面的代码, 我无法正确捕捉回车键,即使在数字键盘中也是如此。 Enter 被捕获为 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
:
The
nl
andnonl
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, thecall 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
手册页的 Notes section:
Generally, KEY_ENTER denotes the character(s) sent by the Enter key on the numeric keypad:
- 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.
这解决了有关 newline/carriage-return 翻译的问题。后续评论提醒您指出手册页在 Initialization 部分提供了基本建议:
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
的手册页说
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. Thenocbreak
routine returns the terminal to normal (cooked) mode.Initially the terminal may or may not be in cbreak mode, as the mode is inherited; therefore, a program should call
cbreak
ornocbreak
explicitly. Most interactive programs using curses set the cbreak mode. Note thatcbreak
overridesraw
. (See curs_getch(3x) for a discussion of how these routines interact withecho
andnoecho
.)
此外,在 curs_getch
中您可以阅读
If
keypad
is TRUE, and a function key is pressed, the token for that function key is returned instead of the raw characters:
- The predefined function keys are listed in
<curses.h>
as macros with values outside the range of 8-bit characters. Their names begin withKEY_
.
也就是说,如果程序调用 keypad
:
KEY_ENTER
keypad(stdscr, TRUE);
为了便于讨论,这里有一个示例,用于解决截至 5 月 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
,returned for KEY_ENTER
的值是不是字符(不能用 %c
打印)。
运行 在带有通常终端描述的 Linux 控制台上,您只会看到数字键盘的回车 return Enter,因为那个描述没有使用应用模式。 Linux控制台支持应用模式,可以写相应的说明。作为快速检查(存在差异...),您可以设置 TERM=vt100
以查看 KEY_ENTER
.