1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 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.138 2010/12/20 00:42:20 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
);
192 * If the associated output stream has been closed, we can discard the
193 * set-buffer. Limit the error check to EBADF, since fflush may fail
194 * for other reasons than trying to operate upon a closed stream.
198 && fflush(sp
->_ofp
) != 0
203 NCURSES_SP_NAME(del_curterm
) (NCURSES_SP_ARGx sp
->_term
);
207 * If this was the current screen, reset everything that the
208 * application might try to use (except cur_term, which may have
209 * multiple references in different screens).
211 if (sp
== CURRENT_SCREEN
) {
222 _nc_unlock_global(curses
);
228 no_mouse_event(SCREEN
*sp GCC_UNUSED
)
234 no_mouse_inline(SCREEN
*sp GCC_UNUSED
)
240 no_mouse_parse(SCREEN
*sp GCC_UNUSED
, int code GCC_UNUSED
)
246 no_mouse_resume(SCREEN
*sp GCC_UNUSED
)
251 no_mouse_wrap(SCREEN
*sp GCC_UNUSED
)
255 #if NCURSES_EXT_FUNCS && USE_COLORFGBG
257 extract_fgbg(char *src
, int *result
)
260 long value
= strtol(src
, &dst
, 0);
264 } else if (value
>= 0) {
267 while (*dst
!= 0 && *dst
!= ';')
275 #define ReturnScreenError() _nc_set_screen(0); \
278 /* OS-independent screen initializations */
280 NCURSES_SP_NAME(_nc_setupscreen
) (
291 int bottom_stolen
= 0;
294 #ifndef USE_TERM_DRIVER
295 bool support_cookies
= USE_XMC_SUPPORT
;
298 T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"),
299 slines
, scolumns
, (void *) output
, filtered
, slk_format
));
301 assert(CURRENT_SCREEN
== 0); /* has been reset in newterm() ! */
308 sp
= _nc_alloc_screen_sp();
312 || ((sp
->_acs_map
= typeCalloc(chtype
, ACS_LEN
)) == 0)
313 || ((sp
->_screen_acs_map
= typeCalloc(bool, ACS_LEN
)) == 0)) {
317 T(("created SP %p", (void *) sp
));
318 sp
->_next_screen
= _nc_screen_chain
;
319 _nc_screen_chain
= sp
;
321 if ((sp
->_current_attr
= typeCalloc(NCURSES_CH_T
, 1)) == 0) {
325 if (!_nc_alloc_screen()
326 || ((SP
->_acs_map
= typeCalloc(chtype
, ACS_LEN
)) == 0)
327 || ((SP
->_screen_acs_map
= typeCalloc(bool, ACS_LEN
)) == 0)) {
331 T(("created SP %p", (void *) SP
));
333 sp
= SP
; /* fixup so SET_LINES and SET_COLS works */
334 sp
->_next_screen
= _nc_screen_chain
;
335 _nc_screen_chain
= sp
;
337 if ((sp
->_current_attr
= typeCalloc(NCURSES_CH_T
, 1)) == 0)
342 * We should always check the screensize, just in case.
345 sp
->_term
= cur_term
;
346 #ifdef USE_TERM_DRIVER
348 _nc_get_screensize(sp
, sp
->_term
, &slines
, &scolumns
);
350 _nc_get_screensize(sp
, &slines
, &scolumns
);
355 T((T_CREATE("screen %s %dx%d"),
356 NCURSES_SP_NAME(termname
) (NCURSES_SP_ARG
), slines
, scolumns
));
358 sp
->_filtered
= filtered
;
360 /* implement filter mode */
364 #ifdef USE_TERM_DRIVER
365 CallDriver(sp
, setfilter
);
368 cursor_down
= parm_down_cursor
= 0;
370 cursor_up
= parm_up_cursor
= 0;
373 cursor_home
= carriage_return
;
375 T(("filter screensize %dx%d", slines
, scolumns
));
378 T(("setting output mode to binary"));
380 setmode(output
, O_BINARY
);
382 NCURSES_SP_NAME(_nc_set_buffer
) (NCURSES_SP_ARGx output
, TRUE
);
383 sp
->_lines
= (NCURSES_SIZE_T
) slines
;
384 sp
->_lines_avail
= (NCURSES_SIZE_T
) slines
;
385 sp
->_columns
= (NCURSES_SIZE_T
) scolumns
;
390 #if NCURSES_EXT_FUNCS
391 sp
->_default_color
= FALSE
;
392 sp
->_has_sgr_39_49
= FALSE
;
395 * Set our assumption of the terminal's default foreground and background
396 * colors. The curs_color man-page states that we can assume that the
397 * background is black. The origin of this assumption appears to be
398 * terminals that displayed colored text, but no colored backgrounds, e.g.,
399 * the first colored terminals around 1980. More recent ones with better
400 * technology can display not only colored backgrounds, but all
401 * combinations. So a terminal might be something other than "white" on
402 * black (green/black looks monochrome too), but black on white or even
405 * White-on-black is the simplest thing to use for monochrome. Almost
406 * all applications that use color paint both text and background, so
407 * the distinction is moot. But a few do not - which is why we leave this
408 * configurable (a better solution is to use assume_default_colors() for
409 * the rare applications that do require that sort of appearance, since
410 * is appears that more users expect to be able to make a white-on-black
411 * or black-on-white display under control of the application than not).
413 #ifdef USE_ASSUMED_COLOR
414 sp
->_default_fg
= COLOR_WHITE
;
415 sp
->_default_bg
= COLOR_BLACK
;
417 sp
->_default_fg
= C_MASK
;
418 sp
->_default_bg
= C_MASK
;
422 * Allow those assumed/default color assumptions to be overridden at
425 if ((env
= getenv("NCURSES_ASSUMED_COLORS")) != 0) {
428 int count
= sscanf(env
, "%d%c%d%c", &fg
, &sep1
, &bg
, &sep2
);
430 sp
->_default_fg
= ((fg
>= 0 && fg
< MaxColors
) ? fg
: C_MASK
);
432 sp
->_default_bg
= ((bg
>= 0 && bg
< MaxColors
) ? bg
: C_MASK
);
434 TR(TRACE_CHARPUT
| TRACE_MOVE
,
435 ("from environment assumed fg=%d, bg=%d",
442 * If rxvt's $COLORFGBG variable is set, use it to specify the assumed
443 * default colors. Note that rxvt (mis)uses bold colors, equating a bold
444 * color to that value plus 8. We'll only use the non-bold color for now -
445 * decide later if it is worth having default attributes as well.
447 if (getenv("COLORFGBG") != 0) {
448 char *p
= getenv("COLORFGBG");
449 TR(TRACE_CHARPUT
| TRACE_MOVE
, ("decoding COLORFGBG %s", p
));
450 p
= extract_fgbg(p
, &(sp
->_default_fg
));
451 p
= extract_fgbg(p
, &(sp
->_default_bg
));
452 if (*p
) /* assume rxvt was compiled with xpm support */
453 p
= extract_fgbg(p
, &(sp
->_default_bg
));
454 TR(TRACE_CHARPUT
| TRACE_MOVE
, ("decoded fg=%d, bg=%d",
455 sp
->_default_fg
, sp
->_default_bg
));
456 if (sp
->_default_fg
>= MaxColors
) {
457 if (set_a_foreground
!= ABSENT_STRING
458 && !strcmp(set_a_foreground
, "\033[3%p1%dm")) {
459 set_a_foreground
= "\033[3%?%p1%{8}%>%t9%e%p1%d%;m";
461 sp
->_default_fg
%= MaxColors
;
464 if (sp
->_default_bg
>= MaxColors
) {
465 if (set_a_background
!= ABSENT_STRING
466 && !strcmp(set_a_background
, "\033[4%p1%dm")) {
467 set_a_background
= "\033[4%?%p1%{8}%>%t9%e%p1%d%;m";
469 sp
->_default_bg
%= MaxColors
;
474 #endif /* NCURSES_EXT_FUNCS */
476 sp
->_maxclick
= DEFAULT_MAXCLICK
;
477 sp
->_mouse_event
= no_mouse_event
;
478 sp
->_mouse_inline
= no_mouse_inline
;
479 sp
->_mouse_parse
= no_mouse_parse
;
480 sp
->_mouse_resume
= no_mouse_resume
;
481 sp
->_mouse_wrap
= no_mouse_wrap
;
485 * If we've no magic cookie support, we suppress attributes that xmc would
486 * affect, i.e., the attributes that affect the rendition of a space.
488 sp
->_ok_attributes
= NCURSES_SP_NAME(termattrs
) (NCURSES_SP_ARG
);
489 if (NCURSES_SP_NAME(has_colors
) (NCURSES_SP_ARG
)) {
490 sp
->_ok_attributes
|= A_COLOR
;
492 #ifdef USE_TERM_DRIVER
497 * If we have no magic-cookie support compiled-in, or if it is suppressed
498 * in the environment, reset the support-flag.
500 if (magic_cookie_glitch
>= 0) {
501 if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) {
502 support_cookies
= FALSE
;
507 if (!support_cookies
&& magic_cookie_glitch
>= 0) {
508 T(("will disable attributes to work w/o magic cookies"));
511 if (magic_cookie_glitch
> 0) { /* tvi, wyse */
513 sp
->_xmc_triggers
= sp
->_ok_attributes
& (
525 * We "should" treat colors as an attribute. The wyse350 (and its
526 * clones) appear to be the only ones that have both colors and magic
530 sp
->_xmc_triggers
|= A_COLOR
;
533 sp
->_xmc_suppress
= sp
->_xmc_triggers
& (chtype
) ~(A_BOLD
);
535 T(("magic cookie attributes %s", _traceattr(sp
->_xmc_suppress
)));
537 * Supporting line-drawing may be possible. But make the regular
538 * video attributes work first.
540 acs_chars
= ABSENT_STRING
;
541 ena_acs
= ABSENT_STRING
;
542 enter_alt_charset_mode
= ABSENT_STRING
;
543 exit_alt_charset_mode
= ABSENT_STRING
;
546 * To keep the cookie support simple, suppress all of the optimization
547 * hooks except for clear_screen and the cursor addressing.
549 if (support_cookies
) {
550 clr_eol
= ABSENT_STRING
;
551 clr_eos
= ABSENT_STRING
;
552 set_attributes
= ABSENT_STRING
;
555 } else if (magic_cookie_glitch
== 0) { /* hpterm */
559 * If magic cookies are not supported, cancel the strings that set
562 if (!support_cookies
&& magic_cookie_glitch
>= 0) {
563 magic_cookie_glitch
= ABSENT_NUMERIC
;
564 set_attributes
= ABSENT_STRING
;
565 enter_blink_mode
= ABSENT_STRING
;
566 enter_bold_mode
= ABSENT_STRING
;
567 enter_dim_mode
= ABSENT_STRING
;
568 enter_reverse_mode
= ABSENT_STRING
;
569 enter_standout_mode
= ABSENT_STRING
;
570 enter_underline_mode
= ABSENT_STRING
;
573 /* initialize normal acs before wide, since we use mapping in the latter */
574 #if !USE_WIDEC_SUPPORT
575 if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp
->_term
)) {
578 enter_alt_charset_mode
= NULL
;
579 exit_alt_charset_mode
= NULL
;
580 set_attributes
= NULL
;
585 NCURSES_SP_NAME(_nc_init_acs
) (NCURSES_SP_ARG
);
586 #if USE_WIDEC_SUPPORT
589 sp
->_screen_acs_fix
= (_nc_unicode_locale()
590 && _nc_locale_breaks_acs(sp
->_term
));
592 env
= _nc_get_locale();
593 sp
->_legacy_coding
= ((env
== 0)
595 || !strcmp(env
, "POSIX"));
596 T(("legacy-coding %d", sp
->_legacy_coding
));
598 sp
->_nc_sp_idcok
= TRUE
;
599 sp
->_nc_sp_idlok
= FALSE
;
604 T(("creating newscr"));
605 NewScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx slines
, scolumns
,
607 if (NewScreen(sp
) == 0) {
610 T(("creating curscr"));
611 CurScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx slines
, scolumns
,
613 if (CurScreen(sp
) == 0) {
617 newscr
= NewScreen(sp
);
618 curscr
= CurScreen(sp
);
621 sp
->_resize
= NCURSES_SP_NAME(resizeterm
);
624 NewScreen(sp
)->_clear
= TRUE
;
625 CurScreen(sp
)->_clear
= FALSE
;
627 NCURSES_SP_NAME(def_shell_mode
) (NCURSES_SP_ARG
);
628 NCURSES_SP_NAME(def_prog_mode
) (NCURSES_SP_ARG
);
630 if (safe_ripoff_sp
&& safe_ripoff_sp
!= safe_ripoff_stack
) {
631 for (rop
= safe_ripoff_stack
;
632 rop
!= safe_ripoff_sp
&& (rop
- safe_ripoff_stack
) < N_RIPS
;
635 /* If we must simulate soft labels, grab off the line to be used.
636 We assume that we must simulate, if it is none of the standard
637 formats (4-4 or 3-2-3) for which there may be some hardware
639 if (rop
->hook
== _nc_slk_initialize
) {
640 if (!(NumLabels
<= 0 || !SLK_STDFMT(slk_format
))) {
648 count
= (rop
->line
< 0) ? -rop
->line
: rop
->line
;
649 T(("ripping off %i lines at %s", count
,
654 w
= NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx
657 ? sp
->_lines_avail
- count
662 rop
->hook(w
, scolumns
);
667 bottom_stolen
+= count
;
669 sp
->_topstolen
= (NCURSES_SIZE_T
) (sp
->_topstolen
+ count
);
671 sp
->_lines_avail
= (NCURSES_SIZE_T
) (sp
->_lines_avail
- count
);
674 /* reset the stack */
675 safe_ripoff_sp
= safe_ripoff_stack
;
678 T(("creating stdscr"));
679 assert((sp
->_lines_avail
+ sp
->_topstolen
+ bottom_stolen
) == slines
);
680 if ((StdScreen(sp
) = NCURSES_SP_NAME(newwin
) (NCURSES_SP_ARGx
682 scolumns
, 0, 0)) == 0) {
685 SET_LINES(sp
->_lines_avail
);
687 stdscr
= StdScreen(sp
);
689 sp
->_prescreen
= FALSE
;
695 _nc_setupscreen(int slines GCC_UNUSED
,
696 int scolumns GCC_UNUSED
,
702 int rc
= NCURSES_SP_NAME(_nc_setupscreen
) (&sp
,
715 * The internal implementation interprets line as the number of lines to rip
716 * off from the top or bottom.
719 NCURSES_SP_NAME(_nc_ripoffline
) (NCURSES_SP_DCLx
721 int (*init
) (WINDOW
*, int))
726 T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM
, line
, init
));
729 if (SP_PARM
!= 0 && SP_PARM
->_prescreen
)
735 if (safe_ripoff_sp
== 0)
736 safe_ripoff_sp
= safe_ripoff_stack
;
737 if (safe_ripoff_sp
< safe_ripoff_stack
+ N_RIPS
) {
738 safe_ripoff_sp
->line
= line
;
739 safe_ripoff_sp
->hook
= init
;
751 _nc_ripoffline(int line
, int (*init
) (WINDOW
*, int))
753 return NCURSES_SP_NAME(_nc_ripoffline
) (CURRENT_SCREEN_PRE
, line
, init
);
758 NCURSES_SP_NAME(ripoffline
) (NCURSES_SP_DCLx
760 int (*init
) (WINDOW
*, int))
762 return NCURSES_SP_NAME(_nc_ripoffline
) (NCURSES_SP_ARGx
769 ripoffline(int line
, int (*init
) (WINDOW
*, int))
771 return NCURSES_SP_NAME(ripoffline
) (CURRENT_SCREEN_PRE
, line
, init
);