From 53e865b65434fa9ec12afc11a076aec244cd3c43 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Wed, 1 Jun 2016 20:03:50 -0700 Subject: put curses/terminfo vars into the environment We need to actually export the curses/terminfo env vars in order for `setupterm()` to be able to use them. While fixing this I reworked the fallback logic implemented by @zanchey in response to issue #1060 in order to simplify the logic and clarify the error messages. This does not allow someone to change the curses/terminfo env vars after the first prompt is displayed (you can but it won't affect the current fish process). It only makes it possible to set `TERM`, `TERMINFO`, and `TERMINFO_DIRS` in *config.fish* or similar config file and have them be honored by fish. --- src/env.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- src/input.cpp | 33 +++++++++++---------------------- src/output.cpp | 13 +++---------- src/output.h | 6 ------ 4 files changed, 53 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/env.cpp b/src/env.cpp index e09064ad..71d85800 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -124,10 +124,15 @@ static null_terminated_array_t export_array; static bool has_changed_exported = true; static void mark_changed_exported() { has_changed_exported = true; } -/// List of all locale variable names. -static const wchar_t *const locale_variable[] = {L"LANG", L"LC_ALL", L"LC_COLLATE", - L"LC_CTYPE", L"LC_MESSAGES", L"LC_MONETARY", - L"LC_NUMERIC", L"LC_TIME", NULL}; +/// List of all locale environment variable names. +static const wchar_t *const locale_variable[] = { + L"LANG", L"LANGUAGE", L"LC_ALL", L"LC_ADDRESS", L"LC_COLLATE", + L"LC_CTYPE", L"LC_IDENTIFICATION", L"LC_MEASUREMENT", L"LC_MESSAGES", L"LC_MONETARY", + L"LC_NAME", L"LC_NUMERIC", L"LC_PAPER", L"LC_TELEPHONE", L"LC_TIME", + NULL}; + +/// List of all curses environment variable names. +static const wchar_t *const curses_variable[] = {L"TERM", L"TERMINFO", L"TERMINFO_DIRS", NULL}; const var_entry_t *env_node_t::find_entry(const wcstring &key) { const var_entry_t *result = NULL; @@ -200,10 +205,40 @@ static void handle_locale() { } } +/// Check if the specified variable is a locale variable. +static bool var_is_curses(const wcstring &key) { + for (size_t i = 0; curses_variable[i]; i++) { + if (key == curses_variable[i]) { + return true; + } + } + return false; +} + +/// Push all curses/terminfo env vars into the global environment where they can be found by those +/// libraries. +static void handle_curses() { + for (size_t i = 0; curses_variable[i]; i++) { + const wchar_t *key = curses_variable[i]; + const env_var_t var = env_get_string(key); + if (!var.empty()) { + const std::string &name = wcs2string(key); + const std::string &value = wcs2string(var); + setenv(name.c_str(), value.c_str(), 1); + } + } + // TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically + // changed. At the present time it can be called just once. Also, we should really only do this + // if the TERM var is set. + // input_init(); +} + /// React to modifying the given variable. static void react_to_variable_change(const wcstring &key) { if (var_is_locale(key)) { handle_locale(); + } else if (var_is_curses(key)) { + handle_curses(); } else if (key == L"fish_term256" || key == L"fish_term24bit") { update_fish_color_support(); reader_react_to_color_change(); diff --git a/src/input.cpp b/src/input.cpp index 5b599e85..b9132b2c 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1,7 +1,6 @@ // Functions for reading a character of input from stdin. #include "config.h" -#include #include #include #include @@ -339,35 +338,25 @@ void update_fish_color_support(void) { int input_init() { if (is_init) return 1; - is_init = true; - input_common_init(&interrupt_handler); - const env_var_t term = env_get_string(L"TERM"); - int errret; - if (setupterm(const_cast(wcs2string(term).c_str()), STDOUT_FILENO, &errret) == ERR) { - debug(0, _(L"Could not set up terminal")); - if (errret == 0) { - debug(0, _(L"Check that your terminal type, '%ls', is supported on this system"), - term.c_str()); - debug(0, _(L"Attempting to use '%ls' instead"), DEFAULT_TERM); - env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT); - const std::string default_term = wcs2string(DEFAULT_TERM); - if (setupterm(const_cast(default_term.c_str()), STDOUT_FILENO, &errret) == - ERR) { - debug(0, _(L"Could not set up terminal")); - exit_without_destructors(1); - } - } else { + int err_ret; + if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) { + env_var_t term = env_get_string(L"TERM"); + debug(0, _(L"Your TERM value of '%ls' is not valid"), term.c_str()); + debug(0, _(L"Check that your terminal type is supported on this system")); + env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT); + if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) { + debug(0, _(L"Unable to setup terminal using your TERM or the '%ls' fallback"), + DEFAULT_TERM); exit_without_destructors(1); + } else { + debug(0, _(L"Using fallback terminal type '%ls' instead"), DEFAULT_TERM); } } - assert(!term.missing()); - output_set_term(term); input_terminfo_init(); - update_fish_color_support(); // If we have no keybindings, add a few simple defaults. diff --git a/src/output.cpp b/src/output.cpp index 0d7c74f0..05238e1e 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -24,6 +24,7 @@ #include "color.h" #include "common.h" +#include "env.h" #include "fallback.h" // IWYU pragma: keep #include "output.h" #include "wutil.h" // IWYU pragma: keep @@ -33,9 +34,6 @@ static int writeb_internal(char c); /// The function used for output. static int (*out)(char c) = writeb_internal; -/// Name of terminal. -static wcstring current_term; - /// Whether term256 and term24bit are supported. static color_support_t color_support = 0; @@ -416,18 +414,13 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) { return result; } -void output_set_term(const wcstring &term) { current_term.assign(term); } - -const wchar_t *output_get_term() { - return current_term.empty() ? L"" : current_term.c_str(); -} - void writembs_check(char *mbs, const char *mbs_name, const char *file, long line) { if (mbs != NULL) { tputs(mbs, 1, &writeb); } else { + env_var_t term = env_get_string(L"TERM"); debug(0, _(L"Tried to use terminfo string %s on line %ld of %s, which is undefined in " L"terminal of type \"%ls\". Please report this error to %s"), - mbs_name, line, file, output_get_term(), PACKAGE_BUGREPORT); + mbs_name, line, file, term.c_str(), PACKAGE_BUGREPORT); } } diff --git a/src/output.h b/src/output.h index 5882676d..2ecebfbf 100644 --- a/src/output.h +++ b/src/output.h @@ -76,12 +76,6 @@ void output_set_writer(int (*writer)(char)); /// Return the current output writer. int (*output_get_writer())(char); -/// Set the terminal name. -void output_set_term(const wcstring &term); - -/// Return the terminal name. -const wchar_t *output_get_term(); - /// Sets what colors are supported. enum { color_support_term256 = 1 << 0, color_support_term24bit = 1 << 1 }; typedef unsigned int color_support_t; -- cgit v1.2.3