2 * generate_language_id_map.c
4 * Generate a memory-efficient map from Windows language IDs to names. This
5 * program runs on Windows and uses LCIDToLocaleName() to enumerate all
6 * languages recognized by Windows.
8 * ----------------------------------------------------------------------------
10 * Copyright (C) 2016 Eric Biggers
12 * This file is free software; you can redistribute it and/or modify it under
13 * the terms of the GNU Lesser General Public License as published by the Free
14 * Software Foundation; either version 3 of the License, or (at your option) any
17 * This file is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this file; if not, see http://www.gnu.org/licenses/.
26 #define WINVER 0x6000 /* Needed for LCIDToLocaleName() declaration */
35 char name[LOCALE_NAME_MAX_LENGTH];
40 uint32_t num_languages = 0;
41 uint32_t name_start_offset = 0;
43 bool need_new_line = true;
45 for (uint32_t lcid = 0; lcid < 65536; lcid++) {
46 wchar_t locale_name[LOCALE_NAME_MAX_LENGTH];
48 if (LCIDToLocaleName(lcid, locale_name, LOCALE_NAME_MAX_LENGTH, 0)) {
49 size_t len = wcslen(locale_name);
50 for (size_t j = 0; j <= len; j++) {
51 if (locale_name[j] > 127) {
53 "ERROR: locale name \"%ls\" "
54 "includes non-ASCII characters",
58 map[num_languages].name[j] = locale_name[j];
60 map[num_languages++].id = lcid;
61 } else if (GetLastError() != ERROR_INVALID_PARAMETER) {
63 "ERROR: LCIDToLocaleName(%"PRIx32"): %u\n",
64 lcid, (unsigned)GetLastError());
69 printf("static const struct {\n");
70 printf("\tu16 id;\n");
71 printf("\tu16 name_start_offset;\n");
72 printf("} language_id_map[%"PRIu32"] = {", num_languages);
73 for (uint32_t i = 0; i < num_languages; i++) {
76 printf("{0x%04x, %4"PRIu32"},", map[i].id, name_start_offset);
77 need_new_line = (i % 4 == 3);
80 name_start_offset += strlen(map[i].name) + 1;
81 if (name_start_offset > 65536) {
82 fprintf(stderr, "ERROR: total length of "
83 "language names is too long!");
90 printf("static const char language_names[%"PRIu32"] =\n",
94 for (uint32_t i = 0; i < num_languages; i++) {
95 size_t len = strlen(map[i].name);
96 need_new_line = (num_chars + len + 3 > 80);
102 printf("%s\\0", map[i].name);
103 num_chars += len + 2;