diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/builtin_printf.cpp | 25 | ||||
-rw-r--r-- | src/common.cpp | 10 | ||||
-rw-r--r-- | src/common.h | 7 | ||||
-rw-r--r-- | src/env.cpp | 68 | ||||
-rw-r--r-- | src/fallback.cpp | 41 | ||||
-rw-r--r-- | src/fallback.h | 9 | ||||
-rw-r--r-- | src/fish.cpp | 5 | ||||
-rw-r--r-- | src/fish_indent.cpp | 12 | ||||
-rw-r--r-- | src/fish_key_reader.cpp | 4 |
9 files changed, 56 insertions, 125 deletions
diff --git a/src/builtin_printf.cpp b/src/builtin_printf.cpp index 36b8e638..d81ab453 100644 --- a/src/builtin_printf.cpp +++ b/src/builtin_printf.cpp @@ -197,24 +197,6 @@ static int octal_to_bin(wchar_t c) { } } -double C_STRTOD(wchar_t const *nptr, wchar_t **endptr) { - double r; - - const wcstring saved_locale = wsetlocale(LC_NUMERIC, NULL); - - if (!saved_locale.empty()) { - wsetlocale(LC_NUMERIC, L"C"); - } - - r = wcstod(nptr, endptr); - - if (!saved_locale.empty()) { - wsetlocale(LC_NUMERIC, saved_locale.c_str()); - } - - return r; -} - void builtin_printf_state_t::fatal_error(const wchar_t *fmt, ...) { // Don't error twice. if (early_exit) return; @@ -283,7 +265,12 @@ uintmax_t raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) { template <> long double raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) { - return C_STRTOD(s, end); + // Forcing the locale to C is questionable but it's what the old C_STRTOD() that I inlined here + // as part of changing how locale management is done by fish. + char * old_locale = setlocale(LC_NUMERIC, "C"); + double val = wcstod(s, end); + setlocale(LC_NUMERIC, old_locale); + return val; } template <typename T> diff --git a/src/common.cpp b/src/common.cpp index 1ad51482..d0fdccb6 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -6,7 +6,6 @@ #include <dlfcn.h> #include <errno.h> #include <limits.h> -#include <locale.h> #include <math.h> #include <signal.h> #include <stdarg.h> @@ -470,19 +469,12 @@ wchar_t *quote_end(const wchar_t *pos) { return 0; } -wcstring wsetlocale(int category, const wchar_t *locale) { - char *lang = locale ? wcs2str(locale) : NULL; - char *res = setlocale(category, lang); - free(lang); - +void fish_setlocale() { // Use ellipsis if on known unicode system, otherwise use $. ellipsis_char = (wcwidth(L'\x2026') > 0) ? L'\x2026' : L'$'; // U+23CE is the "return" character omitted_newline_char = (wcwidth(L'\x23CE') > 0) ? L'\x23CE' : L'~'; - - if (!res) return wcstring(); - return format_string(L"%s", res); } bool contains_internal(const wchar_t *a, int vararg_handle, ...) { diff --git a/src/common.h b/src/common.h index 07342436..87fefed3 100644 --- a/src/common.h +++ b/src/common.h @@ -627,10 +627,9 @@ wchar_t *quote_end(const wchar_t *in); /// interactive command executes, to allow new messages to be printed. void error_reset(); -/// This function behaves exactly like a wide character equivalent of the C function setlocale, -/// except that it will also try to detect if the user is using a Unicode character set, and if so, -/// use the unicode ellipsis character as ellipsis, instead of '$'. -wcstring wsetlocale(int category, const wchar_t *locale); +/// This function should be called after calling `setlocale()` to perform fish specific locale +/// initialization. +void fish_setlocale(); /// Checks if \c needle is included in the list of strings specified. A warning is printed if needle /// is zero. diff --git a/src/env.cpp b/src/env.cpp index 71d85800..c7924aef 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -9,6 +9,9 @@ #include <stdbool.h> #include <stddef.h> #include <stdlib.h> +#ifdef HAVE__NL_MSG_CAT_CNTR +#include <string.h> +#endif #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -168,41 +171,35 @@ static bool var_is_locale(const wcstring &key) { } /// Properly sets all locale information. -static void handle_locale() { - const env_var_t lc_all = env_get_string(L"LC_ALL"); - const wcstring old_locale = wsetlocale(LC_MESSAGES, NULL); +static void handle_locale(const wchar_t *env_var_name) { + debug(2, L"handle_locale() called in response to '%ls' changing", env_var_name); + const char *old_msg_locale = setlocale(LC_MESSAGES, NULL); - // Array of locale constants corresponding to the local variable names defined in - // locale_variable. - static const int cat[] = {0, LC_ALL, LC_COLLATE, LC_CTYPE, - LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME}; - - if (!lc_all.missing()) { - wsetlocale(LC_ALL, lc_all.c_str()); - } else { - const env_var_t lang = env_get_string(L"LANG"); - if (!lang.missing()) { - wsetlocale(LC_ALL, lang.c_str()); - } - - for (int i = 2; locale_variable[i]; i++) { - const env_var_t val = env_get_string(locale_variable[i]); - - if (!val.missing()) { - wsetlocale(cat[i], val.c_str()); - } + for (size_t i = 0; locale_variable[i]; i++) { + const wchar_t *key = locale_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); + debug(3, L"locale var %s='%s'", name.c_str(), value.c_str()); } } - const wcstring new_locale = wsetlocale(LC_MESSAGES, NULL); - if (old_locale != new_locale) { - // Try to make change known to gettext. Both changing _nl_msg_cat_cntr and calling dcgettext - // might potentially tell some gettext implementation that the translation strings should be - // reloaded. We do both and hope for the best. + char *locale = setlocale(LC_ALL, ""); + fish_setlocale(); + debug(2, L"handle_locale() setlocale(): '%s'", locale); + + const char *new_msg_locale = setlocale(LC_MESSAGES, NULL); + debug(3, L"old LC_MESSAGES locale: '%s'", old_msg_locale); + debug(3, L"new LC_MESSAGES locale: '%s'", new_msg_locale); +#ifdef HAVE__NL_MSG_CAT_CNTR + if (strcmp(old_msg_locale, new_msg_locale)) { + // Make change known to GNU gettext. extern int _nl_msg_cat_cntr; _nl_msg_cat_cntr++; - fish_dcgettext("fish", "Changing language to English", LC_MESSAGES); } +#endif } /// Check if the specified variable is a locale variable. @@ -217,7 +214,8 @@ static bool var_is_curses(const wcstring &key) { /// Push all curses/terminfo env vars into the global environment where they can be found by those /// libraries. -static void handle_curses() { +static void handle_curses(const wchar_t *env_var_name) { + debug(2, L"handle_curses() called in response to '%ls' changing", env_var_name); 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); @@ -225,6 +223,7 @@ static void handle_curses() { const std::string &name = wcs2string(key); const std::string &value = wcs2string(var); setenv(name.c_str(), value.c_str(), 1); + debug(3, L"curses var %s='%s'", name.c_str(), value.c_str()); } } // TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically @@ -236,9 +235,9 @@ static void handle_curses() { /// React to modifying the given variable. static void react_to_variable_change(const wcstring &key) { if (var_is_locale(key)) { - handle_locale(); + handle_locale(key.c_str()); } else if (var_is_curses(key)) { - handle_curses(); + handle_curses(key.c_str()); } else if (key == L"fish_term256" || key == L"fish_term24bit") { update_fish_color_support(); reader_react_to_color_change(); @@ -852,14 +851,13 @@ void env_push(bool new_scope) { void env_pop() { if (&top->env != global) { int i; - int locale_changed = 0; - + const wchar_t *locale_changed = NULL; env_node_t *killme = top; for (i = 0; locale_variable[i]; i++) { var_table_t::iterator result = killme->env.find(locale_variable[i]); if (result != killme->env.end()) { - locale_changed = 1; + locale_changed = locale_variable[i]; break; } } @@ -881,7 +879,7 @@ void env_pop() { delete killme; - if (locale_changed) handle_locale(); + if (locale_changed) handle_locale(locale_changed); } else { debug(0, _(L"Tried to pop empty environment stack.")); diff --git a/src/fallback.cpp b/src/fallback.cpp index 9b746842..c3ef3462 100644 --- a/src/fallback.cpp +++ b/src/fallback.cpp @@ -171,7 +171,6 @@ wchar_t *wcsndup(const wchar_t *in, size_t c) { #endif #ifndef HAVE_WCSLCPY - /*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/ /* @@ -189,7 +188,6 @@ wchar_t *wcsndup(const wchar_t *in, size_t c) { * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) { register wchar_t *d = dst; register const wchar_t *s = src; @@ -212,11 +210,9 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) { return s - src - 1; // Count does not include NUL. } - #endif #ifndef HAVE_LRAND48_R - int lrand48_r(struct drand48_data *buffer, long int *result) { *result = rand_r(&buffer->seed); return 0; @@ -226,20 +222,16 @@ int srand48_r(long int seedval, struct drand48_data *buffer) { buffer->seed = (unsigned int)seedval; return 0; } - #endif #ifndef HAVE_FUTIMES - int futimes(int fd, const struct timeval *times) { errno = ENOSYS; return -1; } - #endif #if HAVE_GETTEXT - char *fish_gettext(const char *msgid) { return gettext(msgid); ; @@ -250,35 +242,10 @@ char *fish_bindtextdomain(const char *domainname, const char *dirname) { } char *fish_textdomain(const char *domainname) { return textdomain(domainname); } - #else - char *fish_gettext(const char *msgid) { return (char *)msgid; } - char *fish_bindtextdomain(const char *domainname, const char *dirname) { return NULL; } - char *fish_textdomain(const char *domainname) { return NULL; } - -#endif - -#if HAVE_DCGETTEXT - -char *fish_dcgettext(const char *domainname, const char *msgid, int category) { - return dcgettext(domainname, msgid, category); -} - -#else - -char *fish_dcgettext(const char *domainname, const char *msgid, int category) { - return (char *)msgid; -} - -#endif - -#ifndef HAVE__NL_MSG_CAT_CNTR - -int _nl_msg_cat_cntr = 0; - #endif #ifndef HAVE_KILLPG @@ -299,18 +266,12 @@ double nan(char *tagp) { return 0.0 / 0.0; } #endif #if !HAVE_BROKEN_WCWIDTH - int fish_wcwidth(wchar_t wc) { return wcwidth(wc); } - int fish_wcswidth(const wchar_t *str, size_t n) { return wcswidth(str, n); } - #else - static int mk_wcwidth(wchar_t wc); static int mk_wcswidth(const wchar_t *pwcs, size_t n); - int fish_wcwidth(wchar_t wc) { return mk_wcwidth(wc); } - int fish_wcswidth(const wchar_t *str, size_t n) { return mk_wcswidth(str, n); } /* @@ -373,7 +334,6 @@ int fish_wcswidth(const wchar_t *str, size_t n) { return mk_wcswidth(str, n); } * * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ - struct interval { int first; int last; @@ -502,5 +462,4 @@ static int mk_wcswidth(const wchar_t *pwcs, size_t n) { } return width; } - #endif // HAVE_BROKEN_WCWIDTH diff --git a/src/fallback.h b/src/fallback.h index 09e30142..7a609b8d 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -120,15 +120,6 @@ char *fish_bindtextdomain(const char *domainname, const char *dirname); /// Cover for textdomain(). char *fish_textdomain(const char *domainname); -/// Cover for dcgettext. -char *fish_dcgettext(const char *domainname, const char *msgid, int category); - -#ifndef HAVE__NL_MSG_CAT_CNTR -/// Some gettext implementation use have this variable, and by increasing it, one can tell the -/// system that the translations need to be reloaded. -extern int _nl_msg_cat_cntr; -#endif - #ifndef HAVE_KILLPG /// Send specified signal to specified process group. int killpg(int pgr, int sig); diff --git a/src/fish.cpp b/src/fish.cpp index c4158dde..8a65d626 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -418,11 +418,12 @@ int main(int argc, char **argv) { assert(ANY_SENTINAL >= WILDCARD_RESERVED_BASE && ANY_SENTINAL <= WILDCARD_RESERVED_END); assert(R_SENTINAL >= INPUT_COMMON_BASE && R_SENTINAL <= INPUT_COMMON_END); + program_name = L"fish"; set_main_thread(); setup_fork_guards(); - wsetlocale(LC_ALL, L""); - program_name = L"fish"; + setlocale(LC_ALL, ""); + fish_setlocale(); // struct stat tmp; // stat("----------FISH_HIT_MAIN----------", &tmp); diff --git a/src/fish_indent.cpp b/src/fish_indent.cpp index a1479f47..cab9df03 100644 --- a/src/fish_indent.cpp +++ b/src/fish_indent.cpp @@ -328,12 +328,16 @@ static std::string html_colorize(const wcstring &text, static std::string no_colorize(const wcstring &text) { return wcs2string(text); } int main(int argc, char *argv[]) { + program_name = L"fish_indent"; set_main_thread(); setup_fork_guards(); - - wsetlocale(LC_ALL, L""); - program_name = L"fish_indent"; - + // Using the user's default locale could be a problem if it doesn't use UTF-8 encoding. That's + // because the fish project assumes Unicode UTF-8 encoding in all of its scripts. + // + // TODO: Auto-detect the encoding of the script. We should look for a vim style comment + // (e.g., "# vim: set fileencoding=<encoding-name>:") or an emacs style comment + // (e.g., "# -*- coding: <encoding-name> -*-"). + setlocale(LC_ALL, ""); env_init(); input_init(); diff --git a/src/fish_key_reader.cpp b/src/fish_key_reader.cpp index 1c30c1db..89a6ee53 100644 --- a/src/fish_key_reader.cpp +++ b/src/fish_key_reader.cpp @@ -148,8 +148,7 @@ void setup_and_process_keys(bool continuous_mode) { is_interactive_session = 1; // by definition this is interactive set_main_thread(); setup_fork_guards(); - wsetlocale(LC_ALL, L"POSIX"); - program_name = L"fish_key_reader"; + setlocale(LC_ALL, "POSIX"); env_init(); reader_init(); input_init(); @@ -178,6 +177,7 @@ void setup_and_process_keys(bool continuous_mode) { } int main(int argc, char **argv) { + program_name = L"fish_key_reader"; bool continuous_mode = false; const char *short_opts = "+c"; const struct option long_opts[] = {{"continuous", no_argument, NULL, 'd'}, {NULL, 0, NULL, 0}}; |