如何构建支持超过223列鼠标输入的Curses程序

时间:2017-11-13 03:38:33

标签: c ncurses curses xterm

我正在尝试使用我的终端跨越我的监视器的curses程序。但是,x坐标不能移过第223列,而是绕过它。在源中,这似乎是由于它们被定义为8位,并且位置值仅在前32个值之后开始(即x = raw_x - '')。

以下是来自https://gist.github.com/sylt/93d3f7b77e7f3a881603的示例程序,它演示了使用libncurses5编译时的问题。在其中,如果光标移动到窗口右侧超过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("\033[?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("\033[?1003l\n"); // Disable mouse movement events, as l = low

  endwin();

  return 0;
}
对于好奇的

,您可以使用gcc file.c -lcurses

进行构建

我如何解决此问题?我可以在全屏模式模式下使用vim,并且tmux鼠标交互也可以。这些都依赖于ncurses,因此必须以某种方式修复它。我试了几个小时阅读他们的来源,并尝试了我认为可行的样本。我也尝试了几种printf()终端模式,但似乎都没有启用此模式。如何让我的鼠标事件保持超过8位,从而让列字段保持大于232的值?

1 个答案:

答案 0 :(得分:2)

这是一个依赖于终端的功能(不是ncurses限制)。从20世纪80年代后期开始的原始xterm协议将每个纵坐标编码为一个字节,保留前32个控制字符。这给出256 - 32 = 223。

xterm在2010中引入了一个实验性功能来扩展范围。有一个使用它的ncurses终端描述"xterm-1005"。有人批评说,xterm在2012中引入了一个不同的特征。同样,有"xterm-1006"使用该功能。

ncurses中的描述已添加到2014中。 ncurses 6于2015年发布,并且仍然支持(通过编译时选项)针对ncurses 5的ABI 5.如果您的“ncurses5”至少与2014年的更改一样新,那么该库支持SGR 1006而不做任何更改。

没有制作默认“xterm”部分之一的原因是各种xterm模仿器的可移植性很差(就像他们的文档一样),这只会增加错误报告。但是如果您碰巧使用了支持SGR 1006功能的终端之一(例如xterm ...),那么ncurses库就支持这种功能。