Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting terminal width in C?

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 <sys/ioctl.h> #include <stdio.h>  int main (void) {     struct ttysize ts;     ioctl(0, TIOCGSIZE, &ts);      printf ("lines %d\n", ts.ts_lines);     printf ("columns %d\n", ts.ts_cols); } 

But everytime I try that I get

austin@:~$ gcc test.c -o test test.c: In function ‘main’: test.c:6: error: storage size of ‘ts’ isn’t known test.c:7: error: ‘TIOCGSIZE’ undeclared (first use in this function) test.c:7: error: (Each undeclared identifier is reported only once test.c:7: error: for each function it appears in.) 

Is this the best way to do this, or is there a better way? If not how can I get this to work?

EDIT: fixed code is

#include <sys/ioctl.h> #include <stdio.h>  int main (void) {     struct winsize w;     ioctl(0, TIOCGWINSZ, &w);      printf ("lines %d\n", w.ws_row);     printf ("columns %d\n", w.ws_col);     return 0; } 
like image 674
austin Avatar asked Jun 21 '09 01:06

austin


People also ask

How do you find terminal size?

get_terminal_size() method in Python is used to query the size of a terminal. This method returns the size of a terminal as a pair columns and lines. Here, columns represents width of the terminal window in characters and lines represents height of the terminal window in characters.

What is terminal width?

The “normal” size for a terminal is 80 columns by 24 rows. These dimensions were inherited from the size of common hardware terminals, which, in turn, were influenced by the format of IBM punch cards (80 columns by 12 rows).

How do I set terminal size?

At the top of the window you should go to Edit -> Profile Preferences, General page and check Use custom default terminal size, and then set your preferred horizontal and vertical dimensions.


2 Answers

Have you considered using getenv() ? It allows you to get the system's environment variables which contain the terminals columns and lines.

Alternatively using your method, if you want to see what the kernel sees as the terminal size (better in case terminal is resized), you would need to use TIOCGWINSZ, as opposed to your TIOCGSIZE, like so:

struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); 

and the full code:

#include <sys/ioctl.h> #include <stdio.h> #include <unistd.h>  int main (int argc, char **argv) {     struct winsize w;     ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);      printf ("lines %d\n", w.ws_row);     printf ("columns %d\n", w.ws_col);     return 0;  // make sure your main returns int } 
like image 79
John T Avatar answered Sep 25 '22 00:09

John T


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); } 
like image 20
gamen Avatar answered Sep 25 '22 00:09

gamen