1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2018-2019,2020 Thomas E. Dickey                                *
3*32bb5217SDaniel Fojt  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
331d102085SJan Lentfer  *     and: Thomas E. Dickey                        1996-on                 *
3400d8f3c4SJohn Marino  *     and: Juergen Pfeifer                         2009                    *
35fdd4e1e0SJan Lentfer  ****************************************************************************/
36fdd4e1e0SJan Lentfer 
37fdd4e1e0SJan Lentfer /*
38fdd4e1e0SJan Lentfer  * Terminal setup routines common to termcap and terminfo:
39fdd4e1e0SJan Lentfer  *
40fdd4e1e0SJan Lentfer  *		use_env(bool)
413468e90cSJohn Marino  *		use_tioctl(bool)
42fdd4e1e0SJan Lentfer  *		setupterm(char *, int, int *)
43fdd4e1e0SJan Lentfer  */
44fdd4e1e0SJan Lentfer 
45fdd4e1e0SJan Lentfer #include <curses.priv.h>
46fdd4e1e0SJan Lentfer #include <tic.h>		/* for MAX_NAME_SIZE */
47fdd4e1e0SJan Lentfer 
481d102085SJan Lentfer #if HAVE_LOCALE_H
491d102085SJan Lentfer #include <locale.h>
501d102085SJan Lentfer #endif
511d102085SJan Lentfer 
52*32bb5217SDaniel Fojt MODULE_ID("$Id: lib_setup.c,v 1.207 2020/02/02 23:34:34 tom Exp $")
53fdd4e1e0SJan Lentfer 
54fdd4e1e0SJan Lentfer /****************************************************************************
55fdd4e1e0SJan Lentfer  *
56fdd4e1e0SJan Lentfer  * Terminal size computation
57fdd4e1e0SJan Lentfer  *
58fdd4e1e0SJan Lentfer  ****************************************************************************/
59fdd4e1e0SJan Lentfer 
60fdd4e1e0SJan Lentfer #if HAVE_SIZECHANGE
61fdd4e1e0SJan Lentfer # if !defined(sun) || !TERMIOS
62fdd4e1e0SJan Lentfer #  if HAVE_SYS_IOCTL_H
63fdd4e1e0SJan Lentfer #   include <sys/ioctl.h>
64fdd4e1e0SJan Lentfer #  endif
65fdd4e1e0SJan Lentfer # endif
66fdd4e1e0SJan Lentfer #endif
67fdd4e1e0SJan Lentfer 
68fdd4e1e0SJan Lentfer #if NEED_PTEM_H
69fdd4e1e0SJan Lentfer  /* On SCO, they neglected to define struct winsize in termios.h -- it's only
70fdd4e1e0SJan Lentfer   * in termio.h and ptem.h (the former conflicts with other definitions).
71fdd4e1e0SJan Lentfer   */
72fdd4e1e0SJan Lentfer # include <sys/stream.h>
73fdd4e1e0SJan Lentfer # include <sys/ptem.h>
74fdd4e1e0SJan Lentfer #endif
75fdd4e1e0SJan Lentfer 
761d102085SJan Lentfer #if HAVE_LANGINFO_CODESET
771d102085SJan Lentfer #include <langinfo.h>
781d102085SJan Lentfer #endif
791d102085SJan Lentfer 
80fdd4e1e0SJan Lentfer /*
81fdd4e1e0SJan Lentfer  * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
82fdd4e1e0SJan Lentfer  * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
83fdd4e1e0SJan Lentfer  */
84fdd4e1e0SJan Lentfer #ifdef TIOCGSIZE
85fdd4e1e0SJan Lentfer # define IOCTL_WINSIZE TIOCGSIZE
86fdd4e1e0SJan Lentfer # define STRUCT_WINSIZE struct ttysize
87fdd4e1e0SJan Lentfer # define WINSIZE_ROWS(n) (int)n.ts_lines
88fdd4e1e0SJan Lentfer # define WINSIZE_COLS(n) (int)n.ts_cols
89fdd4e1e0SJan Lentfer #else
90fdd4e1e0SJan Lentfer # ifdef TIOCGWINSZ
91fdd4e1e0SJan Lentfer #  define IOCTL_WINSIZE TIOCGWINSZ
92fdd4e1e0SJan Lentfer #  define STRUCT_WINSIZE struct winsize
93fdd4e1e0SJan Lentfer #  define WINSIZE_ROWS(n) (int)n.ws_row
94fdd4e1e0SJan Lentfer #  define WINSIZE_COLS(n) (int)n.ws_col
95fdd4e1e0SJan Lentfer # endif
96fdd4e1e0SJan Lentfer #endif
97fdd4e1e0SJan Lentfer 
981d102085SJan Lentfer /*
991d102085SJan Lentfer  * Reduce explicit use of "cur_term" global variable.
1001d102085SJan Lentfer  */
1011d102085SJan Lentfer #undef CUR
102*32bb5217SDaniel Fojt #define CUR TerminalType(termp).
1031d102085SJan Lentfer 
1041d102085SJan Lentfer /*
1051d102085SJan Lentfer  * Wrap global variables in this module.
1061d102085SJan Lentfer  */
1071d102085SJan Lentfer #if USE_REENTRANT
10800d8f3c4SJohn Marino 
NCURSES_EXPORT(char *)1091d102085SJan Lentfer NCURSES_EXPORT(char *)
1101d102085SJan Lentfer NCURSES_PUBLIC_VAR(ttytype) (void)
1111d102085SJan Lentfer {
1121d102085SJan Lentfer     static char empty[] = "";
11300d8f3c4SJohn Marino     char *result = empty;
11400d8f3c4SJohn Marino 
11500d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
11600d8f3c4SJohn Marino     if (CURRENT_SCREEN) {
11700d8f3c4SJohn Marino 	TERMINAL *termp = TerminalOf(CURRENT_SCREEN);
11800d8f3c4SJohn Marino 	if (termp != 0) {
119*32bb5217SDaniel Fojt 	    result = TerminalType(termp).term_names;
1201d102085SJan Lentfer 	}
12100d8f3c4SJohn Marino     }
12200d8f3c4SJohn Marino #else
12300d8f3c4SJohn Marino     if (cur_term != 0) {
124*32bb5217SDaniel Fojt 	result = TerminalType(cur_term).term_names;
12500d8f3c4SJohn Marino     }
12600d8f3c4SJohn Marino #endif
12700d8f3c4SJohn Marino     return result;
12800d8f3c4SJohn Marino }
12900d8f3c4SJohn Marino 
1301d102085SJan Lentfer NCURSES_EXPORT(int *)
_nc_ptr_Lines(SCREEN * sp)13100d8f3c4SJohn Marino _nc_ptr_Lines(SCREEN *sp)
1321d102085SJan Lentfer {
13300d8f3c4SJohn Marino     return ptrLines(sp);
1341d102085SJan Lentfer }
13500d8f3c4SJohn Marino 
1361d102085SJan Lentfer NCURSES_EXPORT(int)
NCURSES_PUBLIC_VAR(LINES)1371d102085SJan Lentfer NCURSES_PUBLIC_VAR(LINES) (void)
1381d102085SJan Lentfer {
13900d8f3c4SJohn Marino     return *_nc_ptr_Lines(CURRENT_SCREEN);
1401d102085SJan Lentfer }
14100d8f3c4SJohn Marino 
1421d102085SJan Lentfer NCURSES_EXPORT(int *)
_nc_ptr_Cols(SCREEN * sp)14300d8f3c4SJohn Marino _nc_ptr_Cols(SCREEN *sp)
1441d102085SJan Lentfer {
14500d8f3c4SJohn Marino     return ptrCols(sp);
1461d102085SJan Lentfer }
14700d8f3c4SJohn Marino 
1481d102085SJan Lentfer NCURSES_EXPORT(int)
NCURSES_PUBLIC_VAR(COLS)1491d102085SJan Lentfer NCURSES_PUBLIC_VAR(COLS) (void)
1501d102085SJan Lentfer {
15100d8f3c4SJohn Marino     return *_nc_ptr_Cols(CURRENT_SCREEN);
1521d102085SJan Lentfer }
15300d8f3c4SJohn Marino 
15400d8f3c4SJohn Marino NCURSES_EXPORT(int *)
_nc_ptr_Tabsize(SCREEN * sp)15500d8f3c4SJohn Marino _nc_ptr_Tabsize(SCREEN *sp)
15600d8f3c4SJohn Marino {
15700d8f3c4SJohn Marino     return ptrTabsize(sp);
15800d8f3c4SJohn Marino }
15900d8f3c4SJohn Marino 
1601d102085SJan Lentfer NCURSES_EXPORT(int)
NCURSES_PUBLIC_VAR(TABSIZE)1611d102085SJan Lentfer NCURSES_PUBLIC_VAR(TABSIZE) (void)
1621d102085SJan Lentfer {
16300d8f3c4SJohn Marino     return *_nc_ptr_Tabsize(CURRENT_SCREEN);
1641d102085SJan Lentfer }
1651d102085SJan Lentfer #else
166fdd4e1e0SJan Lentfer NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = "";
167fdd4e1e0SJan Lentfer NCURSES_EXPORT_VAR(int) LINES = 0;
168fdd4e1e0SJan Lentfer NCURSES_EXPORT_VAR(int) COLS = 0;
16900d8f3c4SJohn Marino NCURSES_EXPORT_VAR(int) TABSIZE = 8;
1701d102085SJan Lentfer #endif
171fdd4e1e0SJan Lentfer 
1721d102085SJan Lentfer #if NCURSES_EXT_FUNCS
1731d102085SJan Lentfer NCURSES_EXPORT(int)
NCURSES_SP_NAME(set_tabsize)17400d8f3c4SJohn Marino NCURSES_SP_NAME(set_tabsize) (NCURSES_SP_DCLx int value)
1751d102085SJan Lentfer {
1761d102085SJan Lentfer     int code = OK;
177*32bb5217SDaniel Fojt     if (value <= 0) {
178*32bb5217SDaniel Fojt 	code = ERR;
179*32bb5217SDaniel Fojt     } else {
1801d102085SJan Lentfer #if USE_REENTRANT
18100d8f3c4SJohn Marino 	if (SP_PARM) {
18200d8f3c4SJohn Marino 	    SP_PARM->_TABSIZE = value;
1831d102085SJan Lentfer 	} else {
1841d102085SJan Lentfer 	    code = ERR;
1851d102085SJan Lentfer 	}
1861d102085SJan Lentfer #else
18700d8f3c4SJohn Marino 	(void) SP_PARM;
1881d102085SJan Lentfer 	TABSIZE = value;
1891d102085SJan Lentfer #endif
190*32bb5217SDaniel Fojt     }
1911d102085SJan Lentfer     return code;
1921d102085SJan Lentfer }
19300d8f3c4SJohn Marino 
19400d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
19500d8f3c4SJohn Marino NCURSES_EXPORT(int)
set_tabsize(int value)19600d8f3c4SJohn Marino set_tabsize(int value)
19700d8f3c4SJohn Marino {
19800d8f3c4SJohn Marino     return NCURSES_SP_NAME(set_tabsize) (CURRENT_SCREEN, value);
19900d8f3c4SJohn Marino }
2001d102085SJan Lentfer #endif
20100d8f3c4SJohn Marino #endif /* NCURSES_EXT_FUNCS */
2021d102085SJan Lentfer 
2031d102085SJan Lentfer #if USE_SIGWINCH
2041d102085SJan Lentfer /*
2051d102085SJan Lentfer  * If we have a pending SIGWINCH, set the flag in each screen.
2061d102085SJan Lentfer  */
2071d102085SJan Lentfer NCURSES_EXPORT(int)
_nc_handle_sigwinch(SCREEN * sp)2081d102085SJan Lentfer _nc_handle_sigwinch(SCREEN *sp)
2091d102085SJan Lentfer {
2101d102085SJan Lentfer     SCREEN *scan;
2111d102085SJan Lentfer 
2121d102085SJan Lentfer     if (_nc_globals.have_sigwinch) {
2131d102085SJan Lentfer 	_nc_globals.have_sigwinch = 0;
2141d102085SJan Lentfer 
2151d102085SJan Lentfer 	for (each_screen(scan)) {
2161d102085SJan Lentfer 	    scan->_sig_winch = TRUE;
2171d102085SJan Lentfer 	}
2181d102085SJan Lentfer     }
2191d102085SJan Lentfer 
2201d102085SJan Lentfer     return (sp ? sp->_sig_winch : 0);
2211d102085SJan Lentfer }
2221d102085SJan Lentfer 
2231d102085SJan Lentfer #endif
224fdd4e1e0SJan Lentfer 
225fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
NCURSES_SP_NAME(use_env)22600d8f3c4SJohn Marino NCURSES_SP_NAME(use_env) (NCURSES_SP_DCLx bool f)
227fdd4e1e0SJan Lentfer {
228*32bb5217SDaniel Fojt     START_TRACE();
22900d8f3c4SJohn Marino     T((T_CALLED("use_env(%p,%d)"), (void *) SP_PARM, (int) f));
23000d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
23100d8f3c4SJohn Marino     if (IsPreScreen(SP_PARM)) {
23200d8f3c4SJohn Marino 	SP_PARM->_use_env = f;
23300d8f3c4SJohn Marino     }
23400d8f3c4SJohn Marino #else
2351d102085SJan Lentfer     _nc_prescreen.use_env = f;
23600d8f3c4SJohn Marino #endif
237fdd4e1e0SJan Lentfer     returnVoid;
238fdd4e1e0SJan Lentfer }
239fdd4e1e0SJan Lentfer 
2403468e90cSJohn Marino NCURSES_EXPORT(void)
NCURSES_SP_NAME(use_tioctl)2413468e90cSJohn Marino NCURSES_SP_NAME(use_tioctl) (NCURSES_SP_DCLx bool f)
2423468e90cSJohn Marino {
243*32bb5217SDaniel Fojt     START_TRACE();
2443468e90cSJohn Marino     T((T_CALLED("use_tioctl(%p,%d)"), (void *) SP_PARM, (int) f));
2453468e90cSJohn Marino #if NCURSES_SP_FUNCS
2463468e90cSJohn Marino     if (IsPreScreen(SP_PARM)) {
247*32bb5217SDaniel Fojt 	SP_PARM->use_tioctl = f;
2483468e90cSJohn Marino     }
2493468e90cSJohn Marino #else
2503468e90cSJohn Marino     _nc_prescreen.use_tioctl = f;
2513468e90cSJohn Marino #endif
2523468e90cSJohn Marino     returnVoid;
2533468e90cSJohn Marino }
2543468e90cSJohn Marino 
25500d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
2561d102085SJan Lentfer NCURSES_EXPORT(void)
use_env(bool f)25700d8f3c4SJohn Marino use_env(bool f)
25800d8f3c4SJohn Marino {
2593468e90cSJohn Marino     START_TRACE();
260*32bb5217SDaniel Fojt     T((T_CALLED("use_env(%d)"), (int) f));
26100d8f3c4SJohn Marino     _nc_prescreen.use_env = f;
26200d8f3c4SJohn Marino     returnVoid;
26300d8f3c4SJohn Marino }
2643468e90cSJohn Marino 
2653468e90cSJohn Marino NCURSES_EXPORT(void)
use_tioctl(bool f)2663468e90cSJohn Marino use_tioctl(bool f)
2673468e90cSJohn Marino {
2683468e90cSJohn Marino     START_TRACE();
269*32bb5217SDaniel Fojt     T((T_CALLED("use_tioctl(%d)"), (int) f));
2703468e90cSJohn Marino     _nc_prescreen.use_tioctl = f;
2713468e90cSJohn Marino     returnVoid;
2723468e90cSJohn Marino }
27300d8f3c4SJohn Marino #endif
27400d8f3c4SJohn Marino 
27500d8f3c4SJohn Marino NCURSES_EXPORT(void)
_nc_get_screensize(SCREEN * sp,TERMINAL * termp,int * linep,int * colp)27600d8f3c4SJohn Marino _nc_get_screensize(SCREEN *sp,
27700d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
27800d8f3c4SJohn Marino 		   TERMINAL *termp,
27900d8f3c4SJohn Marino #endif
28000d8f3c4SJohn Marino 		   int *linep, int *colp)
281fdd4e1e0SJan Lentfer /* Obtain lines/columns values from the environment and/or terminfo entry */
282fdd4e1e0SJan Lentfer {
28300d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
28400d8f3c4SJohn Marino     TERMINAL_CONTROL_BLOCK *TCB;
28500d8f3c4SJohn Marino     int my_tabsize;
28600d8f3c4SJohn Marino 
28700d8f3c4SJohn Marino     assert(termp != 0 && linep != 0 && colp != 0);
28800d8f3c4SJohn Marino     TCB = (TERMINAL_CONTROL_BLOCK *) termp;
28900d8f3c4SJohn Marino 
29000d8f3c4SJohn Marino     my_tabsize = TCB->info.tabsize;
2913468e90cSJohn Marino     TCB->drv->td_size(TCB, linep, colp);
29200d8f3c4SJohn Marino 
29300d8f3c4SJohn Marino #if USE_REENTRANT
29400d8f3c4SJohn Marino     if (sp != 0) {
29500d8f3c4SJohn Marino 	sp->_TABSIZE = my_tabsize;
29600d8f3c4SJohn Marino     }
29700d8f3c4SJohn Marino #else
29800d8f3c4SJohn Marino     (void) sp;
29900d8f3c4SJohn Marino     TABSIZE = my_tabsize;
30000d8f3c4SJohn Marino #endif
30100d8f3c4SJohn Marino     T(("TABSIZE = %d", my_tabsize));
30200d8f3c4SJohn Marino #else /* !USE_TERM_DRIVER */
3031d102085SJan Lentfer     TERMINAL *termp = cur_term;
3041d102085SJan Lentfer     int my_tabsize;
305*32bb5217SDaniel Fojt     bool useEnv = _nc_prescreen.use_env;
306*32bb5217SDaniel Fojt     bool useTioctl = _nc_prescreen.use_tioctl;
3071d102085SJan Lentfer 
308fdd4e1e0SJan Lentfer     /* figure out the size of the screen */
309fdd4e1e0SJan Lentfer     T(("screen size: terminfo lines = %d columns = %d", lines, columns));
310fdd4e1e0SJan Lentfer 
311fdd4e1e0SJan Lentfer     *linep = (int) lines;
312fdd4e1e0SJan Lentfer     *colp = (int) columns;
31300d8f3c4SJohn Marino 
314*32bb5217SDaniel Fojt #if NCURSES_SP_FUNCS
315*32bb5217SDaniel Fojt     if (sp) {
316*32bb5217SDaniel Fojt 	useEnv = sp->_use_env;
317*32bb5217SDaniel Fojt 	useTioctl = sp->use_tioctl;
318*32bb5217SDaniel Fojt     }
319*32bb5217SDaniel Fojt #endif
320fdd4e1e0SJan Lentfer 
321*32bb5217SDaniel Fojt     if (useEnv || useTioctl) {
322fdd4e1e0SJan Lentfer #ifdef __EMX__
32300d8f3c4SJohn Marino 	{
324fdd4e1e0SJan Lentfer 	    int screendata[2];
325fdd4e1e0SJan Lentfer 	    _scrsize(screendata);
326fdd4e1e0SJan Lentfer 	    *colp = screendata[0];
3273468e90cSJohn Marino 	    *linep = ((sp != 0 && sp->_filtered)
3283468e90cSJohn Marino 		      ? 1
3293468e90cSJohn Marino 		      : screendata[1]);
330fdd4e1e0SJan Lentfer 	    T(("EMX screen size: environment LINES = %d COLUMNS = %d",
331fdd4e1e0SJan Lentfer 	       *linep, *colp));
332fdd4e1e0SJan Lentfer 	}
333fdd4e1e0SJan Lentfer #endif
334fdd4e1e0SJan Lentfer #if HAVE_SIZECHANGE
33500d8f3c4SJohn Marino 	/* try asking the OS */
3363468e90cSJohn Marino 	if (NC_ISATTY(cur_term->Filedes)) {
337fdd4e1e0SJan Lentfer 	    STRUCT_WINSIZE size;
338fdd4e1e0SJan Lentfer 
339fdd4e1e0SJan Lentfer 	    errno = 0;
340fdd4e1e0SJan Lentfer 	    do {
34100d8f3c4SJohn Marino 		if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) >= 0) {
34200d8f3c4SJohn Marino 		    *linep = ((sp != 0 && sp->_filtered)
34300d8f3c4SJohn Marino 			      ? 1
34400d8f3c4SJohn Marino 			      : WINSIZE_ROWS(size));
34500d8f3c4SJohn Marino 		    *colp = WINSIZE_COLS(size);
34600d8f3c4SJohn Marino 		    T(("SYS screen size: environment LINES = %d COLUMNS = %d",
34700d8f3c4SJohn Marino 		       *linep, *colp));
34800d8f3c4SJohn Marino 		    break;
34900d8f3c4SJohn Marino 		}
350fdd4e1e0SJan Lentfer 	    } while
351fdd4e1e0SJan Lentfer 		(errno == EINTR);
352fdd4e1e0SJan Lentfer 	}
353fdd4e1e0SJan Lentfer #endif /* HAVE_SIZECHANGE */
354fdd4e1e0SJan Lentfer 
355*32bb5217SDaniel Fojt 	if (useEnv) {
356*32bb5217SDaniel Fojt 	    int value;
357*32bb5217SDaniel Fojt 
358*32bb5217SDaniel Fojt 	    if (useTioctl) {
3593468e90cSJohn Marino 		/*
3603468e90cSJohn Marino 		 * If environment variables are used, update them.
3613468e90cSJohn Marino 		 */
3623468e90cSJohn Marino 		if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) {
3633468e90cSJohn Marino 		    _nc_setenv_num("LINES", *linep);
3643468e90cSJohn Marino 		}
3653468e90cSJohn Marino 		if (_nc_getenv_num("COLUMNS") > 0) {
3663468e90cSJohn Marino 		    _nc_setenv_num("COLUMNS", *colp);
3673468e90cSJohn Marino 		}
3683468e90cSJohn Marino 	    }
3693468e90cSJohn Marino 
37000d8f3c4SJohn Marino 	    /*
37100d8f3c4SJohn Marino 	     * Finally, look for environment variables.
37200d8f3c4SJohn Marino 	     *
37300d8f3c4SJohn Marino 	     * Solaris lets users override either dimension with an environment
37400d8f3c4SJohn Marino 	     * variable.
37500d8f3c4SJohn Marino 	     */
37600d8f3c4SJohn Marino 	    if ((value = _nc_getenv_num("LINES")) > 0) {
37700d8f3c4SJohn Marino 		*linep = value;
37800d8f3c4SJohn Marino 		T(("screen size: environment LINES = %d", *linep));
37900d8f3c4SJohn Marino 	    }
38000d8f3c4SJohn Marino 	    if ((value = _nc_getenv_num("COLUMNS")) > 0) {
38100d8f3c4SJohn Marino 		*colp = value;
38200d8f3c4SJohn Marino 		T(("screen size: environment COLUMNS = %d", *colp));
38300d8f3c4SJohn Marino 	    }
3843468e90cSJohn Marino 	}
38500d8f3c4SJohn Marino 
386fdd4e1e0SJan Lentfer 	/* if we can't get dynamic info about the size, use static */
387fdd4e1e0SJan Lentfer 	if (*linep <= 0) {
388fdd4e1e0SJan Lentfer 	    *linep = (int) lines;
389fdd4e1e0SJan Lentfer 	}
390fdd4e1e0SJan Lentfer 	if (*colp <= 0) {
391fdd4e1e0SJan Lentfer 	    *colp = (int) columns;
392fdd4e1e0SJan Lentfer 	}
393fdd4e1e0SJan Lentfer 
394fdd4e1e0SJan Lentfer 	/* the ultimate fallback, assume fixed 24x80 size */
395fdd4e1e0SJan Lentfer 	if (*linep <= 0) {
396fdd4e1e0SJan Lentfer 	    *linep = 24;
397fdd4e1e0SJan Lentfer 	}
398fdd4e1e0SJan Lentfer 	if (*colp <= 0) {
399fdd4e1e0SJan Lentfer 	    *colp = 80;
400fdd4e1e0SJan Lentfer 	}
401fdd4e1e0SJan Lentfer 
402fdd4e1e0SJan Lentfer 	/*
403fdd4e1e0SJan Lentfer 	 * Put the derived values back in the screen-size caps, so
404fdd4e1e0SJan Lentfer 	 * tigetnum() and tgetnum() will do the right thing.
405fdd4e1e0SJan Lentfer 	 */
406*32bb5217SDaniel Fojt 	lines = (NCURSES_INT2) (*linep);
407*32bb5217SDaniel Fojt 	columns = (NCURSES_INT2) (*colp);
408*32bb5217SDaniel Fojt #if NCURSES_EXT_NUMBERS
409*32bb5217SDaniel Fojt #define OldNumber(termp,name) \
410*32bb5217SDaniel Fojt 	(termp)->type.Numbers[(&name - (termp)->type2.Numbers)]
411*32bb5217SDaniel Fojt 	OldNumber(termp, lines) = (short) (*linep);
412*32bb5217SDaniel Fojt 	OldNumber(termp, columns) = (short) (*colp);
413*32bb5217SDaniel Fojt #endif
414fdd4e1e0SJan Lentfer     }
415fdd4e1e0SJan Lentfer 
416fdd4e1e0SJan Lentfer     T(("screen size is %dx%d", *linep, *colp));
417fdd4e1e0SJan Lentfer 
418fdd4e1e0SJan Lentfer     if (VALID_NUMERIC(init_tabs))
4191d102085SJan Lentfer 	my_tabsize = (int) init_tabs;
420fdd4e1e0SJan Lentfer     else
4211d102085SJan Lentfer 	my_tabsize = 8;
4221d102085SJan Lentfer 
4231d102085SJan Lentfer #if USE_REENTRANT
4241d102085SJan Lentfer     if (sp != 0)
4251d102085SJan Lentfer 	sp->_TABSIZE = my_tabsize;
4261d102085SJan Lentfer #else
4271d102085SJan Lentfer     TABSIZE = my_tabsize;
4281d102085SJan Lentfer #endif
429fdd4e1e0SJan Lentfer     T(("TABSIZE = %d", TABSIZE));
43000d8f3c4SJohn Marino #endif /* USE_TERM_DRIVER */
431fdd4e1e0SJan Lentfer }
432fdd4e1e0SJan Lentfer 
433fdd4e1e0SJan Lentfer #if USE_SIZECHANGE
434fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
_nc_update_screensize(SCREEN * sp)4351d102085SJan Lentfer _nc_update_screensize(SCREEN *sp)
436fdd4e1e0SJan Lentfer {
4371d102085SJan Lentfer     int new_lines;
4381d102085SJan Lentfer     int new_cols;
439fdd4e1e0SJan Lentfer 
44000d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
44100d8f3c4SJohn Marino     int old_lines;
44200d8f3c4SJohn Marino     int old_cols;
44300d8f3c4SJohn Marino 
44400d8f3c4SJohn Marino     assert(sp != 0);
44500d8f3c4SJohn Marino 
4463468e90cSJohn Marino     CallDriver_2(sp, td_getsize, &old_lines, &old_cols);
44700d8f3c4SJohn Marino 
44800d8f3c4SJohn Marino #else
44900d8f3c4SJohn Marino     TERMINAL *termp = cur_term;
45000d8f3c4SJohn Marino     int old_lines = lines;
45100d8f3c4SJohn Marino     int old_cols = columns;
45200d8f3c4SJohn Marino #endif
45300d8f3c4SJohn Marino 
454*32bb5217SDaniel Fojt     if (sp != 0) {
45500d8f3c4SJohn Marino 	TINFO_GET_SIZE(sp, sp->_term, &new_lines, &new_cols);
4561d102085SJan Lentfer 	/*
4571d102085SJan Lentfer 	 * See is_term_resized() and resizeterm().
4581d102085SJan Lentfer 	 * We're doing it this way because those functions belong to the upper
4591d102085SJan Lentfer 	 * ncurses library, while this resides in the lower terminfo library.
4601d102085SJan Lentfer 	 */
461*32bb5217SDaniel Fojt 	if (sp->_resize != 0) {
4623468e90cSJohn Marino 	    if ((new_lines != old_lines) || (new_cols != old_cols)) {
46300d8f3c4SJohn Marino 		sp->_resize(NCURSES_SP_ARGx new_lines, new_cols);
4643468e90cSJohn Marino 	    } else if (sp->_sig_winch && (sp->_ungetch != 0)) {
4653468e90cSJohn Marino 		sp->_ungetch(SP_PARM, KEY_RESIZE);	/* so application can know this */
4663468e90cSJohn Marino 	    }
4671d102085SJan Lentfer 	    sp->_sig_winch = FALSE;
4681d102085SJan Lentfer 	}
469fdd4e1e0SJan Lentfer     }
470*32bb5217SDaniel Fojt }
471*32bb5217SDaniel Fojt #endif /* USE_SIZECHANGE */
472fdd4e1e0SJan Lentfer 
473fdd4e1e0SJan Lentfer /****************************************************************************
474fdd4e1e0SJan Lentfer  *
475fdd4e1e0SJan Lentfer  * Terminal setup
476fdd4e1e0SJan Lentfer  *
477fdd4e1e0SJan Lentfer  ****************************************************************************/
478fdd4e1e0SJan Lentfer 
4793468e90cSJohn Marino #if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP
4801d102085SJan Lentfer /*
4811d102085SJan Lentfer  * Return 1 if entry found, 0 if not found, -1 if database not accessible,
4821d102085SJan Lentfer  * just like tgetent().
4831d102085SJan Lentfer  */
48400d8f3c4SJohn Marino int
_nc_setup_tinfo(const char * const tn,TERMTYPE2 * const tp)485*32bb5217SDaniel Fojt _nc_setup_tinfo(const char *const tn, TERMTYPE2 *const tp)
486fdd4e1e0SJan Lentfer {
487fdd4e1e0SJan Lentfer     char filename[PATH_MAX];
488*32bb5217SDaniel Fojt     int status = _nc_read_entry2(tn, filename, tp);
489fdd4e1e0SJan Lentfer 
490fdd4e1e0SJan Lentfer     /*
491fdd4e1e0SJan Lentfer      * If we have an entry, force all of the cancelled strings to null
492fdd4e1e0SJan Lentfer      * pointers so we don't have to test them in the rest of the library.
493fdd4e1e0SJan Lentfer      * (The terminfo compiler bypasses this logic, since it must know if
494fdd4e1e0SJan Lentfer      * a string is cancelled, for merging entries).
495fdd4e1e0SJan Lentfer      */
4961d102085SJan Lentfer     if (status == TGETENT_YES) {
497fdd4e1e0SJan Lentfer 	unsigned n;
498fdd4e1e0SJan Lentfer 	for_each_boolean(n, tp) {
499fdd4e1e0SJan Lentfer 	    if (!VALID_BOOLEAN(tp->Booleans[n]))
500fdd4e1e0SJan Lentfer 		tp->Booleans[n] = FALSE;
501fdd4e1e0SJan Lentfer 	}
502fdd4e1e0SJan Lentfer 	for_each_string(n, tp) {
503fdd4e1e0SJan Lentfer 	    if (tp->Strings[n] == CANCELLED_STRING)
504fdd4e1e0SJan Lentfer 		tp->Strings[n] = ABSENT_STRING;
505fdd4e1e0SJan Lentfer 	}
506fdd4e1e0SJan Lentfer     }
507fdd4e1e0SJan Lentfer     return (status);
508fdd4e1e0SJan Lentfer }
509fdd4e1e0SJan Lentfer #endif
510fdd4e1e0SJan Lentfer 
511fdd4e1e0SJan Lentfer /*
512fdd4e1e0SJan Lentfer **	Take the real command character out of the CC environment variable
513fdd4e1e0SJan Lentfer **	and substitute it in for the prototype given in 'command_character'.
514fdd4e1e0SJan Lentfer */
51500d8f3c4SJohn Marino void
_nc_tinfo_cmdch(TERMINAL * termp,int proto)5163468e90cSJohn Marino _nc_tinfo_cmdch(TERMINAL *termp, int proto)
517fdd4e1e0SJan Lentfer {
518fdd4e1e0SJan Lentfer     char *tmp;
519fdd4e1e0SJan Lentfer 
52000d8f3c4SJohn Marino     /*
52100d8f3c4SJohn Marino      * Only use the character if the string is a single character,
52200d8f3c4SJohn Marino      * since it is fairly common for developers to set the C compiler
52300d8f3c4SJohn Marino      * name as an environment variable - using the same symbol.
52400d8f3c4SJohn Marino      */
52500d8f3c4SJohn Marino     if ((tmp = getenv("CC")) != 0 && strlen(tmp) == 1) {
526*32bb5217SDaniel Fojt 	unsigned i;
527*32bb5217SDaniel Fojt 	char CC = *tmp;
528*32bb5217SDaniel Fojt 
5291d102085SJan Lentfer 	for_each_string(i, &(termp->type)) {
5303468e90cSJohn Marino 	    for (tmp = termp->type.Strings[i]; tmp && *tmp; tmp++) {
5313468e90cSJohn Marino 		if (UChar(*tmp) == proto)
532fdd4e1e0SJan Lentfer 		    *tmp = CC;
533fdd4e1e0SJan Lentfer 	    }
534fdd4e1e0SJan Lentfer 	}
535fdd4e1e0SJan Lentfer     }
5361d102085SJan Lentfer }
537fdd4e1e0SJan Lentfer 
538fdd4e1e0SJan Lentfer /*
5391d102085SJan Lentfer  * Find the locale which is in effect.
540fdd4e1e0SJan Lentfer  */
541fdd4e1e0SJan Lentfer NCURSES_EXPORT(char *)
_nc_get_locale(void)542fdd4e1e0SJan Lentfer _nc_get_locale(void)
543fdd4e1e0SJan Lentfer {
544fdd4e1e0SJan Lentfer     char *env;
5451d102085SJan Lentfer #if HAVE_LOCALE_H
5461d102085SJan Lentfer     /*
5471d102085SJan Lentfer      * This is preferable to using getenv() since it ensures that we are using
5481d102085SJan Lentfer      * the locale which was actually initialized by the application.
5491d102085SJan Lentfer      */
5501d102085SJan Lentfer     env = setlocale(LC_CTYPE, 0);
5511d102085SJan Lentfer #else
552*32bb5217SDaniel Fojt     if (((env = getenv("LANG")) != 0 && *env != '\0')
553fdd4e1e0SJan Lentfer 	|| ((env = getenv("LC_CTYPE")) != 0 && *env != '\0')
554*32bb5217SDaniel Fojt 	|| ((env = getenv("LC_ALL")) != 0 && *env != '\0')) {
5551d102085SJan Lentfer 	;
556fdd4e1e0SJan Lentfer     }
5571d102085SJan Lentfer #endif
5581d102085SJan Lentfer     T(("_nc_get_locale %s", _nc_visbuf(env)));
5591d102085SJan Lentfer     return env;
560fdd4e1e0SJan Lentfer }
561fdd4e1e0SJan Lentfer 
562fdd4e1e0SJan Lentfer /*
563fdd4e1e0SJan Lentfer  * Check if we are running in a UTF-8 locale.
564fdd4e1e0SJan Lentfer  */
565fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
_nc_unicode_locale(void)566fdd4e1e0SJan Lentfer _nc_unicode_locale(void)
567fdd4e1e0SJan Lentfer {
5681d102085SJan Lentfer     int result = 0;
569*32bb5217SDaniel Fojt #if defined(_WIN32) && USE_WIDEC_SUPPORT
5703468e90cSJohn Marino     result = 1;
5713468e90cSJohn Marino #elif HAVE_LANGINFO_CODESET
5721d102085SJan Lentfer     char *env = nl_langinfo(CODESET);
5731d102085SJan Lentfer     result = !strcmp(env, "UTF-8");
5741d102085SJan Lentfer     T(("_nc_unicode_locale(%s) ->%d", env, result));
5751d102085SJan Lentfer #else
576fdd4e1e0SJan Lentfer     char *env = _nc_get_locale();
577fdd4e1e0SJan Lentfer     if (env != 0) {
5781d102085SJan Lentfer 	if (strstr(env, ".UTF-8") != 0) {
5791d102085SJan Lentfer 	    result = 1;
5801d102085SJan Lentfer 	    T(("_nc_unicode_locale(%s) ->%d", env, result));
581fdd4e1e0SJan Lentfer 	}
582fdd4e1e0SJan Lentfer     }
5831d102085SJan Lentfer #endif
5841d102085SJan Lentfer     return result;
5851d102085SJan Lentfer }
5861d102085SJan Lentfer 
5871d102085SJan Lentfer #define CONTROL_N(s) ((s) != 0 && strstr(s, "\016") != 0)
5881d102085SJan Lentfer #define CONTROL_O(s) ((s) != 0 && strstr(s, "\017") != 0)
589fdd4e1e0SJan Lentfer 
590fdd4e1e0SJan Lentfer /*
591fdd4e1e0SJan Lentfer  * Check for known broken cases where a UTF-8 locale breaks the alternate
592fdd4e1e0SJan Lentfer  * character set.
593fdd4e1e0SJan Lentfer  */
594fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
_nc_locale_breaks_acs(TERMINAL * termp)5951d102085SJan Lentfer _nc_locale_breaks_acs(TERMINAL *termp)
596fdd4e1e0SJan Lentfer {
59700d8f3c4SJohn Marino     const char *env_name = "NCURSES_NO_UTF8_ACS";
5983468e90cSJohn Marino     const char *env;
59900d8f3c4SJohn Marino     int value;
60000d8f3c4SJohn Marino     int result = 0;
6011d102085SJan Lentfer 
6023468e90cSJohn Marino     T((T_CALLED("_nc_locale_breaks_acs:%d"), result));
6033468e90cSJohn Marino     if (getenv(env_name) != 0) {
60400d8f3c4SJohn Marino 	result = _nc_getenv_num(env_name);
60500d8f3c4SJohn Marino     } else if ((value = tigetnum("U8")) >= 0) {
60600d8f3c4SJohn Marino 	result = value;		/* use extension feature */
6071d102085SJan Lentfer     } else if ((env = getenv("TERM")) != 0) {
60800d8f3c4SJohn Marino 	if (strstr(env, "linux")) {
60900d8f3c4SJohn Marino 	    result = 1;		/* always broken */
61000d8f3c4SJohn Marino 	} else if (strstr(env, "screen") != 0
611fdd4e1e0SJan Lentfer 		   && ((env = getenv("TERMCAP")) != 0
612fdd4e1e0SJan Lentfer 		       && strstr(env, "screen") != 0)
613fdd4e1e0SJan Lentfer 		   && strstr(env, "hhII00") != 0) {
6141d102085SJan Lentfer 	    if (CONTROL_N(enter_alt_charset_mode) ||
6151d102085SJan Lentfer 		CONTROL_O(enter_alt_charset_mode) ||
6161d102085SJan Lentfer 		CONTROL_N(set_attributes) ||
61700d8f3c4SJohn Marino 		CONTROL_O(set_attributes)) {
61800d8f3c4SJohn Marino 		result = 1;
619fdd4e1e0SJan Lentfer 	    }
620fdd4e1e0SJan Lentfer 	}
62100d8f3c4SJohn Marino     }
6223468e90cSJohn Marino     returnCode(result);
623fdd4e1e0SJan Lentfer }
624fdd4e1e0SJan Lentfer 
625fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
TINFO_SETUP_TERM(TERMINAL ** tp,const char * tname,int Filedes,int * errret,int reuse)62600d8f3c4SJohn Marino TINFO_SETUP_TERM(TERMINAL **tp,
627*32bb5217SDaniel Fojt 		 const char *tname,
62800d8f3c4SJohn Marino 		 int Filedes,
62900d8f3c4SJohn Marino 		 int *errret,
6303468e90cSJohn Marino 		 int reuse)
631fdd4e1e0SJan Lentfer {
63200d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
63300d8f3c4SJohn Marino     TERMINAL_CONTROL_BLOCK *TCB = 0;
63400d8f3c4SJohn Marino #endif
63500d8f3c4SJohn Marino     TERMINAL *termp;
63600d8f3c4SJohn Marino     SCREEN *sp = 0;
637*32bb5217SDaniel Fojt     char *myname;
63800d8f3c4SJohn Marino     int code = ERR;
639fdd4e1e0SJan Lentfer 
640fdd4e1e0SJan Lentfer     START_TRACE();
64100d8f3c4SJohn Marino 
64200d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
64300d8f3c4SJohn Marino     T((T_CALLED("_nc_setupterm_ex(%p,%s,%d,%p)"),
64400d8f3c4SJohn Marino        (void *) tp, _nc_visbuf(tname), Filedes, (void *) errret));
64500d8f3c4SJohn Marino 
64600d8f3c4SJohn Marino     if (tp == 0) {
64700d8f3c4SJohn Marino 	ret_error0(TGETENT_ERR,
64800d8f3c4SJohn Marino 		   "Invalid parameter, internal error.\n");
64900d8f3c4SJohn Marino     } else
65000d8f3c4SJohn Marino 	termp = *tp;
65100d8f3c4SJohn Marino #else
65200d8f3c4SJohn Marino     termp = cur_term;
65300d8f3c4SJohn Marino     T((T_CALLED("setupterm(%s,%d,%p)"), _nc_visbuf(tname), Filedes, (void *) errret));
65400d8f3c4SJohn Marino #endif
655fdd4e1e0SJan Lentfer 
656fdd4e1e0SJan Lentfer     if (tname == 0) {
657fdd4e1e0SJan Lentfer 	tname = getenv("TERM");
658fdd4e1e0SJan Lentfer 	if (tname == 0 || *tname == '\0') {
6593468e90cSJohn Marino #ifdef USE_TERM_DRIVER
6603468e90cSJohn Marino 	    tname = "unknown";
6613468e90cSJohn Marino #else
6621d102085SJan Lentfer 	    ret_error0(TGETENT_ERR, "TERM environment variable not set.\n");
6633468e90cSJohn Marino #endif
664fdd4e1e0SJan Lentfer 	}
665fdd4e1e0SJan Lentfer     }
666*32bb5217SDaniel Fojt     myname = strdup(tname);
6671d102085SJan Lentfer 
668*32bb5217SDaniel Fojt     if (strlen(myname) > MAX_NAME_SIZE) {
6691d102085SJan Lentfer 	ret_error(TGETENT_ERR,
6701d102085SJan Lentfer 		  "TERM environment must be <= %d characters.\n",
671*32bb5217SDaniel Fojt 		  MAX_NAME_SIZE,
672*32bb5217SDaniel Fojt 		  free(myname));
673fdd4e1e0SJan Lentfer     }
674fdd4e1e0SJan Lentfer 
675*32bb5217SDaniel Fojt     T(("your terminal name is %s", myname));
676fdd4e1e0SJan Lentfer 
677fdd4e1e0SJan Lentfer     /*
678fdd4e1e0SJan Lentfer      * Allow output redirection.  This is what SVr3 does.  If stdout is
679fdd4e1e0SJan Lentfer      * directed to a file, screen updates go to standard error.
680fdd4e1e0SJan Lentfer      */
6813468e90cSJohn Marino     if (Filedes == STDOUT_FILENO && !NC_ISATTY(Filedes))
682fdd4e1e0SJan Lentfer 	Filedes = STDERR_FILENO;
683fdd4e1e0SJan Lentfer 
684fdd4e1e0SJan Lentfer     /*
685fdd4e1e0SJan Lentfer      * Check if we have already initialized to use this terminal.  If so, we
686fdd4e1e0SJan Lentfer      * do not need to re-read the terminfo entry, or obtain TTY settings.
687fdd4e1e0SJan Lentfer      *
688fdd4e1e0SJan Lentfer      * This is an improvement on SVr4 curses.  If an application mixes curses
689fdd4e1e0SJan Lentfer      * and termcap calls, it may call both initscr and tgetent.  This is not
690fdd4e1e0SJan Lentfer      * really a good thing to do, but can happen if someone tries using ncurses
691fdd4e1e0SJan Lentfer      * with the readline library.  The problem we are fixing is that when
692fdd4e1e0SJan Lentfer      * tgetent calls setupterm, the resulting Ottyb struct in cur_term is
693fdd4e1e0SJan Lentfer      * zeroed.  A subsequent call to endwin uses the zeroed terminal settings
694fdd4e1e0SJan Lentfer      * rather than the ones saved in initscr.  So we check if cur_term appears
695fdd4e1e0SJan Lentfer      * to contain terminal settings for the same output file as our current
696fdd4e1e0SJan Lentfer      * call - and copy those terminal settings.  (SVr4 curses does not do this,
697fdd4e1e0SJan Lentfer      * however applications that are working around the problem will still work
698fdd4e1e0SJan Lentfer      * properly with this feature).
699fdd4e1e0SJan Lentfer      */
7001d102085SJan Lentfer     if (reuse
70100d8f3c4SJohn Marino 	&& (termp != 0)
7021d102085SJan Lentfer 	&& termp->Filedes == Filedes
7031d102085SJan Lentfer 	&& termp->_termname != 0
704*32bb5217SDaniel Fojt 	&& !strcmp(termp->_termname, myname)
705*32bb5217SDaniel Fojt 	&& _nc_name_match(TerminalType(termp).term_names, myname, "|")) {
706fdd4e1e0SJan Lentfer 	T(("reusing existing terminal information and mode-settings"));
70700d8f3c4SJohn Marino 	code = OK;
7083468e90cSJohn Marino #ifdef USE_TERM_DRIVER
7093468e90cSJohn Marino 	TCB = (TERMINAL_CONTROL_BLOCK *) termp;
7103468e90cSJohn Marino #endif
711fdd4e1e0SJan Lentfer     } else {
71200d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
7133468e90cSJohn Marino 	TERMINAL_CONTROL_BLOCK *my_tcb;
714*32bb5217SDaniel Fojt 	termp = 0;
715*32bb5217SDaniel Fojt 	if ((my_tcb = typeCalloc(TERMINAL_CONTROL_BLOCK, 1)) != 0)
7163468e90cSJohn Marino 	    termp = &(my_tcb->term);
71700d8f3c4SJohn Marino #else
718*32bb5217SDaniel Fojt 	int status;
719*32bb5217SDaniel Fojt 
7201d102085SJan Lentfer 	termp = typeCalloc(TERMINAL, 1);
72100d8f3c4SJohn Marino #endif
7221d102085SJan Lentfer 	if (termp == 0) {
723*32bb5217SDaniel Fojt 	    ret_error1(TGETENT_ERR,
724*32bb5217SDaniel Fojt 		       "Not enough memory to create terminal structure.\n",
725*32bb5217SDaniel Fojt 		       myname, free(myname));
726fdd4e1e0SJan Lentfer 	}
727*32bb5217SDaniel Fojt #if HAVE_SYSCONF
728*32bb5217SDaniel Fojt 	{
729*32bb5217SDaniel Fojt 	    long limit;
730*32bb5217SDaniel Fojt #ifdef LINE_MAX
731*32bb5217SDaniel Fojt 	    limit = LINE_MAX;
732*32bb5217SDaniel Fojt #else
733*32bb5217SDaniel Fojt 	    limit = _nc_globals.getstr_limit;
734*32bb5217SDaniel Fojt #endif
735*32bb5217SDaniel Fojt #ifdef _SC_LINE_MAX
736*32bb5217SDaniel Fojt 	    if (limit < sysconf(_SC_LINE_MAX))
737*32bb5217SDaniel Fojt 		limit = sysconf(_SC_LINE_MAX);
738*32bb5217SDaniel Fojt #endif
739*32bb5217SDaniel Fojt 	    if (_nc_globals.getstr_limit < (int) limit)
740*32bb5217SDaniel Fojt 		_nc_globals.getstr_limit = (int) limit;
741*32bb5217SDaniel Fojt 	}
742*32bb5217SDaniel Fojt #endif /* HAVE_SYSCONF */
743*32bb5217SDaniel Fojt 	T(("using %d for getstr limit", _nc_globals.getstr_limit));
744*32bb5217SDaniel Fojt 
74500d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
74600d8f3c4SJohn Marino 	INIT_TERM_DRIVER();
74700d8f3c4SJohn Marino 	TCB = (TERMINAL_CONTROL_BLOCK *) termp;
748*32bb5217SDaniel Fojt 	code = _nc_globals.term_driver(TCB, myname, errret);
74900d8f3c4SJohn Marino 	if (code == OK) {
75000d8f3c4SJohn Marino 	    termp->Filedes = (short) Filedes;
751*32bb5217SDaniel Fojt 	    termp->_termname = strdup(myname);
75200d8f3c4SJohn Marino 	} else {
753*32bb5217SDaniel Fojt 	    ret_error1(errret ? *errret : TGETENT_ERR,
754*32bb5217SDaniel Fojt 		       "Could not find any driver to handle terminal.\n",
755*32bb5217SDaniel Fojt 		       myname, free(myname));
75600d8f3c4SJohn Marino 	}
75700d8f3c4SJohn Marino #else
7583468e90cSJohn Marino #if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP
759*32bb5217SDaniel Fojt 	status = _nc_setup_tinfo(myname, &TerminalType(termp));
760*32bb5217SDaniel Fojt 	T(("_nc_setup_tinfo returns %d", status));
761fdd4e1e0SJan Lentfer #else
762*32bb5217SDaniel Fojt 	T(("no database available"));
7631d102085SJan Lentfer 	status = TGETENT_NO;
764fdd4e1e0SJan Lentfer #endif
765fdd4e1e0SJan Lentfer 
766fdd4e1e0SJan Lentfer 	/* try fallback list if entry on disk */
7671d102085SJan Lentfer 	if (status != TGETENT_YES) {
768*32bb5217SDaniel Fojt 	    const TERMTYPE2 *fallback = _nc_fallback2(myname);
769fdd4e1e0SJan Lentfer 
770fdd4e1e0SJan Lentfer 	    if (fallback) {
771*32bb5217SDaniel Fojt 		T(("found fallback entry"));
772*32bb5217SDaniel Fojt 		_nc_copy_termtype2(&(TerminalType(termp)), fallback);
7731d102085SJan Lentfer 		status = TGETENT_YES;
774fdd4e1e0SJan Lentfer 	    }
775fdd4e1e0SJan Lentfer 	}
776fdd4e1e0SJan Lentfer 
7771d102085SJan Lentfer 	if (status != TGETENT_YES) {
7781d102085SJan Lentfer 	    del_curterm(termp);
7791d102085SJan Lentfer 	    if (status == TGETENT_ERR) {
780*32bb5217SDaniel Fojt 		free(myname);
7811d102085SJan Lentfer 		ret_error0(status, "terminals database is inaccessible\n");
7821d102085SJan Lentfer 	    } else if (status == TGETENT_NO) {
783*32bb5217SDaniel Fojt 		ret_error1(status, "unknown terminal type.\n",
784*32bb5217SDaniel Fojt 			   myname, free(myname));
785*32bb5217SDaniel Fojt 	    } else {
786*32bb5217SDaniel Fojt 		ret_error0(status, "unexpected return-code\n");
787fdd4e1e0SJan Lentfer 	    }
788fdd4e1e0SJan Lentfer 	}
789*32bb5217SDaniel Fojt #if NCURSES_EXT_NUMBERS
790*32bb5217SDaniel Fojt 	_nc_export_termtype2(&termp->type, &TerminalType(termp));
791*32bb5217SDaniel Fojt #endif
7921d102085SJan Lentfer #if !USE_REENTRANT
793*32bb5217SDaniel Fojt 	save_ttytype(termp);
7941d102085SJan Lentfer #endif
795fdd4e1e0SJan Lentfer 
79600d8f3c4SJohn Marino 	termp->Filedes = (short) Filedes;
797*32bb5217SDaniel Fojt 	termp->_termname = strdup(myname);
7981d102085SJan Lentfer 
7991d102085SJan Lentfer 	set_curterm(termp);
800fdd4e1e0SJan Lentfer 
80100d8f3c4SJohn Marino 	if (command_character)
8023468e90cSJohn Marino 	    _nc_tinfo_cmdch(termp, UChar(*command_character));
803fdd4e1e0SJan Lentfer 
804fdd4e1e0SJan Lentfer 	/*
805fdd4e1e0SJan Lentfer 	 * If an application calls setupterm() rather than initscr() or
806fdd4e1e0SJan Lentfer 	 * newterm(), we will not have the def_prog_mode() call in
807fdd4e1e0SJan Lentfer 	 * _nc_setupscreen().  Do it now anyway, so we can initialize the
808*32bb5217SDaniel Fojt 	 * baudrate.  Also get the shell-mode so that erasechar() works.
809fdd4e1e0SJan Lentfer 	 */
8103468e90cSJohn Marino 	if (NC_ISATTY(Filedes)) {
811*32bb5217SDaniel Fojt 	    NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG);
812*32bb5217SDaniel Fojt 	    NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG);
813fdd4e1e0SJan Lentfer 	    baudrate();
814fdd4e1e0SJan Lentfer 	}
81500d8f3c4SJohn Marino 	code = OK;
81600d8f3c4SJohn Marino #endif
817fdd4e1e0SJan Lentfer     }
818fdd4e1e0SJan Lentfer 
81900d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
82000d8f3c4SJohn Marino     *tp = termp;
82100d8f3c4SJohn Marino     NCURSES_SP_NAME(set_curterm) (sp, termp);
8223468e90cSJohn Marino     TCB->drv->td_init(TCB);
82300d8f3c4SJohn Marino #else
82400d8f3c4SJohn Marino     sp = SP;
82500d8f3c4SJohn Marino #endif
82600d8f3c4SJohn Marino 
827fdd4e1e0SJan Lentfer     /*
828fdd4e1e0SJan Lentfer      * We should always check the screensize, just in case.
829fdd4e1e0SJan Lentfer      */
83000d8f3c4SJohn Marino     TINFO_GET_SIZE(sp, termp, ptrLines(sp), ptrCols(sp));
831fdd4e1e0SJan Lentfer 
832fdd4e1e0SJan Lentfer     if (errret)
8331d102085SJan Lentfer 	*errret = TGETENT_YES;
834fdd4e1e0SJan Lentfer 
83500d8f3c4SJohn Marino #ifndef USE_TERM_DRIVER
836fdd4e1e0SJan Lentfer     if (generic_type) {
8373468e90cSJohn Marino 	/*
8383468e90cSJohn Marino 	 * BSD 4.3's termcap contains mis-typed "gn" for wy99.  Do a sanity
8393468e90cSJohn Marino 	 * check before giving up.
8403468e90cSJohn Marino 	 */
8413468e90cSJohn Marino 	if ((VALID_STRING(cursor_address)
8423468e90cSJohn Marino 	     || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home)))
8433468e90cSJohn Marino 	    && VALID_STRING(clear_screen)) {
844*32bb5217SDaniel Fojt 	    ret_error1(TGETENT_YES, "terminal is not really generic.\n",
845*32bb5217SDaniel Fojt 		       myname, free(myname));
8463468e90cSJohn Marino 	} else {
8473468e90cSJohn Marino 	    del_curterm(termp);
848*32bb5217SDaniel Fojt 	    ret_error1(TGETENT_NO, "I need something more specific.\n",
849*32bb5217SDaniel Fojt 		       myname, free(myname));
850fdd4e1e0SJan Lentfer 	}
8513468e90cSJohn Marino     } else if (hard_copy) {
852*32bb5217SDaniel Fojt 	ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n",
853*32bb5217SDaniel Fojt 		   myname, free(myname));
854fdd4e1e0SJan Lentfer     }
85500d8f3c4SJohn Marino #endif
856*32bb5217SDaniel Fojt     free(myname);
85700d8f3c4SJohn Marino     returnCode(code);
858fdd4e1e0SJan Lentfer }
8591d102085SJan Lentfer 
860*32bb5217SDaniel Fojt #ifdef USE_PTHREADS
861*32bb5217SDaniel Fojt /*
862*32bb5217SDaniel Fojt  * Returns a non-null pointer unless a new screen should be allocated because
863*32bb5217SDaniel Fojt  * no match was found in the pre-screen cache.
864*32bb5217SDaniel Fojt  */
865*32bb5217SDaniel Fojt NCURSES_EXPORT(SCREEN *)
_nc_find_prescr(void)866*32bb5217SDaniel Fojt _nc_find_prescr(void)
867*32bb5217SDaniel Fojt {
868*32bb5217SDaniel Fojt     SCREEN *result = 0;
869*32bb5217SDaniel Fojt     PRESCREEN_LIST *p;
870*32bb5217SDaniel Fojt     pthread_t id = GetThreadID();
871*32bb5217SDaniel Fojt     for (p = _nc_prescreen.allocated; p != 0; p = p->next) {
872*32bb5217SDaniel Fojt 	if (p->id == id) {
873*32bb5217SDaniel Fojt 	    result = p->sp;
874*32bb5217SDaniel Fojt 	    break;
875*32bb5217SDaniel Fojt 	}
876*32bb5217SDaniel Fojt     }
877*32bb5217SDaniel Fojt     return result;
878*32bb5217SDaniel Fojt }
879*32bb5217SDaniel Fojt 
880*32bb5217SDaniel Fojt /*
881*32bb5217SDaniel Fojt  * Tells ncurses to forget that this thread was associated with the pre-screen
882*32bb5217SDaniel Fojt  * cache.  It does not modify the pre-screen cache itself, since that is used
883*32bb5217SDaniel Fojt  * for creating new screens.
884*32bb5217SDaniel Fojt  */
885*32bb5217SDaniel Fojt NCURSES_EXPORT(void)
_nc_forget_prescr(void)886*32bb5217SDaniel Fojt _nc_forget_prescr(void)
887*32bb5217SDaniel Fojt {
888*32bb5217SDaniel Fojt     PRESCREEN_LIST *p, *q;
889*32bb5217SDaniel Fojt     pthread_t id = GetThreadID();
890*32bb5217SDaniel Fojt     for (p = _nc_prescreen.allocated, q = 0; p != 0; q = p, p = p->next) {
891*32bb5217SDaniel Fojt 	if (p->id == id) {
892*32bb5217SDaniel Fojt 	    if (q) {
893*32bb5217SDaniel Fojt 		q->next = p->next;
894*32bb5217SDaniel Fojt 	    } else {
895*32bb5217SDaniel Fojt 		_nc_prescreen.allocated = p->next;
896*32bb5217SDaniel Fojt 	    }
897*32bb5217SDaniel Fojt 	    free(p);
898*32bb5217SDaniel Fojt 	    break;
899*32bb5217SDaniel Fojt 	}
900*32bb5217SDaniel Fojt     }
901*32bb5217SDaniel Fojt }
902*32bb5217SDaniel Fojt #endif /* USE_PTHREADS */
903*32bb5217SDaniel Fojt 
90400d8f3c4SJohn Marino #if NCURSES_SP_FUNCS
90500d8f3c4SJohn Marino /*
90600d8f3c4SJohn Marino  * In case of handling multiple screens, we need to have a screen before
907*32bb5217SDaniel Fojt  * initialization in _nc_setupscreen takes place.  This is to extend the
908*32bb5217SDaniel Fojt  * substitute for some of the stuff in _nc_prescreen, especially for slk and
909*32bb5217SDaniel Fojt  * ripoff handling which should be done per screen.
91000d8f3c4SJohn Marino  */
91100d8f3c4SJohn Marino NCURSES_EXPORT(SCREEN *)
new_prescr(void)91200d8f3c4SJohn Marino new_prescr(void)
91300d8f3c4SJohn Marino {
9143468e90cSJohn Marino     SCREEN *sp;
91500d8f3c4SJohn Marino 
91600d8f3c4SJohn Marino     START_TRACE();
91700d8f3c4SJohn Marino     T((T_CALLED("new_prescr()")));
91800d8f3c4SJohn Marino 
919*32bb5217SDaniel Fojt     _nc_lock_global(screen);
920*32bb5217SDaniel Fojt     if ((sp = _nc_find_prescr()) == 0) {
92100d8f3c4SJohn Marino 	sp = _nc_alloc_screen_sp();
922*32bb5217SDaniel Fojt 	T(("_nc_alloc_screen_sp %p", (void *) sp));
92300d8f3c4SJohn Marino 	if (sp != 0) {
924*32bb5217SDaniel Fojt #ifdef USE_PTHREADS
925*32bb5217SDaniel Fojt 	    PRESCREEN_LIST *p = typeCalloc(PRESCREEN_LIST, 1);
926*32bb5217SDaniel Fojt 	    if (p != 0) {
927*32bb5217SDaniel Fojt 		p->id = GetThreadID();
928*32bb5217SDaniel Fojt 		p->sp = sp;
929*32bb5217SDaniel Fojt 		p->next = _nc_prescreen.allocated;
930*32bb5217SDaniel Fojt 		_nc_prescreen.allocated = p;
931*32bb5217SDaniel Fojt 	    }
932*32bb5217SDaniel Fojt #else
933*32bb5217SDaniel Fojt 	    _nc_prescreen.allocated = sp;
934*32bb5217SDaniel Fojt #endif
93500d8f3c4SJohn Marino 	    sp->rsp = sp->rippedoff;
93600d8f3c4SJohn Marino 	    sp->_filtered = _nc_prescreen.filter_mode;
93700d8f3c4SJohn Marino 	    sp->_use_env = _nc_prescreen.use_env;
93800d8f3c4SJohn Marino #if NCURSES_NO_PADDING
93900d8f3c4SJohn Marino 	    sp->_no_padding = _nc_prescreen._no_padding;
94000d8f3c4SJohn Marino #endif
94100d8f3c4SJohn Marino 	    sp->slk_format = 0;
94200d8f3c4SJohn Marino 	    sp->_slk = 0;
94300d8f3c4SJohn Marino 	    sp->_prescreen = TRUE;
94400d8f3c4SJohn Marino 	    SP_PRE_INIT(sp);
94500d8f3c4SJohn Marino #if USE_REENTRANT
94600d8f3c4SJohn Marino 	    sp->_TABSIZE = _nc_prescreen._TABSIZE;
94700d8f3c4SJohn Marino 	    sp->_ESCDELAY = _nc_prescreen._ESCDELAY;
94800d8f3c4SJohn Marino #endif
94900d8f3c4SJohn Marino 	}
950*32bb5217SDaniel Fojt     } else {
951*32bb5217SDaniel Fojt 	T(("_nc_alloc_screen_sp %p (reuse)", (void *) sp));
952*32bb5217SDaniel Fojt     }
953*32bb5217SDaniel Fojt     _nc_unlock_global(screen);
95400d8f3c4SJohn Marino     returnSP(sp);
95500d8f3c4SJohn Marino }
95600d8f3c4SJohn Marino #endif
95700d8f3c4SJohn Marino 
95800d8f3c4SJohn Marino #ifdef USE_TERM_DRIVER
95900d8f3c4SJohn Marino /*
96000d8f3c4SJohn Marino  * This entrypoint is called from tgetent() to allow a special case of reusing
96100d8f3c4SJohn Marino  * the same TERMINAL data (see comment).
96200d8f3c4SJohn Marino  */
96300d8f3c4SJohn Marino NCURSES_EXPORT(int)
_nc_setupterm(const char * tname,int Filedes,int * errret,int reuse)964*32bb5217SDaniel Fojt _nc_setupterm(const char *tname,
96500d8f3c4SJohn Marino 	      int Filedes,
96600d8f3c4SJohn Marino 	      int *errret,
9673468e90cSJohn Marino 	      int reuse)
96800d8f3c4SJohn Marino {
969*32bb5217SDaniel Fojt     int rc = ERR;
9703468e90cSJohn Marino     TERMINAL *termp = 0;
971*32bb5217SDaniel Fojt 
972*32bb5217SDaniel Fojt     _nc_lock_global(prescreen);
973*32bb5217SDaniel Fojt     START_TRACE();
974*32bb5217SDaniel Fojt     if (TINFO_SETUP_TERM(&termp, tname, Filedes, errret, reuse) == OK) {
975*32bb5217SDaniel Fojt 	_nc_forget_prescr();
976*32bb5217SDaniel Fojt 	if (NCURSES_SP_NAME(set_curterm) (CURRENT_SCREEN_PRE, termp) != 0) {
977*32bb5217SDaniel Fojt 	    rc = OK;
978*32bb5217SDaniel Fojt 	}
979*32bb5217SDaniel Fojt     }
980*32bb5217SDaniel Fojt     _nc_unlock_global(prescreen);
981*32bb5217SDaniel Fojt     return rc;
98200d8f3c4SJohn Marino }
98300d8f3c4SJohn Marino #endif
98400d8f3c4SJohn Marino 
9851d102085SJan Lentfer /*
9861d102085SJan Lentfer  *	setupterm(termname, Filedes, errret)
9871d102085SJan Lentfer  *
9881d102085SJan Lentfer  *	Find and read the appropriate object file for the terminal
9891d102085SJan Lentfer  *	Make cur_term point to the structure.
9901d102085SJan Lentfer  */
9911d102085SJan Lentfer NCURSES_EXPORT(int)
setupterm(const char * tname,int Filedes,int * errret)992*32bb5217SDaniel Fojt setupterm(const char *tname, int Filedes, int *errret)
9931d102085SJan Lentfer {
9943468e90cSJohn Marino     START_TRACE();
9951d102085SJan Lentfer     return _nc_setupterm(tname, Filedes, errret, FALSE);
9961d102085SJan Lentfer }
997