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_set_term.c
3850276Speter**
3950276Speter**	The routine set_term().
4050276Speter**
4150276Speter*/
4250276Speter
4350276Speter#include <curses.priv.h>
4462449Speter#include <tic.h>
4550276Speter
46262629Sdelphij#ifndef CUR
47262629Sdelphij#define CUR SP_TERMTYPE
48262629Sdelphij#endif
4950276Speter
50262685SdelphijMODULE_ID("$Id: lib_set_term.c,v 1.148 2013/08/31 13:33:06 tom Exp $")
51262629Sdelphij
52262629Sdelphij#ifdef USE_TERM_DRIVER
53262629Sdelphij#define MaxColors      InfoOf(sp).maxcolors
54262629Sdelphij#define NumLabels      InfoOf(sp).numlabels
55262629Sdelphij#else
56262629Sdelphij#define MaxColors      max_colors
57262629Sdelphij#define NumLabels      num_labels
58262629Sdelphij#endif
59262629Sdelphij
6076726SpeterNCURSES_EXPORT(SCREEN *)
61166124Srafanset_term(SCREEN *screenp)
6250276Speter{
6362449Speter    SCREEN *oldSP;
64184989Srafan    SCREEN *newSP;
6550276Speter
66262629Sdelphij    T((T_CALLED("set_term(%p)"), (void *) screenp));
6750276Speter
68184989Srafan    _nc_lock_global(curses);
69174993Srafan
70262629Sdelphij    oldSP = CURRENT_SCREEN;
7162449Speter    _nc_set_screen(screenp);
72262629Sdelphij    newSP = screenp;
7350276Speter
74184989Srafan    if (newSP != 0) {
75262629Sdelphij	TINFO_SET_CURTERM(newSP, newSP->_term);
76174993Srafan#if !USE_REENTRANT
77262629Sdelphij	curscr = CurScreen(newSP);
78262629Sdelphij	newscr = NewScreen(newSP);
79262629Sdelphij	stdscr = StdScreen(newSP);
80184989Srafan	COLORS = newSP->_color_count;
81184989Srafan	COLOR_PAIRS = newSP->_pair_count;
82174993Srafan#endif
83178866Srafan    } else {
84262629Sdelphij	TINFO_SET_CURTERM(oldSP, 0);
85178866Srafan#if !USE_REENTRANT
86178866Srafan	curscr = 0;
87178866Srafan	newscr = 0;
88178866Srafan	stdscr = 0;
89178866Srafan	COLORS = 0;
90178866Srafan	COLOR_PAIRS = 0;
91178866Srafan#endif
92178866Srafan    }
9350276Speter
94184989Srafan    _nc_unlock_global(curses);
95174993Srafan
96262629Sdelphij    T((T_RETURN("%p"), (void *) oldSP));
9762449Speter    return (oldSP);
9850276Speter}
9950276Speter
10062449Speterstatic void
101174993Srafan_nc_free_keytry(TRIES * kt)
10250276Speter{
10362449Speter    if (kt != 0) {
10462449Speter	_nc_free_keytry(kt->child);
10562449Speter	_nc_free_keytry(kt->sibling);
10662449Speter	free(kt);
10762449Speter    }
10850276Speter}
10950276Speter
110178866Srafanstatic bool
111178866Srafandelink_screen(SCREEN *sp)
112178866Srafan{
113178866Srafan    SCREEN *last = 0;
114178866Srafan    SCREEN *temp;
115178866Srafan    bool result = FALSE;
116178866Srafan
117178866Srafan    for (each_screen(temp)) {
118178866Srafan	if (temp == sp) {
119178866Srafan	    if (last)
120262629Sdelphij		last->_next_screen = sp->_next_screen;
121178866Srafan	    else
122178866Srafan		_nc_screen_chain = sp->_next_screen;
123178866Srafan	    result = TRUE;
124178866Srafan	    break;
125178866Srafan	}
126178866Srafan	last = temp;
127178866Srafan    }
128178866Srafan    return result;
129178866Srafan}
130178866Srafan
13150276Speter/*
13250276Speter * Free the storage associated with the given SCREEN sp.
13350276Speter */
13476726SpeterNCURSES_EXPORT(void)
135166124Srafandelscreen(SCREEN *sp)
13650276Speter{
137166124Srafan    int i;
13850276Speter
139262629Sdelphij    T((T_CALLED("delscreen(%p)"), (void *) sp));
14050276Speter
141184989Srafan    _nc_lock_global(curses);
142178866Srafan    if (delink_screen(sp)) {
143262629Sdelphij#ifdef USE_SP_RIPOFF
144262629Sdelphij	ripoff_t *rop;
145262629Sdelphij	if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
146262629Sdelphij	    for (rop = safe_ripoff_stack;
147262629Sdelphij		 rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
148262629Sdelphij		 rop++) {
149262629Sdelphij		if (rop->win) {
150262629Sdelphij		    (void) delwin(rop->win);
151262629Sdelphij		    rop->win = 0;
152262629Sdelphij		}
153262629Sdelphij	    }
154262629Sdelphij	}
155262629Sdelphij#endif
15650276Speter
157262629Sdelphij	(void) _nc_freewin(CurScreen(sp));
158262629Sdelphij	(void) _nc_freewin(NewScreen(sp));
159262629Sdelphij	(void) _nc_freewin(StdScreen(sp));
160166124Srafan
161178866Srafan	if (sp->_slk != 0) {
162178866Srafan	    if (sp->_slk->ent != 0) {
163178866Srafan		for (i = 0; i < sp->_slk->labcnt; ++i) {
164178866Srafan		    FreeIfNeeded(sp->_slk->ent[i].ent_text);
165178866Srafan		    FreeIfNeeded(sp->_slk->ent[i].form_text);
166178866Srafan		}
167178866Srafan		free(sp->_slk->ent);
168166124Srafan	    }
169178866Srafan	    free(sp->_slk);
170178866Srafan	    sp->_slk = 0;
171166124Srafan	}
172166124Srafan
173178866Srafan	_nc_free_keytry(sp->_keytry);
174178866Srafan	sp->_keytry = 0;
175166124Srafan
176178866Srafan	_nc_free_keytry(sp->_key_ok);
177178866Srafan	sp->_key_ok = 0;
17850276Speter
179178866Srafan	FreeIfNeeded(sp->_current_attr);
180166124Srafan
181178866Srafan	FreeIfNeeded(sp->_color_table);
182178866Srafan	FreeIfNeeded(sp->_color_pairs);
18350276Speter
184178866Srafan	FreeIfNeeded(sp->oldhash);
185178866Srafan	FreeIfNeeded(sp->newhash);
186178866Srafan	FreeIfNeeded(sp->hashtab);
18750276Speter
188178866Srafan	FreeIfNeeded(sp->_acs_map);
189178866Srafan	FreeIfNeeded(sp->_screen_acs_map);
190166124Srafan
191262685Sdelphij	NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
192262629Sdelphij	NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term);
193178866Srafan	free(sp);
19462449Speter
195178866Srafan	/*
196178866Srafan	 * If this was the current screen, reset everything that the
197178866Srafan	 * application might try to use (except cur_term, which may have
198178866Srafan	 * multiple references in different screens).
199178866Srafan	 */
200262629Sdelphij	if (sp == CURRENT_SCREEN) {
201174993Srafan#if !USE_REENTRANT
202178866Srafan	    curscr = 0;
203178866Srafan	    newscr = 0;
204178866Srafan	    stdscr = 0;
205178866Srafan	    COLORS = 0;
206178866Srafan	    COLOR_PAIRS = 0;
207174993Srafan#endif
208178866Srafan	    _nc_set_screen(0);
209178866Srafan	}
21062449Speter    }
211184989Srafan    _nc_unlock_global(curses);
212174993Srafan
21362449Speter    returnVoid;
21450276Speter}
21550276Speter
21662449Speterstatic bool
217166124Srafanno_mouse_event(SCREEN *sp GCC_UNUSED)
21862449Speter{
21962449Speter    return FALSE;
22062449Speter}
22150276Speter
22262449Speterstatic bool
223166124Srafanno_mouse_inline(SCREEN *sp GCC_UNUSED)
22462449Speter{
22562449Speter    return FALSE;
22662449Speter}
22762449Speter
22862449Speterstatic bool
229184989Srafanno_mouse_parse(SCREEN *sp GCC_UNUSED, int code GCC_UNUSED)
23062449Speter{
23162449Speter    return TRUE;
23262449Speter}
23362449Speter
23462449Speterstatic void
235166124Srafanno_mouse_resume(SCREEN *sp GCC_UNUSED)
23662449Speter{
23762449Speter}
23862449Speter
23962449Speterstatic void
240166124Srafanno_mouse_wrap(SCREEN *sp GCC_UNUSED)
24162449Speter{
24262449Speter}
24362449Speter
24466963Speter#if NCURSES_EXT_FUNCS && USE_COLORFGBG
24562449Speterstatic char *
24662449Speterextract_fgbg(char *src, int *result)
24762449Speter{
24862449Speter    char *dst = 0;
24962449Speter    long value = strtol(src, &dst, 0);
25062449Speter
25162449Speter    if (dst == 0) {
25262449Speter	dst = src;
25362449Speter    } else if (value >= 0) {
25498503Speter	*result = value;
25562449Speter    }
25662449Speter    while (*dst != 0 && *dst != ';')
25762449Speter	dst++;
25862449Speter    if (*dst == ';')
25962449Speter	dst++;
26062449Speter    return dst;
26162449Speter}
26262449Speter#endif
26362449Speter
264262685Sdelphij#define ReturnScreenError() { _nc_set_screen(0); \
265262685Sdelphij                            returnCode(ERR); } while (0)
266262629Sdelphij
267166124Srafan/* OS-independent screen initializations */
26876726SpeterNCURSES_EXPORT(int)
269262629SdelphijNCURSES_SP_NAME(_nc_setupscreen) (
270262629Sdelphij#if NCURSES_SP_FUNCS
271262629Sdelphij				     SCREEN **spp,
272262629Sdelphij#endif
273262629Sdelphij				     int slines,
274262629Sdelphij				     int scolumns,
275262629Sdelphij				     FILE *output,
276262685Sdelphij				     int filtered,
277262629Sdelphij				     int slk_format)
27850276Speter{
279176187Srafan    char *env;
28062449Speter    int bottom_stolen = 0;
281262629Sdelphij    ripoff_t *rop;
282262629Sdelphij    SCREEN *sp;
283262629Sdelphij#ifndef USE_TERM_DRIVER
284166124Srafan    bool support_cookies = USE_XMC_SUPPORT;
285262629Sdelphij#endif
28650276Speter
287166124Srafan    T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"),
288262629Sdelphij       slines, scolumns, (void *) output, filtered, slk_format));
289166124Srafan
290262629Sdelphij    assert(CURRENT_SCREEN == 0);	/* has been reset in newterm() ! */
291262629Sdelphij
292262629Sdelphij#if NCURSES_SP_FUNCS
293262629Sdelphij    assert(spp != 0);
294262629Sdelphij    sp = *spp;
295262629Sdelphij
296262629Sdelphij    if (!sp) {
297262629Sdelphij	sp = _nc_alloc_screen_sp();
298262629Sdelphij	*spp = sp;
299262629Sdelphij    }
300262629Sdelphij    if (!sp
301262629Sdelphij	|| ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0)
302262629Sdelphij	|| ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) {
303262629Sdelphij	ReturnScreenError();
304262629Sdelphij    }
305262629Sdelphij
306262629Sdelphij    T(("created SP %p", (void *) sp));
307262629Sdelphij    sp->_next_screen = _nc_screen_chain;
308262629Sdelphij    _nc_screen_chain = sp;
309262629Sdelphij
310262629Sdelphij    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) {
311262629Sdelphij	ReturnScreenError();
312262629Sdelphij    }
313262629Sdelphij#else
314166124Srafan    if (!_nc_alloc_screen()
315166124Srafan	|| ((SP->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0)
316166124Srafan	|| ((SP->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) {
317166124Srafan	returnCode(ERR);
318166124Srafan    }
31950276Speter
320262629Sdelphij    T(("created SP %p", (void *) SP));
32150276Speter
322262629Sdelphij    sp = SP;			/* fixup so SET_LINES and SET_COLS works */
323262629Sdelphij    sp->_next_screen = _nc_screen_chain;
324262629Sdelphij    _nc_screen_chain = sp;
325262629Sdelphij
326262629Sdelphij    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0)
327166124Srafan	returnCode(ERR);
328262629Sdelphij#endif
329166124Srafan
330174993Srafan    /*
331174993Srafan     * We should always check the screensize, just in case.
332174993Srafan     */
333262629Sdelphij    _nc_set_screen(sp);
334262629Sdelphij    sp->_term = cur_term;
335262629Sdelphij#ifdef USE_TERM_DRIVER
336262629Sdelphij    TCBOf(sp)->csp = sp;
337262629Sdelphij    _nc_get_screensize(sp, sp->_term, &slines, &scolumns);
338262629Sdelphij#else
339262629Sdelphij    _nc_get_screensize(sp, &slines, &scolumns);
340262629Sdelphij#endif
341174993Srafan    SET_LINES(slines);
342174993Srafan    SET_COLS(scolumns);
343174993Srafan
344262629Sdelphij    T((T_CREATE("screen %s %dx%d"),
345262629Sdelphij       NCURSES_SP_NAME(termname) (NCURSES_SP_ARG), slines, scolumns));
346166124Srafan
347262629Sdelphij    sp->_filtered = filtered;
348262629Sdelphij
349166124Srafan    /* implement filter mode */
350166124Srafan    if (filtered) {
351174993Srafan	slines = 1;
352174993Srafan	SET_LINES(slines);
353262629Sdelphij#ifdef USE_TERM_DRIVER
354262629Sdelphij	CallDriver(sp, setfilter);
355262629Sdelphij#else
356166124Srafan	clear_screen = 0;
357166124Srafan	cursor_down = parm_down_cursor = 0;
358166124Srafan	cursor_address = 0;
359166124Srafan	cursor_up = parm_up_cursor = 0;
360166124Srafan	row_address = 0;
361166124Srafan
362166124Srafan	cursor_home = carriage_return;
363262629Sdelphij#endif
364262629Sdelphij	T(("filter screensize %dx%d", slines, scolumns));
365166124Srafan    }
366166124Srafan#ifdef __DJGPP__
367166124Srafan    T(("setting output mode to binary"));
368166124Srafan    fflush(output);
369166124Srafan    setmode(output, O_BINARY);
370166124Srafan#endif
371262629Sdelphij    NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_ARGx output, TRUE);
372262629Sdelphij    sp->_lines = (NCURSES_SIZE_T) slines;
373262629Sdelphij    sp->_lines_avail = (NCURSES_SIZE_T) slines;
374262629Sdelphij    sp->_columns = (NCURSES_SIZE_T) scolumns;
375262685Sdelphij
376262685Sdelphij    fflush(output);
377262685Sdelphij    sp->_ofd = output ? fileno(output) : -1;
378262629Sdelphij    sp->_ofp = output;
379262685Sdelphij    sp->out_limit = (size_t) ((2 + slines) * (6 + scolumns));
380262685Sdelphij    if ((sp->out_buffer = malloc(sp->out_limit)) == 0)
381262685Sdelphij	sp->out_limit = 0;
382262685Sdelphij    sp->out_inuse = 0;
383262685Sdelphij
384262629Sdelphij    SP_PRE_INIT(sp);
385262629Sdelphij    SetNoPadding(sp);
38666963Speter
38766963Speter#if NCURSES_EXT_FUNCS
388262629Sdelphij    sp->_default_color = FALSE;
389262629Sdelphij    sp->_has_sgr_39_49 = FALSE;
39066963Speter
39166963Speter    /*
39266963Speter     * Set our assumption of the terminal's default foreground and background
39366963Speter     * colors.  The curs_color man-page states that we can assume that the
39466963Speter     * background is black.  The origin of this assumption appears to be
39566963Speter     * terminals that displayed colored text, but no colored backgrounds, e.g.,
39666963Speter     * the first colored terminals around 1980.  More recent ones with better
39766963Speter     * technology can display not only colored backgrounds, but all
39866963Speter     * combinations.  So a terminal might be something other than "white" on
39966963Speter     * black (green/black looks monochrome too), but black on white or even
40066963Speter     * on ivory.
40166963Speter     *
40266963Speter     * White-on-black is the simplest thing to use for monochrome.  Almost
40366963Speter     * all applications that use color paint both text and background, so
40466963Speter     * the distinction is moot.  But a few do not - which is why we leave this
40566963Speter     * configurable (a better solution is to use assume_default_colors() for
40666963Speter     * the rare applications that do require that sort of appearance, since
40766963Speter     * is appears that more users expect to be able to make a white-on-black
40866963Speter     * or black-on-white display under control of the application than not).
40966963Speter     */
41066963Speter#ifdef USE_ASSUMED_COLOR
411262629Sdelphij    sp->_default_fg = COLOR_WHITE;
412262629Sdelphij    sp->_default_bg = COLOR_BLACK;
41366963Speter#else
414262629Sdelphij    sp->_default_fg = C_MASK;
415262629Sdelphij    sp->_default_bg = C_MASK;
41666963Speter#endif
41766963Speter
418166124Srafan    /*
419166124Srafan     * Allow those assumed/default color assumptions to be overridden at
420166124Srafan     * runtime:
421166124Srafan     */
422184989Srafan    if ((env = getenv("NCURSES_ASSUMED_COLORS")) != 0) {
423166124Srafan	int fg, bg;
424166124Srafan	char sep1, sep2;
425184989Srafan	int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2);
426166124Srafan	if (count >= 1) {
427262629Sdelphij	    sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : C_MASK);
428166124Srafan	    if (count >= 3) {
429262629Sdelphij		sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : C_MASK);
430166124Srafan	    }
431166124Srafan	    TR(TRACE_CHARPUT | TRACE_MOVE,
432166124Srafan	       ("from environment assumed fg=%d, bg=%d",
433262629Sdelphij		sp->_default_fg,
434262629Sdelphij		sp->_default_bg));
435166124Srafan	}
436166124Srafan    }
43766963Speter#if USE_COLORFGBG
43862449Speter    /*
43962449Speter     * If rxvt's $COLORFGBG variable is set, use it to specify the assumed
44062449Speter     * default colors.  Note that rxvt (mis)uses bold colors, equating a bold
44162449Speter     * color to that value plus 8.  We'll only use the non-bold color for now -
44262449Speter     * decide later if it is worth having default attributes as well.
44362449Speter     */
44462449Speter    if (getenv("COLORFGBG") != 0) {
44562449Speter	char *p = getenv("COLORFGBG");
44697049Speter	TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p));
447262629Sdelphij	p = extract_fgbg(p, &(sp->_default_fg));
448262629Sdelphij	p = extract_fgbg(p, &(sp->_default_bg));
44997049Speter	if (*p)			/* assume rxvt was compiled with xpm support */
450262629Sdelphij	    p = extract_fgbg(p, &(sp->_default_bg));
45197049Speter	TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d",
452262629Sdelphij					sp->_default_fg, sp->_default_bg));
453262629Sdelphij	if (sp->_default_fg >= MaxColors) {
45498503Speter	    if (set_a_foreground != ABSENT_STRING
45598503Speter		&& !strcmp(set_a_foreground, "\033[3%p1%dm")) {
45698503Speter		set_a_foreground = "\033[3%?%p1%{8}%>%t9%e%p1%d%;m";
45798503Speter	    } else {
458262629Sdelphij		sp->_default_fg %= MaxColors;
45998503Speter	    }
46098503Speter	}
461262629Sdelphij	if (sp->_default_bg >= MaxColors) {
46298503Speter	    if (set_a_background != ABSENT_STRING
46398503Speter		&& !strcmp(set_a_background, "\033[4%p1%dm")) {
46498503Speter		set_a_background = "\033[4%?%p1%{8}%>%t9%e%p1%d%;m";
46598503Speter	    } else {
466262629Sdelphij		sp->_default_bg %= MaxColors;
46798503Speter	    }
46898503Speter	}
46962449Speter    }
47062449Speter#endif
47162449Speter#endif /* NCURSES_EXT_FUNCS */
47250276Speter
473262629Sdelphij    sp->_maxclick = DEFAULT_MAXCLICK;
474262629Sdelphij    sp->_mouse_event = no_mouse_event;
475262629Sdelphij    sp->_mouse_inline = no_mouse_inline;
476262629Sdelphij    sp->_mouse_parse = no_mouse_parse;
477262629Sdelphij    sp->_mouse_resume = no_mouse_resume;
478262629Sdelphij    sp->_mouse_wrap = no_mouse_wrap;
479262629Sdelphij    sp->_mouse_fd = -1;
48050276Speter
48162449Speter    /*
482166124Srafan     * If we've no magic cookie support, we suppress attributes that xmc would
483166124Srafan     * affect, i.e., the attributes that affect the rendition of a space.
48462449Speter     */
485262629Sdelphij    sp->_ok_attributes = NCURSES_SP_NAME(termattrs) (NCURSES_SP_ARG);
486262629Sdelphij    if (NCURSES_SP_NAME(has_colors) (NCURSES_SP_ARG)) {
487262629Sdelphij	sp->_ok_attributes |= A_COLOR;
488166124Srafan    }
489262629Sdelphij#ifdef USE_TERM_DRIVER
490262629Sdelphij    _nc_cookie_init(sp);
491262629Sdelphij#else
492166124Srafan#if USE_XMC_SUPPORT
493166124Srafan    /*
494166124Srafan     * If we have no magic-cookie support compiled-in, or if it is suppressed
495166124Srafan     * in the environment, reset the support-flag.
496166124Srafan     */
497166124Srafan    if (magic_cookie_glitch >= 0) {
498166124Srafan	if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) {
499166124Srafan	    support_cookies = FALSE;
500166124Srafan	}
501166124Srafan    }
502166124Srafan#endif
50350276Speter
504166124Srafan    if (!support_cookies && magic_cookie_glitch >= 0) {
505166124Srafan	T(("will disable attributes to work w/o magic cookies"));
506166124Srafan    }
507166124Srafan
508166124Srafan    if (magic_cookie_glitch > 0) {	/* tvi, wyse */
509166124Srafan
510262685Sdelphij	sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT;
511166124Srafan#if 0
512166124Srafan	/*
513166124Srafan	 * We "should" treat colors as an attribute.  The wyse350 (and its
514166124Srafan	 * clones) appear to be the only ones that have both colors and magic
515166124Srafan	 * cookies.
516166124Srafan	 */
517166124Srafan	if (has_colors()) {
518262629Sdelphij	    sp->_xmc_triggers |= A_COLOR;
519166124Srafan	}
520166124Srafan#endif
521262629Sdelphij	sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD);
52250276Speter
523262629Sdelphij	T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress)));
524166124Srafan	/*
525166124Srafan	 * Supporting line-drawing may be possible.  But make the regular
526166124Srafan	 * video attributes work first.
527166124Srafan	 */
528166124Srafan	acs_chars = ABSENT_STRING;
529166124Srafan	ena_acs = ABSENT_STRING;
530166124Srafan	enter_alt_charset_mode = ABSENT_STRING;
531166124Srafan	exit_alt_charset_mode = ABSENT_STRING;
53250276Speter#if USE_XMC_SUPPORT
53362449Speter	/*
534166124Srafan	 * To keep the cookie support simple, suppress all of the optimization
535166124Srafan	 * hooks except for clear_screen and the cursor addressing.
53662449Speter	 */
537166124Srafan	if (support_cookies) {
538166124Srafan	    clr_eol = ABSENT_STRING;
539166124Srafan	    clr_eos = ABSENT_STRING;
540166124Srafan	    set_attributes = ABSENT_STRING;
541166124Srafan	}
54250276Speter#endif
543166124Srafan    } else if (magic_cookie_glitch == 0) {	/* hpterm */
54462449Speter    }
545166124Srafan
546166124Srafan    /*
547166124Srafan     * If magic cookies are not supported, cancel the strings that set
548166124Srafan     * video attributes.
549166124Srafan     */
550166124Srafan    if (!support_cookies && magic_cookie_glitch >= 0) {
551166124Srafan	magic_cookie_glitch = ABSENT_NUMERIC;
552166124Srafan	set_attributes = ABSENT_STRING;
553166124Srafan	enter_blink_mode = ABSENT_STRING;
554166124Srafan	enter_bold_mode = ABSENT_STRING;
555166124Srafan	enter_dim_mode = ABSENT_STRING;
556166124Srafan	enter_reverse_mode = ABSENT_STRING;
557166124Srafan	enter_standout_mode = ABSENT_STRING;
558166124Srafan	enter_underline_mode = ABSENT_STRING;
559166124Srafan    }
560166124Srafan
561166124Srafan    /* initialize normal acs before wide, since we use mapping in the latter */
562174993Srafan#if !USE_WIDEC_SUPPORT
563262629Sdelphij    if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) {
564174993Srafan	acs_chars = NULL;
565174993Srafan	ena_acs = NULL;
566174993Srafan	enter_alt_charset_mode = NULL;
567174993Srafan	exit_alt_charset_mode = NULL;
568174993Srafan	set_attributes = NULL;
569174993Srafan    }
570174993Srafan#endif
571262629Sdelphij#endif
572262629Sdelphij
573262629Sdelphij    NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_ARG);
57497049Speter#if USE_WIDEC_SUPPORT
575262685Sdelphij    sp->_screen_unicode = _nc_unicode_locale();
57697049Speter    _nc_init_wacs();
577262685Sdelphij    if (_nc_wacs == 0) {
578262685Sdelphij	ReturnScreenError();
579262685Sdelphij    }
580166124Srafan
581262685Sdelphij    sp->_screen_acs_fix = (sp->_screen_unicode
582262629Sdelphij			   && _nc_locale_breaks_acs(sp->_term));
58397049Speter#endif
584176187Srafan    env = _nc_get_locale();
585262629Sdelphij    sp->_legacy_coding = ((env == 0)
586176187Srafan			  || !strcmp(env, "C")
587176187Srafan			  || !strcmp(env, "POSIX"));
588262629Sdelphij    T(("legacy-coding %d", sp->_legacy_coding));
58950276Speter
590262629Sdelphij    sp->_nc_sp_idcok = TRUE;
591262629Sdelphij    sp->_nc_sp_idlok = FALSE;
59250276Speter
593262629Sdelphij    sp->oldhash = 0;
594262629Sdelphij    sp->newhash = 0;
59550276Speter
59662449Speter    T(("creating newscr"));
597262629Sdelphij    NewScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns,
598262629Sdelphij					     0, 0);
599262629Sdelphij    if (NewScreen(sp) == 0) {
600262629Sdelphij	ReturnScreenError();
601262629Sdelphij    }
60262449Speter    T(("creating curscr"));
603262629Sdelphij    CurScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns,
604262629Sdelphij					     0, 0);
605262629Sdelphij    if (CurScreen(sp) == 0) {
606262629Sdelphij	ReturnScreenError();
607262629Sdelphij    }
608174993Srafan#if !USE_REENTRANT
609262629Sdelphij    newscr = NewScreen(sp);
610262629Sdelphij    curscr = CurScreen(sp);
611174993Srafan#endif
61250276Speter#if USE_SIZECHANGE
613262629Sdelphij    sp->_resize = NCURSES_SP_NAME(resizeterm);
614262685Sdelphij    sp->_ungetch = safe_ungetch;
61550276Speter#endif
61650276Speter
617262629Sdelphij    NewScreen(sp)->_clear = TRUE;
618262629Sdelphij    CurScreen(sp)->_clear = FALSE;
61950276Speter
620262629Sdelphij    NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG);
621262629Sdelphij    NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG);
62297049Speter
623262629Sdelphij    if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
624262629Sdelphij	for (rop = safe_ripoff_stack;
625262629Sdelphij	     rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
626262629Sdelphij	     rop++) {
62750276Speter
628262629Sdelphij	    /* If we must simulate soft labels, grab off the line to be used.
629262629Sdelphij	       We assume that we must simulate, if it is none of the standard
630262629Sdelphij	       formats (4-4 or 3-2-3) for which there may be some hardware
631262629Sdelphij	       support. */
632262629Sdelphij	    if (rop->hook == _nc_slk_initialize) {
633262629Sdelphij		if (!(NumLabels <= 0 || !SLK_STDFMT(slk_format))) {
634262629Sdelphij		    continue;
635262629Sdelphij		}
636262629Sdelphij	    }
637262629Sdelphij	    if (rop->hook) {
638262629Sdelphij		int count;
639262629Sdelphij		WINDOW *w;
640174993Srafan
641262629Sdelphij		count = (rop->line < 0) ? -rop->line : rop->line;
642262629Sdelphij		T(("ripping off %i lines at %s", count,
643262629Sdelphij		   ((rop->line < 0)
644262629Sdelphij		    ? "bottom"
645262629Sdelphij		    : "top")));
646174993Srafan
647262629Sdelphij		w = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
648262629Sdelphij					     count, scolumns,
649262629Sdelphij					     ((rop->line < 0)
650262629Sdelphij					      ? sp->_lines_avail - count
651262629Sdelphij					      : 0),
652262629Sdelphij					     0);
653262629Sdelphij		if (w) {
654262629Sdelphij		    rop->win = w;
655262629Sdelphij		    rop->hook(w, scolumns);
656262629Sdelphij		} else {
657262629Sdelphij		    ReturnScreenError();
658262629Sdelphij		}
659262629Sdelphij		if (rop->line < 0) {
660262629Sdelphij		    bottom_stolen += count;
661262629Sdelphij		} else {
662262629Sdelphij		    sp->_topstolen = (NCURSES_SIZE_T) (sp->_topstolen + count);
663262629Sdelphij		}
664262629Sdelphij		sp->_lines_avail = (NCURSES_SIZE_T) (sp->_lines_avail - count);
665176187Srafan	    }
66650276Speter	}
667262629Sdelphij	/* reset the stack */
668262629Sdelphij	safe_ripoff_sp = safe_ripoff_stack;
66962449Speter    }
67050276Speter
67162449Speter    T(("creating stdscr"));
672262629Sdelphij    assert((sp->_lines_avail + sp->_topstolen + bottom_stolen) == slines);
673262629Sdelphij    if ((StdScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
674262629Sdelphij						  sp->_lines_avail,
675262629Sdelphij						  scolumns, 0, 0)) == 0) {
676262629Sdelphij	ReturnScreenError();
677262629Sdelphij    }
678262629Sdelphij    SET_LINES(sp->_lines_avail);
679174993Srafan#if !USE_REENTRANT
680262629Sdelphij    stdscr = StdScreen(sp);
681174993Srafan#endif
682262629Sdelphij    sp->_prescreen = FALSE;
683166124Srafan    returnCode(OK);
68450276Speter}
68550276Speter
686262629Sdelphij#if NCURSES_SP_FUNCS
687262629SdelphijNCURSES_EXPORT(int)
688262629Sdelphij_nc_setupscreen(int slines GCC_UNUSED,
689262629Sdelphij		int scolumns GCC_UNUSED,
690262629Sdelphij		FILE *output,
691262685Sdelphij		int filtered,
692262629Sdelphij		int slk_format)
693262629Sdelphij{
694262629Sdelphij    SCREEN *sp = 0;
695262629Sdelphij    int rc = NCURSES_SP_NAME(_nc_setupscreen) (&sp,
696262629Sdelphij					       slines,
697262629Sdelphij					       scolumns,
698262629Sdelphij					       output,
699262629Sdelphij					       filtered,
700262629Sdelphij					       slk_format);
701262629Sdelphij    if (rc != OK)
702262629Sdelphij	_nc_set_screen(0);
703262629Sdelphij    return rc;
704262629Sdelphij}
705262629Sdelphij#endif
706262629Sdelphij
707174993Srafan/*
708174993Srafan * The internal implementation interprets line as the number of lines to rip
709174993Srafan * off from the top or bottom.
710174993Srafan */
71176726SpeterNCURSES_EXPORT(int)
712262629SdelphijNCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx
713262629Sdelphij				 int line,
714262629Sdelphij				 int (*init) (WINDOW *, int))
71550276Speter{
716262629Sdelphij    int code = ERR;
71750276Speter
718262629Sdelphij    START_TRACE();
719262629Sdelphij    T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM, line, init));
72050276Speter
721262629Sdelphij#if NCURSES_SP_FUNCS
722262629Sdelphij    if (SP_PARM != 0 && SP_PARM->_prescreen)
723262629Sdelphij#endif
724262629Sdelphij    {
725262629Sdelphij	if (line == 0) {
726262629Sdelphij	    code = OK;
727262629Sdelphij	} else {
728262629Sdelphij	    if (safe_ripoff_sp == 0)
729262629Sdelphij		safe_ripoff_sp = safe_ripoff_stack;
730262629Sdelphij	    if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) {
731262629Sdelphij		safe_ripoff_sp->line = line;
732262629Sdelphij		safe_ripoff_sp->hook = init;
733262629Sdelphij		(safe_ripoff_sp)++;
734262629Sdelphij		code = OK;
735262629Sdelphij	    }
736262629Sdelphij	}
737166124Srafan    }
738166124Srafan
739262629Sdelphij    returnCode(code);
74050276Speter}
74150276Speter
742262629Sdelphij#if NCURSES_SP_FUNCS
74376726SpeterNCURSES_EXPORT(int)
744262629Sdelphij_nc_ripoffline(int line, int (*init) (WINDOW *, int))
74550276Speter{
746262629Sdelphij    return NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init);
747262629Sdelphij}
748262629Sdelphij#endif
74950276Speter
750262629SdelphijNCURSES_EXPORT(int)
751262629SdelphijNCURSES_SP_NAME(ripoffline) (NCURSES_SP_DCLx
752262629Sdelphij			     int line,
753262629Sdelphij			     int (*init) (WINDOW *, int))
754262629Sdelphij{
755262685Sdelphij    START_TRACE();
756262629Sdelphij    return NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_ARGx
757262629Sdelphij					    (line < 0) ? -1 : 1,
758262629Sdelphij					    init);
759262629Sdelphij}
76050276Speter
761262629Sdelphij#if NCURSES_SP_FUNCS
762262629SdelphijNCURSES_EXPORT(int)
763262629Sdelphijripoffline(int line, int (*init) (WINDOW *, int))
764262629Sdelphij{
765262629Sdelphij    return NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init);
76650276Speter}
767262629Sdelphij#endif
768