mirror of
https://github.com/neovim/neovim.git
synced 2025-09-16 16:28:17 +00:00
vim-patch:8.2.1269: language and locale code spread out (#19964)
Problem: Language and locale code spread out.
Solution: Move relevant code to src/locale.c. (Yegappan Lakshmanan,
closes vim/vim#6509)
054f14bbe5
Also remove redundant <locale.h> includes.
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include "nvim/help.h"
|
#include "nvim/help.h"
|
||||||
#include "nvim/highlight_group.h"
|
#include "nvim/highlight_group.h"
|
||||||
#include "nvim/if_cscope.h"
|
#include "nvim/if_cscope.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/mapping.h"
|
#include "nvim/mapping.h"
|
||||||
#include "nvim/menu.h"
|
#include "nvim/menu.h"
|
||||||
|
@@ -6,12 +6,6 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "auto/config.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
# include <locale.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
@@ -36,6 +30,7 @@
|
|||||||
#include "nvim/ex_session.h"
|
#include "nvim/ex_session.h"
|
||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
#include "nvim/highlight_group.h"
|
#include "nvim/highlight_group.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
|
@@ -14,11 +14,6 @@
|
|||||||
#include "nvim/arglist.h"
|
#include "nvim/arglist.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
#include "nvim/globals.h"
|
|
||||||
#include "nvim/vim.h"
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
# include <locale.h>
|
|
||||||
#endif
|
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/change.h"
|
#include "nvim/change.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
@@ -30,6 +25,7 @@
|
|||||||
#include "nvim/ex_eval.h"
|
#include "nvim/ex_eval.h"
|
||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
|
#include "nvim/globals.h"
|
||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
@@ -39,13 +35,13 @@
|
|||||||
#include "nvim/ops.h"
|
#include "nvim/ops.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/os/fs_defs.h"
|
#include "nvim/os/fs_defs.h"
|
||||||
#include "nvim/os/shell.h"
|
|
||||||
#include "nvim/os_unix.h"
|
#include "nvim/os_unix.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/runtime.h"
|
#include "nvim/runtime.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/undo.h"
|
#include "nvim/undo.h"
|
||||||
|
#include "nvim/vim.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
@@ -776,324 +772,6 @@ void ex_checktime(exarg_T *eap)
|
|||||||
no_check_timestamps = save_no_check_timestamps;
|
no_check_timestamps = save_no_check_timestamps;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LOCALE_H)
|
|
||||||
# define HAVE_GET_LOCALE_VAL
|
|
||||||
|
|
||||||
static char *get_locale_val(int what)
|
|
||||||
{
|
|
||||||
// Obtain the locale value from the libraries.
|
|
||||||
char *loc = setlocale(what, NULL);
|
|
||||||
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @return true when "lang" starts with a valid language name.
|
|
||||||
/// Rejects NULL, empty string, "C", "C.UTF-8" and others.
|
|
||||||
static bool is_valid_mess_lang(char *lang)
|
|
||||||
{
|
|
||||||
return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtain the current messages language. Used to set the default for
|
|
||||||
/// 'helplang'. May return NULL or an empty string.
|
|
||||||
char *get_mess_lang(void)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
#ifdef HAVE_GET_LOCALE_VAL
|
|
||||||
# if defined(LC_MESSAGES)
|
|
||||||
p = get_locale_val(LC_MESSAGES);
|
|
||||||
# else
|
|
||||||
// This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
|
|
||||||
// may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
|
|
||||||
// and LC_MONETARY may be set differently for a Japanese working in the
|
|
||||||
// US.
|
|
||||||
p = get_locale_val(LC_COLLATE);
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
p = os_getenv("LC_ALL");
|
|
||||||
if (!is_valid_mess_lang(p)) {
|
|
||||||
p = os_getenv("LC_MESSAGES");
|
|
||||||
if (!is_valid_mess_lang(p)) {
|
|
||||||
p = os_getenv("LANG");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return is_valid_mess_lang(p) ? p : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complicated #if; matches with where get_mess_env() is used below.
|
|
||||||
#ifdef HAVE_WORKING_LIBINTL
|
|
||||||
/// Get the language used for messages from the environment.
|
|
||||||
static char *get_mess_env(void)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
p = (char *)os_getenv("LC_ALL");
|
|
||||||
if (p == NULL) {
|
|
||||||
p = (char *)os_getenv("LC_MESSAGES");
|
|
||||||
if (p == NULL) {
|
|
||||||
p = (char *)os_getenv("LANG");
|
|
||||||
if (p != NULL && ascii_isdigit(*p)) {
|
|
||||||
p = NULL; // ignore something like "1043"
|
|
||||||
}
|
|
||||||
# ifdef HAVE_GET_LOCALE_VAL
|
|
||||||
if (p == NULL) {
|
|
||||||
p = get_locale_val(LC_CTYPE);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Set the "v:lang" variable according to the current locale setting.
|
|
||||||
/// Also do "v:lc_time"and "v:ctype".
|
|
||||||
void set_lang_var(void)
|
|
||||||
{
|
|
||||||
const char *loc;
|
|
||||||
|
|
||||||
#ifdef HAVE_GET_LOCALE_VAL
|
|
||||||
loc = get_locale_val(LC_CTYPE);
|
|
||||||
#else
|
|
||||||
// setlocale() not supported: use the default value
|
|
||||||
loc = "C";
|
|
||||||
#endif
|
|
||||||
set_vim_var_string(VV_CTYPE, loc, -1);
|
|
||||||
|
|
||||||
// When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
|
|
||||||
// back to LC_CTYPE if it's empty.
|
|
||||||
#ifdef HAVE_WORKING_LIBINTL
|
|
||||||
loc = get_mess_env();
|
|
||||||
#elif defined(LC_MESSAGES)
|
|
||||||
loc = get_locale_val(LC_MESSAGES);
|
|
||||||
#else
|
|
||||||
// In Windows LC_MESSAGES is not defined fallback to LC_CTYPE
|
|
||||||
loc = get_locale_val(LC_CTYPE);
|
|
||||||
#endif
|
|
||||||
set_vim_var_string(VV_LANG, loc, -1);
|
|
||||||
|
|
||||||
#ifdef HAVE_GET_LOCALE_VAL
|
|
||||||
loc = get_locale_val(LC_TIME);
|
|
||||||
#endif
|
|
||||||
set_vim_var_string(VV_LC_TIME, loc, -1);
|
|
||||||
|
|
||||||
#ifdef HAVE_GET_LOCALE_VAL
|
|
||||||
loc = get_locale_val(LC_COLLATE);
|
|
||||||
#else
|
|
||||||
// setlocale() not supported: use the default value
|
|
||||||
loc = "C";
|
|
||||||
#endif
|
|
||||||
set_vim_var_string(VV_COLLATE, loc, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_WORKING_LIBINTL
|
|
||||||
|
|
||||||
/// ":language": Set the language (locale).
|
|
||||||
///
|
|
||||||
/// @param eap
|
|
||||||
void ex_language(exarg_T *eap)
|
|
||||||
{
|
|
||||||
char *loc;
|
|
||||||
char *p;
|
|
||||||
char *name;
|
|
||||||
int what = LC_ALL;
|
|
||||||
char *whatstr = "";
|
|
||||||
# ifdef LC_MESSAGES
|
|
||||||
# define VIM_LC_MESSAGES LC_MESSAGES
|
|
||||||
# else
|
|
||||||
# define VIM_LC_MESSAGES 6789
|
|
||||||
# endif
|
|
||||||
|
|
||||||
name = eap->arg;
|
|
||||||
|
|
||||||
// Check for "messages {name}", "ctype {name}" or "time {name}" argument.
|
|
||||||
// Allow abbreviation, but require at least 3 characters to avoid
|
|
||||||
// confusion with a two letter language name "me" or "ct".
|
|
||||||
p = (char *)skiptowhite((char_u *)eap->arg);
|
|
||||||
if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) {
|
|
||||||
if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) {
|
|
||||||
what = VIM_LC_MESSAGES;
|
|
||||||
name = skipwhite(p);
|
|
||||||
whatstr = "messages ";
|
|
||||||
} else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) {
|
|
||||||
what = LC_CTYPE;
|
|
||||||
name = skipwhite(p);
|
|
||||||
whatstr = "ctype ";
|
|
||||||
} else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) {
|
|
||||||
what = LC_TIME;
|
|
||||||
name = skipwhite(p);
|
|
||||||
whatstr = "time ";
|
|
||||||
} else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) {
|
|
||||||
what = LC_COLLATE;
|
|
||||||
name = skipwhite(p);
|
|
||||||
whatstr = "collate ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*name == NUL) {
|
|
||||||
if (what == VIM_LC_MESSAGES) {
|
|
||||||
p = get_mess_env();
|
|
||||||
} else {
|
|
||||||
p = setlocale(what, NULL);
|
|
||||||
}
|
|
||||||
if (p == NULL || *p == NUL) {
|
|
||||||
p = "Unknown";
|
|
||||||
}
|
|
||||||
smsg(_("Current %slanguage: \"%s\""), whatstr, p);
|
|
||||||
} else {
|
|
||||||
# ifndef LC_MESSAGES
|
|
||||||
if (what == VIM_LC_MESSAGES) {
|
|
||||||
loc = "";
|
|
||||||
} else {
|
|
||||||
# endif
|
|
||||||
loc = setlocale(what, name);
|
|
||||||
# ifdef LC_NUMERIC
|
|
||||||
// Make sure strtod() uses a decimal point, not a comma.
|
|
||||||
setlocale(LC_NUMERIC, "C");
|
|
||||||
# endif
|
|
||||||
# ifndef LC_MESSAGES
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
if (loc == NULL) {
|
|
||||||
semsg(_("E197: Cannot set language to \"%s\""), name);
|
|
||||||
} else {
|
|
||||||
# ifdef HAVE_NL_MSG_CAT_CNTR
|
|
||||||
// Need to do this for GNU gettext, otherwise cached translations
|
|
||||||
// will be used again.
|
|
||||||
extern int _nl_msg_cat_cntr;
|
|
||||||
|
|
||||||
_nl_msg_cat_cntr++;
|
|
||||||
# endif
|
|
||||||
// Reset $LC_ALL, otherwise it would overrule everything.
|
|
||||||
os_setenv("LC_ALL", "", 1);
|
|
||||||
|
|
||||||
if (what != LC_TIME && what != LC_COLLATE) {
|
|
||||||
// Tell gettext() what to translate to. It apparently doesn't
|
|
||||||
// use the currently effective locale.
|
|
||||||
if (what == LC_ALL) {
|
|
||||||
os_setenv("LANG", name, 1);
|
|
||||||
|
|
||||||
// Clear $LANGUAGE because GNU gettext uses it.
|
|
||||||
os_setenv("LANGUAGE", "", 1);
|
|
||||||
}
|
|
||||||
if (what != LC_CTYPE) {
|
|
||||||
os_setenv("LC_MESSAGES", name, 1);
|
|
||||||
set_helplang_default(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
|
|
||||||
set_lang_var();
|
|
||||||
maketitle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char **locales = NULL; // Array of all available locales
|
|
||||||
|
|
||||||
# ifndef WIN32
|
|
||||||
static bool did_init_locales = false;
|
|
||||||
|
|
||||||
/// @return an array of strings for all available locales + NULL for the
|
|
||||||
/// last element or,
|
|
||||||
/// NULL in case of error.
|
|
||||||
static char **find_locales(void)
|
|
||||||
{
|
|
||||||
garray_T locales_ga;
|
|
||||||
char *loc;
|
|
||||||
char *saveptr = NULL;
|
|
||||||
|
|
||||||
// Find all available locales by running command "locale -a". If this
|
|
||||||
// doesn't work we won't have completion.
|
|
||||||
char *locale_a = (char *)get_cmd_output((char_u *)"locale -a", NULL,
|
|
||||||
kShellOptSilent, NULL);
|
|
||||||
if (locale_a == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ga_init(&locales_ga, sizeof(char_u *), 20);
|
|
||||||
|
|
||||||
// Transform locale_a string where each locale is separated by "\n"
|
|
||||||
// into an array of locale strings.
|
|
||||||
loc = os_strtok(locale_a, "\n", &saveptr);
|
|
||||||
|
|
||||||
while (loc != NULL) {
|
|
||||||
loc = xstrdup(loc);
|
|
||||||
GA_APPEND(char *, &locales_ga, loc);
|
|
||||||
loc = os_strtok(NULL, "\n", &saveptr);
|
|
||||||
}
|
|
||||||
xfree(locale_a);
|
|
||||||
// Guarantee that .ga_data is NULL terminated
|
|
||||||
ga_grow(&locales_ga, 1);
|
|
||||||
((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
|
|
||||||
return locales_ga.ga_data;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/// Lazy initialization of all available locales.
|
|
||||||
static void init_locales(void)
|
|
||||||
{
|
|
||||||
# ifndef WIN32
|
|
||||||
if (!did_init_locales) {
|
|
||||||
did_init_locales = true;
|
|
||||||
locales = find_locales();
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
# if defined(EXITFREE)
|
|
||||||
void free_locales(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (locales != NULL) {
|
|
||||||
for (i = 0; locales[i] != NULL; i++) {
|
|
||||||
xfree(locales[i]);
|
|
||||||
}
|
|
||||||
XFREE_CLEAR(locales);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/// Function given to ExpandGeneric() to obtain the possible arguments of the
|
|
||||||
/// ":language" command.
|
|
||||||
char *get_lang_arg(expand_T *xp, int idx)
|
|
||||||
{
|
|
||||||
if (idx == 0) {
|
|
||||||
return "messages";
|
|
||||||
}
|
|
||||||
if (idx == 1) {
|
|
||||||
return "ctype";
|
|
||||||
}
|
|
||||||
if (idx == 2) {
|
|
||||||
return "time";
|
|
||||||
}
|
|
||||||
if (idx == 3) {
|
|
||||||
return "collate";
|
|
||||||
}
|
|
||||||
|
|
||||||
init_locales();
|
|
||||||
if (locales == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return locales[idx - 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Function given to ExpandGeneric() to obtain the available locales.
|
|
||||||
char *get_locales(expand_T *xp, int idx)
|
|
||||||
{
|
|
||||||
init_locales();
|
|
||||||
if (locales == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return locales[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void script_host_execute(char *name, exarg_T *eap)
|
static void script_host_execute(char *name, exarg_T *eap)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
#ifndef NVIM_EX_CMDS2_H
|
#ifndef NVIM_EX_CMDS2_H
|
||||||
#define NVIM_EX_CMDS2_H
|
#define NVIM_EX_CMDS2_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "nvim/ex_cmds_defs.h"
|
#include "nvim/ex_cmds_defs.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
#include "nvim/if_cscope.h"
|
#include "nvim/if_cscope.h"
|
||||||
#include "nvim/input.h"
|
#include "nvim/input.h"
|
||||||
#include "nvim/keycodes.h"
|
#include "nvim/keycodes.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
#include "nvim/mapping.h"
|
#include "nvim/mapping.h"
|
||||||
|
@@ -10,10 +10,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/vim.h"
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
# include <locale.h>
|
|
||||||
#endif
|
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
@@ -38,6 +34,7 @@
|
|||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/version.h"
|
#include "nvim/version.h"
|
||||||
|
#include "nvim/vim.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To implement printing on a platform, the following functions must be
|
* To implement printing on a platform, the following functions must be
|
||||||
|
369
src/nvim/locale.c
Normal file
369
src/nvim/locale.c
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||||
|
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
// locale.c: functions for language/locale configuration
|
||||||
|
|
||||||
|
#include "auto/config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/buffer.h"
|
||||||
|
#include "nvim/charset.h"
|
||||||
|
#include "nvim/eval.h"
|
||||||
|
#include "nvim/garray.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/message.h"
|
||||||
|
#include "nvim/option.h"
|
||||||
|
#include "nvim/os/os.h"
|
||||||
|
#include "nvim/os/shell.h"
|
||||||
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/profile.h"
|
||||||
|
#include "nvim/types.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "locale.c.generated.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LOCALE_H)
|
||||||
|
# define HAVE_GET_LOCALE_VAL
|
||||||
|
|
||||||
|
static char *get_locale_val(int what)
|
||||||
|
{
|
||||||
|
// Obtain the locale value from the libraries.
|
||||||
|
char *loc = setlocale(what, NULL);
|
||||||
|
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @return true when "lang" starts with a valid language name.
|
||||||
|
/// Rejects NULL, empty string, "C", "C.UTF-8" and others.
|
||||||
|
static bool is_valid_mess_lang(char *lang)
|
||||||
|
{
|
||||||
|
return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain the current messages language. Used to set the default for
|
||||||
|
/// 'helplang'. May return NULL or an empty string.
|
||||||
|
char *get_mess_lang(void)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
#ifdef HAVE_GET_LOCALE_VAL
|
||||||
|
# if defined(LC_MESSAGES)
|
||||||
|
p = get_locale_val(LC_MESSAGES);
|
||||||
|
# else
|
||||||
|
// This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
|
||||||
|
// may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
|
||||||
|
// and LC_MONETARY may be set differently for a Japanese working in the
|
||||||
|
// US.
|
||||||
|
p = get_locale_val(LC_COLLATE);
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
p = os_getenv("LC_ALL");
|
||||||
|
if (!is_valid_mess_lang(p)) {
|
||||||
|
p = os_getenv("LC_MESSAGES");
|
||||||
|
if (!is_valid_mess_lang(p)) {
|
||||||
|
p = os_getenv("LANG");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return is_valid_mess_lang(p) ? p : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complicated #if; matches with where get_mess_env() is used below.
|
||||||
|
#ifdef HAVE_WORKING_LIBINTL
|
||||||
|
/// Get the language used for messages from the environment.
|
||||||
|
static char *get_mess_env(void)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
p = (char *)os_getenv("LC_ALL");
|
||||||
|
if (p == NULL) {
|
||||||
|
p = (char *)os_getenv("LC_MESSAGES");
|
||||||
|
if (p == NULL) {
|
||||||
|
p = (char *)os_getenv("LANG");
|
||||||
|
if (p != NULL && ascii_isdigit(*p)) {
|
||||||
|
p = NULL; // ignore something like "1043"
|
||||||
|
}
|
||||||
|
# ifdef HAVE_GET_LOCALE_VAL
|
||||||
|
if (p == NULL) {
|
||||||
|
p = get_locale_val(LC_CTYPE);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Set the "v:lang" variable according to the current locale setting.
|
||||||
|
/// Also do "v:lc_time"and "v:ctype".
|
||||||
|
void set_lang_var(void)
|
||||||
|
{
|
||||||
|
const char *loc;
|
||||||
|
|
||||||
|
#ifdef HAVE_GET_LOCALE_VAL
|
||||||
|
loc = get_locale_val(LC_CTYPE);
|
||||||
|
#else
|
||||||
|
// setlocale() not supported: use the default value
|
||||||
|
loc = "C";
|
||||||
|
#endif
|
||||||
|
set_vim_var_string(VV_CTYPE, loc, -1);
|
||||||
|
|
||||||
|
// When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
|
||||||
|
// back to LC_CTYPE if it's empty.
|
||||||
|
#ifdef HAVE_WORKING_LIBINTL
|
||||||
|
loc = get_mess_env();
|
||||||
|
#elif defined(LC_MESSAGES)
|
||||||
|
loc = get_locale_val(LC_MESSAGES);
|
||||||
|
#else
|
||||||
|
// In Windows LC_MESSAGES is not defined fallback to LC_CTYPE
|
||||||
|
loc = get_locale_val(LC_CTYPE);
|
||||||
|
#endif
|
||||||
|
set_vim_var_string(VV_LANG, loc, -1);
|
||||||
|
|
||||||
|
#ifdef HAVE_GET_LOCALE_VAL
|
||||||
|
loc = get_locale_val(LC_TIME);
|
||||||
|
#endif
|
||||||
|
set_vim_var_string(VV_LC_TIME, loc, -1);
|
||||||
|
|
||||||
|
#ifdef HAVE_GET_LOCALE_VAL
|
||||||
|
loc = get_locale_val(LC_COLLATE);
|
||||||
|
#else
|
||||||
|
// setlocale() not supported: use the default value
|
||||||
|
loc = "C";
|
||||||
|
#endif
|
||||||
|
set_vim_var_string(VV_COLLATE, loc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_LOCALE_H)
|
||||||
|
/// Setup to use the current locale (for ctype() and many other things).
|
||||||
|
void init_locale(void)
|
||||||
|
{
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
# ifdef LC_NUMERIC
|
||||||
|
// Make sure strtod() uses a decimal point, not a comma.
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
# endif
|
||||||
|
|
||||||
|
char localepath[MAXPATHL] = { 0 };
|
||||||
|
snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH));
|
||||||
|
char *tail = path_tail_with_sep(localepath);
|
||||||
|
*tail = NUL;
|
||||||
|
tail = path_tail(localepath);
|
||||||
|
xstrlcpy(tail, "share/locale",
|
||||||
|
sizeof(localepath) - (size_t)(tail - localepath));
|
||||||
|
bindtextdomain(PROJECT_NAME, localepath);
|
||||||
|
textdomain(PROJECT_NAME);
|
||||||
|
TIME_MSG("locale set");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WORKING_LIBINTL
|
||||||
|
|
||||||
|
/// ":language": Set the language (locale).
|
||||||
|
///
|
||||||
|
/// @param eap
|
||||||
|
void ex_language(exarg_T *eap)
|
||||||
|
{
|
||||||
|
char *loc;
|
||||||
|
char *p;
|
||||||
|
char *name;
|
||||||
|
int what = LC_ALL;
|
||||||
|
char *whatstr = "";
|
||||||
|
# ifdef LC_MESSAGES
|
||||||
|
# define VIM_LC_MESSAGES LC_MESSAGES
|
||||||
|
# else
|
||||||
|
# define VIM_LC_MESSAGES 6789
|
||||||
|
# endif
|
||||||
|
|
||||||
|
name = eap->arg;
|
||||||
|
|
||||||
|
// Check for "messages {name}", "ctype {name}" or "time {name}" argument.
|
||||||
|
// Allow abbreviation, but require at least 3 characters to avoid
|
||||||
|
// confusion with a two letter language name "me" or "ct".
|
||||||
|
p = (char *)skiptowhite((char_u *)eap->arg);
|
||||||
|
if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) {
|
||||||
|
if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) {
|
||||||
|
what = VIM_LC_MESSAGES;
|
||||||
|
name = skipwhite(p);
|
||||||
|
whatstr = "messages ";
|
||||||
|
} else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) {
|
||||||
|
what = LC_CTYPE;
|
||||||
|
name = skipwhite(p);
|
||||||
|
whatstr = "ctype ";
|
||||||
|
} else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) {
|
||||||
|
what = LC_TIME;
|
||||||
|
name = skipwhite(p);
|
||||||
|
whatstr = "time ";
|
||||||
|
} else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) {
|
||||||
|
what = LC_COLLATE;
|
||||||
|
name = skipwhite(p);
|
||||||
|
whatstr = "collate ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*name == NUL) {
|
||||||
|
if (what == VIM_LC_MESSAGES) {
|
||||||
|
p = get_mess_env();
|
||||||
|
} else {
|
||||||
|
p = setlocale(what, NULL);
|
||||||
|
}
|
||||||
|
if (p == NULL || *p == NUL) {
|
||||||
|
p = "Unknown";
|
||||||
|
}
|
||||||
|
smsg(_("Current %slanguage: \"%s\""), whatstr, p);
|
||||||
|
} else {
|
||||||
|
# ifndef LC_MESSAGES
|
||||||
|
if (what == VIM_LC_MESSAGES) {
|
||||||
|
loc = "";
|
||||||
|
} else {
|
||||||
|
# endif
|
||||||
|
loc = setlocale(what, name);
|
||||||
|
# ifdef LC_NUMERIC
|
||||||
|
// Make sure strtod() uses a decimal point, not a comma.
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
# endif
|
||||||
|
# ifndef LC_MESSAGES
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
if (loc == NULL) {
|
||||||
|
semsg(_("E197: Cannot set language to \"%s\""), name);
|
||||||
|
} else {
|
||||||
|
# ifdef HAVE_NL_MSG_CAT_CNTR
|
||||||
|
// Need to do this for GNU gettext, otherwise cached translations
|
||||||
|
// will be used again.
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
|
||||||
|
_nl_msg_cat_cntr++;
|
||||||
|
# endif
|
||||||
|
// Reset $LC_ALL, otherwise it would overrule everything.
|
||||||
|
os_setenv("LC_ALL", "", 1);
|
||||||
|
|
||||||
|
if (what != LC_TIME && what != LC_COLLATE) {
|
||||||
|
// Tell gettext() what to translate to. It apparently doesn't
|
||||||
|
// use the currently effective locale.
|
||||||
|
if (what == LC_ALL) {
|
||||||
|
os_setenv("LANG", name, 1);
|
||||||
|
|
||||||
|
// Clear $LANGUAGE because GNU gettext uses it.
|
||||||
|
os_setenv("LANGUAGE", "", 1);
|
||||||
|
}
|
||||||
|
if (what != LC_CTYPE) {
|
||||||
|
os_setenv("LC_MESSAGES", name, 1);
|
||||||
|
set_helplang_default(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
|
||||||
|
set_lang_var();
|
||||||
|
maketitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **locales = NULL; // Array of all available locales
|
||||||
|
|
||||||
|
# ifndef WIN32
|
||||||
|
static bool did_init_locales = false;
|
||||||
|
|
||||||
|
/// @return an array of strings for all available locales + NULL for the
|
||||||
|
/// last element or,
|
||||||
|
/// NULL in case of error.
|
||||||
|
static char **find_locales(void)
|
||||||
|
{
|
||||||
|
garray_T locales_ga;
|
||||||
|
char *loc;
|
||||||
|
char *saveptr = NULL;
|
||||||
|
|
||||||
|
// Find all available locales by running command "locale -a". If this
|
||||||
|
// doesn't work we won't have completion.
|
||||||
|
char *locale_a = (char *)get_cmd_output((char_u *)"locale -a", NULL,
|
||||||
|
kShellOptSilent, NULL);
|
||||||
|
if (locale_a == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ga_init(&locales_ga, sizeof(char_u *), 20);
|
||||||
|
|
||||||
|
// Transform locale_a string where each locale is separated by "\n"
|
||||||
|
// into an array of locale strings.
|
||||||
|
loc = os_strtok(locale_a, "\n", &saveptr);
|
||||||
|
|
||||||
|
while (loc != NULL) {
|
||||||
|
loc = xstrdup(loc);
|
||||||
|
GA_APPEND(char *, &locales_ga, loc);
|
||||||
|
loc = os_strtok(NULL, "\n", &saveptr);
|
||||||
|
}
|
||||||
|
xfree(locale_a);
|
||||||
|
// Guarantee that .ga_data is NULL terminated
|
||||||
|
ga_grow(&locales_ga, 1);
|
||||||
|
((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
|
||||||
|
return locales_ga.ga_data;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/// Lazy initialization of all available locales.
|
||||||
|
static void init_locales(void)
|
||||||
|
{
|
||||||
|
# ifndef WIN32
|
||||||
|
if (!did_init_locales) {
|
||||||
|
did_init_locales = true;
|
||||||
|
locales = find_locales();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
# if defined(EXITFREE)
|
||||||
|
void free_locales(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (locales != NULL) {
|
||||||
|
for (i = 0; locales[i] != NULL; i++) {
|
||||||
|
xfree(locales[i]);
|
||||||
|
}
|
||||||
|
XFREE_CLEAR(locales);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/// Function given to ExpandGeneric() to obtain the possible arguments of the
|
||||||
|
/// ":language" command.
|
||||||
|
char *get_lang_arg(expand_T *xp, int idx)
|
||||||
|
{
|
||||||
|
if (idx == 0) {
|
||||||
|
return "messages";
|
||||||
|
}
|
||||||
|
if (idx == 1) {
|
||||||
|
return "ctype";
|
||||||
|
}
|
||||||
|
if (idx == 2) {
|
||||||
|
return "time";
|
||||||
|
}
|
||||||
|
if (idx == 3) {
|
||||||
|
return "collate";
|
||||||
|
}
|
||||||
|
|
||||||
|
init_locales();
|
||||||
|
if (locales == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return locales[idx - 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function given to ExpandGeneric() to obtain the available locales.
|
||||||
|
char *get_locales(expand_T *xp, int idx)
|
||||||
|
{
|
||||||
|
init_locales();
|
||||||
|
if (locales == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return locales[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
10
src/nvim/locale.h
Normal file
10
src/nvim/locale.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef NVIM_LOCALE_H
|
||||||
|
#define NVIM_LOCALE_H
|
||||||
|
|
||||||
|
#include "nvim/ex_cmds_defs.h"
|
||||||
|
#include "nvim/types.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "locale.h.generated.h"
|
||||||
|
#endif
|
||||||
|
#endif // NVIM_LOCALE_H
|
@@ -25,23 +25,19 @@
|
|||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
|
#include "nvim/garray.h"
|
||||||
|
#include "nvim/grid.h"
|
||||||
#include "nvim/hashtab.h"
|
#include "nvim/hashtab.h"
|
||||||
#include "nvim/highlight.h"
|
#include "nvim/highlight.h"
|
||||||
#include "nvim/highlight_group.h"
|
#include "nvim/highlight_group.h"
|
||||||
#include "nvim/iconv.h"
|
#include "nvim/iconv.h"
|
||||||
#include "nvim/if_cscope.h"
|
#include "nvim/if_cscope.h"
|
||||||
#include "nvim/insexpand.h"
|
#include "nvim/insexpand.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
|
#include "nvim/log.h"
|
||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
#include "nvim/mapping.h"
|
#include "nvim/mapping.h"
|
||||||
#include "nvim/ui_client.h"
|
|
||||||
#include "nvim/vim.h"
|
|
||||||
#ifdef HAVE_LOCALE_H
|
|
||||||
# include <locale.h>
|
|
||||||
#endif
|
|
||||||
#include "nvim/garray.h"
|
|
||||||
#include "nvim/grid.h"
|
|
||||||
#include "nvim/log.h"
|
|
||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
@@ -70,8 +66,10 @@
|
|||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
|
#include "nvim/ui_client.h"
|
||||||
#include "nvim/ui_compositor.h"
|
#include "nvim/ui_compositor.h"
|
||||||
#include "nvim/version.h"
|
#include "nvim/version.h"
|
||||||
|
#include "nvim/vim.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include "nvim/os/os_win_console.h"
|
# include "nvim/os/os_win_console.h"
|
||||||
@@ -801,30 +799,6 @@ static int get_number_arg(const char *p, int *idx, int def)
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LOCALE_H)
|
|
||||||
/// Setup to use the current locale (for ctype() and many other things).
|
|
||||||
static void init_locale(void)
|
|
||||||
{
|
|
||||||
setlocale(LC_ALL, "");
|
|
||||||
|
|
||||||
# ifdef LC_NUMERIC
|
|
||||||
// Make sure strtod() uses a decimal point, not a comma.
|
|
||||||
setlocale(LC_NUMERIC, "C");
|
|
||||||
# endif
|
|
||||||
|
|
||||||
char localepath[MAXPATHL] = { 0 };
|
|
||||||
snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH));
|
|
||||||
char *tail = path_tail_with_sep(localepath);
|
|
||||||
*tail = NUL;
|
|
||||||
tail = path_tail(localepath);
|
|
||||||
xstrlcpy(tail, "share/locale",
|
|
||||||
sizeof(localepath) - (size_t)(tail - localepath));
|
|
||||||
bindtextdomain(PROJECT_NAME, localepath);
|
|
||||||
textdomain(PROJECT_NAME);
|
|
||||||
TIME_MSG("locale set");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static uint64_t server_connect(char *server_addr, const char **errmsg)
|
static uint64_t server_connect(char *server_addr, const char **errmsg)
|
||||||
{
|
{
|
||||||
if (server_addr == NULL) {
|
if (server_addr == NULL) {
|
||||||
|
@@ -39,7 +39,6 @@
|
|||||||
#include "nvim/edit.h"
|
#include "nvim/edit.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
#include "nvim/ex_cmds2.h"
|
|
||||||
#include "nvim/ex_docmd.h"
|
#include "nvim/ex_docmd.h"
|
||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
#include "nvim/ex_session.h"
|
#include "nvim/ex_session.h"
|
||||||
@@ -53,6 +52,7 @@
|
|||||||
#include "nvim/indent.h"
|
#include "nvim/indent.h"
|
||||||
#include "nvim/indent_c.h"
|
#include "nvim/indent_c.h"
|
||||||
#include "nvim/keycodes.h"
|
#include "nvim/keycodes.h"
|
||||||
|
#include "nvim/locale.h"
|
||||||
#include "nvim/macros.h"
|
#include "nvim/macros.h"
|
||||||
#include "nvim/mapping.h"
|
#include "nvim/mapping.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
|
Reference in New Issue
Block a user