如何构建支持超过 223 列鼠标输入的 Curses 程序
How to Build Curses Program That Supports More Than 223 Columns of Mouse Input
我正在尝试让一个 curses 程序在我的终端上跨显示器工作。但是,x 坐标不能移动超过第 223 列,而是循环。在源代码中,这似乎是由于它们被定义为 8 位,并且位置值仅在前 32 个值之后开始(即 x = raw_x - ' ')。
这是来自 https://gist.github.com/sylt/93d3f7b77e7f3a881603 的示例程序,演示了使用 libncurses5 编译时的问题。在其中,如果您的光标移动到 window 右侧超过 233 列,则 x 值将循环回到 0 - ' ',即 -32
#include <curses.h>
#include <stdio.h>
int main()
{
initscr();
cbreak();
noecho();
// Enables keypad mode. This makes (at least for me) mouse events getting
// reported as KEY_MOUSE, instead as of random letters.
keypad(stdscr, TRUE);
// Don't mask any mouse events
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
printf("3[?1003h\n"); // Makes the terminal report mouse movement events
for (;;) {
int c = wgetch(stdscr);
// Exit the program on new line fed
if (c == '\n')
break;
char buffer[512];
size_t max_size = sizeof(buffer);
if (c == ERR) {
snprintf(buffer, max_size, "Nothing happened.");
}
else if (c == KEY_MOUSE) {
MEVENT event;
if (getmouse(&event) == OK) {
snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0x%08lx",
event.y, event.x, event.bstate);
}
else {
snprintf(buffer, max_size, "Got bad mouse event.");
}
}
else {
snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
}
move(0, 0);
insertln();
addstr(buffer);
clrtoeol();
move(0, 0);
}
printf("3[?1003l\n"); // Disable mouse movement events, as l = low
endwin();
return 0;
}
出于好奇,您可以使用 gcc file.c -lcurses
构建它
我该如何解决这个问题?我可以在全屏模式下使用 vim,tmux 鼠标交互也可以。这些都依赖于 ncurses,因此必须以某种方式修复它。我花了几个小时尝试阅读他们的来源,并尝试尝试我认为可行的样本。我也尝试了几种 printf() 终端模式,但 none 似乎启用了这种模式。我怎样才能让我的鼠标事件保持超过 8 位,从而让列字段保持大于 232 的值?
这是一个依赖于终端的特性(不是 ncurses 本身的限制)。 1980 年代后期的原始 xterm 协议将每个纵坐标编码为一个字节,为控制字符保留前 32 个。这给出 256 - 32 = 223.
xterm 在 2010 to extend the range. There is an ncurses terminal description "xterm-1005" which uses that. Some criticized that, and xterm introduced an different feature in 2012. Again, there is a "xterm-1006" 中使用该功能引入了一项实验性功能。
在 2014 中添加了 ncurses 中的描述。 ncurses 6 于 2015 年发布,并且仍然支持(通过编译时选项)ncurses 5 的 ABI 5。如果您的 "ncurses5" 至少与 2014 年的更改一样新,则该库支持 SGR 1006 而无需更改。
不将这些部分之一作为默认设置的原因 "xterm" 是各种 xterm 模仿器之间的可移植性很差(就像它们的文档一样),这只会增加错误报告。但是,如果您碰巧使用支持 SGR 1006 功能的终端之一(例如 xterm...),则 ncurses 库支持该功能。
我正在尝试让一个 curses 程序在我的终端上跨显示器工作。但是,x 坐标不能移动超过第 223 列,而是循环。在源代码中,这似乎是由于它们被定义为 8 位,并且位置值仅在前 32 个值之后开始(即 x = raw_x - ' ')。
这是来自 https://gist.github.com/sylt/93d3f7b77e7f3a881603 的示例程序,演示了使用 libncurses5 编译时的问题。在其中,如果您的光标移动到 window 右侧超过 233 列,则 x 值将循环回到 0 - ' ',即 -32
#include <curses.h>
#include <stdio.h>
int main()
{
initscr();
cbreak();
noecho();
// Enables keypad mode. This makes (at least for me) mouse events getting
// reported as KEY_MOUSE, instead as of random letters.
keypad(stdscr, TRUE);
// Don't mask any mouse events
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
printf("3[?1003h\n"); // Makes the terminal report mouse movement events
for (;;) {
int c = wgetch(stdscr);
// Exit the program on new line fed
if (c == '\n')
break;
char buffer[512];
size_t max_size = sizeof(buffer);
if (c == ERR) {
snprintf(buffer, max_size, "Nothing happened.");
}
else if (c == KEY_MOUSE) {
MEVENT event;
if (getmouse(&event) == OK) {
snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0x%08lx",
event.y, event.x, event.bstate);
}
else {
snprintf(buffer, max_size, "Got bad mouse event.");
}
}
else {
snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
}
move(0, 0);
insertln();
addstr(buffer);
clrtoeol();
move(0, 0);
}
printf("3[?1003l\n"); // Disable mouse movement events, as l = low
endwin();
return 0;
}
出于好奇,您可以使用 gcc file.c -lcurses
我该如何解决这个问题?我可以在全屏模式下使用 vim,tmux 鼠标交互也可以。这些都依赖于 ncurses,因此必须以某种方式修复它。我花了几个小时尝试阅读他们的来源,并尝试尝试我认为可行的样本。我也尝试了几种 printf() 终端模式,但 none 似乎启用了这种模式。我怎样才能让我的鼠标事件保持超过 8 位,从而让列字段保持大于 232 的值?
这是一个依赖于终端的特性(不是 ncurses 本身的限制)。 1980 年代后期的原始 xterm 协议将每个纵坐标编码为一个字节,为控制字符保留前 32 个。这给出 256 - 32 = 223.
xterm 在 2010 to extend the range. There is an ncurses terminal description "xterm-1005" which uses that. Some criticized that, and xterm introduced an different feature in 2012. Again, there is a "xterm-1006" 中使用该功能引入了一项实验性功能。
在 2014 中添加了 ncurses 中的描述。 ncurses 6 于 2015 年发布,并且仍然支持(通过编译时选项)ncurses 5 的 ABI 5。如果您的 "ncurses5" 至少与 2014 年的更改一样新,则该库支持 SGR 1006 而无需更改。
不将这些部分之一作为默认设置的原因 "xterm" 是各种 xterm 模仿器之间的可移植性很差(就像它们的文档一样),这只会增加错误报告。但是,如果您碰巧使用支持 SGR 1006 功能的终端之一(例如 xterm...),则 ncurses 库支持该功能。