18.12. Terminal Window SizeMost 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.
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. ExampleFigure 18.22 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 18.22 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 Figure 18.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(); } |