1998-03-01 12:21:12 +08:00
|
|
|
/****************************************************************************
|
|
|
|
* Copyright (c) 1998 Free Software Foundation, Inc. *
|
|
|
|
* *
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
|
|
|
* copy of this software and associated documentation files (the *
|
|
|
|
* "Software"), to deal in the Software without restriction, including *
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
|
|
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is *
|
|
|
|
* furnished to do so, subject to the following conditions: *
|
|
|
|
* *
|
|
|
|
* The above copyright notice and this permission notice shall be included *
|
|
|
|
* in all copies or substantial portions of the Software. *
|
|
|
|
* *
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
|
|
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
|
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
|
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
|
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
|
|
|
* *
|
|
|
|
* Except as contained in this notice, the name(s) of the above copyright *
|
|
|
|
* holders shall not be used in advertising or otherwise to promote the *
|
|
|
|
* sale, use or other dealings in this Software without prior written *
|
|
|
|
* authorization. *
|
|
|
|
****************************************************************************/
|
1997-05-15 12:00:00 +08:00
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
/****************************************************************************
|
|
|
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
|
|
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
|
|
|
****************************************************************************/
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Terminal setup routines common to termcap and terminfo:
|
|
|
|
*
|
|
|
|
* use_env(bool)
|
|
|
|
* setupterm(char *, int, int *)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <curses.priv.h>
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
#if defined(SVR4_TERMIO) && !defined(_POSIX_SOURCE)
|
1997-05-15 12:00:00 +08:00
|
|
|
#define _POSIX_SOURCE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <term.h> /* lines, columns, cur_term */
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
MODULE_ID("$Id: lib_setup.c,v 1.37 1998/02/11 12:13:56 tom Exp $")
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* Terminal size computation
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
#if HAVE_SIZECHANGE
|
|
|
|
# if !defined(sun) || !HAVE_TERMIOS_H
|
|
|
|
# if HAVE_SYS_IOCTL_H
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if NEED_PTEM_H
|
|
|
|
/* On SCO, they neglected to define struct winsize in termios.h -- it's only
|
|
|
|
* in termio.h and ptem.h (the former conflicts with other definitions).
|
|
|
|
*/
|
|
|
|
# include <sys/stream.h>
|
|
|
|
# include <sys/ptem.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
|
|
|
|
* Solaris, IRIX) define TIOCGWINSZ and struct winsize.
|
|
|
|
*/
|
|
|
|
#ifdef TIOCGSIZE
|
|
|
|
# define IOCTL_WINSIZE TIOCGSIZE
|
|
|
|
# define STRUCT_WINSIZE struct ttysize
|
|
|
|
# define WINSIZE_ROWS(n) (int)n.ts_lines
|
|
|
|
# define WINSIZE_COLS(n) (int)n.ts_cols
|
|
|
|
#else
|
|
|
|
# ifdef TIOCGWINSZ
|
|
|
|
# define IOCTL_WINSIZE TIOCGWINSZ
|
|
|
|
# define STRUCT_WINSIZE struct winsize
|
|
|
|
# define WINSIZE_ROWS(n) (int)n.ws_row
|
|
|
|
# define WINSIZE_COLS(n) (int)n.ws_col
|
|
|
|
# endif
|
1997-05-15 12:00:00 +08:00
|
|
|
#endif
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
extern TERMINAL *cur_term;
|
|
|
|
|
1997-05-15 12:00:00 +08:00
|
|
|
static int _use_env = TRUE;
|
|
|
|
|
|
|
|
static void do_prototype(void);
|
|
|
|
|
|
|
|
void use_env(bool f)
|
|
|
|
{
|
|
|
|
_use_env = f;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LINES, COLS, TABSIZE;
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
static void _nc_get_screensize(int *linep, int *colp)
|
|
|
|
/* Obtain lines/columns values from the environment and/or terminfo entry */
|
1997-05-15 12:00:00 +08:00
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
char *rows, *cols;
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
/* figure out the size of the screen */
|
|
|
|
T(("screen size: terminfo lines = %d columns = %d", lines, columns));
|
|
|
|
|
|
|
|
if (!_use_env)
|
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
*linep = (int)lines;
|
|
|
|
*colp = (int)columns;
|
1997-05-15 12:00:00 +08:00
|
|
|
}
|
|
|
|
else /* usually want to query LINES and COLUMNS from environment */
|
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
*linep = *colp = 0;
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
/* first, look for environment variables */
|
|
|
|
rows = getenv("LINES");
|
1998-03-01 12:21:12 +08:00
|
|
|
if (rows != 0)
|
|
|
|
*linep = atoi(rows);
|
1997-05-15 12:00:00 +08:00
|
|
|
cols = getenv("COLUMNS");
|
1998-03-01 12:21:12 +08:00
|
|
|
if (cols != 0)
|
|
|
|
*colp = atoi(cols);
|
|
|
|
T(("screen size: environment LINES = %d COLUMNS = %d",*linep,*colp));
|
1997-05-15 12:00:00 +08:00
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
#if HAVE_SIZECHANGE
|
1997-05-15 12:00:00 +08:00
|
|
|
/* if that didn't work, maybe we can try asking the OS */
|
1998-03-01 12:21:12 +08:00
|
|
|
if (*linep <= 0 || *colp <= 0)
|
1997-05-15 12:00:00 +08:00
|
|
|
{
|
|
|
|
if (isatty(cur_term->Filedes))
|
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
STRUCT_WINSIZE size;
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
do {
|
1998-03-01 12:21:12 +08:00
|
|
|
if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) < 0
|
1997-05-15 12:00:00 +08:00
|
|
|
&& errno != EINTR)
|
|
|
|
goto failure;
|
|
|
|
} while
|
|
|
|
(errno == EINTR);
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
*linep = WINSIZE_ROWS(size);
|
|
|
|
*colp = WINSIZE_COLS(size);
|
1997-05-15 12:00:00 +08:00
|
|
|
}
|
|
|
|
/* FALLTHRU */
|
|
|
|
failure:;
|
|
|
|
}
|
1998-03-01 12:21:12 +08:00
|
|
|
#endif /* HAVE_SIZECHANGE */
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
/* if we can't get dynamic info about the size, use static */
|
1998-03-01 12:21:12 +08:00
|
|
|
if (*linep <= 0 || *colp <= 0)
|
1997-05-15 12:00:00 +08:00
|
|
|
if (lines > 0 && columns > 0)
|
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
*linep = (int)lines;
|
|
|
|
*colp = (int)columns;
|
1997-05-15 12:00:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* the ultimate fallback, assume fixed 24x80 size */
|
1998-03-01 12:21:12 +08:00
|
|
|
if (*linep <= 0 || *colp <= 0)
|
1997-05-15 12:00:00 +08:00
|
|
|
{
|
1998-03-01 12:21:12 +08:00
|
|
|
*linep = 24;
|
|
|
|
*colp = 80;
|
1997-05-15 12:00:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the derived values back in the screen-size caps, so
|
|
|
|
* tigetnum() and tgetnum() will do the right thing.
|
|
|
|
*/
|
1998-03-01 12:21:12 +08:00
|
|
|
lines = (short)(*linep);
|
|
|
|
columns = (short)(*colp);
|
1997-05-15 12:00:00 +08:00
|
|
|
}
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
T(("screen size is %dx%d", *linep, *colp));
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
#ifdef init_tabs
|
|
|
|
if (init_tabs != -1)
|
|
|
|
TABSIZE = (int)init_tabs;
|
|
|
|
else
|
|
|
|
#endif /* init_tabs */
|
|
|
|
TABSIZE = 8;
|
|
|
|
T(("TABSIZE = %d", TABSIZE));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
#if USE_SIZECHANGE
|
|
|
|
void _nc_update_screensize(void)
|
|
|
|
{
|
|
|
|
int my_lines, my_cols;
|
|
|
|
|
|
|
|
_nc_get_screensize(&my_lines, &my_cols);
|
|
|
|
if (SP != 0 && SP->_resize != 0)
|
|
|
|
SP->_resize(my_lines, my_cols);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1997-05-15 12:00:00 +08:00
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* Terminal setup
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#define ret_error(code, fmt, arg) if (errret) {\
|
|
|
|
*errret = code;\
|
|
|
|
returnCode(ERR);\
|
|
|
|
} else {\
|
|
|
|
fprintf(stderr, fmt, arg);\
|
|
|
|
exit(EXIT_FAILURE);\
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ret_error0(code, msg) if (errret) {\
|
|
|
|
*errret = code;\
|
|
|
|
returnCode(ERR);\
|
|
|
|
} else {\
|
|
|
|
fprintf(stderr, msg);\
|
|
|
|
exit(EXIT_FAILURE);\
|
|
|
|
}
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
#if USE_DATABASE
|
1997-05-15 12:00:00 +08:00
|
|
|
static int grab_entry(const char *const tn, TERMTYPE *const tp)
|
|
|
|
/* return 1 if entry found, 0 if not found, -1 if database not accessible */
|
|
|
|
{
|
|
|
|
char filename[PATH_MAX];
|
|
|
|
int status;
|
|
|
|
|
|
|
|
if ((status = _nc_read_entry(tn, filename, tp)) == 1)
|
|
|
|
return(1);
|
|
|
|
|
|
|
|
#ifndef PURE_TERMINFO
|
|
|
|
/*
|
|
|
|
* Try falling back on the termcap file. Note: allowing this call
|
|
|
|
* links the entire terminfo/termcap compiler into the startup code.
|
|
|
|
* It's preferable to build a real terminfo database and use that.
|
|
|
|
*/
|
|
|
|
status = _nc_read_termcap_entry(tn, tp);
|
|
|
|
#endif /* PURE_TERMINFO */
|
|
|
|
|
|
|
|
return(status);
|
|
|
|
}
|
1998-03-01 12:21:12 +08:00
|
|
|
#endif
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
char ttytype[NAMESIZE];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* setupterm(termname, Filedes, errret)
|
|
|
|
*
|
|
|
|
* Find and read the appropriate object file for the terminal
|
|
|
|
* Make cur_term point to the structure.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int setupterm(const char *tname, int Filedes, int *errret)
|
|
|
|
{
|
|
|
|
struct term *term_ptr;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
T((T_CALLED("setupterm(\"%s\",%d,%p)"), tname, Filedes, errret));
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
if (tname == 0) {
|
1997-05-15 12:00:00 +08:00
|
|
|
tname = getenv("TERM");
|
1998-03-01 12:21:12 +08:00
|
|
|
if (tname == 0 || *tname == '\0')
|
1997-05-15 12:00:00 +08:00
|
|
|
ret_error0(-1, "TERM environment variable not set.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
T(("your terminal name is %s", tname));
|
|
|
|
|
|
|
|
term_ptr = typeCalloc(TERMINAL, 1);
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
if (term_ptr == 0)
|
1997-05-15 12:00:00 +08:00
|
|
|
ret_error0(-1, "Not enough memory to create terminal structure.\n") ;
|
1998-03-01 12:21:12 +08:00
|
|
|
#if USE_DATABASE
|
1997-05-15 12:00:00 +08:00
|
|
|
status = grab_entry(tname, &term_ptr->type);
|
1998-03-01 12:21:12 +08:00
|
|
|
#else
|
|
|
|
status = 0;
|
|
|
|
#endif
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
/* try fallback list if entry on disk */
|
|
|
|
if (status != 1)
|
|
|
|
{
|
|
|
|
const TERMTYPE *fallback = _nc_fallback(tname);
|
|
|
|
|
|
|
|
if (fallback)
|
|
|
|
{
|
|
|
|
memcpy(&term_ptr->type, fallback, sizeof(TERMTYPE));
|
|
|
|
status = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == -1)
|
|
|
|
{
|
|
|
|
ret_error0(-1, "terminals database is inaccessible\n");
|
|
|
|
}
|
|
|
|
else if (status == 0)
|
|
|
|
{
|
|
|
|
ret_error(0, "'%s': unknown terminal type.\n", tname);
|
|
|
|
}
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
set_curterm(term_ptr);
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
if (command_character && getenv("CC"))
|
|
|
|
do_prototype();
|
|
|
|
|
|
|
|
strncpy(ttytype, cur_term->type.term_names, NAMESIZE - 1);
|
|
|
|
ttytype[NAMESIZE - 1] = '\0';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allow output redirection. This is what SVr3 does.
|
|
|
|
* If stdout is directed to a file, screen updates go
|
|
|
|
* to standard error.
|
|
|
|
*/
|
|
|
|
if (Filedes == STDOUT_FILENO && !isatty(Filedes))
|
|
|
|
Filedes = STDERR_FILENO;
|
|
|
|
cur_term->Filedes = Filedes;
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
_nc_get_screensize(&LINES, &COLS);
|
1997-05-15 12:00:00 +08:00
|
|
|
|
|
|
|
if (errret)
|
|
|
|
*errret = 1;
|
|
|
|
|
|
|
|
T((T_CREATE("screen %s %dx%d"), tname, LINES, COLS));
|
|
|
|
|
1998-03-01 12:21:12 +08:00
|
|
|
if (generic_type)
|
|
|
|
ret_error(0, "'%s': I need something more specific.\n", tname);
|
|
|
|
if (hard_copy)
|
|
|
|
ret_error(1, "'%s': I can't handle hardcopy terminals.\n", tname);
|
|
|
|
|
1997-05-15 12:00:00 +08:00
|
|
|
returnCode(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** do_prototype()
|
|
|
|
**
|
|
|
|
** Take the real command character out of the CC environment variable
|
|
|
|
** and substitute it in for the prototype given in 'command_character'.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_prototype(void)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
char CC;
|
|
|
|
char proto;
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
tmp = getenv("CC");
|
|
|
|
CC = *tmp;
|
|
|
|
proto = *command_character;
|
|
|
|
|
|
|
|
for (i=0; i < STRCOUNT; i++) {
|
|
|
|
j = 0;
|
|
|
|
while (cur_term->type.Strings[i][j]) {
|
|
|
|
if (cur_term->type.Strings[i][j] == proto)
|
|
|
|
cur_term->type.Strings[i][j] = CC;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|