FreeRDP
xkb_layout_ids.c
1 
20 #include <freerdp/config.h>
21 
22 #include "xkb_layout_ids.h"
23 
24 #include <string.h>
25 
26 #include <winpr/crt.h>
27 
28 #include <freerdp/locale/keyboard.h>
29 
30 #include "liblocale.h"
31 
32 typedef struct
33 {
34  const char* variant; /* XKB Keyboard layout variant */
35  UINT32 keyboardLayoutID; /* Keyboard Layout ID */
36 } XKB_VARIANT;
37 
38 typedef struct
39 {
40  const char* layout; /* XKB Keyboard layout */
41  UINT32 keyboardLayoutID; /* Keyboard Layout ID */
42  const XKB_VARIANT* variants;
43 } XKB_LAYOUT;
44 
45 /* Those have been generated automatically and are waiting to be filled by hand */
46 
47 /* USA */
48 static const XKB_VARIANT us_variants[] = {
49  { "chr", 0 }, /* Cherokee */
50  { "euro", 0 }, /* With EuroSign on 5 */
51  { "intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (with dead keys) */
52  { "alt-intl",
53  KBD_UNITED_STATES_INTERNATIONAL }, /* Alternative international (former us_intl) */
54  { "colemak", 0 }, /* Colemak */
55  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
56  { "dvorak-intl", KBD_UNITED_STATES_DVORAK }, /* Dvorak international */
57  { "dvorak-l", KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND }, /* Left handed Dvorak */
58  { "dvorak-r", KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND }, /* Right handed Dvorak */
59  { "dvorak-classic", KBD_UNITED_STATES_DVORAK }, /* Classic Dvorak */
60  { "dvp", KBD_UNITED_STATES_DVORAK_PROGRAMMER }, /* Programmer Dvorak */
61  { "rus", 0 }, /* Russian phonetic */
62  { "mac", KBD_US }, /* Macintosh */
63  { "altgr-intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (AltGr dead keys) */
64  { "olpc2", KBD_US }, /* Group toggle on multiply/divide key */
65  { "", 0 },
66 };
67 
68 /* Afghanistan */
69 static const XKB_VARIANT af_variants[] = {
70  { "ps", KBD_PASHTO }, /* Pashto */
71  { "uz", KBD_UZBEK_CYRILLIC }, /* Southern Uzbek */
72  { "olpc-ps", KBD_PASHTO }, /* OLPC Pashto */
73  { "olpc-fa", 0 }, /* OLPC Dari */
74  { "olpc-uz", KBD_UZBEK_CYRILLIC }, /* OLPC Southern Uzbek */
75  { "", 0 },
76 };
77 
78 /* Arabic */
79 static const XKB_VARIANT ara_variants[] = {
80  { "azerty", KBD_ARABIC_102_AZERTY }, /* azerty */
81  { "azerty_digits", KBD_ARABIC_102_AZERTY }, /* azerty/digits */
82  { "digits", KBD_ARABIC_102_AZERTY }, /* digits */
83  { "qwerty", KBD_ARABIC_101 }, /* qwerty */
84  { "qwerty_digits", KBD_ARABIC_101 }, /* qwerty/digits */
85  { "buckwalter", KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L }, /* Buckwalter */
86  { "", 0 },
87 };
88 
89 /* Armenia */
90 static const XKB_VARIANT am_variants[] = {
91  { "phonetic", 0 }, /* Phonetic */
92  { "phonetic-alt", 0 }, /* Alternative Phonetic */
93  { "eastern", KBD_ARMENIAN_EASTERN }, /* Eastern */
94  { "western", KBD_ARMENIAN_WESTERN }, /* Western */
95  { "eastern-alt", KBD_ARMENIAN_EASTERN }, /* Alternative Eastern */
96  { "", 0 },
97 };
98 
99 /* Azerbaijan */
100 static const XKB_VARIANT az_variants[] = {
101  { "cyrillic", KBD_AZERI_CYRILLIC }, /* Cyrillic */
102  { "", 0 },
103 };
104 
105 /* Belarus */
106 static const XKB_VARIANT by_variants[] = {
107  { "winkeys", KBD_BELARUSIAN }, /* Winkeys */
108  { "latin", KBD_BELARUSIAN }, /* Latin */
109  { "", 0 },
110 };
111 
112 /* Belgium */
113 static const XKB_VARIANT be_variants[] = {
114  { "oss", KBD_BELGIAN_FRENCH }, /* Alternative */
115  { "oss_latin9", KBD_BELGIAN_FRENCH }, /* Alternative, latin-9 only */
116  { "oss_sundeadkeys", KBD_BELGIAN_PERIOD }, /* Alternative, Sun dead keys */
117  { "iso-alternate", KBD_BELGIAN_COMMA }, /* ISO Alternate */
118  { "nodeadkeys", KBD_BELGIAN_COMMA }, /* Eliminate dead keys */
119  { "sundeadkeys", KBD_BELGIAN_PERIOD }, /* Sun dead keys */
120  { "wang", KBD_BELGIAN_FRENCH }, /* Wang model 724 azerty */
121  { "", 0 },
122 };
123 
124 /* Bangladesh */
125 static const XKB_VARIANT bd_variants[] = {
126  { "probhat", KBD_BENGALI_INSCRIPT }, /* Probhat */
127  { "", 0 },
128 };
129 
130 /* India */
131 static const XKB_VARIANT in_variants[] = {
132  { "ben", KBD_BENGALI }, /* Bengali */
133  { "ben_probhat", KBD_BENGALI_INSCRIPT }, /* Bengali Probhat */
134  { "guj", KBD_GUJARATI }, /* Gujarati */
135  { "guru", 0 }, /* Gurmukhi */
136  { "jhelum", 0 }, /* Gurmukhi Jhelum */
137  { "kan", KBD_KANNADA }, /* Kannada */
138  { "mal", KBD_MALAYALAM }, /* Malayalam */
139  { "mal_lalitha", KBD_MALAYALAM }, /* Malayalam Lalitha */
140  { "ori", 0 }, /* Oriya */
141  { "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */
142  { "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */
143  { "tam_TSCII", KBD_TAMIL }, /* Tamil TSCII Typewriter */
144  { "tam", KBD_TAMIL }, /* Tamil */
145  { "tel", KBD_TELUGU }, /* Telugu */
146  { "urd-phonetic", KBD_URDU }, /* Urdu, Phonetic */
147  { "urd-phonetic3", KBD_URDU }, /* Urdu, Alternative phonetic */
148  { "urd-winkeys", KBD_URDU }, /* Urdu, Winkeys */
149  { "bolnagri", KBD_HINDI_TRADITIONAL }, /* Hindi Bolnagri */
150  { "hin-wx", KBD_HINDI_TRADITIONAL }, /* Hindi Wx */
151  { "", 0 },
152 };
153 
154 /* Bosnia and Herzegovina */
155 static const XKB_VARIANT ba_variants[] = {
156  { "alternatequotes", KBD_BOSNIAN }, /* Use guillemets for quotes */
157  { "unicode", KBD_BOSNIAN }, /* Use Bosnian digraphs */
158  { "unicodeus", KBD_BOSNIAN }, /* US keyboard with Bosnian digraphs */
159  { "us", KBD_BOSNIAN_CYRILLIC }, /* US keyboard with Bosnian letters */
160  { "", 0 },
161 };
162 
163 /* Brazil */
164 static const XKB_VARIANT br_variants[] = {
165  { "nodeadkeys", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Eliminate dead keys */
166  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
167  { "nativo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo */
168  { "nativo-us", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for USA keyboards */
169  { "nativo-epo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for Esperanto */
170  { "", 0 },
171 };
172 
173 /* Bulgaria */
174 static const XKB_VARIANT bg_variants[] = {
175  { "phonetic", KBD_BULGARIAN_LATIN }, /* Traditional Phonetic */
176  { "bas_phonetic", KBD_BULGARIAN_LATIN }, /* Standard Phonetic */
177  { "", 0 },
178 };
179 
180 /* Morocco */
181 static const XKB_VARIANT ma_variants[] = {
182  { "french", KBD_FRENCH }, /* French */
183  { "tifinagh", 0 }, /* Tifinagh */
184  { "tifinagh-alt", 0 }, /* Tifinagh Alternative */
185  { "tifinagh-alt-phonetic", 0 }, /* Tifinagh Alternative Phonetic */
186  { "tifinagh-extended", 0 }, /* Tifinagh Extended */
187  { "tifinagh-phonetic", 0 }, /* Tifinagh Phonetic */
188  { "tifinagh-extended-phonetic", 0 }, /* Tifinagh Extended Phonetic */
189  { "", 0 },
190 };
191 
192 /* Canada */
193 static const XKB_VARIANT ca_variants[] = {
194  { "fr", KBD_CANADIAN_FRENCH }, /* French Dvorak */
195  { "fr-dvorak", KBD_UNITED_STATES_DVORAK }, /* French Dvorak */
196  { "fr-legacy", KBD_CANADIAN_FRENCH_LEGACY }, /* French (legacy) */
197  { "multix", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual */
198  { "multi", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, first part */
199  { "multi-2gr", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, second part */
200  { "ike", KBD_INUKTITUT_LATIN }, /* Inuktitut */
201  { "shs", 0 }, /* Secwepemctsin */
202  { "kut", 0 }, /* Ktunaxa */
203  { "", 0 },
204 };
205 
206 /* China */
207 static const XKB_VARIANT cn_variants[] = {
208  { "tib", 0 }, /* Tibetan */
209  { "tib_asciinum", 0 }, /* Tibetan (with ASCII numerals) */
210  { "", 0 },
211 };
212 
213 /* Croatia */
214 static const XKB_VARIANT hr_variants[] = {
215  { "alternatequotes", KBD_CROATIAN }, /* Use guillemets for quotes */
216  { "unicode", KBD_CROATIAN }, /* Use Croatian digraphs */
217  { "unicodeus", KBD_CROATIAN }, /* US keyboard with Croatian digraphs */
218  { "us", KBD_CROATIAN }, /* US keyboard with Croatian letters */
219  { "", 0 },
220 };
221 
222 /* Czechia */
223 static const XKB_VARIANT cz_variants[] = {
224  { "bksl", KBD_CZECH_PROGRAMMERS }, /* With &lt;\|&gt; key */
225  { "qwerty", KBD_CZECH_QWERTY }, /* qwerty */
226  { "qwerty_bksl", KBD_CZECH_QWERTY }, /* qwerty, extended Backslash */
227  { "ucw", KBD_CZECH }, /* UCW layout (accented letters only) */
228  { "", 0 },
229 };
230 
231 /* Denmark */
232 static const XKB_VARIANT dk_variants[] = {
233  { "nodeadkeys", KBD_DANISH }, /* Eliminate dead keys */
234  { "mac", KBD_DANISH }, /* Macintosh */
235  { "mac_nodeadkeys", KBD_DANISH }, /* Macintosh, eliminate dead keys */
236  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
237  { "", 0 },
238 };
239 
240 /* Netherlands */
241 static const XKB_VARIANT nl_variants[] = {
242  { "sundeadkeys", KBD_SWISS_FRENCH }, /* Sun dead keys */
243  { "mac", KBD_SWISS_FRENCH }, /* Macintosh */
244  { "std", KBD_SWISS_FRENCH }, /* Standard */
245  { "", 0 },
246 };
247 
248 /* Estonia */
249 static const XKB_VARIANT ee_variants[] = {
250  { "nodeadkeys", KBD_US }, /* Eliminate dead keys */
251  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
252  { "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Estonian letters */
253  { "", 0 },
254 };
255 
256 /* Iran */
257 static const XKB_VARIANT ir_variants[] = {
258  { "pro", 0 }, /* Pro */
259  { "keypad", 0 }, /* Keypad */
260  { "pro_keypad", 0 }, /* Pro Keypad */
261  { "ku", 0 }, /* Kurdish, Latin Q */
262  { "ku_f", 0 }, /* Kurdish, (F) */
263  { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
264  { "ku_ara", 0 }, /* Kurdish, Arabic-Latin */
265  { "", 0 },
266 };
267 
268 /* Iraq */
269 static const XKB_VARIANT iq_variants[] = {
270  { "ku", 0 }, /* Kurdish, Latin Q */
271  { "ku_f", 0 }, /* Kurdish, (F) */
272  { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
273  { "ku_ara", 0 }, /* Kurdish, Arabic-Latin */
274  { "", 0 },
275 };
276 
277 /* Faroe Islands */
278 static const XKB_VARIANT fo_variants[] = {
279  { "nodeadkeys", 0 }, /* Eliminate dead keys */
280  { "", 0 },
281 };
282 
283 /* Finland */
284 static const XKB_VARIANT fi_variants[] = {
285  { "nodeadkeys", 0 }, /* Eliminate dead keys */
286  { "smi", 0 }, /* Northern Saami */
287  { "classic", 0 }, /* Classic */
288  { "mac", 0 }, /* Macintosh */
289  { "", 0 },
290 };
291 
292 /* France */
293 static const XKB_VARIANT fr_variants[] = {
294  { "nodeadkeys", 0 }, /* Eliminate dead keys */
295  { "sundeadkeys", 0 }, /* Sun dead keys */
296  { "oss", 0 }, /* Alternative */
297  { "oss_latin9", 0 }, /* Alternative, latin-9 only */
298  { "oss_nodeadkeys", 0 }, /* Alternative, eliminate dead keys */
299  { "oss_sundeadkeys", 0 }, /* Alternative, Sun dead keys */
300  { "latin9", 0 }, /* (Legacy) Alternative */
301  { "latin9_nodeadkeys", 0 }, /* (Legacy) Alternative, eliminate dead keys */
302  { "latin9_sundeadkeys", 0 }, /* (Legacy) Alternative, Sun dead keys */
303  { "bepo", KBD_FRENCH_BEPO }, /* Bepo, ergonomic, Dvorak way */
304  { "bepo_latin9", 0 }, /* Bepo, ergonomic, Dvorak way, latin-9 only */
305  { "dvorak", 0 }, /* Dvorak */
306  { "mac", 0 }, /* Macintosh */
307  { "bre", 0 }, /* Breton */
308  { "oci", 0 }, /* Occitan */
309  { "geo", 0 }, /* Georgian AZERTY Tskapo */
310  { "", 0 },
311 };
312 
313 /* Ghana */
314 static const XKB_VARIANT gh_variants[] = {
315  { "generic", 0 }, /* Multilingual */
316  { "akan", 0 }, /* Akan */
317  { "ewe", 0 }, /* Ewe */
318  { "fula", 0 }, /* Fula */
319  { "ga", 0 }, /* Ga */
320  { "hausa", 0 }, /* Hausa */
321  { "", 0 },
322 };
323 
324 /* Georgia */
325 static const XKB_VARIANT ge_variants[] = {
326  { "ergonomic", 0 }, /* Ergonomic */
327  { "mess", 0 }, /* MESS */
328  { "ru", 0 }, /* Russian */
329  { "os", 0 }, /* Ossetian */
330  { "", 0 },
331 };
332 
333 /* Germany */
334 static const XKB_VARIANT de_variants[] = {
335  { "deadacute", KBD_GERMAN }, /* Dead acute */
336  { "deadgraveacute", KBD_GERMAN }, /* Dead grave acute */
337  { "nodeadkeys", KBD_GERMAN }, /* Eliminate dead keys */
338  { "ro", KBD_GERMAN }, /* Romanian keyboard with German letters */
339  { "ro_nodeadkeys",
340  KBD_GERMAN }, /* Romanian keyboard with German letters, eliminate dead keys */
341  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
342  { "sundeadkeys", KBD_GERMAN }, /* Sun dead keys */
343  { "neo", KBD_GERMAN_NEO }, /* Neo 2 */
344  { "mac", KBD_GERMAN }, /* Macintosh */
345  { "mac_nodeadkeys", KBD_GERMAN }, /* Macintosh, eliminate dead keys */
346  { "dsb", KBD_GERMAN }, /* Lower Sorbian */
347  { "dsb_qwertz", KBD_GERMAN }, /* Lower Sorbian (qwertz) */
348  { "qwerty", KBD_GERMAN_IBM }, /* qwerty */
349  { "", 0 },
350 };
351 
352 /* Greece */
353 static const XKB_VARIANT gr_variants[] = {
354  { "simple", KBD_GREEK_220 }, /* Simple */
355  { "extended", KBD_GREEK_319 }, /* Extended */
356  { "nodeadkeys", KBD_GREEK_319 }, /* Eliminate dead keys */
357  { "polytonic", KBD_GREEK_POLYTONIC }, /* Polytonic */
358  { "", 0 },
359 };
360 
361 /* Hungary */
362 static const XKB_VARIANT hu_variants[] = {
363  { "standard", KBD_HUNGARIAN_101_KEY }, /* Standard */
364  { "nodeadkeys", KBD_HUNGARIAN_101_KEY }, /* Eliminate dead keys */
365  { "qwerty", KBD_HUNGARIAN_101_KEY }, /* qwerty */
366  { "101_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Dead keys */
367  { "101_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Eliminate dead keys */
368  { "101_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Dead keys */
369  { "101_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Eliminate dead keys */
370  { "101_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Dead keys */
371  { "101_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Eliminate dead keys */
372  { "101_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Dead keys */
373  { "101_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Eliminate dead keys */
374  { "102_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Dead keys */
375  { "102_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Eliminate dead keys */
376  { "102_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Dead keys */
377  { "102_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Eliminate dead keys */
378  { "102_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Dead keys */
379  { "102_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Eliminate dead keys */
380  { "102_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Dead keys */
381  { "102_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Eliminate dead keys */
382  { "", 0 },
383 };
384 
385 /* Iceland */
386 static const XKB_VARIANT is_variants[] = {
387  { "Sundeadkeys", KBD_ICELANDIC }, /* Sun dead keys */
388  { "nodeadkeys", KBD_ICELANDIC }, /* Eliminate dead keys */
389  { "mac", KBD_ICELANDIC }, /* Macintosh */
390  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
391  { "", 0 },
392 };
393 
394 /* Israel */
395 static const XKB_VARIANT il_variants[] = {
396  { "lyx", KBD_HEBREW }, /* lyx */
397  { "phonetic", KBD_HEBREW }, /* Phonetic */
398  { "biblical", KBD_HEBREW }, /* Biblical Hebrew (Tiro) */
399  { "", 0 },
400 };
401 
402 /* Italy */
403 static const XKB_VARIANT it_variants[] = {
404  { "nodeadkeys", KBD_ITALIAN_142 }, /* Eliminate dead keys */
405  { "mac", KBD_ITALIAN }, /* Macintosh */
406  { "geo", KBD_GEORGIAN }, /* Georgian */
407  { "", 0 },
408 };
409 
410 /* Japan */
411 static const XKB_VARIANT jp_variants[] = {
412  { "kana", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Kana */
413  { "OADG109A", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* OADG 109A */
414  { "", 0 },
415 };
416 
417 /* Kyrgyzstan */
418 static const XKB_VARIANT kg_variants[] = {
419  { "phonetic", KBD_KYRGYZ_CYRILLIC }, /* Phonetic */
420  { "", 0 },
421 };
422 
423 /* Kazakhstan */
424 static const XKB_VARIANT kz_variants[] = {
425  { "ruskaz", KBD_KAZAKH }, /* Russian with Kazakh */
426  { "kazrus", KBD_KAZAKH }, /* Kazakh with Russian */
427  { "", 0 },
428 };
429 
430 /* Latin America */
431 static const XKB_VARIANT latam_variants[] = {
432  { "nodeadkeys", KBD_LATIN_AMERICAN }, /* Eliminate dead keys */
433  { "deadtilde", KBD_LATIN_AMERICAN }, /* Include dead tilde */
434  { "sundeadkeys", KBD_LATIN_AMERICAN }, /* Sun dead keys */
435  { "", 0 },
436 };
437 
438 /* Lithuania */
439 static const XKB_VARIANT lt_variants[] = {
440  { "std", KBD_LITHUANIAN }, /* Standard */
441  { "us", KBD_LITHUANIAN_IBM }, /* US keyboard with Lithuanian letters */
442  { "ibm", KBD_LITHUANIAN_IBM }, /* IBM (LST 1205-92) */
443  { "lekp", KBD_LITHUANIAN }, /* LEKP */
444  { "lekpa", KBD_LITHUANIAN }, /* LEKPa */
445  { "balticplus", KBD_LITHUANIAN }, /* Baltic+ */
446  { "", 0 },
447 };
448 
449 /* Latvia */
450 static const XKB_VARIANT lv_variants[] = {
451  { "apostrophe", KBD_LATVIAN }, /* Apostrophe (') variant */
452  { "tilde", KBD_LATVIAN }, /* Tilde (~) variant */
453  { "fkey", KBD_LATVIAN }, /* F-letter (F) variant */
454  { "", 0 },
455 };
456 
457 /* Montenegro */
458 static const XKB_VARIANT me_variants[] = {
459  { "cyrillic", 0 }, /* Cyrillic */
460  { "cyrillicyz", 0 }, /* Cyrillic, Z and ZHE swapped */
461  { "latinunicode", 0 }, /* Latin unicode */
462  { "latinyz", 0 }, /* Latin qwerty */
463  { "latinunicodeyz", 0 }, /* Latin unicode qwerty */
464  { "cyrillicalternatequotes", 0 }, /* Cyrillic with guillemets */
465  { "latinalternatequotes", 0 }, /* Latin with guillemets */
466  { "", 0 },
467 };
468 
469 /* Macedonia */
470 static const XKB_VARIANT mk_variants[] = {
471  { "nodeadkeys", KBD_FYRO_MACEDONIAN }, /* Eliminate dead keys */
472  { "", 0 },
473 };
474 
475 /* Malta */
476 static const XKB_VARIANT mt_variants[] = {
477  { "us", KBD_MALTESE_48_KEY }, /* Maltese keyboard with US layout */
478  { "", 0 },
479 };
480 
481 /* Norway */
482 static const XKB_VARIANT no_variants[] = {
483  { "nodeadkeys", KBD_NORWEGIAN }, /* Eliminate dead keys */
484  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
485  { "smi", KBD_NORWEGIAN_WITH_SAMI }, /* Northern Saami */
486  { "smi_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Northern Saami, eliminate dead keys */
487  { "mac", KBD_NORWEGIAN }, /* Macintosh */
488  { "mac_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Macintosh, eliminate dead keys */
489  { "", 0 },
490 };
491 
492 /* Poland */
493 static const XKB_VARIANT pl_variants[] = {
494  { "qwertz", KBD_POLISH_214 }, /* qwertz */
495  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
496  { "dvorak_quotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on quotemark key */
497  { "dvorak_altquotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on key 1 */
498  { "csb", 0 }, /* Kashubian */
499  { "ru_phonetic_dvorak", KBD_UNITED_STATES_DVORAK }, /* Russian phonetic Dvorak */
500  { "", 0 },
501 };
502 
503 /* Portugal */
504 static const XKB_VARIANT pt_variants[] = {
505  { "nodeadkeys", KBD_PORTUGUESE }, /* Eliminate dead keys */
506  { "sundeadkeys", KBD_PORTUGUESE }, /* Sun dead keys */
507  { "mac", KBD_PORTUGUESE }, /* Macintosh */
508  { "mac_nodeadkeys", KBD_PORTUGUESE }, /* Macintosh, eliminate dead keys */
509  { "mac_sundeadkeys", KBD_PORTUGUESE }, /* Macintosh, Sun dead keys */
510  { "nativo", KBD_PORTUGUESE }, /* Nativo */
511  { "nativo-us", KBD_PORTUGUESE }, /* Nativo for USA keyboards */
512  { "nativo-epo", KBD_PORTUGUESE }, /* Nativo for Esperanto */
513  { "", 0 },
514 };
515 
516 /* Romania */
517 static const XKB_VARIANT ro_variants[] = {
518  { "cedilla", KBD_ROMANIAN }, /* Cedilla */
519  { "std", KBD_ROMANIAN }, /* Standard */
520  { "std_cedilla", KBD_ROMANIAN }, /* Standard (Cedilla) */
521  { "winkeys", KBD_ROMANIAN }, /* Winkeys */
522  { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
523  { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
524  { "crh_dobruca1", KBD_TATAR }, /* Crimean Tatar (Dobruca-1 Q) */
525  { "crh_dobruca2", KBD_TATAR }, /* Crimean Tatar (Dobruca-2 Q) */
526  { "", 0 },
527 };
528 
529 /* Russia */
530 static const XKB_VARIANT ru_variants[] = {
531  { "phonetic", KBD_RUSSIAN }, /* Phonetic */
532  { "phonetic_winkeys", KBD_RUSSIAN }, /* Phonetic Winkeys */
533  { "typewriter", KBD_RUSSIAN_TYPEWRITER }, /* Typewriter */
534  { "legacy", KBD_RUSSIAN }, /* Legacy */
535  { "tt", KBD_TATAR }, /* Tatar */
536  { "os_legacy", 0 }, /* Ossetian, legacy */
537  { "os_winkeys", 0 }, /* Ossetian, Winkeys */
538  { "cv", 0 }, /* Chuvash */
539  { "cv_latin", 0 }, /* Chuvash Latin */
540  { "udm", 0 }, /* Udmurt */
541  { "kom", 0 }, /* Komi */
542  { "sah", 0 }, /* Yakut */
543  { "xal", 0 }, /* Kalmyk */
544  { "dos", 0 }, /* DOS */
545  { "", 0 },
546 };
547 
548 /* Serbia */
549 static const XKB_VARIANT rs_variants[] = {
550  { "yz", KBD_SERBIAN_CYRILLIC }, /* Z and ZHE swapped */
551  { "latin", KBD_SERBIAN_LATIN }, /* Latin */
552  { "latinunicode", KBD_SERBIAN_LATIN }, /* Latin Unicode */
553  { "latinyz", KBD_SERBIAN_LATIN }, /* Latin qwerty */
554  { "latinunicodeyz", KBD_SERBIAN_LATIN }, /* Latin Unicode qwerty */
555  { "alternatequotes", KBD_SERBIAN_CYRILLIC }, /* With guillemets */
556  { "latinalternatequotes", KBD_SERBIAN_LATIN }, /* Latin with guillemets */
557  { "", 0 },
558 };
559 
560 /* Slovenia */
561 static const XKB_VARIANT si_variants[] = {
562  { "alternatequotes", KBD_SLOVENIAN }, /* Use guillemets for quotes */
563  { "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Slovenian letters */
564  { "", 0 },
565 };
566 
567 /* Slovakia */
568 static const XKB_VARIANT sk_variants[] = {
569  { "bksl", KBD_SLOVAK }, /* Extended Backslash */
570  { "qwerty", KBD_SLOVAK_QWERTY }, /* qwerty */
571  { "qwerty_bksl", KBD_SLOVAK_QWERTY }, /* qwerty, extended Backslash */
572  { "", 0 },
573 };
574 
575 /* Spain */
576 static const XKB_VARIANT es_variants[] = {
577  { "nodeadkeys", KBD_SPANISH_VARIATION }, /* Eliminate dead keys */
578  { "deadtilde", KBD_SPANISH_VARIATION }, /* Include dead tilde */
579  { "sundeadkeys", KBD_SPANISH }, /* Sun dead keys */
580  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
581  { "ast", KBD_SPANISH_VARIATION }, /* Asturian variant with bottom-dot H and bottom-dot L */
582  { "cat", KBD_SPANISH_VARIATION }, /* Catalan variant with middle-dot L */
583  { "mac", KBD_SPANISH }, /* Macintosh */
584  { "", 0 },
585 };
586 
587 /* Sweden */
588 static const XKB_VARIANT se_variants[] = {
589  { "nodeadkeys", KBD_SWEDISH }, /* Eliminate dead keys */
590  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
591  { "rus", KBD_RUSSIAN }, /* Russian phonetic */
592  { "rus_nodeadkeys", KBD_RUSSIAN }, /* Russian phonetic, eliminate dead keys */
593  { "smi", KBD_SWEDISH_WITH_SAMI }, /* Northern Saami */
594  { "mac", KBD_SWEDISH }, /* Macintosh */
595  { "svdvorak", KBD_UNITED_STATES_DVORAK }, /* Svdvorak */
596  { "", 0 },
597 };
598 
599 /* Switzerland */
600 static const XKB_VARIANT ch_variants[] = {
601  { "de_nodeadkeys", KBD_SWISS_GERMAN }, /* German, eliminate dead keys */
602  { "de_sundeadkeys", KBD_SWISS_GERMAN }, /* German, Sun dead keys */
603  { "fr", KBD_SWISS_FRENCH }, /* French */
604  { "fr_nodeadkeys", KBD_SWISS_FRENCH }, /* French, eliminate dead keys */
605  { "fr_sundeadkeys", KBD_SWISS_FRENCH }, /* French, Sun dead keys */
606  { "fr_mac", KBD_SWISS_FRENCH }, /* French (Macintosh) */
607  { "de_mac", KBD_SWISS_GERMAN }, /* German (Macintosh) */
608  { "", 0 },
609 };
610 
611 /* Syria */
612 static const XKB_VARIANT sy_variants[] = {
613  { "syc", KBD_SYRIAC }, /* Syriac */
614  { "syc_phonetic", KBD_SYRIAC_PHONETIC }, /* Syriac phonetic */
615  { "ku", 0 }, /* Kurdish, Latin Q */
616  { "ku_f", 0 }, /* Kurdish, (F) */
617  { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
618  { "", 0 },
619 };
620 
621 /* Tajikistan */
622 static const XKB_VARIANT tj_variants[] = {
623  { "legacy", 0 }, /* Legacy */
624  { "", 0 },
625 };
626 
627 /* Sri Lanka */
628 static const XKB_VARIANT lk_variants[] = {
629  { "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */
630  { "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */
631  { "", 0 },
632 };
633 
634 /* Thailand */
635 static const XKB_VARIANT th_variants[] = {
636  { "tis", KBD_THAI_KEDMANEE_NON_SHIFTLOCK }, /* TIS-820.2538 */
637  { "pat", KBD_THAI_PATTACHOTE }, /* Pattachote */
638  { "", 0 },
639 };
640 
641 /* Turkey */
642 static const XKB_VARIANT tr_variants[] = {
643  { "f", KBD_TURKISH_F }, /* (F) */
644  { "alt", KBD_TURKISH_Q }, /* Alt-Q */
645  { "sundeadkeys", KBD_TURKISH_F }, /* Sun dead keys */
646  { "ku", 0 }, /* Kurdish, Latin Q */
647  { "ku_f", 0 }, /* Kurdish, (F) */
648  { "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
649  { "intl", KBD_TURKISH_F }, /* International (with dead keys) */
650  { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
651  { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
652  { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
653  { "", 0 },
654 };
655 
656 /* Ukraine */
657 static const XKB_VARIANT ua_variants[] = {
658  { "phonetic", KBD_UKRAINIAN }, /* Phonetic */
659  { "typewriter", KBD_UKRAINIAN }, /* Typewriter */
660  { "winkeys", KBD_UKRAINIAN }, /* Winkeys */
661  { "legacy", KBD_UKRAINIAN }, /* Legacy */
662  { "rstu", KBD_UKRAINIAN }, /* Standard RSTU */
663  { "rstu_ru", KBD_UKRAINIAN }, /* Standard RSTU on Russian layout */
664  { "homophonic", KBD_UKRAINIAN }, /* Homophonic */
665  { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
666  { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
667  { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
668  { "", 0 },
669 };
670 
671 /* United Kingdom */
672 static const XKB_VARIANT gb_variants[] = {
673  { "extd", KBD_UNITED_KINGDOM_EXTENDED }, /* Extended - Winkeys */
674  { "intl", KBD_UNITED_KINGDOM_EXTENDED }, /* International (with dead keys) */
675  { "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
676  { "dvorakukp", KBD_UNITED_STATES_DVORAK }, /* Dvorak (UK Punctuation) */
677  { "mac", KBD_UNITED_KINGDOM }, /* Macintosh */
678  { "colemak", 0 }, /* Colemak */
679  { "", 0 },
680 };
681 
682 /* Uzbekistan */
683 static const XKB_VARIANT uz_variants[] = {
684  { "latin", 0 }, /* Latin */
685  { "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
686  { "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
687  { "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
688  { "", 0 },
689 };
690 
691 /* Korea, Republic of */
692 static const XKB_VARIANT kr_variants[] = {
693  { "kr104", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* 101/104 key Compatible */
694  { "", 0 },
695 };
696 
697 /* Ireland */
698 static const XKB_VARIANT ie_variants[] = {
699  { "CloGaelach", KBD_GAELIC }, /* CloGaelach */
700  { "UnicodeExpert", KBD_GAELIC }, /* UnicodeExpert */
701  { "ogam", KBD_GAELIC }, /* Ogham */
702  { "ogam_is434", KBD_GAELIC }, /* Ogham IS434 */
703  { "", 0 },
704 };
705 
706 /* Pakistan */
707 static const XKB_VARIANT pk_variants[] = {
708  { "urd-crulp", 0 }, /* CRULP */
709  { "urd-nla", 0 }, /* NLA */
710  { "ara", KBD_ARABIC_101 }, /* Arabic */
711  { "", 0 },
712 };
713 
714 /* Esperanto */
715 static const XKB_VARIANT epo_variants[] = {
716  { "legacy", 0 }, /* displaced semicolon and quote (obsolete) */
717  { "", 0 },
718 };
719 
720 /* Nigeria */
721 static const XKB_VARIANT ng_variants[] = {
722  { "igbo", 0 }, /* Igbo */
723  { "yoruba", 0 }, /* Yoruba */
724  { "hausa", 0 }, /* Hausa */
725  { "", 0 },
726 };
727 
728 /* Braille */
729 static const XKB_VARIANT brai_variants[] = {
730  { "left_hand", 0 }, /* Left hand */
731  { "right_hand", 0 }, /* Right hand */
732  { "", 0 },
733 };
734 
735 /* Turkmenistan */
736 static const XKB_VARIANT tm_variants[] = {
737  { "alt", KBD_TURKISH_Q }, /* Alt-Q */
738  { "", 0 },
739 };
740 
741 static const XKB_LAYOUT xkbLayouts[] = {
742  { "us", KBD_US, us_variants }, /* USA */
743  { "ad", 0, NULL }, /* Andorra */
744  { "af", KBD_FARSI, af_variants }, /* Afghanistan */
745  { "ara", KBD_ARABIC_101, ara_variants }, /* Arabic */
746  { "al", 0, NULL }, /* Albania */
747  { "am", KBD_ARMENIAN_EASTERN, am_variants }, /* Armenia */
748  { "az", KBD_AZERI_CYRILLIC, az_variants }, /* Azerbaijan */
749  { "by", KBD_BELARUSIAN, by_variants }, /* Belarus */
750  { "be", KBD_BELGIAN_FRENCH, be_variants }, /* Belgium */
751  { "bd", KBD_BENGALI, bd_variants }, /* Bangladesh */
752  { "in", KBD_HINDI_TRADITIONAL, in_variants }, /* India */
753  { "ba", KBD_CROATIAN, ba_variants }, /* Bosnia and Herzegovina */
754  { "br", KBD_PORTUGUESE_BRAZILIAN_ABNT, br_variants }, /* Brazil */
755  { "bg", KBD_BULGARIAN_LATIN, bg_variants }, /* Bulgaria */
756  { "ma", KBD_FRENCH, ma_variants }, /* Morocco */
757  { "mm", 0, NULL }, /* Myanmar */
758  { "ca", KBD_US, ca_variants }, /* Canada */
759  { "cd", 0, NULL }, /* Congo, Democratic Republic of the */
760  { "cn", KBD_CHINESE_TRADITIONAL_PHONETIC, cn_variants }, /* China */
761  { "hr", KBD_CROATIAN, hr_variants }, /* Croatia */
762  { "cz", KBD_CZECH, cz_variants }, /* Czechia */
763  { "dk", KBD_DANISH, dk_variants }, /* Denmark */
764  { "nl", KBD_DUTCH, nl_variants }, /* Netherlands */
765  { "bt", 0, NULL }, /* Bhutan */
766  { "ee", KBD_ESTONIAN, ee_variants }, /* Estonia */
767  { "ir", 0, ir_variants }, /* Iran */
768  { "iq", 0, iq_variants }, /* Iraq */
769  { "fo", 0, fo_variants }, /* Faroe Islands */
770  { "fi", KBD_FINNISH, fi_variants }, /* Finland */
771  { "fr", KBD_FRENCH, fr_variants }, /* France */
772  { "gh", 0, gh_variants }, /* Ghana */
773  { "gn", 0, NULL }, /* Guinea */
774  { "ge", KBD_GEORGIAN, ge_variants }, /* Georgia */
775  { "at", KBD_GERMAN, de_variants }, /* Austria */
776  { "de", KBD_GERMAN, de_variants }, /* Germany */
777  { "gr", KBD_GREEK, gr_variants }, /* Greece */
778  { "hu", KBD_HUNGARIAN, hu_variants }, /* Hungary */
779  { "is", KBD_ICELANDIC, is_variants }, /* Iceland */
780  { "il", KBD_HEBREW, il_variants }, /* Israel */
781  { "it", KBD_ITALIAN, it_variants }, /* Italy */
782  { "jp", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, jp_variants }, /* Japan */
783  { "kg", 0, kg_variants }, /* Kyrgyzstan */
784  { "kh", 0, NULL }, /* Cambodia */
785  { "kz", KBD_KAZAKH, kz_variants }, /* Kazakhstan */
786  { "la", 0, NULL }, /* Laos */
787  { "latam", KBD_LATIN_AMERICAN, latam_variants }, /* Latin America */
788  { "lt", KBD_LITHUANIAN, lt_variants }, /* Lithuania */
789  { "lv", KBD_LATVIAN, lv_variants }, /* Latvia */
790  { "mao", KBD_MAORI, NULL }, /* Maori */
791  { "me", KBD_SERBIAN_LATIN, me_variants }, /* Montenegro */
792  { "mk", KBD_FYRO_MACEDONIAN, mk_variants }, /* Macedonia */
793  { "mt", KBD_MALTESE_48_KEY, mt_variants }, /* Malta */
794  { "mn", KBD_MONGOLIAN_CYRILLIC, NULL }, /* Mongolia */
795  { "no", KBD_NORWEGIAN, no_variants }, /* Norway */
796  { "pl", KBD_POLISH_PROGRAMMERS, pl_variants }, /* Poland */
797  { "pt", KBD_PORTUGUESE, pt_variants }, /* Portugal */
798  { "ro", KBD_ROMANIAN, ro_variants }, /* Romania */
799  { "ru", KBD_RUSSIAN, ru_variants }, /* Russia */
800  { "rs", KBD_SERBIAN_LATIN, rs_variants }, /* Serbia */
801  { "si", KBD_SLOVENIAN, si_variants }, /* Slovenia */
802  { "sk", KBD_SLOVAK, sk_variants }, /* Slovakia */
803  { "es", KBD_SPANISH, es_variants }, /* Spain */
804  { "se", KBD_SWEDISH, se_variants }, /* Sweden */
805  { "ch", KBD_SWISS_GERMAN, ch_variants }, /* Switzerland */
806  { "sy", KBD_SYRIAC, sy_variants }, /* Syria */
807  { "tj", 0, tj_variants }, /* Tajikistan */
808  { "lk", 0, lk_variants }, /* Sri Lanka */
809  { "th", KBD_THAI_KEDMANEE, th_variants }, /* Thailand */
810  { "tr", KBD_TURKISH_Q, tr_variants }, /* Turkey */
811  { "ua", KBD_UKRAINIAN, ua_variants }, /* Ukraine */
812  { "gb", KBD_UNITED_KINGDOM, gb_variants }, /* United Kingdom */
813  { "uz", KBD_UZBEK_CYRILLIC, uz_variants }, /* Uzbekistan */
814  { "vn", KBD_VIETNAMESE, NULL }, /* Vietnam */
815  { "kr", KBD_KOREAN_INPUT_SYSTEM_IME_2000, kr_variants }, /* Korea, Republic of */
816  { "ie", KBD_UNITED_KINGDOM, ie_variants }, /* Ireland */
817  { "pk", 0, pk_variants }, /* Pakistan */
818  { "mv", 0, NULL }, /* Maldives */
819  { "za", KBD_US, NULL }, /* South Africa */
820  { "epo", 0, epo_variants }, /* Esperanto */
821  { "np", KBD_NEPALI, NULL }, /* Nepal */
822  { "ng", 0, ng_variants }, /* Nigeria */
823  { "et", 0, NULL }, /* Ethiopia */
824  { "sn", 0, NULL }, /* Senegal */
825  { "brai", 0, brai_variants }, /* Braille */
826  { "tm", KBD_TURKISH_Q, tm_variants }, /* Turkmenistan */
827 };
828 
829 static UINT32 find_keyboard_layout_variant(const XKB_LAYOUT* layout, const char* variant)
830 {
831  WINPR_ASSERT(layout);
832  WINPR_ASSERT(variant);
833 
834  const XKB_VARIANT* variants = layout->variants;
835  if (variants)
836  {
837  const XKB_VARIANT* var = variants;
838  while (var->variant && (strlen(var->variant) != 0))
839  {
840  if (strcmp(var->variant, variant) == 0)
841  return var->keyboardLayoutID;
842  var++;
843  }
844  }
845 
846  return layout->keyboardLayoutID;
847 }
848 
849 UINT32 find_keyboard_layout_in_xorg_rules(const char* layout, const char* variant)
850 {
851  if ((layout == NULL) || (variant == NULL))
852  return 0;
853 
854  DEBUG_KBD("xkbLayout: %s\txkbVariant: %s", layout, variant);
855 
856  for (size_t i = 0; i < ARRAYSIZE(xkbLayouts); i++)
857  {
858  const XKB_LAYOUT* cur = &xkbLayouts[i];
859  if (strcmp(cur->layout, layout) == 0)
860  return find_keyboard_layout_variant(cur, variant);
861  }
862 
863  return 0;
864 }