Terminal Window Size





Terminal Window Size

Most UNIX systems provide a way to keep track of the current terminal window size and to have the kernel notify the foreground process group when the size changes. The kernel maintains a winsize structure for every terminal and pseudo terminal:

   struct winsize {
     unsigned short ws_row;       /* rows, in characters */
     unsigned short ws_col;       /* columns, in characters */
     unsigned short ws_xpixel;    /* horizontal size, pixels (unused) */
     unsigned short ws_ypixel;    /* vertical size, pixels (unused) */
   };

The rules for this structure are as follows.

  • We can fetch the current value of this structure using an ioctl (Section 3.15) of TIOCGWINSZ.

  • We can store a new value of this structure in the kernel using an ioctl of TIOCSWINSZ. If this new value differs from the current value stored in the kernel, a SIGWINCH signal is sent to the foreground process group. (Note from Figure that the default action for this signal is to be ignored.)

  • Other than storing the current value of the structure and generating a signal when the value changes, the kernel does nothing else with this structure. Interpreting the structure is entirely up to the application.

The reason for providing this feature is to notify applications (such as the vi editor) when the window size changes. When it receives the signal, the application can fetch the new size and redraw the screen.

Example

Figure shows a program that prints the current window size and goes to sleep. Each time the window size changes, SIGWINCH is caught and the new size is printed. We have to terminate this program with a signal.

Running the program in Figure on a windowed terminal gives us

$ ./a.out
35 rows, 80 columns       initial size
SIGWINCH received         change window size: signal is caught
40 rows, 123 columns
SIGWINCH received         and again
42 rows, 33 columns
^? $                      type the interrupt key to terminate

22. Print window size
#include "apue.h"
#include <termios.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif

static void
pr_winsize(int fd)
{
    struct winsize size;

    if (ioctl(fd, TIOCGWINSZ, (char *) &size) < 0)
        err_sys("TIOCGWINSZ error");
    printf("%d rows, %d columns\n", size.ws_row, size.ws_col);
}

static void
sig_winch(int signo)
{
    printf("SIGWINCH received\n");
    pr_winsize(STDIN_FILENO);
}

int
main(void)
{
    if (isatty(STDIN_FILENO) == 0)
        exit(1);
    if (signal(SIGWINCH, sig_winch) == SIG_ERR)
        err_sys("signal error");
    pr_winsize(STDIN_FILENO);   /* print initial size */
    for ( ; ; )                 /* and sleep forever */
        pause();
}


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows