1/****************************************************************************
2 * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
3 *                                                                          *
4 * Permission is hereby granted, free of charge, to any person obtaining a  *
5 * copy of this software and associated documentation files (the            *
6 * "Software"), to deal in the Software without restriction, including      *
7 * without limitation the rights to use, copy, modify, merge, publish,      *
8 * distribute, distribute with modifications, sublicense, and/or sell       *
9 * copies of the Software, and to permit persons to whom the Software is    *
10 * furnished to do so, subject to the following conditions:                 *
11 *                                                                          *
12 * The above copyright notice and this permission notice shall be included  *
13 * in all copies or substantial portions of the Software.                   *
14 *                                                                          *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22 *                                                                          *
23 * Except as contained in this notice, the name(s) of the above copyright   *
24 * holders shall not be used in advertising or otherwise to promote the     *
25 * sale, use or other dealings in this Software without prior written       *
26 * authorization.                                                           *
27 ****************************************************************************/
28
29/****************************************************************************
30 *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31 *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32 *     and: Thomas E. Dickey                        1996-on                 *
33 *     and: Juergen Pfeifer                         2009                    *
34 ****************************************************************************/
35
36/*
37**	lib_set_term.c
38**
39**	The routine set_term().
40**
41*/
42
43#include <curses.priv.h>
44#include <tic.h>
45
46#ifndef CUR
47#define CUR SP_TERMTYPE
48#endif
49
50MODULE_ID("$Id: lib_set_term.c,v 1.148 2013/08/31 13:33:06 tom Exp $")
51
52#ifdef USE_TERM_DRIVER
53#define MaxColors      InfoOf(sp).maxcolors
54#define NumLabels      InfoOf(sp).numlabels
55#else
56#define MaxColors      max_colors
57#define NumLabels      num_labels
58#endif
59
60NCURSES_EXPORT(SCREEN *)
61set_term(SCREEN *screenp)
62{
63    SCREEN *oldSP;
64    SCREEN *newSP;
65
66    T((T_CALLED("set_term(%p)"), (void *) screenp));
67
68    _nc_lock_global(curses);
69
70    oldSP = CURRENT_SCREEN;
71    _nc_set_screen(screenp);
72    newSP = screenp;
73
74    if (newSP != 0) {
75	TINFO_SET_CURTERM(newSP, newSP->_term);
76#if !USE_REENTRANT
77	curscr = CurScreen(newSP);
78	newscr = NewScreen(newSP);
79	stdscr = StdScreen(newSP);
80	COLORS = newSP->_color_count;
81	COLOR_PAIRS = newSP->_pair_count;
82#endif
83    } else {
84	TINFO_SET_CURTERM(oldSP, 0);
85#if !USE_REENTRANT
86	curscr = 0;
87	newscr = 0;
88	stdscr = 0;
89	COLORS = 0;
90	COLOR_PAIRS = 0;
91#endif
92    }
93
94    _nc_unlock_global(curses);
95
96    T((T_RETURN("%p"), (void *) oldSP));
97    return (oldSP);
98}
99
100static void
101_nc_free_keytry(TRIES * kt)
102{
103    if (kt != 0) {
104	_nc_free_keytry(kt->child);
105	_nc_free_keytry(kt->sibling);
106	free(kt);
107    }
108}
109
110static bool
111delink_screen(SCREEN *sp)
112{
113    SCREEN *last = 0;
114    SCREEN *temp;
115    bool result = FALSE;
116
117    for (each_screen(temp)) {
118	if (temp == sp) {
119	    if (last)
120		last->_next_screen = sp->_next_screen;
121	    else
122		_nc_screen_chain = sp->_next_screen;
123	    result = TRUE;
124	    break;
125	}
126	last = temp;
127    }
128    return result;
129}
130
131/*
132 * Free the storage associated with the given SCREEN sp.
133 */
134NCURSES_EXPORT(void)
135delscreen(SCREEN *sp)
136{
137    int i;
138
139    T((T_CALLED("delscreen(%p)"), (void *) sp));
140
141    _nc_lock_global(curses);
142    if (delink_screen(sp)) {
143#ifdef USE_SP_RIPOFF
144	ripoff_t *rop;
145	if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
146	    for (rop = safe_ripoff_stack;
147		 rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
148		 rop++) {
149		if (rop->win) {
150		    (void) delwin(rop->win);
151		    rop->win = 0;
152		}
153	    }
154	}
155#endif
156
157	(void) _nc_freewin(CurScreen(sp));
158	(void) _nc_freewin(NewScreen(sp));
159	(void) _nc_freewin(StdScreen(sp));
160
161	if (sp->_slk != 0) {
162	    if (sp->_slk->ent != 0) {
163		for (i = 0; i < sp->_slk->labcnt; ++i) {
164		    FreeIfNeeded(sp->_slk->ent[i].ent_text);
165		    FreeIfNeeded(sp->_slk->ent[i].form_text);
166		}
167		free(sp->_slk->ent);
168	    }
169	    free(sp->_slk);
170	    sp->_slk = 0;
171	}
172
173	_nc_free_keytry(sp->_keytry);
174	sp->_keytry = 0;
175
176	_nc_free_keytry(sp->_key_ok);
177	sp->_key_ok = 0;
178
179	FreeIfNeeded(sp->_current_attr);
180
181	FreeIfNeeded(sp->_color_table);
182	FreeIfNeeded(sp->_color_pairs);
183
184	FreeIfNeeded(sp->oldhash);
185	FreeIfNeeded(sp->newhash);
186	FreeIfNeeded(sp->hashtab);
187
188	FreeIfNeeded(sp->_acs_map);
189	FreeIfNeeded(sp->_screen_acs_map);
190
191	NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
192	NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term);
193	free(sp);
194
195	/*
196	 * If this was the current screen, reset everything that the
197	 * application might try to use (except cur_term, which may have
198	 * multiple references in different screens).
199	 */
200	if (sp == CURRENT_SCREEN) {
201#if !USE_REENTRANT
202	    curscr = 0;
203	    newscr = 0;
204	    stdscr = 0;
205	    COLORS = 0;
206	    COLOR_PAIRS = 0;
207#endif
208	    _nc_set_screen(0);
209	}
210    }
211    _nc_unlock_global(curses);
212
213    returnVoid;
214}
215
216static bool
217no_mouse_event(SCREEN *sp GCC_UNUSED)
218{
219    return FALSE;
220}
221
222static bool
223no_mouse_inline(SCREEN *sp GCC_UNUSED)
224{
225    return FALSE;
226}
227
228static bool
229no_mouse_parse(SCREEN *sp GCC_UNUSED, int code GCC_UNUSED)
230{
231    return TRUE;
232}
233
234static void
235no_mouse_resume(SCREEN *sp GCC_UNUSED)
236{
237}
238
239static void
240no_mouse_wrap(SCREEN *sp GCC_UNUSED)
241{
242}
243
244#if NCURSES_EXT_FUNCS && USE_COLORFGBG
245static char *
246extract_fgbg(char *src, int *result)
247{
248    char *dst = 0;
249    long value = strtol(src, &dst, 0);
250
251    if (dst == 0) {
252	dst = src;
253    } else if (value >= 0) {
254	*result = value;
255    }
256    while (*dst != 0 && *dst != ';')
257	dst++;
258    if (*dst == ';')
259	dst++;
260    return dst;
261}
262#endif
263
264#define ReturnScreenError() { _nc_set_screen(0); \
265                            returnCode(ERR); } while (0)
266
267/* OS-independent screen initializations */
268NCURSES_EXPORT(int)
269NCURSES_SP_NAME(_nc_setupscreen) (
270#if NCURSES_SP_FUNCS
271				     SCREEN **spp,
272#endif
273				     int slines,
274				     int scolumns,
275				     FILE *output,
276				     int filtered,
277				     int slk_format)
278{
279    char *env;
280    int bottom_stolen = 0;
281    ripoff_t *rop;
282    SCREEN *sp;
283#ifndef USE_TERM_DRIVER
284    bool support_cookies = USE_XMC_SUPPORT;
285#endif
286
287    T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"),
288       slines, scolumns, (void *) output, filtered, slk_format));
289
290    assert(CURRENT_SCREEN == 0);	/* has been reset in newterm() ! */
291
292#if NCURSES_SP_FUNCS
293    assert(spp != 0);
294    sp = *spp;
295
296    if (!sp) {
297	sp = _nc_alloc_screen_sp();
298	*spp = sp;
299    }
300    if (!sp
301	|| ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0)
302	|| ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) {
303	ReturnScreenError();
304    }
305
306    T(("created SP %p", (void *) sp));
307    sp->_next_screen = _nc_screen_chain;
308    _nc_screen_chain = sp;
309
310    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) {
311	ReturnScreenError();
312    }
313#else
314    if (!_nc_alloc_screen()
315	|| ((SP->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0)
316	|| ((SP->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) {
317	returnCode(ERR);
318    }
319
320    T(("created SP %p", (void *) SP));
321
322    sp = SP;			/* fixup so SET_LINES and SET_COLS works */
323    sp->_next_screen = _nc_screen_chain;
324    _nc_screen_chain = sp;
325
326    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0)
327	returnCode(ERR);
328#endif
329
330    /*
331     * We should always check the screensize, just in case.
332     */
333    _nc_set_screen(sp);
334    sp->_term = cur_term;
335#ifdef USE_TERM_DRIVER
336    TCBOf(sp)->csp = sp;
337    _nc_get_screensize(sp, sp->_term, &slines, &scolumns);
338#else
339    _nc_get_screensize(sp, &slines, &scolumns);
340#endif
341    SET_LINES(slines);
342    SET_COLS(scolumns);
343
344    T((T_CREATE("screen %s %dx%d"),
345       NCURSES_SP_NAME(termname) (NCURSES_SP_ARG), slines, scolumns));
346
347    sp->_filtered = filtered;
348
349    /* implement filter mode */
350    if (filtered) {
351	slines = 1;
352	SET_LINES(slines);
353#ifdef USE_TERM_DRIVER
354	CallDriver(sp, setfilter);
355#else
356	clear_screen = 0;
357	cursor_down = parm_down_cursor = 0;
358	cursor_address = 0;
359	cursor_up = parm_up_cursor = 0;
360	row_address = 0;
361
362	cursor_home = carriage_return;
363#endif
364	T(("filter screensize %dx%d", slines, scolumns));
365    }
366#ifdef __DJGPP__
367    T(("setting output mode to binary"));
368    fflush(output);
369    setmode(output, O_BINARY);
370#endif
371    NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_ARGx output, TRUE);
372    sp->_lines = (NCURSES_SIZE_T) slines;
373    sp->_lines_avail = (NCURSES_SIZE_T) slines;
374    sp->_columns = (NCURSES_SIZE_T) scolumns;
375
376    fflush(output);
377    sp->_ofd = output ? fileno(output) : -1;
378    sp->_ofp = output;
379    sp->out_limit = (size_t) ((2 + slines) * (6 + scolumns));
380    if ((sp->out_buffer = malloc(sp->out_limit)) == 0)
381	sp->out_limit = 0;
382    sp->out_inuse = 0;
383
384    SP_PRE_INIT(sp);
385    SetNoPadding(sp);
386
387#if NCURSES_EXT_FUNCS
388    sp->_default_color = FALSE;
389    sp->_has_sgr_39_49 = FALSE;
390
391    /*
392     * Set our assumption of the terminal's default foreground and background
393     * colors.  The curs_color man-page states that we can assume that the
394     * background is black.  The origin of this assumption appears to be
395     * terminals that displayed colored text, but no colored backgrounds, e.g.,
396     * the first colored terminals around 1980.  More recent ones with better
397     * technology can display not only colored backgrounds, but all
398     * combinations.  So a terminal might be something other than "white" on
399     * black (green/black looks monochrome too), but black on white or even
400     * on ivory.
401     *
402     * White-on-black is the simplest thing to use for monochrome.  Almost
403     * all applications that use color paint both text and background, so
404     * the distinction is moot.  But a few do not - which is why we leave this
405     * configurable (a better solution is to use assume_default_colors() for
406     * the rare applications that do require that sort of appearance, since
407     * is appears that more users expect to be able to make a white-on-black
408     * or black-on-white display under control of the application than not).
409     */
410#ifdef USE_ASSUMED_COLOR
411    sp->_default_fg = COLOR_WHITE;
412    sp->_default_bg = COLOR_BLACK;
413#else
414    sp->_default_fg = C_MASK;
415    sp->_default_bg = C_MASK;
416#endif
417
418    /*
419     * Allow those assumed/default color assumptions to be overridden at
420     * runtime:
421     */
422    if ((env = getenv("NCURSES_ASSUMED_COLORS")) != 0) {
423	int fg, bg;
424	char sep1, sep2;
425	int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2);
426	if (count >= 1) {
427	    sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : C_MASK);
428	    if (count >= 3) {
429		sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : C_MASK);
430	    }
431	    TR(TRACE_CHARPUT | TRACE_MOVE,
432	       ("from environment assumed fg=%d, bg=%d",
433		sp->_default_fg,
434		sp->_default_bg));
435	}
436    }
437#if USE_COLORFGBG
438    /*
439     * If rxvt's $COLORFGBG variable is set, use it to specify the assumed
440     * default colors.  Note that rxvt (mis)uses bold colors, equating a bold
441     * color to that value plus 8.  We'll only use the non-bold color for now -
442     * decide later if it is worth having default attributes as well.
443     */
444    if (getenv("COLORFGBG") != 0) {
445	char *p = getenv("COLORFGBG");
446	TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p));
447	p = extract_fgbg(p, &(sp->_default_fg));
448	p = extract_fgbg(p, &(sp->_default_bg));
449	if (*p)			/* assume rxvt was compiled with xpm support */
450	    p = extract_fgbg(p, &(sp->_default_bg));
451	TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d",
452					sp->_default_fg, sp->_default_bg));
453	if (sp->_default_fg >= MaxColors) {
454	    if (set_a_foreground != ABSENT_STRING
455		&& !strcmp(set_a_foreground, "\033[3%p1%dm")) {
456		set_a_foreground = "\033[3%?%p1%{8}%>%t9%e%p1%d%;m";
457	    } else {
458		sp->_default_fg %= MaxColors;
459	    }
460	}
461	if (sp->_default_bg >= MaxColors) {
462	    if (set_a_background != ABSENT_STRING
463		&& !strcmp(set_a_background, "\033[4%p1%dm")) {
464		set_a_background = "\033[4%?%p1%{8}%>%t9%e%p1%d%;m";
465	    } else {
466		sp->_default_bg %= MaxColors;
467	    }
468	}
469    }
470#endif
471#endif /* NCURSES_EXT_FUNCS */
472
473    sp->_maxclick = DEFAULT_MAXCLICK;
474    sp->_mouse_event = no_mouse_event;
475    sp->_mouse_inline = no_mouse_inline;
476    sp->_mouse_parse = no_mouse_parse;
477    sp->_mouse_resume = no_mouse_resume;
478    sp->_mouse_wrap = no_mouse_wrap;
479    sp->_mouse_fd = -1;
480
481    /*
482     * If we've no magic cookie support, we suppress attributes that xmc would
483     * affect, i.e., the attributes that affect the rendition of a space.
484     */
485    sp->_ok_attributes = NCURSES_SP_NAME(termattrs) (NCURSES_SP_ARG);
486    if (NCURSES_SP_NAME(has_colors) (NCURSES_SP_ARG)) {
487	sp->_ok_attributes |= A_COLOR;
488    }
489#ifdef USE_TERM_DRIVER
490    _nc_cookie_init(sp);
491#else
492#if USE_XMC_SUPPORT
493    /*
494     * If we have no magic-cookie support compiled-in, or if it is suppressed
495     * in the environment, reset the support-flag.
496     */
497    if (magic_cookie_glitch >= 0) {
498	if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) {
499	    support_cookies = FALSE;
500	}
501    }
502#endif
503
504    if (!support_cookies && magic_cookie_glitch >= 0) {
505	T(("will disable attributes to work w/o magic cookies"));
506    }
507
508    if (magic_cookie_glitch > 0) {	/* tvi, wyse */
509
510	sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT;
511#if 0
512	/*
513	 * We "should" treat colors as an attribute.  The wyse350 (and its
514	 * clones) appear to be the only ones that have both colors and magic
515	 * cookies.
516	 */
517	if (has_colors()) {
518	    sp->_xmc_triggers |= A_COLOR;
519	}
520#endif
521	sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD);
522
523	T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress)));
524	/*
525	 * Supporting line-drawing may be possible.  But make the regular
526	 * video attributes work first.
527	 */
528	acs_chars = ABSENT_STRING;
529	ena_acs = ABSENT_STRING;
530	enter_alt_charset_mode = ABSENT_STRING;
531	exit_alt_charset_mode = ABSENT_STRING;
532#if USE_XMC_SUPPORT
533	/*
534	 * To keep the cookie support simple, suppress all of the optimization
535	 * hooks except for clear_screen and the cursor addressing.
536	 */
537	if (support_cookies) {
538	    clr_eol = ABSENT_STRING;
539	    clr_eos = ABSENT_STRING;
540	    set_attributes = ABSENT_STRING;
541	}
542#endif
543    } else if (magic_cookie_glitch == 0) {	/* hpterm */
544    }
545
546    /*
547     * If magic cookies are not supported, cancel the strings that set
548     * video attributes.
549     */
550    if (!support_cookies && magic_cookie_glitch >= 0) {
551	magic_cookie_glitch = ABSENT_NUMERIC;
552	set_attributes = ABSENT_STRING;
553	enter_blink_mode = ABSENT_STRING;
554	enter_bold_mode = ABSENT_STRING;
555	enter_dim_mode = ABSENT_STRING;
556	enter_reverse_mode = ABSENT_STRING;
557	enter_standout_mode = ABSENT_STRING;
558	enter_underline_mode = ABSENT_STRING;
559    }
560
561    /* initialize normal acs before wide, since we use mapping in the latter */
562#if !USE_WIDEC_SUPPORT
563    if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) {
564	acs_chars = NULL;
565	ena_acs = NULL;
566	enter_alt_charset_mode = NULL;
567	exit_alt_charset_mode = NULL;
568	set_attributes = NULL;
569    }
570#endif
571#endif
572
573    NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_ARG);
574#if USE_WIDEC_SUPPORT
575    sp->_screen_unicode = _nc_unicode_locale();
576    _nc_init_wacs();
577    if (_nc_wacs == 0) {
578	ReturnScreenError();
579    }
580
581    sp->_screen_acs_fix = (sp->_screen_unicode
582			   && _nc_locale_breaks_acs(sp->_term));
583#endif
584    env = _nc_get_locale();
585    sp->_legacy_coding = ((env == 0)
586			  || !strcmp(env, "C")
587			  || !strcmp(env, "POSIX"));
588    T(("legacy-coding %d", sp->_legacy_coding));
589
590    sp->_nc_sp_idcok = TRUE;
591    sp->_nc_sp_idlok = FALSE;
592
593    sp->oldhash = 0;
594    sp->newhash = 0;
595
596    T(("creating newscr"));
597    NewScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns,
598					     0, 0);
599    if (NewScreen(sp) == 0) {
600	ReturnScreenError();
601    }
602    T(("creating curscr"));
603    CurScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns,
604					     0, 0);
605    if (CurScreen(sp) == 0) {
606	ReturnScreenError();
607    }
608#if !USE_REENTRANT
609    newscr = NewScreen(sp);
610    curscr = CurScreen(sp);
611#endif
612#if USE_SIZECHANGE
613    sp->_resize = NCURSES_SP_NAME(resizeterm);
614    sp->_ungetch = safe_ungetch;
615#endif
616
617    NewScreen(sp)->_clear = TRUE;
618    CurScreen(sp)->_clear = FALSE;
619
620    NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG);
621    NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG);
622
623    if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
624	for (rop = safe_ripoff_stack;
625	     rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
626	     rop++) {
627
628	    /* If we must simulate soft labels, grab off the line to be used.
629	       We assume that we must simulate, if it is none of the standard
630	       formats (4-4 or 3-2-3) for which there may be some hardware
631	       support. */
632	    if (rop->hook == _nc_slk_initialize) {
633		if (!(NumLabels <= 0 || !SLK_STDFMT(slk_format))) {
634		    continue;
635		}
636	    }
637	    if (rop->hook) {
638		int count;
639		WINDOW *w;
640
641		count = (rop->line < 0) ? -rop->line : rop->line;
642		T(("ripping off %i lines at %s", count,
643		   ((rop->line < 0)
644		    ? "bottom"
645		    : "top")));
646
647		w = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
648					     count, scolumns,
649					     ((rop->line < 0)
650					      ? sp->_lines_avail - count
651					      : 0),
652					     0);
653		if (w) {
654		    rop->win = w;
655		    rop->hook(w, scolumns);
656		} else {
657		    ReturnScreenError();
658		}
659		if (rop->line < 0) {
660		    bottom_stolen += count;
661		} else {
662		    sp->_topstolen = (NCURSES_SIZE_T) (sp->_topstolen + count);
663		}
664		sp->_lines_avail = (NCURSES_SIZE_T) (sp->_lines_avail - count);
665	    }
666	}
667	/* reset the stack */
668	safe_ripoff_sp = safe_ripoff_stack;
669    }
670
671    T(("creating stdscr"));
672    assert((sp->_lines_avail + sp->_topstolen + bottom_stolen) == slines);
673    if ((StdScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
674						  sp->_lines_avail,
675						  scolumns, 0, 0)) == 0) {
676	ReturnScreenError();
677    }
678    SET_LINES(sp->_lines_avail);
679#if !USE_REENTRANT
680    stdscr = StdScreen(sp);
681#endif
682    sp->_prescreen = FALSE;
683    returnCode(OK);
684}
685
686#if NCURSES_SP_FUNCS
687NCURSES_EXPORT(int)
688_nc_setupscreen(int slines GCC_UNUSED,
689		int scolumns GCC_UNUSED,
690		FILE *output,
691		int filtered,
692		int slk_format)
693{
694    SCREEN *sp = 0;
695    int rc = NCURSES_SP_NAME(_nc_setupscreen) (&sp,
696					       slines,
697					       scolumns,
698					       output,
699					       filtered,
700					       slk_format);
701    if (rc != OK)
702	_nc_set_screen(0);
703    return rc;
704}
705#endif
706
707/*
708 * The internal implementation interprets line as the number of lines to rip
709 * off from the top or bottom.
710 */
711NCURSES_EXPORT(int)
712NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx
713				 int line,
714				 int (*init) (WINDOW *, int))
715{
716    int code = ERR;
717
718    START_TRACE();
719    T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM, line, init));
720
721#if NCURSES_SP_FUNCS
722    if (SP_PARM != 0 && SP_PARM->_prescreen)
723#endif
724    {
725	if (line == 0) {
726	    code = OK;
727	} else {
728	    if (safe_ripoff_sp == 0)
729		safe_ripoff_sp = safe_ripoff_stack;
730	    if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) {
731		safe_ripoff_sp->line = line;
732		safe_ripoff_sp->hook = init;
733		(safe_ripoff_sp)++;
734		code = OK;
735	    }
736	}
737    }
738
739    returnCode(code);
740}
741
742#if NCURSES_SP_FUNCS
743NCURSES_EXPORT(int)
744_nc_ripoffline(int line, int (*init) (WINDOW *, int))
745{
746    return NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init);
747}
748#endif
749
750NCURSES_EXPORT(int)
751NCURSES_SP_NAME(ripoffline) (NCURSES_SP_DCLx
752			     int line,
753			     int (*init) (WINDOW *, int))
754{
755    START_TRACE();
756    return NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_ARGx
757					    (line < 0) ? -1 : 1,
758					    init);
759}
760
761#if NCURSES_SP_FUNCS
762NCURSES_EXPORT(int)
763ripoffline(int line, int (*init) (WINDOW *, int))
764{
765    return NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init);
766}
767#endif
768