home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- ** ^FILE: winsize.c - implement the routine get_winsize()
- **
- ** ^DESCRIPTION:
- ** Implement the get_winsize() function for various windowing and
- ** operating systems.
- **
- ** ^HISTORY:
- ** 10/01/90 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
-
-
- /***************************************************************************
- ** ^FUNCTION: get_winsize - get the current window size
- **
- ** ^SYNOPSIS:
- ** void get_winsize( fd, nrows, ncols )
- **
- ** ^PARAMETERS:
- ** int fd;
- ** -- file-descriptor associated with the "output-window"
- **
- ** int *nrows;
- ** -- pointer to number of rows in window
- **
- ** int *ncols;
- ** -- pointer to number of columns in window
- **
- ** ^DESCRIPTION:
- ** Get_winsize will attempt to determine the maximum number of
- ** rows and colums that will fit on one screen-full of the associated
- ** output device. If it fails to do this, it will assume the "window"
- ** is a 24x80 (rows by columns) display.
- **
- ** ^REQUIREMENTS:
- ** fd must correspond to a valid output device.
- **
- ** ^SIDE-EFFECTS:
- ** The memory addressed by nrows and ncols is assigned the corresponding
- ** appropriate value(s).
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** System dependent.
- ***^^**********************************************************************/
-
- #include <stdio.h>
-
- #ifdef __ANSI_C__
- # define GET_WINSIZE(fd,nrows,ncols) \
- void get_winsize( int fd, int *nrows, int *ncols )
- #else
- # define GET_WINSIZE(fd,nrows,ncols) \
- void get_winsize( fd, nrows, ncols ) \
- int fd, *nrows, *ncols; /* nrows and ncols are passed by reference */
- #endif
-
- #define DEFAULT_ROWS 24
- #define DEFAULT_COLS 80
-
- #ifdef vms
-
- #include <stdio.h>
- #include <iodef.h>
- #include <ssdef.h>
- #include <descrip.h>
- #include <useful.h>
-
- /* structure to contain terminal characteristics */
- typedef struct {
- short garb1, cols;
- char garb2, garb3, garb4, rows;
- } termchar_t;
-
- int sys$assign();
- int sys$qiow();
- int sys$dassgn();
-
- GET_WINSIZE( fd, nrows, ncols )
- {
- int c, charlen = 8;
- termchar_t termchar;
- int chan;
- $DESCRIPTOR( devnam,"SYS$COMMAND" );
-
- sys$assign( &devnam, &chan, 0, 0 );
- sys$qiow( 0, chan, IO$_SENSEMODE, 0, 0, 0, &termchar, &charlen, 0, 0, 0, 0 );
- sys$dassgn( chan );
-
- *nrows = ( termchar.rows > 0 ) ? (int) termchar.rows : DEFAULT_ROWS;
- *ncols = ( termchar.cols > 0 ) ? (int) termchar.cols : DEFAULT_COLS;
- }
-
- #else
- #ifdef unix
-
- /*
- ** we will either try to access terminfo through the termcap-interface
- ** in the curses library (which would require linking with -lcurses)
- ** or use termcap directly (which would require linking with -ltermcap)
- */
- #ifndef USE_TERMCAP
- #if ( defined(USE_TERMINFO) || defined(USE_CURSES) )
- #define USE_TERMCAP
- #endif
- #endif
-
-
- #ifdef USE_TERMCAP
- # define TERMBUFSIZ 1024
- # define UNKNOWN_TERM "unknown"
- # define DUMB_TERMBUF "dumb:co#80:hc:"
- extern int tgetent();
- extern int tgetnum();
- #endif
-
-
- /* try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
- #include <termios.h>
- #if ( !defined(TIOCGWINSZ) && !defined(TIOCGSIZE) && !defined(WIOCGETD) )
- #include <sys/ioctl.h>
- #endif
-
- /* if still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
- #if ( !defined(TIOCGWINSZ) && !defined(TIOCGSIZE) && !defined(WIOCGETD) )
- #include <sgtty.h>
- #endif
-
- #include <useful.h>
-
- /*
- ** get_winsize() -- determine # of rows/columns that will fit on the screen.
- **
- ** The environment variables $LINES and $COLUMNS will be used if they exist.
- ** If not, then the TIOCGWINSZ call to ioctl() is used (if it is defined).
- ** If not, then the TIOCGSIZE call to ioctl() is used (if it is defined).
- ** If not, then the WIOCGETD call to ioctl() is used (if it is defined).
- ** If not, then get the info from terminfo/termcap (if it is there)
- ** Otherwise, assume we have a 24x80 screen.
- */
-
- extern int ioctl();
- extern int isatty();
- extern long atol();
- extern char *getenv();
-
- GET_WINSIZE( fd, nrows, ncols )
- {
- char *lines_env, *cols_env;
- long lrow = 0, lcol = 0;
- int lines = 0, cols = 0;
- #ifdef USE_TERMCAP
- char term_buf[ TERMBUFSIZ ], *term_env;
- #endif
- #ifdef TIOCGWINSZ
- struct winsize win;
- #else
- #ifdef TIOCGSIZE
- struct ttysize win;
- #else
- #ifdef WIOCGETD
- struct uwdata win;
- #endif
- #endif
- #endif
-
- /* make sure that fd corresponds to a terminal */
- if ( !isatty( fd ) ) {
- *nrows = DEFAULT_ROWS;
- *ncols = DEFAULT_COLS;
- return;
- }
-
- /* LINES & COLUMNS environment variables override everything else */
- lines_env = getenv( "LINES" );
- if ( lines_env && (lrow = atol(lines_env)) > 0 ) {
- *nrows = lines = (int) lrow;
- }
-
- cols_env = getenv( "COLUMNS" );
- if ( cols_env && (lcol = atol(cols_env)) > 0 ) {
- *ncols = cols = (int) lcol;
- }
-
- #ifdef TIOCGWINSZ
- /* see what ioctl() has to say (overrides terminfo & termcap) */
- if ( (!lines || !cols) && ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
- if ( !lines && win.ws_row > 0 ) {
- *nrows = lines = (int) win.ws_row;
- }
-
- if ( !cols && win.ws_col > 0 ) {
- *ncols = cols = (int) win.ws_col;
- }
- }/*if*/
- #else
- #ifdef TIOCGSIZE
- /* see what ioctl() has to say (overrides terminfo & termcap) */
- if ( (!lines || !cols) && ioctl(fd, TIOCGSIZE, &win) != -1 ) {
- if ( !lines && win.ts_lines > 0 )
- *nrows = lines = (int) win.ts_lines;
-
- if ( !cols && win.ts_cols > 0 )
- *ncols = cols = (int) win.ts_cols;
- }/*if*/
- #else
- #ifdef WIOCGETD
- /* see what ioctl() has to say (overrides terminfo & termcap) */
- if ( (!lines || !cols) && ioctl(fd, WIOCGETD, &win) != -1 ) {
- if ( !lines && win.uw_height > 0 )
- *nrows = lines = (int) (win.uw_height / win.uw_vs);
-
- if ( !cols && win.uw_width > 0 )
- *ncols = cols = (int) (win.uw_width / win.uw_hs);
- }/*if*/
- #endif
- #endif
- #endif
-
- #ifdef USE_TERMCAP
- /* see what terminfo/termcap has to say */
- if ( !lines || !cols ) {
- if ( !(term_env = getenv("TERM")) )
- term_env = UNKNOWN_TERM;
-
- if ( (tgetent(term_buf, term_env) <= 0) )
- strcpy( term_buf, DUMB_TERMBUF );
-
- if ( !lines && (lrow = tgetnum("li")) > 0 )
- *nrows = lines = (int) lrow;
-
- if ( !cols && (lcol = tgetnum("co")) > 0 )
- *ncols = cols = (int) lcol;
- }
- #endif
-
- /* use 80x24 if all else fails */
- if ( !lines ) *nrows = DEFAULT_ROWS;
- if ( !cols ) *ncols = DEFAULT_COLS;
-
- }/*get_winsize()*/
-
- #else
-
- GET_WINSIZE( fd, nrows, ncols )
- {
- /* just use 80x24 */
- *nrows = DEFAULT_ROWS;
- *ncols = DEFAULT_COLS;
- }
-
- #endif /* not a vms system */
- #endif /* not a unix-system */
-
- #ifdef WINSIZE_TEST
-
- #ifdef vms
- # include <ssdef.h>
- #endif
-
- /* test get_winsize to see if it works */
- main()
- {
- int rows, cols;
-
- get_winsize( fileno(stderr), &rows, &cols );
- printf( "Output will be %d rows by %d columns\n", rows, cols );
-
- #ifdef vms
- exit( SS$_NORMAL );
- #else
- exit( 0 );
- #endif
-
- }
-
- #endif
-