Getting terminal width in C?

后端 未结 8 663
自闭症患者
自闭症患者 2020-11-22 16:07

I\'ve been looking for a way to get the terminal width from within my C program. What I keep coming up with is something along the lines of:

#include 

        
相关标签:
8条回答
  • 2020-11-22 16:43
    #include <stdio.h>
    #include <stdlib.h>
    #include <termcap.h>
    #include <error.h>
    
    static char termbuf[2048];
    
    int main(void)
    {
        char *termtype = getenv("TERM");
    
        if (tgetent(termbuf, termtype) < 0) {
            error(EXIT_FAILURE, 0, "Could not access the termcap data base.\n");
        }
    
        int lines = tgetnum("li");
        int columns = tgetnum("co");
        printf("lines = %d; columns = %d.\n", lines, columns);
        return 0;
    }
    

    Needs to be compiled with -ltermcap . There is a lot of other useful information you can get using termcap. Check the termcap manual using info termcap for more details.

    0 讨论(0)
  • 2020-11-22 16:44

    To add a more complete answer, what I've found to work for me is to use @John_T's solution with some bits added in from Rosetta Code, along with some troubleshooting figuring out dependencies. It might be a bit inefficient, but with smart programming you can make it work and not be opening your terminal file all the time.

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ioctl.h> // ioctl, TIOCGWINSZ
    #include <err.h>       // err
    #include <fcntl.h>     // open
    #include <unistd.h>    // close
    #include <termios.h>   // don't remember, but it's needed
    
    size_t* get_screen_size()
    {
      size_t* result = malloc(sizeof(size_t) * 2);
      if(!result) err(1, "Memory Error");
    
      struct winsize ws;
      int fd;
    
      fd = open("/dev/tty", 0_RDWR);
      if(fd < 0 || ioctl(fd, TIOCGWINSZ, &ws) < 0) err(8, "/dev/tty");
    
      result[0] = ws.ws_row;
      result[1] = ws.ws_col;
    
      close(fd);
    
      return result;
    }
    

    If you make sure not to call it all but maybe every once in awhile you should be fine, it should even update when the user resizes the terminal window (because you're opening the file and reading it every time).

    If you aren't using TIOCGWINSZ see the first answer on this form https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/.

    Oh, and don't forget to free() the result.

    0 讨论(0)
  • 2020-11-22 16:47

    So not suggesting an answer here, but:

    linux-pc:~/scratch$ echo $LINES

    49

    linux-pc:~/scratch$ printenv | grep LINES

    linux-pc:~/scratch$

    Ok, and I notice that if I resize the GNOME terminal, the LINES and COLUMNS variables follow that.

    Kinda seems like GNOME terminal is creating these environment variables itself?

    0 讨论(0)
  • 2020-11-22 16:50

    If you have ncurses installed and are using it, you can use getmaxyx() to find the dimensions of the terminal.

    0 讨论(0)
  • 2020-11-22 17:00

    This example is a bit on the lengthy side, but I believe it's the most portable way of detecting the terminal dimensions. This also handles resize events.

    As tim and rlbond suggests, I'm using ncurses. It guarantees a great improvement in terminal compatability as compared to reading environment variables directly.

    #include <ncurses.h>
    #include <string.h>
    #include <signal.h>
    
    // SIGWINCH is called when the window is resized.
    void handle_winch(int sig){
      signal(SIGWINCH, SIG_IGN);
    
      // Reinitialize the window to update data structures.
      endwin();
      initscr();
      refresh();
      clear();
    
      char tmp[128];
      sprintf(tmp, "%dx%d", COLS, LINES);
    
      // Approximate the center
      int x = COLS / 2 - strlen(tmp) / 2;
      int y = LINES / 2 - 1;
    
      mvaddstr(y, x, tmp);
      refresh();
    
      signal(SIGWINCH, handle_winch);
    }
    
    int main(int argc, char *argv[]){
      initscr();
      // COLS/LINES are now set
    
      signal(SIGWINCH, handle_winch);
    
      while(getch() != 27){
        /* Nada */
      }
    
      endwin();
    
      return(0);
    }
    
    0 讨论(0)
  • 2020-11-22 17:01

    Assuming you are on Linux, I think you want to use the ncurses library instead. I am pretty sure the ttysize stuff you have is not in stdlib.

    0 讨论(0)
提交回复
热议问题