我存储了属性并尝试恢复终端设置,但程序没有恢复到原始模式。我该怎么做?

JJJ*_*ohn 1 c vt100

我目前正在开发一个程序,该程序在启动时呈现一个绿色方块。该程序允许用户通过键入“d”将方块向右移动两个空格,而无需额外的 Enter 和回显。要恢复用户需要键入字符后按 Enter 且终端回显的原始模式,用户应键入“]”而不需要额外的 Enter。然而,当我对此进行测试时,程序并没有按预期恢复到原始模式。这是代码

struct termios orig_termios;

void clear_screen()
{
  printf("\033[H\033[J\033[?25l");
  fflush(stdout);
}

void green_square()
{
  printf("\033[42m  \033[0m");
}

void move_cursor(int hx, int hy)
{
  printf("\033[%d;%dH", hy, hx);
  fflush(stdout);
}

void disableRawMode()
{
  tcsetattr(0, TCSAFLUSH, &orig_termios);
}

void enableRawMode()
{
  tcgetattr(0, &orig_termios);
  atexit(disableRawMode);

  struct termios raw = orig_termios;
  raw.c_lflag &= ~(ECHO | ICANON);

  tcsetattr(0, TCSAFLUSH, &raw);
}

int main()
{
  int x = 1; // starting position of the green square
  int y = 1;
  enableRawMode();

  while (1)
  {
    clear_screen();
    move_cursor(x, y);
    green_square();
    char c = getchar();
    if (c == 'd')
    {
      x += 2; // move right 2 spaces
    }
    else if (c == ']')
    {
      disableRawMode();
      exit(0);
    }
    usleep(10000); // wait for 100 milliseconds
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用 gcc 编译了代码。我跑过去了./a.out。当我用“]”终止它时,终端的光标保持不可见的状态。

我也试过了tcsetattr(0, TCSANOW, &orig_termios);也不行。

我如何解决它

Joh*_*ger 5

我存储了属性并尝试恢复终端设置,但程序没有恢复到原始模式。我该怎么做?

您在评论中澄清说,您的意思是输入光标在程序终止后仍然不可见。当然是这样,因为您只恢复终端属性,而光标状态不属于这些属性(如果终端甚至支持光标)。终端属性几乎都是关于与终端设备之间的数据传输的特性。

此外,程序并不是通过设置终端属性来首先关闭光标的。相反,它通过在每次调用 期间向终端发送一个用于该目的的 ANSI 转义序列* ( )来关闭光标。因此,如果您希望程序在终止之前打开光标,那么它应该发送相应的 ANSI 序列:。\033[?25lclear_screen()\033[?25h

另请注意,如果程序无法做到这一点——例如,如果它是通过 Ctrl-C 而不是通过键入“]”终止的——那么您应该能够通过reset在终端。


*对于某些 DEC 终端品种 - 它位于指定给制造商使用的“私有”代码范围内,因此它可能会执行不同的操作或对其他终端没有任何影响。