aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtin_printf.cpp25
-rw-r--r--src/common.cpp10
-rw-r--r--src/common.h7
-rw-r--r--src/env.cpp68
-rw-r--r--src/fallback.cpp41
-rw-r--r--src/fallback.h9
-rw-r--r--src/fish.cpp5
-rw-r--r--src/fish_indent.cpp12
-rw-r--r--src/fish_key_reader.cpp4
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}};