150276Speter/****************************************************************************
2262685Sdelphij * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
350276Speter *                                                                          *
450276Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
550276Speter * copy of this software and associated documentation files (the            *
650276Speter * "Software"), to deal in the Software without restriction, including      *
750276Speter * without limitation the rights to use, copy, modify, merge, publish,      *
850276Speter * distribute, distribute with modifications, sublicense, and/or sell       *
950276Speter * copies of the Software, and to permit persons to whom the Software is    *
1050276Speter * furnished to do so, subject to the following conditions:                 *
1150276Speter *                                                                          *
1250276Speter * The above copyright notice and this permission notice shall be included  *
1350276Speter * in all copies or substantial portions of the Software.                   *
1450276Speter *                                                                          *
1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2250276Speter *                                                                          *
2350276Speter * Except as contained in this notice, the name(s) of the above copyright   *
2450276Speter * holders shall not be used in advertising or otherwise to promote the     *
2550276Speter * sale, use or other dealings in this Software without prior written       *
2650276Speter * authorization.                                                           *
2750276Speter ****************************************************************************/
2850276Speter
2950276Speter/****************************************************************************
3050276Speter *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
3150276Speter *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32166124Srafan *     and: Thomas E. Dickey                        1996-on                 *
33262629Sdelphij *     and: Juergen Pfeifer                         2009                    *
3450276Speter ****************************************************************************/
3550276Speter
3650276Speter/*
3750276Speter**	lib_newterm.c
3850276Speter**
3950276Speter**	The newterm() function.
4050276Speter**
4150276Speter*/
4250276Speter
4350276Speter#include <curses.priv.h>
4450276Speter
45262629Sdelphij#ifndef CUR
46262629Sdelphij#define CUR SP_TERMTYPE
47262629Sdelphij#endif
48262629Sdelphij
4962449Speter#include <tic.h>
5050276Speter
51262685SdelphijMODULE_ID("$Id: lib_newterm.c,v 1.90 2013/09/28 21:02:56 tom Exp $")
5250276Speter
53262629Sdelphij#ifdef USE_TERM_DRIVER
54262629Sdelphij#define NumLabels      InfoOf(SP_PARM).numlabels
55262629Sdelphij#else
56262629Sdelphij#define NumLabels      num_labels
57262629Sdelphij#endif
58262629Sdelphij
5962449Speter#ifndef ONLCR			/* Allows compilation under the QNX 4.2 OS */
6050276Speter#define ONLCR 0
6150276Speter#endif
6250276Speter
6350276Speter/*
6450276Speter * SVr4/XSI Curses specify that hardware echo is turned off in initscr, and not
6550276Speter * restored during the curses session.  The library simulates echo in software.
6650276Speter * (The behavior is unspecified if the application enables hardware echo).
6750276Speter *
6850276Speter * The newterm function also initializes terminal settings, and since initscr
6950276Speter * is supposed to behave as if it calls newterm, we do it here.
7050276Speter */
71166124Srafanstatic NCURSES_INLINE int
72262629Sdelphij_nc_initscr(NCURSES_SP_DCL0)
7350276Speter{
74166124Srafan    int result = ERR;
75262629Sdelphij    TERMINAL *term = TerminalOf(SP_PARM);
76166124Srafan
7762449Speter    /* for extended XPG4 conformance requires cbreak() at this point */
7862449Speter    /* (SVr4 curses does this anyway) */
79262629Sdelphij    if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) {
80166124Srafan	TTY buf;
8150276Speter
82262629Sdelphij	buf = term->Nttyb;
8350276Speter#ifdef TERMIOS
84262629Sdelphij	buf.c_lflag &= (unsigned) ~(ECHO | ECHONL);
85262629Sdelphij	buf.c_iflag &= (unsigned) ~(ICRNL | INLCR | IGNCR);
86262629Sdelphij	buf.c_oflag &= (unsigned) ~(ONLCR);
87166124Srafan#elif HAVE_SGTTY_H
88166124Srafan	buf.sg_flags &= ~(ECHO | CRMOD);
8950276Speter#else
90166124Srafan	memset(&buf, 0, sizeof(buf));
9150276Speter#endif
92262629Sdelphij	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
93262629Sdelphij	if (result == OK)
94262629Sdelphij	    term->Nttyb = buf;
95166124Srafan    }
96166124Srafan    return result;
9750276Speter}
9850276Speter
9950276Speter/*
10050276Speter * filter() has to be called before either initscr() or newterm(), so there is
10150276Speter * apparently no way to make this flag apply to some terminals and not others,
10250276Speter * aside from possibly delaying a filter() call until some terminals have been
10350276Speter * initialized.
10450276Speter */
10576726SpeterNCURSES_EXPORT(void)
106262629SdelphijNCURSES_SP_NAME(filter) (NCURSES_SP_DCL0)
107262629Sdelphij{
108262629Sdelphij    START_TRACE();
109262629Sdelphij    T((T_CALLED("filter(%p)"), (void *) SP_PARM));
110262629Sdelphij#if NCURSES_SP_FUNCS
111262629Sdelphij    if (IsPreScreen(SP_PARM)) {
112262629Sdelphij	SP_PARM->_filtered = TRUE;
113262629Sdelphij    }
114262629Sdelphij#else
115262629Sdelphij    _nc_prescreen.filter_mode = TRUE;
116262629Sdelphij#endif
117262629Sdelphij    returnVoid;
118262629Sdelphij}
119262629Sdelphij
120262629Sdelphij#if NCURSES_SP_FUNCS
121262629SdelphijNCURSES_EXPORT(void)
12262449Speterfilter(void)
12350276Speter{
124166124Srafan    START_TRACE();
125262629Sdelphij    T((T_CALLED("filter()")));
126174993Srafan    _nc_prescreen.filter_mode = TRUE;
12797049Speter    returnVoid;
12850276Speter}
129262629Sdelphij#endif
13050276Speter
131166124Srafan#if NCURSES_EXT_FUNCS
132166124Srafan/*
133166124Srafan * An extension, allowing the application to open a new screen without
134166124Srafan * requiring it to also be filtered.
135166124Srafan */
136166124SrafanNCURSES_EXPORT(void)
137262629SdelphijNCURSES_SP_NAME(nofilter) (NCURSES_SP_DCL0)
138262629Sdelphij{
139262629Sdelphij    START_TRACE();
140262629Sdelphij    T((T_CALLED("nofilter(%p)"), (void *) SP_PARM));
141262629Sdelphij#if NCURSES_SP_FUNCS
142262629Sdelphij    if (IsPreScreen(SP_PARM)) {
143262629Sdelphij	SP_PARM->_filtered = FALSE;
144262629Sdelphij    }
145262629Sdelphij#else
146262629Sdelphij    _nc_prescreen.filter_mode = FALSE;
147262629Sdelphij#endif
148262629Sdelphij    returnVoid;
149262629Sdelphij}
150262629Sdelphij
151262629Sdelphij#if NCURSES_SP_FUNCS
152262629SdelphijNCURSES_EXPORT(void)
153166124Srafannofilter(void)
154166124Srafan{
155166124Srafan    START_TRACE();
156262629Sdelphij    T((T_CALLED("nofilter()")));
157174993Srafan    _nc_prescreen.filter_mode = FALSE;
158166124Srafan    returnVoid;
159166124Srafan}
160166124Srafan#endif
161262629Sdelphij#endif /* NCURSES_EXT_FUNCS */
162166124Srafan
16376726SpeterNCURSES_EXPORT(SCREEN *)
164262629SdelphijNCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx
165262629Sdelphij			  NCURSES_CONST char *name,
166262629Sdelphij			  FILE *ofp,
167262629Sdelphij			  FILE *ifp)
16850276Speter{
169166124Srafan    int value;
17062449Speter    int errret;
171262629Sdelphij    SCREEN *result = 0;
17262449Speter    SCREEN *current;
173184989Srafan    TERMINAL *its_term;
174262629Sdelphij    FILE *_ofp = ofp ? ofp : stdout;
175262629Sdelphij    FILE *_ifp = ifp ? ifp : stdin;
176262629Sdelphij    int cols;
177262629Sdelphij    int slk_format;
178262629Sdelphij    int filter_mode;
179262629Sdelphij    TERMINAL *new_term = 0;
18050276Speter
181166124Srafan    START_TRACE();
182262629Sdelphij    T((T_CALLED("newterm(%p, \"%s\", %p,%p)"),
183262629Sdelphij       (void *) SP_PARM,
184262685Sdelphij       (name ? name : ""),
185262629Sdelphij       (void *) ofp,
186262629Sdelphij       (void *) ifp));
18750276Speter
188262629Sdelphij#if NCURSES_SP_FUNCS
189262629Sdelphij    assert(SP_PARM != 0);
190262629Sdelphij    if (SP_PARM == 0)
191262629Sdelphij	returnSP(SP_PARM);
192262629Sdelphij#endif
193262629Sdelphij
194184989Srafan    _nc_init_pthreads();
195184989Srafan    _nc_lock_global(curses);
196184989Srafan
197262629Sdelphij    current = CURRENT_SCREEN;
198262629Sdelphij    its_term = (current ? current->_term : 0);
199184989Srafan
200262629Sdelphij    INIT_TERM_DRIVER();
201166124Srafan    /* this loads the capability entry, then sets LINES and COLS */
202262629Sdelphij    if (
203262629Sdelphij#if NCURSES_SP_FUNCS
204262629Sdelphij	   SP_PARM->_prescreen &&
205262629Sdelphij#endif
206262629Sdelphij	   TINFO_SETUP_TERM(&new_term, name,
207262629Sdelphij			    fileno(_ofp), &errret, FALSE) != ERR) {
208178866Srafan
209262629Sdelphij	_nc_set_screen(0);
210262629Sdelphij#ifdef USE_TERM_DRIVER
211262629Sdelphij	assert(new_term != 0);
212262629Sdelphij#endif
213262629Sdelphij
214262629Sdelphij#if NCURSES_SP_FUNCS
215262629Sdelphij	slk_format = SP_PARM->slk_format;
216262629Sdelphij	filter_mode = SP_PARM->_filtered;
217262629Sdelphij#else
218262629Sdelphij	slk_format = _nc_globals.slk_format;
219262629Sdelphij	filter_mode = _nc_prescreen.filter_mode;
220262629Sdelphij#endif
221262629Sdelphij
222166124Srafan	/*
223166124Srafan	 * This actually allocates the screen structure, and saves the original
224166124Srafan	 * terminal settings.
225166124Srafan	 */
226262629Sdelphij	if (NCURSES_SP_NAME(_nc_setupscreen) (
227262629Sdelphij#if NCURSES_SP_FUNCS
228262629Sdelphij						 &SP_PARM,
229262629Sdelphij#endif
230262629Sdelphij						 *(ptrLines(SP_PARM)),
231262629Sdelphij						 *(ptrCols(SP_PARM)),
232262629Sdelphij						 _ofp,
233262629Sdelphij						 filter_mode,
234262629Sdelphij						 slk_format) == ERR) {
235166124Srafan	    _nc_set_screen(current);
236166124Srafan	    result = 0;
237166124Srafan	} else {
238262629Sdelphij#ifdef USE_TERM_DRIVER
239262629Sdelphij	    TERMINAL_CONTROL_BLOCK *TCB;
240262629Sdelphij#elif !NCURSES_SP_FUNCS
241262629Sdelphij	    _nc_set_screen(CURRENT_SCREEN);
242262629Sdelphij#endif
243262629Sdelphij	    assert(SP_PARM != 0);
244262629Sdelphij	    cols = *(ptrCols(SP_PARM));
245262629Sdelphij#ifdef USE_TERM_DRIVER
246262629Sdelphij	    _nc_set_screen(SP_PARM);
247262629Sdelphij	    TCB = (TERMINAL_CONTROL_BLOCK *) new_term;
248262629Sdelphij	    TCB->csp = SP_PARM;
249262629Sdelphij#endif
250184989Srafan	    /*
251184989Srafan	     * In setupterm() we did a set_curterm(), but it was before we set
252262629Sdelphij	     * CURRENT_SCREEN.  So the "current" screen's terminal pointer was
253262629Sdelphij	     * overwritten with a different terminal.  Later, in
254262629Sdelphij	     * _nc_setupscreen(), we set CURRENT_SCREEN and the terminal
255262629Sdelphij	     * pointer in the new screen.
256184989Srafan	     *
257184989Srafan	     * Restore the terminal-pointer for the pre-existing screen, if
258184989Srafan	     * any.
259184989Srafan	     */
260184989Srafan	    if (current)
261184989Srafan		current->_term = its_term;
262184989Srafan
263262629Sdelphij#ifdef USE_TERM_DRIVER
264262629Sdelphij	    SP_PARM->_term = new_term;
265262629Sdelphij#else
266262629Sdelphij	    new_term = SP_PARM->_term;
267262629Sdelphij#endif
268262629Sdelphij
269262629Sdelphij	    /* allow user to set maximum escape delay from the environment */
270262629Sdelphij	    if ((value = _nc_getenv_num("ESCDELAY")) >= 0) {
271262629Sdelphij		NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value);
272262629Sdelphij	    }
273262629Sdelphij
274166124Srafan	    /* if the terminal type has real soft labels, set those up */
275262629Sdelphij	    if (slk_format && NumLabels > 0 && SLK_STDFMT(slk_format))
276262629Sdelphij		_nc_slk_initialize(StdScreen(SP_PARM), cols);
27750276Speter
278262629Sdelphij	    SP_PARM->_ifd = fileno(_ifp);
279262629Sdelphij	    NCURSES_SP_NAME(typeahead) (NCURSES_SP_ARGx fileno(_ifp));
28050276Speter#ifdef TERMIOS
281262629Sdelphij	    SP_PARM->_use_meta = ((new_term->Ottyb.c_cflag & CSIZE) == CS8 &&
282262685Sdelphij				  !(new_term->Ottyb.c_iflag & ISTRIP)) ||
283262685Sdelphij		USE_KLIBC_KBD;
28450276Speter#else
285262629Sdelphij	    SP_PARM->_use_meta = FALSE;
28650276Speter#endif
287262629Sdelphij	    SP_PARM->_endwin = FALSE;
288262629Sdelphij#ifndef USE_TERM_DRIVER
289166124Srafan	    /*
290166124Srafan	     * Check whether we can optimize scrolling under dumb terminals in
291166124Srafan	     * case we do not have any of these capabilities, scrolling
292166124Srafan	     * optimization will be useless.
293166124Srafan	     */
294262629Sdelphij	    SP_PARM->_scrolling = ((scroll_forward && scroll_reverse) ||
295262629Sdelphij				   ((parm_rindex ||
296262629Sdelphij				     parm_insert_line ||
297262629Sdelphij				     insert_line) &&
298262629Sdelphij				    (parm_index ||
299262629Sdelphij				     parm_delete_line ||
300262629Sdelphij				     delete_line)));
301262629Sdelphij#endif
30250276Speter
303262629Sdelphij	    NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG);		/* sets a field in the screen structure */
30450276Speter
305262629Sdelphij	    SP_PARM->_keytry = 0;
30650276Speter
307262629Sdelphij	    /* compute movement costs so we can do better move optimization */
308262629Sdelphij#ifdef USE_TERM_DRIVER
309262629Sdelphij	    TCBOf(SP_PARM)->drv->scinit(SP_PARM);
310262685Sdelphij#else /* ! USE_TERM_DRIVER */
311166124Srafan	    /*
312166124Srafan	     * Check for mismatched graphic-rendition capabilities.  Most SVr4
313166124Srafan	     * terminfo trees contain entries that have rmul or rmso equated to
314166124Srafan	     * sgr0 (Solaris curses copes with those entries).  We do this only
315166124Srafan	     * for curses, since many termcap applications assume that
316166124Srafan	     * smso/rmso and smul/rmul are paired, and will not function
317166124Srafan	     * properly if we remove rmso or rmul.  Curses applications
318166124Srafan	     * shouldn't be looking at this detail.
319166124Srafan	     */
32050276Speter#define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode))
321262629Sdelphij	    SP_PARM->_use_rmso = SGR0_TEST(exit_standout_mode);
322262629Sdelphij	    SP_PARM->_use_rmul = SGR0_TEST(exit_underline_mode);
323262685Sdelphij#if USE_ITALIC
324262685Sdelphij	    SP_PARM->_use_ritm = SGR0_TEST(exit_italics_mode);
325262685Sdelphij#endif
32650276Speter
327166124Srafan	    /* compute movement costs so we can do better move optimization */
328166124Srafan	    _nc_mvcur_init();
32950276Speter
330166124Srafan	    /* initialize terminal to a sane state */
331166124Srafan	    _nc_screen_init();
332262685Sdelphij#endif /* USE_TERM_DRIVER */
33350276Speter
334166124Srafan	    /* Initialize the terminal line settings. */
335262629Sdelphij	    _nc_initscr(NCURSES_SP_ARG);
33650276Speter
337166124Srafan	    _nc_signal_handler(TRUE);
338262629Sdelphij	    result = SP_PARM;
339166124Srafan	}
340166124Srafan    }
341184989Srafan    _nc_unlock_global(curses);
342166124Srafan    returnSP(result);
34350276Speter}
344262629Sdelphij
345262629Sdelphij#if NCURSES_SP_FUNCS
346262629SdelphijNCURSES_EXPORT(SCREEN *)
347262629Sdelphijnewterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp)
348262629Sdelphij{
349262629Sdelphij    return NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp);
350262629Sdelphij}
351262629Sdelphij#endif
352