xref: /reactos/dll/keyboard/kbdrost/kbdrost.c (revision 8a978a17)
1 // This file is converted by code7bit.
2 // code7bit: https://github.com/katahiromz/code7bit
3 // To revert conversion, please execute "code7bit -r <file>".
4 /*
5  * ReactOS Romanian (Standard) Keyboard layout
6  * Copyright (C) 2018 ReactOS
7  * Author: Ștefan Fulea (stefan dot fulea at mail dot com)
8  * License: LGPL, see: LGPL.txt
9  *
10  * Thanks to: http://www.barcodeman.com/altek/mule/scandoc.php
11  * and http://win.tue.nl/~aeb/linux/kbd/scancodes-1.html
12  *
13  * Romanian standard layout as defined in SR 13392:2004 by
14  * Romanian Standards Association (ASRO), with enacted use in
15  * romanian public institutions through Order no. 414/25.09.2006
16  * http://legislatie.just.ro/Public/FormaPrintabila/00000G22CFKNTV3ZAR52IRPL5V03Y1CD
17  *
18  * The combining characters, non-romanian diacritics and other
19  * symbols were taken as reference from Microsoft's demo layout:
20  * https://docs.microsoft.com/en-us/globalization/keyboards/kbdrost.html
21  *
22  * Finally, considering the amount of combining characters unused in Romanian
23  * but present by default in this language's keyboard layouts, I've took the
24  * liberty to add one combining character that it may use but I haven't
25  * encountered as of the time of this writing. The combining comma below,
26  * provides an alternative way of generating romanian S-comma and T-comma
27  * characters and is set as a dead character under letter Q.
28  *
29  */
30 
31 #define WIN32_NO_STATUS
32 #include <stdarg.h>
33 #include <windef.h>
34 #include <winuser.h>
35 #include <ndk/kbd.h>
36 
37 #ifdef _M_IA64
38 #define ROSDATA static __declspec(allocate(".data"))
39 #else
40 #ifdef _MSC_VER
41 #pragma data_seg(".data")
42 #define ROSDATA static
43 #else
44 #define ROSDATA static __attribute__((section(".data")))
45 #endif
46 #endif
47 
48 #define VK_EMPTY  0xff   /* The non-existent VK */
49 
50 #define KNUMS     KBDNUMPAD|KBDSPECIAL /* Special + number pad */
51 #define KMEXT     KBDEXT|KBDMULTIVK    /* Multi + ext */
52 
53 ROSDATA USHORT scancode_to_vk[] =
54 {
55   /* Numbers Row */
56   /* - 00 - */
57   /* 1 ...         2 ...         3 ...         4 ... */
58   VK_EMPTY,     VK_ESCAPE,    '1',          '2',
59   '3',          '4',          '5',          '6',
60   '7',          '8',          '9',          '0',
61   VK_OEM_MINUS, VK_OEM_PLUS,  VK_BACK,
62 
63   /* - 0f - */
64   /* First Letters Row */
65   VK_TAB,       'Q',          'W',          'E',
66   'R',          'T',          'Y',          'U',
67   'I',          'O',          'P',
68   VK_OEM_4,     VK_OEM_6,     VK_RETURN,
69 
70   /* - 1d - */
71   /* Second Letters Row */
72   VK_LCONTROL,
73   'A',          'S',          'D',          'F',
74   'G',          'H',          'J',          'K',
75   'L',          VK_OEM_1,     VK_OEM_7,     VK_OEM_3,
76   VK_LSHIFT,    VK_OEM_5,
77 
78   /* - 2c - */
79   /* Third letters row */
80   'Z',          'X',          'C',          'V',
81   'B',          'N',          'M',          VK_OEM_COMMA,
82   VK_OEM_PERIOD,VK_OEM_2,     VK_RSHIFT,
83 
84   /* - 37 - */
85   /* Bottom Row */
86   VK_MULTIPLY,  VK_LMENU,     VK_SPACE,     VK_CAPITAL,
87 
88   /* - 3b - */
89   /* F-Keys */
90   VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6,
91   VK_F7, VK_F8, VK_F9, VK_F10,
92 
93   /* - 45 - */
94   /* Locks */
95   VK_NUMLOCK | KMEXT,
96   VK_SCROLL | KBDMULTIVK,
97 
98   /* - 47 - */
99   /* Number-Pad */
100   VK_HOME | KNUMS,      VK_UP | KNUMS,         VK_PRIOR | KNUMS, VK_SUBTRACT,
101   VK_LEFT | KNUMS,      VK_CLEAR | KNUMS,      VK_RIGHT | KNUMS, VK_ADD,
102   VK_END | KNUMS,       VK_DOWN | KNUMS,       VK_NEXT | KNUMS,
103   VK_INSERT | KNUMS,    VK_DELETE | KNUMS,
104 
105   /* - 54 - */
106   /* Presumably PrtSc */
107   VK_SNAPSHOT,
108 
109   /* - 55 - */
110   /* Oddities, and the remaining standard F-Keys */
111   VK_EMPTY,     VK_OEM_102,     VK_F11,       VK_F12,
112 
113   /* - 59 - */
114   VK_CLEAR,     VK_EMPTY,     VK_EMPTY,     VK_EMPTY,     VK_EMPTY, /* EREOF */
115   VK_EMPTY,     VK_EMPTY,     VK_EMPTY,     VK_EMPTY,     VK_EMPTY, /* ZOOM */
116   VK_HELP,
117 
118   /* - 64 - */
119   /* Even more F-Keys (for example, NCR keyboards from the early 90's) */
120   VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F20,
121   VK_F21, VK_F22, VK_F23,
122 
123   /* - 6f - */
124   /* Not sure who uses these codes */
125   VK_EMPTY, VK_EMPTY, VK_EMPTY,
126 
127   /* - 72 - */
128   VK_EMPTY, VK_EMPTY, VK_EMPTY, VK_EMPTY,
129 
130   /* - 76 - */
131   /* One more f-key */
132   VK_F24,
133 
134   /* - 77 - */
135   VK_EMPTY, VK_EMPTY, VK_EMPTY, VK_EMPTY,
136   VK_EMPTY, VK_EMPTY, VK_EMPTY, VK_EMPTY, /* PA1 */
137   VK_EMPTY,
138 
139   /* - 80 - */
140   0
141 };
142 
143 ROSDATA VSC_VK extcode0_to_vk[] =
144 {
145   { 0x10, VK_MEDIA_PREV_TRACK | KBDEXT },
146   { 0x19, VK_MEDIA_NEXT_TRACK | KBDEXT },
147   { 0x1D, VK_RCONTROL | KBDEXT },
148   { 0x20, VK_VOLUME_MUTE | KBDEXT },
149   { 0x21, VK_LAUNCH_APP2 | KBDEXT },
150   { 0x22, VK_MEDIA_PLAY_PAUSE | KBDEXT },
151   { 0x24, VK_MEDIA_STOP | KBDEXT },
152   { 0x2E, VK_VOLUME_DOWN | KBDEXT },
153   { 0x30, VK_VOLUME_UP | KBDEXT },
154   { 0x32, VK_BROWSER_HOME | KBDEXT },
155   { 0x35, VK_DIVIDE | KBDEXT },
156   { 0x37, VK_SNAPSHOT | KBDEXT },
157   { 0x38, VK_RMENU | KBDEXT },
158   { 0x47, VK_HOME | KBDEXT },
159   { 0x48, VK_UP | KBDEXT },
160   { 0x49, VK_PRIOR | KBDEXT },
161   { 0x4B, VK_LEFT | KBDEXT },
162   { 0x4D, VK_RIGHT | KBDEXT },
163   { 0x4F, VK_END | KBDEXT },
164   { 0x50, VK_DOWN | KBDEXT },
165   { 0x51, VK_NEXT | KBDEXT },
166   { 0x52, VK_INSERT | KBDEXT },
167   { 0x53, VK_DELETE | KBDEXT },
168   { 0x5B, VK_LWIN | KBDEXT },
169   { 0x5C, VK_RWIN | KBDEXT },
170   { 0x5D, VK_APPS | KBDEXT },
171   { 0x5F, VK_SLEEP | KBDEXT },
172   { 0x65, VK_BROWSER_SEARCH | KBDEXT },
173   { 0x66, VK_BROWSER_FAVORITES | KBDEXT },
174   { 0x67, VK_BROWSER_REFRESH | KBDEXT },
175   { 0x68, VK_BROWSER_STOP | KBDEXT },
176   { 0x69, VK_BROWSER_FORWARD | KBDEXT },
177   { 0x6A, VK_BROWSER_BACK | KBDEXT },
178   { 0x6B, VK_LAUNCH_APP1 | KBDEXT },
179   { 0x6C, VK_LAUNCH_MAIL | KBDEXT },
180   { 0x6D, VK_LAUNCH_MEDIA_SELECT | KBDEXT },
181   { 0x1C, VK_RETURN | KBDEXT },
182   { 0x46, VK_CANCEL | KBDEXT },
183   { 0, 0 }
184 };
185 
186 ROSDATA VSC_VK extcode1_to_vk[] =
187 {
188   { 0x1d, VK_PAUSE },
189   { 0, 0 }
190 };
191 
192 ROSDATA VK_TO_BIT modifier_keys[] =
193 {
194   { VK_SHIFT,   KBDSHIFT },
195   { VK_CONTROL, KBDCTRL },
196   { VK_MENU,    KBDALT },
197   { 0,          0 }
198 };
199 
200 ROSDATA MODIFIERS modifier_bits =
201 {
202   modifier_keys,
203    7,
204    { 0, 1, 2, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, 3, 4 }
205    /* Modifiers order: NONE, SHIFT, CTRL, ALTGR, SHIFT-ALTGR */
206 };
207 
208 ROSDATA VK_TO_WCHARS2 key_to_chars_2mod[] =
209 {
210   /* The alphabet */
211   { 'A', CAPLOK, {'a', 'A'} },
212   { 'B', CAPLOK, {'b', 'B'} },
213   { 'C', CAPLOK, {'c', 'C'} },
214   { 'F', CAPLOK, {'f', 'F'} },
215   { 'G', CAPLOK, {'g', 'G'} },
216   { 'H', CAPLOK, {'h', 'H'} },
217   { 'I', CAPLOK, {'i', 'I'} },
218   { 'J', CAPLOK, {'j', 'J'} },
219   { 'K', CAPLOK, {'k', 'K'} },
220   { 'M', CAPLOK, {'m', 'M'} },
221   { 'N', CAPLOK, {'n', 'N'} },
222   { 'O', CAPLOK, {'o', 'O'} },
223   { 'R', CAPLOK, {'r', 'R'} },
224   { 'T', CAPLOK, {'t', 'T'} },
225   { 'U', CAPLOK, {'u', 'U'} },
226   { 'V', CAPLOK, {'v', 'V'} },
227   { 'W', CAPLOK, {'w', 'W'} },
228   { 'X', CAPLOK, {'x', 'X'} },
229   { 'Y', CAPLOK, {'y', 'Y'} },
230   { 'Z', CAPLOK, {'z', 'Z'} },
231 
232   /* Specials */
233   { VK_OEM_2, 0, {'/', '?'} },
234 
235   /* Keys that do not have shift states */
236   { VK_TAB,      0, {'\t','\t'} },
237   { VK_ADD,      0, {'+', '+'} },
238   { VK_SUBTRACT, 0, {'-', '-'} },
239   { VK_MULTIPLY, 0, {'*', '*'} },
240   { VK_DIVIDE,   0, {'/', '/'} },
241 
242   { 0, 0 }
243 };
244 
245 ROSDATA VK_TO_WCHARS3 key_to_chars_3mod[] =
246 {
247   /* Legacy (telnet-style) ascii escapes */
248   { VK_OEM_102, 0, {'\\','|', 0x1c /* FS */} },
249   { VK_BACK,    0, {0x8, 0x8, 0x7F } },
250   { VK_ESCAPE,  0, {0x1b,0x1b,0x1b } },
251   { VK_RETURN,  0, {'\r','\r','\n'} },
252   { VK_SPACE,   0, {' ', ' ', ' '} },
253   { VK_CANCEL,  0, {0x3, 0x3, 0x3} },
254   { 0, 0 }
255 };
256 
257 ROSDATA VK_TO_WCHARS4 key_to_chars_4mod[] =
258 {
259   { '1', 0, {'1', '!', WCH_NONE, 0x0303 /* COMBINING TILDE */} },
260   { '2', 0, {'2', '@', WCH_NONE, 0x030C /* COMBINING CARON */} },
261   { '3', 0, {'3', '#', WCH_NONE, 0x0302 /* COMBINING CIRCUMFLEX */} },
262   { '4', 0, {'4', '$', WCH_NONE, 0x0306 /* COMBINING BREVE */} },
263   { '5', 0, {'5', '%', WCH_NONE, 0x030A /* COMBINING RING ABOVE */} },
264   { '6', 0, {'6', '^', WCH_NONE, 0x0328 /* COMBINING OGONEK */} },
265   { '7', 0, {'7', '&', WCH_NONE, 0x0300 /* COMBINING GRAVE ACCENT */} },
266   { '8', 0, {'8', '*', WCH_NONE, 0x0307 /* COMBINING DOT ABOVE */} },
267   { '9', 0, {'9', '(', WCH_NONE, 0x0301 /* COMBINING ACUTE ACCENT */} },
268   { '0', 0, {'0', ')', WCH_NONE, 0x030B /* COMBINING DOUBLE ACUTE ACCENT */} },
269   { 'Q', CAPLOK, {'q', 'Q', WCH_NONE, 0x0326 /* COMBINING COMMA BELOW */} },
270   { 'E', CAPLOK, {'e', 'E', WCH_NONE, 0x20AC /* EURO SIGN */} },
271   { 'P', CAPLOK, {'p', 'P', WCH_NONE, 0x00A7 /* SECTION SIGN */} },
272   { 'S', CAPLOK, {'s', 'S', WCH_NONE, 0x00DF /* LATIN SMALL LETTER SHARP S */} },
273   { 0, 0 }
274 };
275 
276 ROSDATA VK_TO_WCHARS5 key_to_chars_5mod[] =
277 {
278   { VK_OEM_3, 0,  {0x201E /* DOUBLE QUOTE 99 LOW */, 0x201D /* DOUBLE QUOTE 99 HIGH */, WCH_NONE, '`', '~' } },
279   { VK_OEM_MINUS, 0, {'-', '_', WCH_NONE, 0x0308 /* COMBINING DIAERESIS */, 0x2013 /* EN DASH */} },
280   { VK_OEM_PLUS, 0, {'=', '+', WCH_NONE, 0x0327 /* COMBINING CEDILLA */, 0x00B1 /* PLUS-MINUS SIGN */} },
281   { VK_OEM_4, CAPLOK, {0x0103 /* a BREVE */, 0x0102 /* A BREVE */, 0x1b /* ESC */, '[', '{' } },
282   { VK_OEM_6, CAPLOK, {0x00ee /* i CIRCUMFLEX */, 0x00ce /* I CIRCUMFLEX */, 0x1d /* GS */, ']', '}' } },
283   { 'D', CAPLOK, {'d', 'D', WCH_NONE, 0x0111 /* d WITH STROKE */, 0x0110 /* D WITH STROKE */} },
284   { 'L', CAPLOK, {'l', 'L', WCH_NONE, 0x0142 /* l WITH STROKE */, 0x0141 /* L WITH STROKE */} },
285   { VK_OEM_1, CAPLOK, {0x0219 /* s COMMA */, 0x0218 /* S COMMA */, WCH_NONE, ';', ':' } },
286   { VK_OEM_7, CAPLOK, {0x021B /* t COMMA */, 0x021A /* T COMMA */, WCH_NONE, '\'', '"' } },
287   { VK_OEM_5, CAPLOK, {0x00e2 /* a CIRCUMFLEX */, 0x00c2 /* A CIRCUMFLEX */, 0x1c /* FS */, '\\', '|' } },
288   { VK_OEM_COMMA, 0, {',', ';', WCH_NONE, '<', 0x00AB /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ } },
289   { VK_OEM_PERIOD, 0, {'.', ':', WCH_NONE, '>', 0x00BB /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ } },
290   { 0, 0 }
291 };
292 
293 ROSDATA VK_TO_WCHARS1 keypad_numbers[] =
294 {
295   { VK_NUMPAD0,  0, {'0'} },
296   { VK_NUMPAD1,  0, {'1'} },
297   { VK_NUMPAD2,  0, {'2'} },
298   { VK_NUMPAD3,  0, {'3'} },
299   { VK_NUMPAD4,  0, {'4'} },
300   { VK_NUMPAD5,  0, {'5'} },
301   { VK_NUMPAD6,  0, {'6'} },
302   { VK_NUMPAD7,  0, {'7'} },
303   { VK_NUMPAD8,  0, {'8'} },
304   { VK_NUMPAD9,  0, {'9'} },
305   { VK_DECIMAL,  0, {','} },
306   { 0, 0 }
307 };
308 
309 #define vk_master(n, x) { (PVK_TO_WCHARS1)x, n, sizeof(x[0]) }
310 ROSDATA VK_TO_WCHAR_TABLE vk_to_wchar_master_table[] =
311 {
312   vk_master(2, key_to_chars_2mod),
313   vk_master(3, key_to_chars_3mod),
314   vk_master(4, key_to_chars_4mod),
315   vk_master(5, key_to_chars_5mod),
316   vk_master(1, keypad_numbers),
317   { 0, 0, 0 }
318 };
319 
320 ROSDATA VSC_LPWSTR key_names[] =
321 {
322   { 0x01, L"Esc" },
323   { 0x0e, L"Retro\u0219tergere" },
324   { 0x0f, L"Tabulator" },
325   { 0x1c, L"Intrare" },
326   { 0x1d, L"Control" },
327   { 0x2a, L"Schimb" },
328   { 0x35, L"/ (num.)" },
329   { 0x36, L"Schimb dreapta" },
330   { 0x37, L"* (num.)" },
331   { 0x38, L"Alt" },
332   { 0x39, L"Spa\u021Biu" },
333   { 0x3a, L"MAJUSCULE" },
334   { 0x3b, L"F1" },
335   { 0x3c, L"F2" },
336   { 0x3d, L"F3" },
337   { 0x3e, L"F4" },
338   { 0x3f, L"F5" },
339   { 0x40, L"F6" },
340   { 0x41, L"F7" },
341   { 0x42, L"F8" },
342   { 0x43, L"F9" },
343   { 0x44, L"F10" },
344   { 0x45, L"Pauz\u0103" },
345   { 0x46, L"Fix. derulare" },
346   { 0x47, L"7 (num.)" },
347   { 0x48, L"8 (num.)" },
348   { 0x49, L"9 (num.)" },
349   { 0x4a, L"- (num.)" },
350   { 0x4b, L"4 (num.)" },
351   { 0x4c, L"5 (num.)" },
352   { 0x4d, L"6 (num.)" },
353   { 0x4e, L"+ (num.)" },
354   { 0x4f, L"1 (num.)" },
355   { 0x50, L"2 (num.)" },
356   { 0x51, L"3 (num.)" },
357   { 0x52, L"0 (num.)" },
358   { 0x53, L"Sep. zecimal" },
359   { 0x54, L"Sys Req" },
360   { 0x56, L"\\" },
361   { 0x57, L"F11" },
362   { 0x58, L"F12" },
363   { 0x7c, L"F13" },
364   { 0x7d, L"F14" },
365   { 0x7e, L"F15" },
366   { 0x7f, L"F16" },
367   { 0x80, L"F17" },
368   { 0x81, L"F18" },
369   { 0x82, L"F19" },
370   { 0x83, L"F20" },
371   { 0x84, L"F21" },
372   { 0x85, L"F22" },
373   { 0x86, L"F23" },
374   { 0x87, L"F24" },
375   { 0, NULL }
376 };
377 
378 ROSDATA VSC_LPWSTR extended_key_names[] =
379 {
380   { 0x1c, L"Intr. numerice" },
381   { 0x1d, L"Control dreapta" },
382   { 0x37, L"Imprimare" },
383   { 0x38, L"Alt dreapta" },
384   { 0x45, L"Fix. numerice" },
385   { 0x46, L"\u00CEntrerupere" },
386   { 0x47, L"Acas\u0103" },
387   { 0x48, L"Sus" },
388   { 0x49, L"Pag. sus" },
389   { 0x4b, L"St\u00E2nga" },
390   { 0x4c, L"Centru" },
391   { 0x4d, L"Dreapta" },
392   { 0x4f, L"Sf\u00E2r\u0219it" },
393   { 0x50, L"Jos" },
394   { 0x51, L"Pag. jos" },
395   { 0x52, L"Inser\u021Bie" },
396   { 0x53, L"\u0218tergere" },
397   { 0x54, L"Meniu" },
398   { 0x56, L"Ajutor" },
399   { 0x5b, L"Meniu st\u00E2nga" },
400   { 0x5c, L"Meniu dreapta" },
401   { 0, NULL }
402 };
403 
404 ROSDATA DEADKEY_LPWSTR dead_key_names[] =
405 {
406     L"\x0300"   L"Accent grav",
407     L"\x0301"   L"Accent acut",
408     L"\x0302"   L"Circumflex",
409     L"\x0303"   L"Tild\u0103",
410     L"\x0306"   L"Breve",
411     L"\x0307"   L"Suprapunct",
412     L"\x0308"   L"Trem\u0103",
413     L"\x030A"   L"Supracerc",
414     L"\x030B"   L"Accent acut dublu",
415     L"\x030C"   L"Caron",
416     L"\x0326"   L"Virgul\u0103",
417     L"\x0327"   L"Sedil\u0103",
418     L"\x0328"   L"Ogonek",
419     NULL
420 };
421 
422 #define DEADTRANS(ch, accent, comp, flags) MAKELONG(ch, accent), comp, flags
423 ROSDATA DEADKEY dead_key[] =
424 {
425   /*
426    * combining diacritics: tilde, caron, circumflex,
427    * breve, ring above, ogonek, grave accent, dot above,
428    * acute accent, double acute accent, and comma below
429    */
430   #include "deadkeys/tilde"
431   #include "deadkeys/caron"
432   #include "deadkeys/circumflex"
433   #include "deadkeys/breve"
434   #include "deadkeys/ring_above"
435   #include "deadkeys/ogonek"
436   #include "deadkeys/grave_acc"
437   #include "deadkeys/dot_above"
438   #include "deadkeys/acute_acc"
439   #include "deadkeys/dbl_acute_acc"
440   #include "deadkeys/comma_below"
441 
442   { 0, 0 }
443 };
444 
445 /* Finally, the master table */
446 ROSDATA KBDTABLES keyboard_layout_table =
447 {
448   /* modifier assignments */
449   &modifier_bits,
450 
451   /* character from vk tables */
452   vk_to_wchar_master_table,
453 
454   /* diacritical marks */
455   dead_key,
456 
457   /* Key names */
458   key_names,
459   extended_key_names,
460   dead_key_names,
461 
462   /* scan code to virtual key maps */
463   scancode_to_vk,
464   sizeof(scancode_to_vk) / sizeof(scancode_to_vk[0]),
465   extcode0_to_vk,
466   extcode1_to_vk,
467 
468   MAKELONG(KLLF_ALTGR, 1), /* Version 1.0 */
469 
470   /* Ligatures (Romanian doesn't have any) */
471   0,
472   0,
473   NULL
474 };
475 
476 PKBDTABLES WINAPI KbdLayerDescriptor(VOID)
477 {
478   return &keyboard_layout_table;
479 }
480