GnuCash c935c2f+
Loading...
Searching...
No Matches
gnucash-locale-windows.c
1/*
2 * gnucash-locale-windows.c -- Windows specific locale handling
3 *
4 * Copyright (C) 2020 John Ralls <jralls@ceridwen.us>
5 * Copyright (C) 2021 Geert Janssens <geert@kobaltwit.be>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, contact:
19 *
20 * Free Software Foundation Voice: +1-617-542-5942
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
22 * Boston, MA 02110-1301, USA gnu@gnu.org
23 */
24
25#include <Windows.h>
26#include <fcntl.h>
27#include <glib/gi18n.h>
28#include "gnucash-locale-platform.h"
29
30static void
31rectify_utf(const char* envvar, const char* locale,
32 const char* dot, const char* rest)
33{
34 char *new_locale;
35 if (rest && *rest)
36 new_locale = g_strdup_printf ("%s.UTF-%s@%s",
37 locale, dot + 3, rest);
38 else
39 new_locale = g_strdup_printf ("%s.UTF-%s", locale, dot + 3);
40
41 _putenv_s (envvar, new_locale);
42 g_free(new_locale);
43}
44
45static void
46rectify_iso(const char* envvar, const char* locale,
47 const char* dot, const char* rest)
48{
49
50 char *eefn = strstr (dot, "8859");
51
52 if (!(eefn && *eefn))
53 return;
54
55 char* isonum = (*(eefn + 4) == '-') ? eefn + 5 : eefn + 4;
56
57 if (*isonum == '\0')
58 return;
59
60 char *new_locale;
61 if (rest && *rest)
62 new_locale = g_strdup_printf ("%s.ISO-8859-%s@%s", locale, isonum, rest);
63 else
64 new_locale = g_strdup_printf ("%s.ISO-8859-%s", locale, isonum);
65
66 _putenv_s (envvar, new_locale);
67 g_free (new_locale);
68}
69
70static void
71rectify_environment_charset(const char* envvar)
72{
73 if (!(envvar && *envvar))
74 return;
75 if (strcmp (envvar, "LANG") && strncmp (envvar, "LC_", 3))
76 return;
77 char* saveptr;
78 char* varval = getenv (envvar);
79 char* locale = strtok_r (varval, ".", &saveptr);
80 char* dot = strtok_r (NULL, "@", &saveptr);
81
82 if (!dot) //strsep didn't find a .
83 return;
84
85 char* rest = strtok_r (NULL, "@", &saveptr);
86
87 if ((strncasecmp (dot, "utf", 3) == 0 || strncasecmp (dot, "ucs", 3) == 0) &&
88 dot[3] != '-')
89 return rectify_utf (envvar, locale, dot, rest);
90
91 if (strncasecmp (dot, "iso", 3) == 0 && strlen (dot) >= 8 &&
92 dot[3] != '-' && dot[8] != '-')
93 return rectify_iso (envvar, locale, dot, rest);
94
95 //Otherwise do nothing
96}
97
98/* If one of the Unix locale variables LC_ALL, LC_MESSAGES, or LANG is
99 * set in the environment check to see if it's a valid locale and if
100 * it is set both the Windows and POSIX locales to that. If not
101 * retrieve the Windows locale and set POSIX to match.
102 */
103char *
104set_platform_locale(void)
105{
106 WCHAR lpLocaleName[LOCALE_NAME_MAX_LENGTH];
107 char *locale = NULL;
108 /* Prevent Bug 799320 by ensuring that the localization
109 environment variables of interest have well-formed UTF or
110 ISO-8859 specifiers for GnuLib's interpretation of well-formed,
111 which means having minuses in the right places. This only
112 protects agains missing hyphens, it won't help if you specify
113 utf42 as a charset when you meant utf32.
114 */
115 rectify_environment_charset ("LANG");
116 rectify_environment_charset ("LC_ALL");
117 rectify_environment_charset ("LC_MESSAGES");
118 rectify_environment_charset ("LC_CTYPE");
119
120 if (((locale = getenv ("LC_ALL")) != NULL && locale[0] != '\0') ||
121 ((locale = getenv ("LC_MESSAGES")) != NULL && locale[0] != '\0') ||
122 ((locale = getenv ("LANG")) != NULL && locale[0] != '\0'))
123 {
124 gunichar2* wlocale = NULL;
125 int len = 0;
126 len = strchr(locale, '.') - locale;
127 locale[2] = '-';
128 wlocale = g_utf8_to_utf16 (locale, len, NULL, NULL, NULL);
129 if (IsValidLocaleName(wlocale))
130 {
131 LCID lcid = LocaleNameToLCID(wlocale, LOCALE_ALLOW_NEUTRAL_NAMES);
132 SetThreadLocale(lcid);
133 locale[2] = '_';
134 setlocale (LC_ALL, locale);
135 g_free(wlocale);
136 return g_strdup (locale);
137 }
138 g_free(locale);
139 g_free(wlocale);
140 }
141 if (GetUserDefaultLocaleName(lpLocaleName, LOCALE_NAME_MAX_LENGTH))
142 {
143 locale = g_utf16_to_utf8((gunichar2*)lpLocaleName,
144 LOCALE_NAME_MAX_LENGTH,
145 NULL, NULL, NULL);
146 (locale)[2] = '_';
147 setlocale (LC_ALL, locale);
148 return locale;
149 }
150 return g_strdup("C");
151}