refactor(build): graduate HAVE_LOCALE_H feature

Merge locale.h into os/lang.h
Having a source file with the same name as a system header we use is
considered an anti-pattern.
This commit is contained in:
bfredl 2023-02-27 19:37:43 +01:00 committed by Björn Linse
parent 166b149d5b
commit 1b3c1f6c06
12 changed files with 347 additions and 411 deletions

View File

@ -35,7 +35,6 @@ check_symbol_exists(_NSGetEnviron crt_externs.h HAVE__NSGETENVIRON)
# Headers
check_include_files(langinfo.h HAVE_LANGINFO_H)
check_include_files(locale.h HAVE_LOCALE_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(sys/utsname.h HAVE_SYS_UTSNAME_H)
check_include_files(termios.h HAVE_TERMIOS_H)

View File

@ -18,7 +18,6 @@
#cmakedefine HAVE_FD_CLOEXEC
#cmakedefine HAVE_FSEEKO
#cmakedefine HAVE_LANGINFO_H
#cmakedefine HAVE_LOCALE_H
#cmakedefine HAVE_NL_LANGINFO_CODESET
#cmakedefine HAVE_NL_MSG_CAT_CNTR
#cmakedefine HAVE_PWD_FUNCS

View File

@ -40,7 +40,6 @@
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/locale.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"
@ -50,6 +49,7 @@
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"

View File

@ -45,7 +45,6 @@
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/lib/queue.h"
#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"
#include "nvim/main.h"
@ -62,6 +61,7 @@
#include "nvim/optionstr.h"
#include "nvim/os/fileio.h"
#include "nvim/os/fs_defs.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/os/stdpaths_defs.h"

View File

@ -66,7 +66,6 @@ defsfile:write(string.format([[
#include "nvim/ex_session.h"
#include "nvim/help.h"
#include "nvim/indent.h"
#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
@ -75,6 +74,7 @@ defsfile:write(string.format([[
#include "nvim/message.h"
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/os/lang.h"
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/runtime.h"

View File

@ -1,377 +0,0 @@
// 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 <stdbool.h>
#include <stdio.h>
#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/ex_cmds_defs.h"
#include "nvim/garray.h"
#include "nvim/gettext.h"
#include "nvim/locale.h"
#include "nvim/macros.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"
#include "nvim/vim.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(const 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 = skiptowhite(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 MSWIN
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 = get_cmd_output("locale -a", NULL, kShellOptSilent, NULL);
if (locale_a == NULL) {
return NULL;
}
ga_init(&locales_ga, sizeof(char *), 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 **)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 MSWIN
if (did_init_locales) {
return;
}
did_init_locales = true;
locales = find_locales();
# endif
}
# if defined(EXITFREE)
void free_locales(void)
{
if (locales == NULL) {
return;
}
for (int 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

View File

@ -1,10 +0,0 @@
#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

View File

@ -41,7 +41,6 @@
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/locale.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"
@ -60,6 +59,7 @@
#include "nvim/optionstr.h"
#include "nvim/os/fileio.h"
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
@ -192,12 +192,10 @@ void early_init(mparm_T *paramp)
TIME_MSG("early init");
#if defined(HAVE_LOCALE_H)
// Setup to use the current locale (for ctype() and many other things).
// NOTE: Translated messages with encodings other than latin1 will not
// work until set_init_1() has been called!
init_locale();
#endif
// tabpage local options (p_ch) must be set before allocating first tabpage.
set_init_tablocal();

View File

@ -29,6 +29,7 @@
#include <ctype.h>
#include <errno.h>
#include <iconv.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -67,10 +68,6 @@
#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
typedef struct {
int rangeStart;
int rangeEnd;
@ -2193,10 +2190,7 @@ char *enc_locale(void)
if (!(s = nl_langinfo(CODESET)) || *s == NUL)
#endif
{
#if defined(HAVE_LOCALE_H)
if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL)
#endif
{
if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL) {
if ((s = os_getenv("LC_ALL"))) {
if ((s = os_getenv("LC_CTYPE"))) {
s = os_getenv("LANG");

View File

@ -62,7 +62,6 @@
#include "nvim/indent_c.h"
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/locale.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"

View File

@ -7,16 +7,347 @@
# include <CoreServices/CoreServices.h>
# undef Boolean
# undef FileInfo
# include "auto/config.h"
# ifdef HAVE_LOCALE_H
# include <locale.h>
# endif
# include "nvim/os/os.h"
#endif
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include "auto/config.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/garray.h"
#include "nvim/gettext.h"
#include "nvim/macros.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/profile.h"
#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/lang.c.generated.h"
#endif
static char *get_locale_val(int what)
{
// Obtain the locale value from the libraries.
char *loc = setlocale(what, NULL);
return loc;
}
/// @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(const 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;
#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
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"
}
if (p == NULL) {
p = get_locale_val(LC_CTYPE);
}
}
}
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;
loc = get_locale_val(LC_CTYPE);
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);
loc = get_locale_val(LC_TIME);
set_vim_var_string(VV_LC_TIME, loc, -1);
loc = get_locale_val(LC_COLLATE);
set_vim_var_string(VV_COLLATE, loc, -1);
}
/// 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");
}
#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 = skiptowhite(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 MSWIN
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 = get_cmd_output("locale -a", NULL, kShellOptSilent, NULL);
if (locale_a == NULL) {
return NULL;
}
ga_init(&locales_ga, sizeof(char *), 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 **)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 MSWIN
if (did_init_locales) {
return;
}
did_init_locales = true;
locales = find_locales();
# endif
}
# if defined(EXITFREE)
void free_locales(void)
{
if (locales == NULL) {
return;
}
for (int 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
void lang_init(void)
{

View File

@ -1,6 +1,9 @@
#ifndef NVIM_OS_LANG_H
#define NVIM_OS_LANG_H
#include "nvim/ex_cmds_defs.h"
#include "nvim/types.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/lang.h.generated.h"
#endif