X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_setup.c;h=eb8dff76e99a3cdb09582f1059736fd4d162d3fd;hp=05caca22dcb7dd1ad8a44b8f43296b1eb139f71c;hb=78e49873c69dc0494bb34c62f897f8b446584a33;hpb=a8987e73ec254703634802b4f7ee30d3a485524d diff --git a/ncurses/tinfo/lib_setup.c b/ncurses/tinfo/lib_setup.c index 05caca22..eb8dff76 100644 --- a/ncurses/tinfo/lib_setup.c +++ b/ncurses/tinfo/lib_setup.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. * + * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-2003 * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -47,9 +48,13 @@ #define _POSIX_SOURCE #endif +#if HAVE_LOCALE_H +#include +#endif + #include /* lines, columns, cur_term */ -MODULE_ID("$Id: lib_setup.c,v 1.79 2003/12/27 18:24:26 tom Exp $") +MODULE_ID("$Id: lib_setup.c,v 1.113 2009/02/14 22:21:40 tom Exp $") /**************************************************************************** * @@ -73,6 +78,10 @@ MODULE_ID("$Id: lib_setup.c,v 1.79 2003/12/27 18:24:26 tom Exp $") # include #endif +#if HAVE_LANGINFO_CODESET +#include +#endif + /* * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, * Solaris, IRIX) define TIOCGWINSZ and struct winsize. @@ -91,29 +100,134 @@ MODULE_ID("$Id: lib_setup.c,v 1.79 2003/12/27 18:24:26 tom Exp $") # endif #endif +/* + * Reduce explicit use of "cur_term" global variable. + */ +#undef CUR +#define CUR termp->type. + +/* + * Wrap global variables in this module. + */ +#if USE_REENTRANT +NCURSES_EXPORT(char *) +NCURSES_PUBLIC_VAR(ttytype) (void) +{ + static char empty[] = ""; + return cur_term ? cur_term->type.term_names : empty; +} +NCURSES_EXPORT(int *) +_nc_ptr_Lines(void) +{ + return ptrLines(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(LINES) (void) +{ + return *_nc_ptr_Lines(); +} +NCURSES_EXPORT(int *) +_nc_ptr_Cols(void) +{ + return ptrCols(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(COLS) (void) +{ + return *_nc_ptr_Cols(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(TABSIZE) (void) +{ + return SP ? SP->_TABSIZE : 8; +} +#else NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = ""; NCURSES_EXPORT_VAR(int) LINES = 0; NCURSES_EXPORT_VAR(int) COLS = 0; NCURSES_EXPORT_VAR(int) TABSIZE = 0; +#endif + +#if NCURSES_EXT_FUNCS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(set_tabsize) (NCURSES_SP_DCLx int value) +{ + int code = OK; +#if USE_REENTRANT + if (SP_PARM) { + SP_PARM->_TABSIZE = value; + } else { + code = ERR; + } +#else + (void) SP_PARM; + TABSIZE = value; +#endif + return code; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +set_tabsize(int value) +{ + return NCURSES_SP_NAME(set_tabsize) (CURRENT_SCREEN, value); +} +#endif +#endif /* NCURSES_EXT_FUNCS */ + +#if USE_SIGWINCH +/* + * If we have a pending SIGWINCH, set the flag in each screen. + */ +NCURSES_EXPORT(int) +_nc_handle_sigwinch(SCREEN *sp) +{ + SCREEN *scan; + + if (_nc_globals.have_sigwinch) { + _nc_globals.have_sigwinch = 0; + + for (each_screen(scan)) { + scan->_sig_winch = TRUE; + } + } + + return (sp ? sp->_sig_winch : 0); +} -static int _use_env = TRUE; +#endif NCURSES_EXPORT(void) -use_env(bool f) +NCURSES_SP_NAME(use_env) (NCURSES_SP_DCLx bool f) { T((T_CALLED("use_env()"))); - _use_env = f; + if (IsPreScreen(SP_PARM)) { + SP_PARM->_use_env = f; + } else { + _nc_prescreen.use_env = f; + } returnVoid; } -static void -_nc_get_screensize(int *linep, int *colp) +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +use_env(bool f) +{ + NCURSES_SP_NAME(use_env) (CURRENT_SCREEN, f); +} +#endif + +NCURSES_EXPORT(void) +_nc_get_screensize(SCREEN *sp, int *linep, int *colp) /* Obtain lines/columns values from the environment and/or terminfo entry */ { + TERMINAL *termp = cur_term; + int my_tabsize; + /* figure out the size of the screen */ T(("screen size: terminfo lines = %d columns = %d", lines, columns)); - if (!_use_env) { + if (!_nc_prescreen.use_env) { *linep = (int) lines; *colp = (int) columns; } else { /* usually want to query LINES and COLUMNS from environment */ @@ -159,7 +273,7 @@ _nc_get_screensize(int *linep, int *colp) * environment variable. */ if (*linep <= 0) - *linep = WINSIZE_ROWS(size); + *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size); if (*colp <= 0) *colp = WINSIZE_COLS(size); } @@ -195,21 +309,42 @@ _nc_get_screensize(int *linep, int *colp) T(("screen size is %dx%d", *linep, *colp)); if (VALID_NUMERIC(init_tabs)) - TABSIZE = (int) init_tabs; + my_tabsize = (int) init_tabs; else - TABSIZE = 8; + my_tabsize = 8; + +#if USE_REENTRANT + if (sp != 0) + sp->_TABSIZE = my_tabsize; +#else + TABSIZE = my_tabsize; +#endif T(("TABSIZE = %d", TABSIZE)); } #if USE_SIZECHANGE NCURSES_EXPORT(void) -_nc_update_screensize(void) +_nc_update_screensize(SCREEN *sp) { - int my_lines, my_cols; + TERMINAL *termp = cur_term; + int old_lines = lines; + int new_lines; + int old_cols = columns; + int new_cols; + + _nc_get_screensize(sp, &new_lines, &new_cols); - _nc_get_screensize(&my_lines, &my_cols); - if (SP != 0 && SP->_resize != 0) - SP->_resize(my_lines, my_cols); + /* + * See is_term_resized() and resizeterm(). + * We're doing it this way because those functions belong to the upper + * ncurses library, while this resides in the lower terminfo library. + */ + if (sp != 0 + && sp->_resize != 0) { + if ((new_lines != old_lines) || (new_cols != old_cols)) + sp->_resize(new_lines, new_cols); + sp->_sig_winch = FALSE; + } } #endif @@ -236,38 +371,15 @@ _nc_update_screensize(void) } #if USE_DATABASE || USE_TERMCAP +/* + * Return 1 if entry found, 0 if not found, -1 if database not accessible, + * just like tgetent(). + */ static int -grab_entry(const char *const tn, TERMTYPE * const tp) -/* return 1 if entry found, 0 if not found, -1 if database not accessible */ +grab_entry(const char *const tn, TERMTYPE *const tp) { -#if USE_DATABASE char filename[PATH_MAX]; -#endif - int status; - - /* - * $TERM shouldn't contain pathname delimiters. - */ - if (strchr(tn, '/')) - return 0; - -#if USE_DATABASE - if ((status = _nc_read_entry(tn, filename, tp)) != 1) { - -#if !PURE_TERMINFO - /* - * Try falling back on the termcap file. - * Note: allowing this call links the entire terminfo/termcap - * compiler into the startup code. It's preferable to build a - * real terminfo database and use that. - */ - status = _nc_read_termcap_entry(tn, tp); -#endif /* PURE_TERMINFO */ - - } -#else - status = _nc_read_termcap_entry(tn, tp); -#endif + int status = _nc_read_entry(tn, filename, tp); /* * If we have an entry, force all of the cancelled strings to null @@ -275,7 +387,7 @@ grab_entry(const char *const tn, TERMTYPE * const tp) * (The terminfo compiler bypasses this logic, since it must know if * a string is cancelled, for merging entries). */ - if (status == 1) { + if (status == TGETENT_YES) { unsigned n; for_each_boolean(n, tp) { if (!VALID_BOOLEAN(tp->Booleans[n])) @@ -295,41 +407,51 @@ grab_entry(const char *const tn, TERMTYPE * const tp) ** ** Take the real command character out of the CC environment variable ** and substitute it in for the prototype given in 'command_character'. -** */ static void -do_prototype(void) +do_prototype(TERMINAL * termp) { - int i; + unsigned i; char CC; char proto; char *tmp; - tmp = getenv("CC"); - CC = *tmp; - proto = *command_character; + if ((tmp = getenv("CC")) != 0) { + if ((CC = *tmp) != 0) { + proto = *command_character; - for_each_string(i, &(cur_term->type)) { - for (tmp = cur_term->type.Strings[i]; *tmp; tmp++) { - if (*tmp == proto) - *tmp = CC; + for_each_string(i, &(termp->type)) { + for (tmp = termp->type.Strings[i]; *tmp; tmp++) { + if (*tmp == proto) + *tmp = CC; + } + } } } } /* - * Check if we are running in a UTF-8 locale. + * Find the locale which is in effect. */ NCURSES_EXPORT(char *) _nc_get_locale(void) { char *env; +#if HAVE_LOCALE_H + /* + * This is preferable to using getenv() since it ensures that we are using + * the locale which was actually initialized by the application. + */ + env = setlocale(LC_CTYPE, 0); +#else if (((env = getenv("LC_ALL")) != 0 && *env != '\0') || ((env = getenv("LC_CTYPE")) != 0 && *env != '\0') || ((env = getenv("LANG")) != 0 && *env != '\0')) { - return env; + ; } - return 0; +#endif + T(("_nc_get_locale %s", _nc_visbuf(env))); + return env; } /* @@ -338,46 +460,62 @@ _nc_get_locale(void) NCURSES_EXPORT(int) _nc_unicode_locale(void) { + int result = 0; +#if HAVE_LANGINFO_CODESET + char *env = nl_langinfo(CODESET); + result = !strcmp(env, "UTF-8"); + T(("_nc_unicode_locale(%s) ->%d", env, result)); +#else char *env = _nc_get_locale(); if (env != 0) { - if (strstr(env, ".UTF-8") != 0) - return 1; + if (strstr(env, ".UTF-8") != 0) { + result = 1; + T(("_nc_unicode_locale(%s) ->%d", env, result)); + } } - return 0; +#endif + return result; } +#define CONTROL_N(s) ((s) != 0 && strstr(s, "\016") != 0) +#define CONTROL_O(s) ((s) != 0 && strstr(s, "\017") != 0) + /* * Check for known broken cases where a UTF-8 locale breaks the alternate * character set. */ NCURSES_EXPORT(int) -_nc_locale_breaks_acs(void) +_nc_locale_breaks_acs(TERMINAL * termp) { - char *env = getenv("TERM"); - if (env != 0) { + char *env; + + if ((env = getenv("NCURSES_NO_UTF8_ACS")) != 0) { + return atoi(env); + } else if ((env = getenv("TERM")) != 0) { if (strstr(env, "linux")) return 1; /* always broken */ if (strstr(env, "screen") != 0 && ((env = getenv("TERMCAP")) != 0 && strstr(env, "screen") != 0) && strstr(env, "hhII00") != 0) { - return 1; + if (CONTROL_N(enter_alt_charset_mode) || + CONTROL_O(enter_alt_charset_mode) || + CONTROL_N(set_attributes) || + CONTROL_O(set_attributes)) + return 1; } } return 0; } /* - * setupterm(termname, Filedes, errret) - * - * Find and read the appropriate object file for the terminal - * Make cur_term point to the structure. - * + * This entrypoint is called from tgetent() to allow a special case of reusing + * the same TERMINAL data (see comment). */ - NCURSES_EXPORT(int) -setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) +_nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) { + TERMINAL *termp; int status; START_TRACE(); @@ -386,11 +524,13 @@ setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) if (tname == 0) { tname = getenv("TERM"); if (tname == 0 || *tname == '\0') { - ret_error0(-1, "TERM environment variable not set.\n"); + ret_error0(TGETENT_ERR, "TERM environment variable not set.\n"); } } + if (strlen(tname) > MAX_NAME_SIZE) { - ret_error(-1, "TERM environment must be <= %d characters.\n", + ret_error(TGETENT_ERR, + "TERM environment must be <= %d characters.\n", MAX_NAME_SIZE); } @@ -419,56 +559,57 @@ setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) * however applications that are working around the problem will still work * properly with this feature). */ - if (cur_term != 0 - && cur_term->Filedes == Filedes - && cur_term->_termname != 0 - && !strcmp(cur_term->_termname, tname) - && _nc_name_match(cur_term->type.term_names, tname, "|")) { + if (reuse + && (termp = cur_term) != 0 + && termp->Filedes == Filedes + && termp->_termname != 0 + && !strcmp(termp->_termname, tname) + && _nc_name_match(termp->type.term_names, tname, "|")) { T(("reusing existing terminal information and mode-settings")); } else { - TERMINAL *term_ptr; - term_ptr = typeCalloc(TERMINAL, 1); + termp = typeCalloc(TERMINAL, 1); - if (term_ptr == 0) { - ret_error0(-1, + if (termp == 0) { + ret_error0(TGETENT_ERR, "Not enough memory to create terminal structure.\n"); } #if USE_DATABASE || USE_TERMCAP - status = grab_entry(tname, &term_ptr->type); + status = grab_entry(tname, &termp->type); #else - status = 0; + status = TGETENT_NO; #endif /* try fallback list if entry on disk */ - if (status != 1) { + if (status != TGETENT_YES) { const TERMTYPE *fallback = _nc_fallback(tname); if (fallback) { - term_ptr->type = *fallback; - status = 1; + termp->type = *fallback; + status = TGETENT_YES; } } - if (status <= 0) { - del_curterm(term_ptr); - if (status == -1) { - ret_error0(-1, "terminals database is inaccessible\n"); - } else if (status == 0) { - ret_error(0, "'%s': unknown terminal type.\n", tname); + if (status != TGETENT_YES) { + del_curterm(termp); + if (status == TGETENT_ERR) { + ret_error0(status, "terminals database is inaccessible\n"); + } else if (status == TGETENT_NO) { + ret_error(status, "'%s': unknown terminal type.\n", tname); } } +#if !USE_REENTRANT + strncpy(ttytype, termp->type.term_names, NAMESIZE - 1); + ttytype[NAMESIZE - 1] = '\0'; +#endif - set_curterm(term_ptr); - - if (command_character && getenv("CC")) - do_prototype(); + termp->Filedes = Filedes; + termp->_termname = strdup(tname); - strncpy(ttytype, cur_term->type.term_names, NAMESIZE - 1); - ttytype[NAMESIZE - 1] = '\0'; + set_curterm(termp); - cur_term->Filedes = Filedes; - cur_term->_termname = strdup(tname); + if (command_character && getenv("CC")) + do_prototype(termp); /* * If an application calls setupterm() rather than initscr() or @@ -485,18 +626,28 @@ setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) /* * We should always check the screensize, just in case. */ - _nc_get_screensize(&LINES, &COLS); + _nc_get_screensize(SP, ptrLines(), ptrCols()); if (errret) - *errret = 1; - - T((T_CREATE("screen %s %dx%d"), tname, LINES, COLS)); + *errret = TGETENT_YES; if (generic_type) { - ret_error(0, "'%s': I need something more specific.\n", tname); + ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname); } if (hard_copy) { - ret_error(1, "'%s': I can't handle hardcopy terminals.\n", tname); + ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname); } returnCode(OK); } + +/* + * setupterm(termname, Filedes, errret) + * + * Find and read the appropriate object file for the terminal + * Make cur_term point to the structure. + */ +NCURSES_EXPORT(int) +setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) +{ + return _nc_setupterm(tname, Filedes, errret, FALSE); +}