/** * FreeRDP: A Remote Desktop Protocol Implementation * Keyboard Mapping * * Copyright 2009-2012 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FREERDP_LOCALE_KEYBOARD_H #define FREERDP_LOCALE_KEYBOARD_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct rdp_remap_table FREERDP_REMAP_TABLE; typedef enum { RDP_KEYBOARD_LAYOUT_TYPE_STANDARD = 1, RDP_KEYBOARD_LAYOUT_TYPE_VARIANT = 2, RDP_KEYBOARD_LAYOUT_TYPE_IME = 4 } FREERDP_KEYBOARD_LAYOUT_TYPES; typedef struct { UINT16 id; UINT8 primaryId; UINT8 subId; char locale[512]; char primaryLanguage[512]; char primaryLanguageSymbol[512]; char subLanguage[512]; char subLanguageSymbol[512]; } RDP_CODEPAGE; typedef struct { DWORD code; /* Keyboard layout code */ char* name; /* Keyboard layout name */ } RDP_KEYBOARD_LAYOUT; /* Keyboard layout IDs */ typedef enum { KBD_ARABIC_101 = 0x00000401, KBD_BULGARIAN = 0x00000402, KBD_CHINESE_TRADITIONAL_US = 0x00000404, KBD_CZECH = 0x00000405, KBD_DANISH = 0x00000406, KBD_GERMAN = 0x00000407, KBD_GREEK = 0x00000408, KBD_US = 0x00000409, KBD_SPANISH = 0x0000040A, KBD_FINNISH = 0x0000040B, KBD_FRENCH = 0x0000040C, KBD_HEBREW = 0x0000040D, KBD_HUNGARIAN = 0x0000040E, KBD_ICELANDIC = 0x0000040F, KBD_ITALIAN = 0x00000410, KBD_JAPANESE = 0x00000411, KBD_KOREAN = 0x00000412, KBD_DUTCH = 0x00000413, KBD_NORWEGIAN = 0x00000414, KBD_POLISH_PROGRAMMERS = 0x00000415, KBD_PORTUGUESE_BRAZILIAN_ABNT = 0x00000416, KBD_ROMANIAN = 0x00000418, KBD_RUSSIAN = 0x00000419, KBD_CROATIAN = 0x0000041A, KBD_SLOVAK = 0x0000041B, KBD_ALBANIAN = 0x0000041C, KBD_SWEDISH = 0x0000041D, KBD_THAI_KEDMANEE = 0x0000041E, KBD_TURKISH_Q = 0x0000041F, KBD_URDU = 0x00000420, KBD_UKRAINIAN = 0x00000422, KBD_BELARUSIAN = 0x00000423, KBD_SLOVENIAN = 0x00000424, KBD_ESTONIAN = 0x00000425, KBD_LATVIAN = 0x00000426, KBD_LITHUANIAN_IBM = 0x00000427, KBD_FARSI = 0x00000429, KBD_VIETNAMESE = 0x0000042A, KBD_ARMENIAN_EASTERN = 0x0000042B, KBD_AZERI_LATIN = 0x0000042C, KBD_FYRO_MACEDONIAN = 0x0000042F, KBD_GEORGIAN = 0x00000437, KBD_FAEROESE = 0x00000438, KBD_DEVANAGARI_INSCRIPT = 0x00000439, KBD_MALTESE_47_KEY = 0x0000043A, KBD_NORWEGIAN_WITH_SAMI = 0x0000043B, KBD_KAZAKH = 0x0000043F, KBD_KYRGYZ_CYRILLIC = 0x00000440, KBD_TATAR = 0x00000444, KBD_BENGALI = 0x00000445, KBD_PUNJABI = 0x00000446, KBD_GUJARATI = 0x00000447, KBD_TAMIL = 0x00000449, KBD_TELUGU = 0x0000044A, KBD_KANNADA = 0x0000044B, KBD_MALAYALAM = 0x0000044C, KBD_MARATHI = 0x0000044E, KBD_MONGOLIAN_CYRILLIC = 0x00000450, KBD_UNITED_KINGDOM_EXTENDED = 0x00000452, KBD_SYRIAC = 0x0000045A, KBD_NEPALI = 0x00000461, KBD_PASHTO = 0x00000463, KBD_DIVEHI_PHONETIC = 0x00000465, KBD_LUXEMBOURGISH = 0x0000046E, KBD_MAORI = 0x00000481, KBD_CHINESE_SIMPLIFIED_US = 0x00000804, KBD_SWISS_GERMAN = 0x00000807, KBD_UNITED_KINGDOM = 0x00000809, KBD_LATIN_AMERICAN = 0x0000080A, KBD_BELGIAN_FRENCH = 0x0000080C, KBD_BELGIAN_PERIOD = 0x00000813, KBD_PORTUGUESE = 0x00000816, KBD_SERBIAN_LATIN = 0x0000081A, KBD_AZERI_CYRILLIC = 0x0000082C, KBD_SWEDISH_WITH_SAMI = 0x0000083B, KBD_UZBEK_CYRILLIC = 0x00000843, KBD_INUKTITUT_LATIN = 0x0000085D, KBD_CANADIAN_FRENCH_LEGACY = 0x00000C0C, KBD_SERBIAN_CYRILLIC = 0x00000C1A, KBD_CANADIAN_FRENCH = 0x00001009, KBD_SWISS_FRENCH = 0x0000100C, KBD_BOSNIAN = 0x0000141A, KBD_IRISH = 0x00001809, KBD_BOSNIAN_CYRILLIC = 0x0000201A } FREERDP_KBD_LAYOUT_ID; /* Keyboard layout variant IDs */ typedef enum { KBD_ARABIC_102 = 0x00010401, KBD_BULGARIAN_LATIN = 0x00010402, KBD_CZECH_QWERTY = 0x00010405, KBD_GERMAN_IBM = 0x00010407, KBD_GREEK_220 = 0x00010408, KBD_UNITED_STATES_DVORAK = 0x00010409, KBD_SPANISH_VARIATION = 0x0001040A, KBD_HUNGARIAN_101_KEY = 0x0001040E, KBD_ITALIAN_142 = 0x00010410, KBD_POLISH_214 = 0x00010415, KBD_PORTUGUESE_BRAZILIAN_ABNT2 = 0x00010416, KBD_ROMANIAN_STANDARD = 0x00010418, KBD_RUSSIAN_TYPEWRITER = 0x00010419, KBD_SLOVAK_QWERTY = 0x0001041B, KBD_THAI_PATTACHOTE = 0x0001041E, KBD_TURKISH_F = 0x0001041F, KBD_LATVIAN_QWERTY = 0x00010426, KBD_LITHUANIAN = 0x00010427, KBD_ARMENIAN_WESTERN = 0x0001042B, KBD_GEORGIAN_QUERTY = 0x00010437, KBD_HINDI_TRADITIONAL = 0x00010439, KBD_MALTESE_48_KEY = 0x0001043A, KBD_SAMI_EXTENDED_NORWAY = 0x0001043B, KBD_BENGALI_INSCRIPT = 0x00010445, KBD_KHMER = 0x00010453, KBD_SYRIAC_PHONETIC = 0x0001045A, KBD_DIVEHI_TYPEWRITER = 0x00010465, KBD_BELGIAN_COMMA = 0x0001080C, KBD_FINNISH_WITH_SAMI = 0x0001083B, KBD_CANADIAN_MULTILINGUAL_STANDARD = 0x00011009, KBD_GAELIC = 0x00011809, KBD_ARABIC_102_AZERTY = 0x00020401, KBD_CZECH_PROGRAMMERS = 0x00020405, KBD_GREEK_319 = 0x00020408, KBD_UNITED_STATES_INTERNATIONAL = 0x00020409, KBD_HEBREW_STANDARD = 0x0002040D, /** @since version 3.6.0 */ KBD_RUSSIAN_PHONETIC = 0x00020419, KBD_THAI_KEDMANEE_NON_SHIFTLOCK = 0x0002041E, KBD_BANGLA = 0x00020445, KBD_SAMI_EXTENDED_FINLAND_SWEDEN = 0x0002083B, KBD_GREEK_220_LATIN = 0x00030408, KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND = 0x00030409, KBD_THAI_PATTACHOTE_NON_SHIFTLOCK = 0x0003041E, KBD_BULGARIAN_PHONETIC = 0x00040402, KBD_GREEK_319_LATIN = 0x00040408, KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND = 0x00040409, KBD_UNITED_STATES_DVORAK_PROGRAMMER = 0x19360409, KBD_GREEK_LATIN = 0x00050408, KBD_PERSIAN = 0x00050429, KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L = 0x00050409, KBD_GREEK_POLYTONIC = 0x00060408, KBD_FRENCH_BEPO = WINPR_CXX_COMPAT_CAST(int, 0xa000040c), KBD_GERMAN_NEO = WINPR_CXX_COMPAT_CAST(int, 0xB0000407) } FREERDP_KBD_LAYPUT_VARIANT_ID; /* Global Input Method Editor (IME) IDs */ typedef enum { KBD_CHINESE_TRADITIONAL_PHONETIC = WINPR_CXX_COMPAT_CAST(int, 0xE0010404), KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 = WINPR_CXX_COMPAT_CAST(int, 0xE0010411), KBD_KOREAN_INPUT_SYSTEM_IME_2000 = WINPR_CXX_COMPAT_CAST(int, 0xE0010412), KBD_CHINESE_SIMPLIFIED_QUANPIN = WINPR_CXX_COMPAT_CAST(int, 0xE0010804), KBD_CHINESE_TRADITIONAL_CHANGJIE = WINPR_CXX_COMPAT_CAST(int, 0xE0020404), KBD_CHINESE_SIMPLIFIED_SHUANGPIN = WINPR_CXX_COMPAT_CAST(int, 0xE0020804), KBD_CHINESE_TRADITIONAL_QUICK = WINPR_CXX_COMPAT_CAST(int, 0xE0030404), KBD_CHINESE_SIMPLIFIED_ZHENGMA = WINPR_CXX_COMPAT_CAST(int, 0xE0030804), KBD_CHINESE_TRADITIONAL_BIG5_CODE = WINPR_CXX_COMPAT_CAST(int, 0xE0040404), KBD_CHINESE_TRADITIONAL_ARRAY = WINPR_CXX_COMPAT_CAST(int, 0xE0050404), KBD_CHINESE_SIMPLIFIED_NEIMA = WINPR_CXX_COMPAT_CAST(int, 0xE0050804), KBD_CHINESE_TRADITIONAL_DAYI = WINPR_CXX_COMPAT_CAST(int, 0xE0060404), KBD_CHINESE_TRADITIONAL_UNICODE = WINPR_CXX_COMPAT_CAST(int, 0xE0070404), KBD_CHINESE_TRADITIONAL_NEW_PHONETIC = WINPR_CXX_COMPAT_CAST(int, 0xE0080404), KBD_CHINESE_TRADITIONAL_NEW_CHANGJIE = WINPR_CXX_COMPAT_CAST(int, 0xE0090404), KBD_CHINESE_TRADITIONAL_MICROSOFT_PINYIN_IME_3 = WINPR_CXX_COMPAT_CAST(int, 0xE00E0804), KBD_CHINESE_TRADITIONAL_ALPHANUMERIC = WINPR_CXX_COMPAT_CAST(int, 0xE00F0404) } FREERDP_KBD_IME_ID; /** @brief Deallocation function for a \b RDP_KEYBOARD_LAYOUT array of \b count size * * @param layouts An array allocated by \ref freerdp_keyboard_get_layouts * @param count The number of \b RDP_KEYBOARD_LAYOUT members * */ FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts, size_t count); /** @brief Return an allocated array of available keyboard layouts * * @param types The types of layout queried. A mask of \b RDP_KEYBOARD_LAYOUT_TYPES * @param count A pointer that will be set to the number of elements in the returned array * * @return An allocated array of keyboard layouts, free with \b freerdp_keyboard_layouts_free */ WINPR_ATTR_MALLOC(freerdp_keyboard_layouts_free, 1) WINPR_ATTR_NODISCARD FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types, size_t* count); /** @brief Get a string representation of a keyboard layout. * * @param keyboardLayoutId The keyboard layout to get a string for * * @return The string representation of the layout or the string \b "unknown" in case there is * none. */ WINPR_ATTR_NODISCARD FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId); /** @brief Get a keyboard layout id from a string * * @param name The string to convert to a layout id. Must not be \b nullptr * * @return The keyboard layout id or \b 0 in case of no mapping */ WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_get_layout_id_from_name(const char* name); #if !defined(WITHOUT_FREERDP_3x_DEPRECATED) WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId)); WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_init_ex( DWORD keyboardLayoutId, const char* keyboardRemappingList)); WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode)); WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode(DWORD scancode, BOOL extended)); #endif /** @brief deallocate a \b FREERDP_REMAP_TABLE * * @param table The table to deallocate, may be \b nullptr * * @since version 3.11.0 */ FREERDP_API void freerdp_keyboard_remap_free(FREERDP_REMAP_TABLE* table); /** @brief parses a key=value string and creates a RDP scancode remapping table from it. * * @param list A string containing the comma separated key=value pairs (e.g. * 'key=val,key2=val2,...') * * @return An allocated array of values to remap. Must be deallocated by \ref * freerdp_keyboard_remap_free * * @since version 3.11.0 */ WINPR_ATTR_MALLOC(freerdp_keyboard_remap_free, 1) WINPR_ATTR_NODISCARD FREERDP_API FREERDP_REMAP_TABLE* freerdp_keyboard_remap_string_to_list(const char* list); /** @brief does remap a RDP scancode according to the remap table provided. * * @param remap_table The remapping table to use * @param rdpScanCode the RDP scancode to remap * * @return The remapped RDP scancode (or the rdpScanCode if not remapped) or \b 0 in case of any * failures * * @since version 3.11.0 */ WINPR_ATTR_NODISCARD FREERDP_API DWORD freerdp_keyboard_remap_key(const FREERDP_REMAP_TABLE* remap_table, DWORD rdpScanCode); /** @brief deallocator for a \b RDP_CODEPAGE array allocated by \ref * freerdp_keyboard_get_matching_codepages * * @param codepages The codepages to free, may be \b nullptr */ FREERDP_API void freerdp_codepages_free(RDP_CODEPAGE* codepages); /** @brief return an allocated array of matching codepages * * @param column The column the filter is applied to: * - 0 : RDP_CODEPAGE::locale * - 1 : RDP_CODEPAGE::PrimaryLanguage * - 2 : RDP_CODEPAGE::PrimaryLanguageSymbol * - 3 : RDP_CODEPAGE::Sublanguage * - 4 : RDP_CODEPAGE::SublanguageSymbol * @param filter A filter pattern or \b nullptr for no filtering. Simple string match, no * expressions supported (e.g. \b strstr match) * @param count A pointer that will be set to the number of codepages found, may be \b nullptr * * @return An allocated array of \b RDP_CODEPAGE of size \b count or \b nullptr if no match. Must * be freed by \ref freerdp_codepages_free */ WINPR_ATTR_MALLOC(freerdp_codepages_free, 1) WINPR_ATTR_NODISCARD FREERDP_API RDP_CODEPAGE* freerdp_keyboard_get_matching_codepages(DWORD column, const char* filter, size_t* count); /** @brief get a string representation of a RDP scancode * * @param scancode The RDP scancode to get a string for * * @return A string describing the RDP scancode or \b nullptr if it does not exist */ WINPR_ATTR_NODISCARD FREERDP_API const char* freerdp_keyboard_scancode_name(DWORD scancode); #ifdef __cplusplus } #endif #endif /* FREERDP_LOCALE_KEYBOARD_H */