|
23 | 23 | #include <stdio.h> |
24 | 24 | #include <stdlib.h> |
25 | 25 | #include <string.h> |
| 26 | +#include <strings.h> |
26 | 27 |
|
27 | 28 | #include <uniconv.h> |
28 | 29 | #include <unictype.h> |
@@ -57,6 +58,81 @@ const ucs4_t char_nul = 0x00000000; |
57 | 58 |
|
58 | 59 |
|
59 | 60 |
|
| 61 | +#ifdef _WIN32 |
| 62 | +static const char *get_locale_from_environment() |
| 63 | +{ |
| 64 | + const char *locale = getenv("LC_ALL"); |
| 65 | + if (locale == NULL || locale[0] == '\0') { |
| 66 | + locale = getenv("LC_CTYPE"); |
| 67 | + } |
| 68 | + if (locale == NULL || locale[0] == '\0') { |
| 69 | + locale = getenv("LANG"); |
| 70 | + } |
| 71 | + return locale != NULL && locale[0] != '\0' ? locale : NULL; |
| 72 | +} |
| 73 | + |
| 74 | + |
| 75 | +static int is_all_digits(const char *s) |
| 76 | +{ |
| 77 | + if (s == NULL || s[0] == '\0') { |
| 78 | + return 0; |
| 79 | + } |
| 80 | + for (const char *p = s; *p != '\0'; p++) { |
| 81 | + if (*p < '0' || *p > '9') { |
| 82 | + return 0; |
| 83 | + } |
| 84 | + } |
| 85 | + return 1; |
| 86 | +} |
| 87 | + |
| 88 | + |
| 89 | +static const char *extract_locale_encoding(const char *locale) |
| 90 | +{ |
| 91 | + static char encoding_buffer[32]; |
| 92 | + if (locale == NULL) { |
| 93 | + return NULL; |
| 94 | + } |
| 95 | + |
| 96 | + const char *dot = strrchr(locale, '.'); |
| 97 | + if (dot == NULL || dot[1] == '\0') { |
| 98 | + return NULL; |
| 99 | + } |
| 100 | + |
| 101 | + const char *start = dot + 1; |
| 102 | + const char *end = strchr(start, '@'); |
| 103 | + size_t len = end == NULL ? strlen(start) : (size_t) (end - start); |
| 104 | + if (len == 0 || len >= sizeof(encoding_buffer)) { |
| 105 | + return NULL; |
| 106 | + } |
| 107 | + |
| 108 | + memcpy(encoding_buffer, start, len); |
| 109 | + encoding_buffer[len] = '\0'; |
| 110 | + if (strcasecmp(encoding_buffer, "UTF8") == 0 |
| 111 | + || strcasecmp(encoding_buffer, "UTF-8") == 0 |
| 112 | + || strcasecmp(encoding_buffer, "CP65001") == 0 |
| 113 | + || strcmp(encoding_buffer, "65001") == 0) |
| 114 | + { |
| 115 | + return "UTF-8"; |
| 116 | + } |
| 117 | + if ((encoding_buffer[0] == 'C' || encoding_buffer[0] == 'c') |
| 118 | + && (encoding_buffer[1] == 'P' || encoding_buffer[1] == 'p') |
| 119 | + && is_all_digits(encoding_buffer + 2)) |
| 120 | + { |
| 121 | + encoding_buffer[0] = 'C'; |
| 122 | + encoding_buffer[1] = 'P'; |
| 123 | + return encoding_buffer; |
| 124 | + } |
| 125 | + if (is_all_digits(encoding_buffer)) { |
| 126 | + static char codepage_buffer[32]; |
| 127 | + snprintf(codepage_buffer, sizeof(codepage_buffer), "CP%s", encoding_buffer); |
| 128 | + return codepage_buffer; |
| 129 | + } |
| 130 | + return encoding_buffer; |
| 131 | +} |
| 132 | +#endif |
| 133 | + |
| 134 | + |
| 135 | + |
60 | 136 | int is_char_at(const uint32_t *text, const size_t idx, const ucs4_t expected_char) |
61 | 137 | { |
62 | 138 | return text != NULL && u32_cmp(text + idx, &expected_char, 1) == 0; |
@@ -265,6 +341,22 @@ char *u32_strconv_to_arg(const uint32_t *src, const char *targetEncoding) |
265 | 341 |
|
266 | 342 |
|
267 | 343 |
|
| 344 | +const char *get_default_encoding() |
| 345 | +{ |
| 346 | + const char *system_encoding = locale_charset(); |
| 347 | + |
| 348 | + #ifdef _WIN32 |
| 349 | + const char *env_encoding = extract_locale_encoding(get_locale_from_environment()); |
| 350 | + if (env_encoding != NULL) { |
| 351 | + return check_encoding(env_encoding, system_encoding); |
| 352 | + } |
| 353 | + #endif |
| 354 | + |
| 355 | + return system_encoding; |
| 356 | +} |
| 357 | + |
| 358 | + |
| 359 | + |
268 | 360 | const char *check_encoding(const char *manual_encoding, const char *system_encoding) |
269 | 361 | { |
270 | 362 | if (manual_encoding != NULL) { |
|
0 commit comments