GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcurses/base/lib_set_term.c Lines: 0 203 0.0 %
Date: 2017-11-07 Branches: 0 114 0.0 %

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