1 /****************************************************************************
2 * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc. *
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: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
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. *
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 *
27 ****************************************************************************/
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 ****************************************************************************/
39 ** The routine set_term().
43 #include <curses.priv.h>
47 #define CUR SP_TERMTYPE
50 MODULE_ID("$Id: lib_set_term.c,v 1.153 2015/08/07 23:57:58 tom Exp $")
52 #ifdef USE_TERM_DRIVER
53 #define MaxColors InfoOf(sp).maxcolors
54 #define NumLabels InfoOf(sp).numlabels
56 #define MaxColors max_colors
57 #define NumLabels num_labels
60 NCURSES_EXPORT(SCREEN
*)
61 set_term(SCREEN
*screenp
)
66 T((T_CALLED("set_term(%p)"), (void *) screenp
));
68 _nc_lock_global(curses
);
70 oldSP
= CURRENT_SCREEN
;
71 _nc_set_screen(screenp
);
75 TINFO_SET_CURTERM(newSP
, newSP
->_term
);
77 curscr
= CurScreen(newSP
);
78 newscr
= NewScreen(newSP
);
79 stdscr
= StdScreen(newSP
);
80 COLORS
= newSP
->_color_count
;
81 COLOR_PAIRS
= newSP
->_pair_count
;
84 TINFO_SET_CURTERM(oldSP
, 0);
94 _nc_unlock_global(curses
);
96 T((T_RETURN("%p"), (void *) oldSP
));
101 _nc_free_keytry(TRIES
* kt
)
104 _nc_free_keytry(kt
->child
);
105 _nc_free_keytry(kt
->sibling
);
111 delink_screen(SCREEN
*sp
)
117 for (each_screen(temp
)) {
120 last
->_next_screen
= sp
->_next_screen
;
122 _nc_screen_chain
= sp
->_next_screen
;
132 * Free the storage associated with the given SCREEN sp.
135 delscreen(SCREEN
*sp
)
139 T((T_CALLED("delscreen(%p)"), (void *) sp
));
141 _nc_lock_global(curses
);
142 if (delink_screen(sp
)) {
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
;
150 (void) delwin(rop
->win
);
157 (void) _nc_freewin(CurScreen(sp
));
158 (void) _nc_freewin(NewScreen(sp
));
159 (void) _nc_freewin(StdScreen(sp
));
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
);
173 _nc_free_keytry(sp
->_keytry
);
176 _nc_free_keytry(sp
->_key_ok
);
179 FreeIfNeeded(sp
->_current_attr
);
181 FreeIfNeeded(sp
->_color_table
);
182 FreeIfNeeded(sp
->_color_pairs
);
184 FreeIfNeeded(sp
->oldhash
);
185 FreeIfNeeded(sp
->newhash
);
186 FreeIfNeeded(sp
->hashtab
);
188 FreeIfNeeded(sp
->_acs_map
);
189 FreeIfNeeded(sp
->_screen_acs_map
);
191 NCURSES_SP_NAME(_nc_flush
) (NCURSES_SP_ARG
);
192 NCURSES_SP_NAME(del_curterm
) (NCURSES_SP_ARGx sp
->_term
);
193 FreeIfNeeded(sp
->out_buffer
);
197 * If this was the current screen, reset everything that the
198 * application might try to use (except cur_term, which may have
199 * multiple references in different screens).
201 if (sp
== CURRENT_SCREEN
) {
210 #if USE_WIDEC_SUPPORT
212 FreeIfNeeded(_nc_wacs
);
218 _nc_unlock_global(curses
);
224 no_mouse_event(SCREEN
*sp GCC_UNUSED
)
230 no_mouse_inline(SCREEN
*sp GCC_UNUSED
)
236 no_mouse_parse(SCREEN
*sp GCC_UNUSED
, int code GCC_UNUSED
)
242 no_mouse_resume(SCREEN
*sp GCC_UNUSED
)
247 no_mouse_wrap(SCREEN
*sp GCC_UNUSED
)
251 #if NCURSES_EXT_FUNCS && USE_COLORFGBG
253 extract_fgbg(const char *src
, int *result
)
257 long value
= strtol(src
, &tmp
, 0);
259 if ((dst
= tmp
) == 0) {
261 } else if (value
>= 0) {
264 while (*dst
!= 0 && *dst
!= ';')
272 #define ReturnScreenError() do { _nc_set_screen(0); \
273 returnCode(ERR); } while (0)
275 /* OS-independent screen initializations */
277 NCURSES_SP_NAME(_nc_setupscreen
) (
288 int bottom_stolen
= 0;
291 #ifndef USE_TERM_DRIVER
292 bool support_cookies
= USE_XMC_SUPPORT
;
295 T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"),
296 slines
, scolumns
, (void *) output
, filtered
, slk_format
));
298 assert(CURRENT_SCREEN
== 0); /* has been reset in newterm() ! */
305 sp
= _nc_alloc_screen_sp();
309 || ((sp
->_acs_map
= typeCalloc(chtype
, ACS_LEN
)) == 0)
310 || ((sp
->_screen_acs_map
= typeCalloc(bool, ACS_LEN
)) == 0)) {
314 T(("created SP %p", (void *) sp
));
315 sp
->_next_screen
= _nc_screen_chain
;
316 _nc_screen_chain
= sp
;
318 if ((sp
->_current_attr
= typeCalloc(NCURSES_CH_T
, 1)) == 0) {
322 if (!_nc_alloc_screen()
323 || ((SP
->_acs_map
= typeCalloc(chtype
, ACS_LEN
)) == 0)
324 || ((SP
->_screen_acs_map
= typeCalloc(bool, ACS_LEN
)) == 0)) {
328 T(("created SP %p", (void *) SP
));
330 sp
= SP
; /* fixup so SET_LINES and SET_COLS works */
331 sp
->_next_screen
= _nc_screen_chain
;
332 _nc_screen_chain
= sp
;
334 if ((sp
->_current_attr
= typeCalloc(NCURSES_CH_T
, 1)) == 0)
339 * We should always check the screensize, just in case.
342 sp
->_term
= cur_term
;
343 #ifdef USE_TERM_DRIVER
345 _nc_get_screensize(sp
, sp
->_term
, &slines
, &scolumns
);
347 _nc_get_screensize(sp
, &slines
, &scolumns
);
352 T((T_CREATE("screen %s %dx%d"),
353 NCURSES_SP_NAME(termname
) (NCURSES_SP_ARG
), slines
, scolumns
));
355 sp
->_filtered
= filtered
;
357 /* implement filter mode */
361 #ifdef USE_TERM_DRIVER
362 CallDriver(sp
, td_setfilter
);
365 cursor_down
= parm_down_cursor
= 0;
367 cursor_up
= parm_up_cursor
= 0;
370 cursor_home
= carriage_return
;
372 T(("filter screensize %dx%d", slines
, scolumns
));
375 T(("setting output mode to binary"));
377 setmode(output
, O_BINARY
);
379 NCURSES_SP_NAME(_nc_set_buffer
) (NCURSES_SP_ARGx output
, TRUE
);
380 sp
->_lines
= (NCURSES_SIZE_T
) slines
;
381 sp
->_lines_avail
= (NCURSES_SIZE_T
) slines
;
382 sp
->_columns
= (NCURSES_SIZE_T
) scolumns
;
385 sp
->_ofd
= output
? fileno(output
) : -1;
387 sp
->out_limit
= (size_t) ((2 + slines
) * (6 + scolumns
));
388 if ((sp
->out_buffer
= malloc(sp
->out_limit
)) == 0)
395 #if NCURSES_EXT_FUNCS
396 sp
->_default_color
= FALSE
;
397 sp
->_has_sgr_39_49
= FALSE
;
400 * Set our assumption of the terminal's default foreground and background
401 * colors. The curs_color man-page states that we can assume that the
402 * background is black. The origin of this assumption appears to be
403 * terminals that displayed colored text, but no colored backgrounds, e.g.,
404 * the first colored terminals around 1980. More recent ones with better
405 * technology can display not only colored backgrounds, but all
406 * combinations. So a terminal might be something other than "white" on
407 * black (green/black looks monochrome too), but black on white or even
410 * White-on-black is the simplest thing to use for monochrome. Almost
411 * all applications that use color paint both text and background, so
412 * the distinction is moot. But a few do not - which is why we leave this
413 * configurable (a better solution is to use assume_default_colors() for
414 * the rare applications that do require that sort of appearance, since
415 * is appears that more users expect to be able to make a white-on-black
416 * or black-on-white display under control of the application than not).
418 #ifdef USE_ASSUMED_COLOR
419 sp
->_default_fg
= COLOR_WHITE
;
420 sp
->_default_bg
= COLOR_BLACK
;
422 sp
->_default_fg
= C_MASK
;
423 sp
->_default_bg
= C_MASK
;
427 * Allow those assumed/default color assumptions to be overridden at
430 if ((env
= getenv("NCURSES_ASSUMED_COLORS")) != 0) {
433 int count
= sscanf(env
, "%d%c%d%c", &fg
, &sep1
, &bg
, &sep2
);
435 sp
->_default_fg
= ((fg
>= 0 && fg
< MaxColors
) ? fg
: C_MASK
);
437 sp
->_default_bg
= ((bg
>= 0 && bg
< MaxColors
) ? bg
: C_MASK
);
439 TR(TRACE_CHARPUT
| TRACE_MOVE
,
440 ("from environment assumed fg=%d, bg=%d",
447 * If rxvt's $COLORFGBG variable is set, use it to specify the assumed
448 * default colors. Note that rxvt (mis)uses bold colors, equating a bold
449 * color to that value plus 8. We'll only use the non-bold color for now -
450 * decide later if it is worth having default attributes as well.
452 if (getenv("COLORFGBG") != 0) {
453 const char *p
= getenv("COLORFGBG");
454 TR(TRACE_CHARPUT
| TRACE_MOVE
, ("decoding COLORFGBG %s", p
));
455 p
= extract_fgbg(p
, &(sp
->_default_fg
));
456 p
= extract_fgbg(p
, &(sp
->_default_bg
));
457 if (*p
) /* assume rxvt was compiled with xpm support */
458 p
= extract_fgbg(p
, &(sp
->_default_bg
));
459 TR(TRACE_CHARPUT
| TRACE_MOVE
, ("decoded fg=%d, bg=%d",
460 sp
->_default_fg
, sp
->_default_bg
));
461 if (sp
->_default_fg
>= MaxColors
) {
462 if (set_a_foreground
!= ABSENT_STRING
463 && !strcmp(set_a_foreground
, "\033[3%p1%dm")) {
464 set_a_foreground
= strdup("\033[3%?%p1%{8}%>%t9%e%p1%d%;m");
466 sp
->_default_fg
%= MaxColors
;
469 if (sp
->_default_bg
>= MaxColors
) {
470 if (set_a_background
!= ABSENT_STRING
471 && !strcmp(set_a_background
, "\033[4%p1%dm")) {
472 set_a_background
= strdup("\033[4%?%p1%{8}%>%t9%e%p1%d%;m");
474 sp
->_default_bg
%= MaxColors
;
479 #endif /* NCURSES_EXT_FUNCS */
481 sp
->_maxclick
= DEFAULT_MAXCLICK
;
482 sp
->_mouse_event
= no_mouse_event
;
483 sp
->_mouse_inline
= no_mouse_inline
;
484 sp
->_mouse_parse
= no_mouse_parse
;
485 sp
->_mouse_resume
= no_mouse_resume
;
486 sp
->_mouse_wrap
= no_mouse_wrap
;
490 * If we've no magic cookie support, we suppress attributes that xmc would
491 * affect, i.e., the attributes that affect the rendition of a space.
493 sp
->_ok_attributes
= NCURSES_SP_NAME(termattrs
) (NCURSES_SP_ARG
);
494 if (NCURSES_SP_NAME(has_colors
) (NCURSES_SP_ARG
)) {
495 sp
->_ok_attributes
|= A_COLOR
;
497 #ifdef USE_TERM_DRIVER
502 * If we have no magic-cookie support compiled-in, or if it is suppressed
503 * in the environment, reset the support-flag.
505 if (magic_cookie_glitch
>= 0) {
506 if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) {
507 support_cookies
= FALSE
;
512 if (!support_cookies
&& magic_cookie_glitch
>= 0) {
513 T(("will disable attributes to work w/o magic cookies"));
516 if (magic_cookie_glitch
> 0) { /* tvi, wyse */
518 sp
->_xmc_triggers
= sp
->_ok_attributes
& XMC_CONFLICT
;
521 * We "should" treat colors as an attribute. The wyse350 (and its
522 * clones) appear to be the only ones that have both colors and magic
526 sp
->_xmc_triggers
|= A_COLOR
;
529 sp
->_xmc_suppress
= sp
->_xmc_triggers
& (chtype
) ~(A_BOLD
);
531 T(("magic cookie attributes %s", _traceattr(sp
->_xmc_suppress
)));
533 * Supporting line-drawing may be possible. But make the regular
534 * video attributes work first.
536 acs_chars
= ABSENT_STRING
;
537 ena_acs
= ABSENT_STRING
;
538 enter_alt_charset_mode
= ABSENT_STRING
;
539 exit_alt_charset_mode
= ABSENT_STRING
;
542 * To keep the cookie support simple, suppress all of the optimization
543 * hooks except for clear_screen and the cursor addressing.
545 if (support_cookies
) {
546 clr_eol
= ABSENT_STRING
;
547 clr_eos
= ABSENT_STRING
;
548 set_attributes
= ABSENT_STRING
;
551 } else if (magic_cookie_glitch
== 0) { /* hpterm */
555 * If magic cookies are not supported, cancel the strings that set
558 if (!support_cookies
&& magic_cookie_glitch
>= 0) {
559 magic_cookie_glitch
= ABSENT_NUMERIC
;
560 set_attributes
= ABSENT_STRING
;
561 enter_blink_mode
= ABSENT_STRING
;
562 enter_bold_mode
= ABSENT_STRING
;
563 enter_dim_mode
= ABSENT_STRING
;
564 enter_reverse_mode
= ABSENT_STRING
;
565 enter_standout_mode
= ABSENT_STRING
;
566 enter_underline_mode
= ABSENT_STRING
;
569 /* initialize normal acs before wide, since we use mapping in the latter */
570 #if !USE_WIDEC_SUPPORT
571 if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp
->_term
)) {
574 enter_alt_charset_mode
= NULL
;
575 exit_alt_charset_mode
= NULL
;
576 set_attributes
= NULL
;
581 NCURSES_SP_NAME(_nc_init_acs
) (NCURSES_SP_ARG
);
582 #if USE_WIDEC_SUPPORT
583 sp
->_screen_unicode
= _nc_unicode_locale();
591 sp
->_screen_acs_fix
= (sp
->_screen_unicode
592 && _nc_locale_breaks_acs(sp
->_term
));
594 env
= _nc_get_locale();
595 sp
->_legacy_coding
= ((env
== 0)
597 || !strcmp(env
, "POSIX"));
598 T(("legacy-coding %d", sp
->_legacy_coding
));
600 sp
->_nc_sp_idcok
= TRUE
;
601 sp
->_nc_sp_idlok
= FALSE
;
606 T(("creating newscr"));
607 NewScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx slines
, scolumns
,
609 if (NewScreen(sp
) == 0) {
612 T(("creating curscr"));
613 CurScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx slines
, scolumns
,
615 if (CurScreen(sp
) == 0) {
619 newscr
= NewScreen(sp
);
620 curscr
= CurScreen(sp
);
623 sp
->_resize
= NCURSES_SP_NAME(resizeterm
);
624 sp
->_ungetch
= safe_ungetch
;
627 NewScreen(sp
)->_clear
= TRUE
;
628 CurScreen(sp
)->_clear
= FALSE
;
630 NCURSES_SP_NAME(def_shell_mode
) (NCURSES_SP_ARG
);
631 NCURSES_SP_NAME(def_prog_mode
) (NCURSES_SP_ARG
);
633 if (safe_ripoff_sp
&& safe_ripoff_sp
!= safe_ripoff_stack
) {
634 for (rop
= safe_ripoff_stack
;
635 rop
!= safe_ripoff_sp
&& (rop
- safe_ripoff_stack
) < N_RIPS
;
638 /* If we must simulate soft labels, grab off the line to be used.
639 We assume that we must simulate, if it is none of the standard
640 formats (4-4 or 3-2-3) for which there may be some hardware
642 if (rop
->hook
== _nc_slk_initialize
) {
643 if (!(NumLabels
<= 0 || !SLK_STDFMT(slk_format
))) {
651 count
= (rop
->line
< 0) ? -rop
->line
: rop
->line
;
652 T(("ripping off %i lines at %s", count
,
657 w
= NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx
660 ? sp
->_lines_avail
- count
665 rop
->hook(w
, scolumns
);
670 bottom_stolen
+= count
;
672 sp
->_topstolen
= (NCURSES_SIZE_T
) (sp
->_topstolen
+ count
);
674 sp
->_lines_avail
= (NCURSES_SIZE_T
) (sp
->_lines_avail
- count
);
677 /* reset the stack */
678 safe_ripoff_sp
= safe_ripoff_stack
;
681 T(("creating stdscr"));
682 assert((sp
->_lines_avail
+ sp
->_topstolen
+ bottom_stolen
) == slines
);
683 if ((StdScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx
685 scolumns
, 0, 0)) == 0) {
688 SET_LINES(sp
->_lines_avail
);
690 stdscr
= StdScreen(sp
);
692 sp
->_prescreen
= FALSE
;
698 _nc_setupscreen(int slines GCC_UNUSED
,
699 int scolumns GCC_UNUSED
,
705 int rc
= NCURSES_SP_NAME(_nc_setupscreen
) (&sp
,
718 * The internal implementation interprets line as the number of lines to rip
719 * off from the top or bottom.
722 NCURSES_SP_NAME(_nc_ripoffline
) (NCURSES_SP_DCLx
724 int (*init
) (WINDOW
*, int))
729 T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM
, line
, init
));
732 if (SP_PARM
!= 0 && SP_PARM
->_prescreen
)
738 if (safe_ripoff_sp
== 0)
739 safe_ripoff_sp
= safe_ripoff_stack
;
740 if (safe_ripoff_sp
< safe_ripoff_stack
+ N_RIPS
) {
741 safe_ripoff_sp
->line
= line
;
742 safe_ripoff_sp
->hook
= init
;
754 _nc_ripoffline(int line
, int (*init
) (WINDOW
*, int))
756 return NCURSES_SP_NAME(_nc_ripoffline
) (CURRENT_SCREEN_PRE
, line
, init
);
761 NCURSES_SP_NAME(ripoffline
) (NCURSES_SP_DCLx
763 int (*init
) (WINDOW
*, int))
766 return NCURSES_SP_NAME(_nc_ripoffline
) (NCURSES_SP_ARGx
773 ripoffline(int line
, int (*init
) (WINDOW
*, int))
775 return NCURSES_SP_NAME(ripoffline
) (CURRENT_SCREEN_PRE
, line
, init
);