cvt100

I stored the attributes and tried to restore the terminal settings, but the program did not restore to the original mode. How do I do?


I am currently working on a program that renders a green square upon launch. The program allows the user to move the square to the right by two spaces by typing 'd' without an extra Enter and echoing. To restore the original mode where the user needs to type characters followed by Enter and the terminal echoes, the user should type ']' without an extra Enter. However, when I tested this, the program did not restore to the original mode as expected. here is the code

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;
}

I compiled the code with gcc. I ran it by ./a.out. When I terminated it by ']', the terminal's cursor remained the state of invisible.

I also tried tcsetattr(0, TCSANOW, &orig_termios); it does't work either.

how do i fix it


Solution

  • I stored the attributes and tried to restore the terminal settings, but the program did not restore to the original mode. How do I do?

    You clarified in comments that you mean that the input cursor remained invisible after program termination. Naturally so, because you restore only the terminal attributes, and the cursor state is not among these (if the terminal even supports a cursor at all). The terminal attributes are pretty much all about characteristics of data transfer to and from the terminal device.

    Moreover, it is not by setting terminal attributes that your program turns off the cursor in the first place. Rather, it turns off the cursor by sending the terminal an ANSI escape sequence serving that purpose* (\033[?25l) during each call to clear_screen(). Thus, if you want the program to turn on the cursor before it terminates then it should send the corresponding ANSI sequence: \033[?25h.

    Note also that if the program fails to do that -- for example, if it is terminated by a Ctrl-C instead of by typing a ']' -- then you should be able to restore the the cursor by running the reset command in the terminal.


    *For some varieties of DEC terminals -- it is in the range of "private" codes designated for manufacturer use, so it may do something different or have no effect at all on other terminals.