Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
90
third_party/FreeRDP/libfreerdp/locale/CMakeLists.txt
vendored
Normal file
90
third_party/FreeRDP/libfreerdp/locale/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# libfreerdp-locale cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(MODULE_NAME "freerdp-locale")
|
||||
set(MODULE_PREFIX "FREERDP_LOCALE")
|
||||
|
||||
set(SRCS keyboard_layout.c keyboard.c locale.c liblocale.h)
|
||||
|
||||
if(NOT WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
set(X11_SRCS keyboard_x11.c keyboard_x11.h xkb_layout_ids.c xkb_layout_ids.h)
|
||||
|
||||
set(XKBFILE_SRCS keyboard_xkbfile.c keyboard_xkbfile.h)
|
||||
endif()
|
||||
|
||||
set(SUN_SRCS keyboard_sun.c keyboard_sun.h)
|
||||
|
||||
set(APPLE_SRCS keyboard_apple.c keyboard_apple.h)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
cmake_dependent_option(WITH_KEYBOARD_LAYOUT_FROM_FILE "Use keyboard definitions from JSON file" OFF WITH_WINPR_JSON OFF)
|
||||
if(WITH_KEYBOARD_LAYOUT_FROM_FILE)
|
||||
freerdp_definition_add(FREERDP_RESOURCE_ROOT="${FREERDP_RESOURCE_ROOT}")
|
||||
freerdp_definition_add(WITH_KEYBOARD_LAYOUT_FROM_FILE)
|
||||
|
||||
install(FILES KeyboardLayoutMap.json DESTINATION ${FREERDP_RESOURCE_ROOT})
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Solaris)
|
||||
set(WITH_SUN true)
|
||||
endif()
|
||||
|
||||
if(APPLE AND (NOT IOS))
|
||||
list(APPEND SRCS ${APPLE_SRCS})
|
||||
find_library(CARBON Carbon)
|
||||
freerdp_library_add(${CARBON})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_library(CORE_FOUNDATION CoreFoundation REQUIRED)
|
||||
freerdp_library_add(${CORE_FOUNDATION})
|
||||
endif()
|
||||
|
||||
if(WITH_X11 AND NOT WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
find_package(X11 REQUIRED)
|
||||
freerdp_pc_add_requires_private("x11")
|
||||
|
||||
freerdp_definition_add(WITH_X11)
|
||||
freerdp_include_directory_add(${X11_INCLUDE_DIR})
|
||||
list(APPEND SRCS ${X11_SRCS})
|
||||
freerdp_library_add(${X11_LIBRARIES})
|
||||
|
||||
if(WITH_SUN)
|
||||
freerdp_definition_add(WITH_SUN)
|
||||
list(APPEND SRCS ${SUN_SRCS})
|
||||
endif()
|
||||
|
||||
if(X11_Xkbfile_FOUND AND (NOT APPLE))
|
||||
freerdp_pc_add_requires_private("xkbfile")
|
||||
freerdp_definition_add(WITH_XKBFILE)
|
||||
freerdp_include_directory_add(${X11_Xkbfile_INCLUDE_PATH})
|
||||
list(APPEND SRCS ${XKBFILE_SRCS})
|
||||
freerdp_library_add(${X11_Xkbfile_LIB})
|
||||
else()
|
||||
list(APPEND SRCS ${X11_KEYMAP_SRCS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_WAYLAND AND NOT WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
freerdp_definition_add(WITH_WAYLAND)
|
||||
endif()
|
||||
|
||||
freerdp_module_add(${SRCS})
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
1118
third_party/FreeRDP/libfreerdp/locale/KeyboardLayoutMap.json
vendored
Normal file
1118
third_party/FreeRDP/libfreerdp/locale/KeyboardLayoutMap.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
524
third_party/FreeRDP/libfreerdp/locale/keyboard.c
vendored
Normal file
524
third_party/FreeRDP/libfreerdp/locale/keyboard.c
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Keyboard Localization
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/string.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/locale/locale.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
#define TAG FREERDP_TAG("locale.keyboard")
|
||||
|
||||
#if defined(__MACOSX__)
|
||||
#include "keyboard_apple.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_X11
|
||||
#include "keyboard_x11.h"
|
||||
|
||||
#ifdef WITH_XKBFILE
|
||||
#include "keyboard_xkbfile.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
static WINPR_KEYCODE_TYPE maptype = WINPR_KEYCODE_TYPE_NONE;
|
||||
static DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2] = WINPR_C_ARRAY_INIT;
|
||||
static DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256] = WINPR_C_ARRAY_INIT;
|
||||
static DWORD REMAPPING_TABLE[0x10000] = WINPR_C_ARRAY_INIT;
|
||||
#endif
|
||||
|
||||
struct rdp_remap_table
|
||||
{
|
||||
DWORD table[0x10000];
|
||||
};
|
||||
|
||||
struct scancode_map_entry
|
||||
{
|
||||
DWORD scancode;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static const struct scancode_map_entry RDP_SCANCODE_MAP[] = {
|
||||
{ RDP_SCANCODE_ESCAPE, "VK_ESCAPE" },
|
||||
{ RDP_SCANCODE_KEY_1, "VK_KEY_1" },
|
||||
{ RDP_SCANCODE_KEY_2, "VK_KEY_2" },
|
||||
{ RDP_SCANCODE_KEY_3, "VK_KEY_3" },
|
||||
{ RDP_SCANCODE_KEY_4, "VK_KEY_4" },
|
||||
{ RDP_SCANCODE_KEY_5, "VK_KEY_5" },
|
||||
{ RDP_SCANCODE_KEY_6, "VK_KEY_6" },
|
||||
{ RDP_SCANCODE_KEY_7, "VK_KEY_7" },
|
||||
{ RDP_SCANCODE_KEY_8, "VK_KEY_8" },
|
||||
{ RDP_SCANCODE_KEY_9, "VK_KEY_9" },
|
||||
{ RDP_SCANCODE_KEY_0, "VK_KEY_0" },
|
||||
{ RDP_SCANCODE_OEM_MINUS, "VK_OEM_MINUS" },
|
||||
{ RDP_SCANCODE_OEM_PLUS, "VK_OEM_PLUS" },
|
||||
{ RDP_SCANCODE_BACKSPACE, "VK_BACK Backspace" },
|
||||
{ RDP_SCANCODE_TAB, "VK_TAB" },
|
||||
{ RDP_SCANCODE_KEY_Q, "VK_KEY_Q" },
|
||||
{ RDP_SCANCODE_KEY_W, "VK_KEY_W" },
|
||||
{ RDP_SCANCODE_KEY_E, "VK_KEY_E" },
|
||||
{ RDP_SCANCODE_KEY_R, "VK_KEY_R" },
|
||||
{ RDP_SCANCODE_KEY_T, "VK_KEY_T" },
|
||||
{ RDP_SCANCODE_KEY_Y, "VK_KEY_Y" },
|
||||
{ RDP_SCANCODE_KEY_U, "VK_KEY_U" },
|
||||
{ RDP_SCANCODE_KEY_I, "VK_KEY_I" },
|
||||
{ RDP_SCANCODE_KEY_O, "VK_KEY_O" },
|
||||
{ RDP_SCANCODE_KEY_P, "VK_KEY_P" },
|
||||
{ RDP_SCANCODE_OEM_4, "VK_OEM_4 '[' on US" },
|
||||
{ RDP_SCANCODE_OEM_6, "VK_OEM_6 ']' on US" },
|
||||
{ RDP_SCANCODE_RETURN, "VK_RETURN Normal Enter" },
|
||||
{ RDP_SCANCODE_LCONTROL, "VK_LCONTROL" },
|
||||
{ RDP_SCANCODE_KEY_A, "VK_KEY_A" },
|
||||
{ RDP_SCANCODE_KEY_S, "VK_KEY_S" },
|
||||
{ RDP_SCANCODE_KEY_D, "VK_KEY_D" },
|
||||
{ RDP_SCANCODE_KEY_F, "VK_KEY_F" },
|
||||
{ RDP_SCANCODE_KEY_G, "VK_KEY_G" },
|
||||
{ RDP_SCANCODE_KEY_H, "VK_KEY_H" },
|
||||
{ RDP_SCANCODE_KEY_J, "VK_KEY_J" },
|
||||
{ RDP_SCANCODE_KEY_K, "VK_KEY_K" },
|
||||
{ RDP_SCANCODE_KEY_L, "VK_KEY_L" },
|
||||
{ RDP_SCANCODE_OEM_1, "VK_OEM_1 ';' on US" },
|
||||
{ RDP_SCANCODE_OEM_7, "VK_OEM_7 on US" },
|
||||
{ RDP_SCANCODE_OEM_3, "VK_OEM_3 Top left, '`' on US, JP DBE_SBCSCHAR" },
|
||||
{ RDP_SCANCODE_LSHIFT, "VK_LSHIFT" },
|
||||
{ RDP_SCANCODE_OEM_5, "VK_OEM_5 Next to Enter, '\' on US" },
|
||||
{ RDP_SCANCODE_KEY_Z, "VK_KEY_Z" },
|
||||
{ RDP_SCANCODE_KEY_X, "VK_KEY_X" },
|
||||
{ RDP_SCANCODE_KEY_C, "VK_KEY_C" },
|
||||
{ RDP_SCANCODE_KEY_V, "VK_KEY_V" },
|
||||
{ RDP_SCANCODE_KEY_B, "VK_KEY_B" },
|
||||
{ RDP_SCANCODE_KEY_N, "VK_KEY_N" },
|
||||
{ RDP_SCANCODE_KEY_M, "VK_KEY_M" },
|
||||
{ RDP_SCANCODE_OEM_COMMA, "VK_OEM_COMMA" },
|
||||
{ RDP_SCANCODE_OEM_PERIOD, "VK_OEM_PERIOD" },
|
||||
{ RDP_SCANCODE_OEM_2, "VK_OEM_2 '/' on US" },
|
||||
{ RDP_SCANCODE_RSHIFT, "VK_RSHIFT" },
|
||||
{ RDP_SCANCODE_MULTIPLY, "VK_MULTIPLY Numerical" },
|
||||
{ RDP_SCANCODE_LMENU, "VK_LMENU Left 'Alt' key" },
|
||||
{ RDP_SCANCODE_SPACE, "VK_SPACE" },
|
||||
{ RDP_SCANCODE_CAPSLOCK, "VK_CAPITAL 'Caps Lock', JP DBE_ALPHANUMERIC" },
|
||||
{ RDP_SCANCODE_F1, "VK_F1" },
|
||||
{ RDP_SCANCODE_F2, "VK_F2" },
|
||||
{ RDP_SCANCODE_F3, "VK_F3" },
|
||||
{ RDP_SCANCODE_F4, "VK_F4" },
|
||||
{ RDP_SCANCODE_F5, "VK_F5" },
|
||||
{ RDP_SCANCODE_F6, "VK_F6" },
|
||||
{ RDP_SCANCODE_F7, "VK_F7" },
|
||||
{ RDP_SCANCODE_F8, "VK_F8" },
|
||||
{ RDP_SCANCODE_F9, "VK_F9" },
|
||||
{ RDP_SCANCODE_F10, "VK_F10" },
|
||||
{ RDP_SCANCODE_NUMLOCK, "VK_NUMLOCK" },
|
||||
{ RDP_SCANCODE_SCROLLLOCK, "VK_SCROLL 'Scroll Lock', JP OEM_SCROLL" },
|
||||
{ RDP_SCANCODE_NUMPAD7, "VK_NUMPAD7" },
|
||||
{ RDP_SCANCODE_NUMPAD8, "VK_NUMPAD8" },
|
||||
{ RDP_SCANCODE_NUMPAD9, "VK_NUMPAD9" },
|
||||
{ RDP_SCANCODE_SUBTRACT, "VK_SUBTRACT" },
|
||||
{ RDP_SCANCODE_NUMPAD4, "VK_NUMPAD4" },
|
||||
{ RDP_SCANCODE_NUMPAD5, "VK_NUMPAD5" },
|
||||
{ RDP_SCANCODE_NUMPAD6, "VK_NUMPAD6" },
|
||||
{ RDP_SCANCODE_ADD, "VK_ADD" },
|
||||
{ RDP_SCANCODE_NUMPAD1, "VK_NUMPAD1" },
|
||||
{ RDP_SCANCODE_NUMPAD2, "VK_NUMPAD2" },
|
||||
{ RDP_SCANCODE_NUMPAD3, "VK_NUMPAD3" },
|
||||
{ RDP_SCANCODE_NUMPAD0, "VK_NUMPAD0" },
|
||||
{ RDP_SCANCODE_DECIMAL, "VK_DECIMAL Numerical, '.' on US" },
|
||||
{ RDP_SCANCODE_SYSREQ, "Sys Req" },
|
||||
{ RDP_SCANCODE_OEM_102, "VK_OEM_102 Lower left '\' on US" },
|
||||
{ RDP_SCANCODE_F11, "VK_F11" },
|
||||
{ RDP_SCANCODE_F12, "VK_F12" },
|
||||
{ RDP_SCANCODE_SLEEP, "VK_SLEEP OEM_8 on FR (undocumented?)" },
|
||||
{ RDP_SCANCODE_ZOOM, "VK_ZOOM (undocumented?)" },
|
||||
{ RDP_SCANCODE_HELP, "VK_HELP (undocumented?)" },
|
||||
{ RDP_SCANCODE_F13, "VK_F13" },
|
||||
{ RDP_SCANCODE_F14, "VK_F14" },
|
||||
{ RDP_SCANCODE_F15, "VK_F15" },
|
||||
{ RDP_SCANCODE_F16, "VK_F16" },
|
||||
{ RDP_SCANCODE_F17, "VK_F17" },
|
||||
{ RDP_SCANCODE_F18, "VK_F18" },
|
||||
{ RDP_SCANCODE_F19, "VK_F19" },
|
||||
{ RDP_SCANCODE_F20, "VK_F20" },
|
||||
{ RDP_SCANCODE_F21, "VK_F21" },
|
||||
{ RDP_SCANCODE_F22, "VK_F22" },
|
||||
{ RDP_SCANCODE_F23, "VK_F23" },
|
||||
{ RDP_SCANCODE_F24, "VK_F24" },
|
||||
{ RDP_SCANCODE_HIRAGANA, "JP DBE_HIRAGANA" },
|
||||
{ RDP_SCANCODE_HANJA_KANJI, "VK_HANJA / VK_KANJI (undocumented?)" },
|
||||
{ RDP_SCANCODE_KANA_HANGUL, "VK_KANA / VK_HANGUL (undocumented?)" },
|
||||
{ RDP_SCANCODE_ABNT_C1, "VK_ABNT_C1 JP OEM_102" },
|
||||
{ RDP_SCANCODE_F24_JP, "JP F24" },
|
||||
{ RDP_SCANCODE_CONVERT_JP, "JP VK_CONVERT" },
|
||||
{ RDP_SCANCODE_NONCONVERT_JP, "JP VK_NONCONVERT" },
|
||||
{ RDP_SCANCODE_TAB_JP, "JP TAB" },
|
||||
{ RDP_SCANCODE_BACKSLASH_JP, "JP OEM_5 ('\')" },
|
||||
{ RDP_SCANCODE_ABNT_C2, "VK_ABNT_C2, JP" },
|
||||
{ RDP_SCANCODE_HANJA, "KR VK_HANJA" },
|
||||
{ RDP_SCANCODE_HANGUL, "KR VK_HANGUL" },
|
||||
{ RDP_SCANCODE_RETURN_KP, "not RDP_SCANCODE_RETURN Numerical Enter" },
|
||||
{ RDP_SCANCODE_RCONTROL, "VK_RCONTROL" },
|
||||
{ RDP_SCANCODE_DIVIDE, "VK_DIVIDE Numerical" },
|
||||
{ RDP_SCANCODE_PRINTSCREEN, "VK_EXECUTE/VK_PRINT/VK_SNAPSHOT Print Screen" },
|
||||
{ RDP_SCANCODE_RMENU, "VK_RMENU Right 'Alt' / 'Alt Gr'" },
|
||||
{ RDP_SCANCODE_PAUSE, "VK_PAUSE Pause / Break (Slightly special handling)" },
|
||||
{ RDP_SCANCODE_HOME, "VK_HOME" },
|
||||
{ RDP_SCANCODE_UP, "VK_UP" },
|
||||
{ RDP_SCANCODE_PRIOR, "VK_PRIOR 'Page Up'" },
|
||||
{ RDP_SCANCODE_LEFT, "VK_LEFT" },
|
||||
{ RDP_SCANCODE_RIGHT, "VK_RIGHT" },
|
||||
{ RDP_SCANCODE_END, "VK_END" },
|
||||
{ RDP_SCANCODE_DOWN, "VK_DOWN" },
|
||||
{ RDP_SCANCODE_NEXT, "VK_NEXT 'Page Down'" },
|
||||
{ RDP_SCANCODE_INSERT, "VK_INSERT" },
|
||||
{ RDP_SCANCODE_DELETE, "VK_DELETE" },
|
||||
{ RDP_SCANCODE_NULL, "<00>" },
|
||||
{ RDP_SCANCODE_HELP2, "Help - documented, different from VK_HELP" },
|
||||
{ RDP_SCANCODE_LWIN, "VK_LWIN" },
|
||||
{ RDP_SCANCODE_RWIN, "VK_RWIN" },
|
||||
{ RDP_SCANCODE_APPS, "VK_APPS Application" },
|
||||
{ RDP_SCANCODE_POWER_JP, "JP POWER" },
|
||||
{ RDP_SCANCODE_SLEEP_JP, "JP SLEEP" },
|
||||
{ RDP_SCANCODE_NUMLOCK_EXTENDED, "should be RDP_SCANCODE_NUMLOCK" },
|
||||
{ RDP_SCANCODE_RSHIFT_EXTENDED, "should be RDP_SCANCODE_RSHIFT" },
|
||||
{ RDP_SCANCODE_VOLUME_MUTE, "VK_VOLUME_MUTE" },
|
||||
{ RDP_SCANCODE_VOLUME_DOWN, "VK_VOLUME_DOWN" },
|
||||
{ RDP_SCANCODE_VOLUME_UP, "VK_VOLUME_UP" },
|
||||
{ RDP_SCANCODE_MEDIA_NEXT_TRACK, "VK_MEDIA_NEXT_TRACK" },
|
||||
{ RDP_SCANCODE_MEDIA_PREV_TRACK, "VK_MEDIA_PREV_TRACK" },
|
||||
{ RDP_SCANCODE_MEDIA_STOP, "VK_MEDIA_MEDIA_STOP" },
|
||||
{ RDP_SCANCODE_MEDIA_PLAY_PAUSE, "VK_MEDIA_MEDIA_PLAY_PAUSE" },
|
||||
{ RDP_SCANCODE_BROWSER_BACK, "VK_BROWSER_BACK" },
|
||||
{ RDP_SCANCODE_BROWSER_FORWARD, "VK_BROWSER_FORWARD" },
|
||||
{ RDP_SCANCODE_BROWSER_REFRESH, "VK_BROWSER_REFRESH" },
|
||||
{ RDP_SCANCODE_BROWSER_STOP, "VK_BROWSER_STOP" },
|
||||
{ RDP_SCANCODE_BROWSER_SEARCH, "VK_BROWSER_SEARCH" },
|
||||
{ RDP_SCANCODE_BROWSER_FAVORITES, "VK_BROWSER_FAVORITES" },
|
||||
{ RDP_SCANCODE_BROWSER_HOME, "VK_BROWSER_HOME" },
|
||||
{ RDP_SCANCODE_LAUNCH_MAIL, "VK_LAUNCH_MAIL" },
|
||||
{ RDP_SCANCODE_LAUNCH_MEDIA_SELECT, "VK_LAUNCH_MEDIA_SELECT" },
|
||||
{ RDP_SCANCODE_LAUNCH_APP1, "VK_LAUNCH_APP1" },
|
||||
{ RDP_SCANCODE_LAUNCH_APP2, "VK_LAUNCH_APP2" },
|
||||
};
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
static int freerdp_detect_keyboard(DWORD* keyboardLayoutId)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
CHAR name[KL_NAMELENGTH + 1] = WINPR_C_ARRAY_INIT;
|
||||
if (GetKeyboardLayoutNameA(name))
|
||||
{
|
||||
ULONG rc;
|
||||
|
||||
errno = 0;
|
||||
rc = strtoul(name, nullptr, 16);
|
||||
if (errno == 0)
|
||||
*keyboardLayoutId = rc;
|
||||
}
|
||||
|
||||
if (*keyboardLayoutId == 0)
|
||||
{
|
||||
const HKL layout = GetKeyboardLayout(0);
|
||||
const uint32_t masked = (uint32_t)(((uintptr_t)layout >> 16) & 0xFFFF);
|
||||
*keyboardLayoutId = masked;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__MACOSX__)
|
||||
if (*keyboardLayoutId == 0)
|
||||
freerdp_detect_keyboard_layout_from_cf(keyboardLayoutId);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_X11
|
||||
if (*keyboardLayoutId == 0)
|
||||
freerdp_detect_keyboard_layout_from_xkb(keyboardLayoutId);
|
||||
#endif
|
||||
|
||||
if (*keyboardLayoutId == 0)
|
||||
freerdp_detect_keyboard_layout_from_system_locale(keyboardLayoutId);
|
||||
|
||||
if (*keyboardLayoutId == 0)
|
||||
*keyboardLayoutId = ENGLISH_UNITED_STATES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
static int freerdp_keyboard_init_apple(WINPR_ATTR_UNUSED const DWORD* keyboardLayoutId,
|
||||
DWORD* x11_keycode_to_rdp_scancode, size_t count)
|
||||
{
|
||||
WINPR_ASSERT(x11_keycode_to_rdp_scancode);
|
||||
WINPR_ASSERT(keyboardLayoutId);
|
||||
WINPR_ASSERT(count <= UINT32_MAX);
|
||||
for (size_t keycode = 8; keycode < count; keycode++)
|
||||
{
|
||||
const DWORD vkcode =
|
||||
GetVirtualKeyCodeFromKeycode((UINT32)keycode - 8u, WINPR_KEYCODE_TYPE_APPLE);
|
||||
x11_keycode_to_rdp_scancode[keycode] =
|
||||
GetVirtualScanCodeFromVirtualKeyCode(vkcode, WINPR_KBD_TYPE_IBM_ENHANCED);
|
||||
}
|
||||
|
||||
maptype = WINPR_KEYCODE_TYPE_APPLE;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int freerdp_keyboard_init_x11_evdev(WINPR_ATTR_UNUSED const DWORD* keyboardLayoutId,
|
||||
DWORD* x11_keycode_to_rdp_scancode, size_t count)
|
||||
{
|
||||
WINPR_ASSERT(keyboardLayoutId);
|
||||
WINPR_ASSERT(x11_keycode_to_rdp_scancode);
|
||||
WINPR_ASSERT(count <= UINT32_MAX);
|
||||
|
||||
for (size_t keycode = 0; keycode < count; keycode++)
|
||||
{
|
||||
const DWORD vkcode =
|
||||
GetVirtualKeyCodeFromKeycode((UINT32)keycode, WINPR_KEYCODE_TYPE_EVDEV);
|
||||
x11_keycode_to_rdp_scancode[keycode] =
|
||||
GetVirtualScanCodeFromVirtualKeyCode(vkcode, WINPR_KBD_TYPE_IBM_ENHANCED);
|
||||
}
|
||||
maptype = WINPR_KEYCODE_TYPE_EVDEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD freerdp_keyboard_init(DWORD keyboardLayoutId)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
if (status < 0)
|
||||
status = freerdp_keyboard_init_apple(&keyboardLayoutId, X11_KEYCODE_TO_VIRTUAL_SCANCODE,
|
||||
ARRAYSIZE(X11_KEYCODE_TO_VIRTUAL_SCANCODE));
|
||||
#endif
|
||||
|
||||
#if defined(WITH_X11) || defined(WITH_WAYLAND)
|
||||
|
||||
#ifdef WITH_XKBFILE
|
||||
if (status < 0)
|
||||
{
|
||||
status = freerdp_keyboard_init_xkbfile(&keyboardLayoutId, X11_KEYCODE_TO_VIRTUAL_SCANCODE,
|
||||
ARRAYSIZE(X11_KEYCODE_TO_VIRTUAL_SCANCODE));
|
||||
if (status >= 0)
|
||||
maptype = WINPR_KEYCODE_TYPE_XKB;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status < 0)
|
||||
status = freerdp_keyboard_init_x11_evdev(&keyboardLayoutId, X11_KEYCODE_TO_VIRTUAL_SCANCODE,
|
||||
ARRAYSIZE(X11_KEYCODE_TO_VIRTUAL_SCANCODE));
|
||||
|
||||
#endif
|
||||
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "Platform keyboard detection failed, trying autodetection");
|
||||
|
||||
freerdp_detect_keyboard(&keyboardLayoutId);
|
||||
|
||||
ZeroMemory(VIRTUAL_SCANCODE_TO_X11_KEYCODE, sizeof(VIRTUAL_SCANCODE_TO_X11_KEYCODE));
|
||||
|
||||
WINPR_STATIC_ASSERT(ARRAYSIZE(VIRTUAL_SCANCODE_TO_X11_KEYCODE) <= UINT32_MAX);
|
||||
for (size_t keycode = 0; keycode < ARRAYSIZE(VIRTUAL_SCANCODE_TO_X11_KEYCODE); keycode++)
|
||||
{
|
||||
const DWORD x11 = X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode];
|
||||
const DWORD sc = RDP_SCANCODE_CODE(x11);
|
||||
const BOOL ex = RDP_SCANCODE_EXTENDED(x11);
|
||||
VIRTUAL_SCANCODE_TO_X11_KEYCODE[sc][ex ? 1 : 0] = (UINT32)keycode;
|
||||
}
|
||||
|
||||
return keyboardLayoutId;
|
||||
}
|
||||
#endif
|
||||
|
||||
FREERDP_REMAP_TABLE* freerdp_keyboard_remap_string_to_list(const char* list)
|
||||
{
|
||||
const size_t remap_table_size = 0x10000;
|
||||
|
||||
FREERDP_REMAP_TABLE* remap_table = calloc(1, sizeof(FREERDP_REMAP_TABLE));
|
||||
if (!remap_table)
|
||||
return nullptr;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(remap_table->table); x++)
|
||||
remap_table->table[x] = (UINT32)x;
|
||||
|
||||
if (!list)
|
||||
return remap_table;
|
||||
|
||||
BOOL success = FALSE;
|
||||
char* copy = _strdup(list);
|
||||
if (!copy)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
char* context = nullptr;
|
||||
char* token = strtok_s(copy, ",", &context);
|
||||
while (token)
|
||||
{
|
||||
UINT32 key = 0;
|
||||
UINT32 value = 0;
|
||||
if (!freerdp_extract_key_value(token, &key, &value))
|
||||
goto fail;
|
||||
if (key >= remap_table_size)
|
||||
goto fail;
|
||||
remap_table->table[key] = value;
|
||||
token = strtok_s(nullptr, ",", &context);
|
||||
}
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
fail:
|
||||
free(copy);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
free(remap_table);
|
||||
return nullptr;
|
||||
}
|
||||
return remap_table;
|
||||
}
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, const char* keyboardRemappingList)
|
||||
{
|
||||
DWORD res = freerdp_keyboard_init(keyboardLayoutId);
|
||||
|
||||
memset(REMAPPING_TABLE, 0, sizeof(REMAPPING_TABLE));
|
||||
if (keyboardRemappingList)
|
||||
{
|
||||
char* copy = _strdup(keyboardRemappingList);
|
||||
char* context = nullptr;
|
||||
char* token = nullptr;
|
||||
if (!copy)
|
||||
goto fail;
|
||||
token = strtok_s(copy, ",", &context);
|
||||
while (token)
|
||||
{
|
||||
DWORD key = 0;
|
||||
DWORD value = 0;
|
||||
if (!freerdp_extract_key_value(token, &key, &value))
|
||||
goto fail;
|
||||
if (key >= ARRAYSIZE(REMAPPING_TABLE))
|
||||
goto fail;
|
||||
REMAPPING_TABLE[key] = value;
|
||||
token = strtok_s(nullptr, ",", &context);
|
||||
}
|
||||
fail:
|
||||
free(copy);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode)
|
||||
{
|
||||
if (keycode >= ARRAYSIZE(X11_KEYCODE_TO_VIRTUAL_SCANCODE))
|
||||
{
|
||||
WLog_ERR(TAG, "KeyCode %" PRIu32 " exceeds allowed value range [0,%" PRIuz "]", keycode,
|
||||
ARRAYSIZE(X11_KEYCODE_TO_VIRTUAL_SCANCODE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DWORD scancode = X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode];
|
||||
if (scancode >= ARRAYSIZE(REMAPPING_TABLE))
|
||||
{
|
||||
WLog_ERR(TAG, "ScanCode %" PRIu32 " exceeds allowed value range [0,%" PRIuz "]", scancode,
|
||||
ARRAYSIZE(REMAPPING_TABLE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DWORD remapped = REMAPPING_TABLE[scancode];
|
||||
#if defined(WITH_DEBUG_KBD)
|
||||
const BOOL ex = RDP_SCANCODE_EXTENDED(scancode);
|
||||
const DWORD sc = RDP_SCANCODE_CODE(scancode);
|
||||
#endif
|
||||
|
||||
DEBUG_KBD("x11 keycode: %02" PRIX32 " -> rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", keycode,
|
||||
scancode, sc, ex ? " extended" : "");
|
||||
|
||||
if (remapped != 0)
|
||||
{
|
||||
#if defined(WITH_DEBUG_KBD)
|
||||
const DWORD rsc = RDP_SCANCODE_CODE(remapped);
|
||||
const BOOL rex = RDP_SCANCODE_EXTENDED(remapped);
|
||||
#endif
|
||||
|
||||
DEBUG_KBD("remapped scancode: [%04" PRIx16 "] %02" PRIX8 "[%s] -> [%04" PRIx16 "] %02" PRIX8
|
||||
"[%s]",
|
||||
scancode, sc, ex ? " extended" : "", remapped, rsc, rex ? " extended" : "");
|
||||
return remapped;
|
||||
}
|
||||
return scancode;
|
||||
}
|
||||
|
||||
DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode(DWORD scancode, BOOL extended)
|
||||
{
|
||||
if (scancode >= ARRAYSIZE(VIRTUAL_SCANCODE_TO_X11_KEYCODE))
|
||||
{
|
||||
WLog_ERR(TAG, "ScanCode %" PRIu32 " exceeds allowed value range [0,%" PRIuz "]", scancode,
|
||||
ARRAYSIZE(VIRTUAL_SCANCODE_TO_X11_KEYCODE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DWORD* x11 = VIRTUAL_SCANCODE_TO_X11_KEYCODE[scancode];
|
||||
WINPR_ASSERT(x11);
|
||||
|
||||
if (extended)
|
||||
return x11[1];
|
||||
else
|
||||
return x11[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* freerdp_keyboard_scancode_name(DWORD scancode)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(RDP_SCANCODE_MAP); x++)
|
||||
{
|
||||
const struct scancode_map_entry* entry = &RDP_SCANCODE_MAP[x];
|
||||
if (entry->scancode == scancode)
|
||||
return entry->name;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DWORD freerdp_keyboard_remap_key(const FREERDP_REMAP_TABLE* remap_table, DWORD rdpScanCode)
|
||||
{
|
||||
if (!remap_table || (ARRAYSIZE(remap_table->table) <= rdpScanCode))
|
||||
return 0;
|
||||
|
||||
return remap_table->table[rdpScanCode];
|
||||
}
|
||||
|
||||
void freerdp_keyboard_remap_free(FREERDP_REMAP_TABLE* table)
|
||||
{
|
||||
free(table);
|
||||
}
|
||||
241
third_party/FreeRDP/libfreerdp/locale/keyboard_apple.c
vendored
Normal file
241
third_party/FreeRDP/libfreerdp/locale/keyboard_apple.c
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Apple Core Foundation Keyboard Mapping
|
||||
*
|
||||
* Copyright 2021 Thincast Technologies GmbH
|
||||
* Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
|
||||
#include <freerdp/locale/locale.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "keyboard_apple.h"
|
||||
|
||||
struct KEYBOARD_LAYOUT_MAPPING_
|
||||
{
|
||||
const char* inputSourceId; /* Apple input source id (com.apple.keylayout or inputmethod) */
|
||||
DWORD code; /* mapped rdp keyboard layout id */
|
||||
};
|
||||
typedef struct KEYBOARD_LAYOUT_MAPPING_ KEYBOARD_LAYOUT_MAPPING;
|
||||
|
||||
static const KEYBOARD_LAYOUT_MAPPING KEYBOARD_MAPPING_TABLE[] = {
|
||||
{ "com.apple.inputmethod.Kotoeri.Japanese", JAPANESE },
|
||||
{ "com.apple.inputmethod.Kotoeri.Japanese.FullWidthRoman", JAPANESE },
|
||||
{ "com.apple.inputmethod.Kotoeri.Japanese.HalfWidthKana", JAPANESE },
|
||||
{ "com.apple.inputmethod.Kotoeri.Japanese.Katakana", JAPANESE },
|
||||
{ "com.apple.inputmethod.Kotoeri.Katakana", JAPANESE },
|
||||
{ "com.apple.inputmethod.Kotoeri.Roman", JAPANESE },
|
||||
{ "com.apple.inputmethod.kotoeri.Ainu", JAPANESE },
|
||||
{ "com.apple.keylayout.2SetHangul", KOREAN },
|
||||
{ "com.apple.keylayout.390Hangul", KOREAN },
|
||||
{ "com.apple.keylayout.3SetHangul", KOREAN },
|
||||
{ "com.apple.keylayout.AfghanDari", KBD_PERSIAN },
|
||||
{ "com.apple.keylayout.AfghanPashto", PASHTO },
|
||||
{ "com.apple.keylayout.AfghanUzbek", UZBEK_LATIN },
|
||||
{ "com.apple.keylayout.Arabic", ARABIC_SAUDI_ARABIA },
|
||||
{ "com.apple.keylayout.Arabic-QWERTY", ARABIC_EGYPT },
|
||||
{ "com.apple.keylayout.ArabicPC", ARABIC_EGYPT },
|
||||
{ "com.apple.keylayout.Armenian-HMQWERTY", ARMENIAN },
|
||||
{ "com.apple.keylayout.Armenian-WesternQWERTY", ARMENIAN },
|
||||
{ "com.apple.keylayout.Australian", ENGLISH_AUSTRALIAN },
|
||||
{ "com.apple.keylayout.Austrian", GERMAN_STANDARD },
|
||||
{ "com.apple.keylayout.Azeri", AZERI_LATIN },
|
||||
{ "com.apple.keylayout.Bangla", KBD_BANGLA },
|
||||
{ "com.apple.keylayout.Bangla-QWERTY", KBD_BANGLA },
|
||||
{ "com.apple.keylayout.Belgian", DUTCH_BELGIAN },
|
||||
{ "com.apple.keylayout.Brazilian", PORTUGUESE_BRAZILIAN },
|
||||
{ "com.apple.keylayout.British", ENGLISH_UNITED_KINGDOM },
|
||||
{ "com.apple.keylayout.British-PC", ENGLISH_UNITED_KINGDOM },
|
||||
{ "com.apple.keylayout.Bulgarian", BULGARIAN },
|
||||
{ "com.apple.keylayout.Bulgarian-Phonetic", KBD_BULGARIAN_PHONETIC },
|
||||
{ "com.apple.keylayout.Byelorussian", BELARUSIAN },
|
||||
{ "com.apple.keylayout.Canadian", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Canadian-CSA", KBD_CANADIAN_MULTILINGUAL_STANDARD },
|
||||
{ "com.apple.keylayout.CangjieKeyboard", CHINESE_TAIWAN },
|
||||
{ "com.apple.keylayout.Cherokee-Nation", CHEROKEE },
|
||||
{ "com.apple.keylayout.Cherokee-QWERTY", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Colemak", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Croatian", CROATIAN },
|
||||
{ "com.apple.keylayout.Croatian-PC", CROATIAN },
|
||||
{ "com.apple.keylayout.Czech", CZECH },
|
||||
{ "com.apple.keylayout.Czech-QWERTY", KBD_CZECH_QWERTY },
|
||||
{ "com.apple.keylayout.DVORAK-QWERTYCMD", KBD_UNITED_STATES_DVORAK },
|
||||
{ "com.apple.keylayout.Danish", DANISH },
|
||||
{ "com.apple.keylayout.Devanagari", HINDI },
|
||||
{ "com.apple.keylayout.Devanagari-QWERTY", HINDI },
|
||||
{ "com.apple.keylayout.Dutch", KBD_UNITED_STATES_INTERNATIONAL },
|
||||
{ "com.apple.keylayout.Dvorak", KBD_UNITED_STATES_DVORAK },
|
||||
{ "com.apple.keylayout.Dvorak-Left", KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND },
|
||||
{ "com.apple.keylayout.Dvorak-Right", KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND },
|
||||
{ "com.apple.keylayout.Estonian", ESTONIAN },
|
||||
{ "com.apple.keylayout.Faroese", FAEROESE },
|
||||
{ "com.apple.keylayout.Finnish", FINNISH },
|
||||
{ "com.apple.keylayout.FinnishExtended", KBD_SAMI_EXTENDED_FINLAND_SWEDEN },
|
||||
{ "com.apple.keylayout.FinnishSami-PC", KBD_FINNISH_WITH_SAMI },
|
||||
{ "com.apple.keylayout.French", KBD_BELGIAN_FRENCH },
|
||||
{ "com.apple.keylayout.French-PC", FRENCH_STANDARD },
|
||||
{ "com.apple.keylayout.French-numerical", KBD_BELGIAN_FRENCH },
|
||||
{ "com.apple.keylayout.GJCRomaja", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Georgian-QWERTY", KBD_GEORGIAN_QUERTY },
|
||||
{ "com.apple.keylayout.German", GERMAN_STANDARD },
|
||||
{ "com.apple.keylayout.Greek", GREEK },
|
||||
{ "com.apple.keylayout.GreekPolytonic", KBD_GREEK_POLYTONIC },
|
||||
{ "com.apple.keylayout.Gujarati", GUJARATI },
|
||||
{ "com.apple.keylayout.Gujarati-QWERTY", GUJARATI },
|
||||
{ "com.apple.keylayout.Gurmukhi", PUNJABI },
|
||||
{ "com.apple.keylayout.Gurmukhi-QWERTY", PUNJABI },
|
||||
{ "com.apple.keylayout.HNCRomaja", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Hawaiian", HAWAIIAN },
|
||||
{ "com.apple.keylayout.Hebrew", HEBREW },
|
||||
{ "com.apple.keylayout.Hebrew-PC", HEBREW },
|
||||
{ "com.apple.keylayout.Hebrew-QWERTY", HEBREW },
|
||||
{ "com.apple.keylayout.Hungarian", HUNGARIAN },
|
||||
{ "com.apple.keylayout.Hungarian-QWERTY", HUNGARIAN },
|
||||
{ "com.apple.keylayout.Icelandic", ICELANDIC },
|
||||
{ "com.apple.keylayout.Inuktitut-Nunavut", INUKTITUT },
|
||||
{ "com.apple.keylayout.Inuktitut-Nutaaq", INUKTITUT },
|
||||
{ "com.apple.keylayout.Inuktitut-QWERTY", INUKTITUT },
|
||||
{ "com.apple.keylayout.InuttitutNunavik", INUKTITUT },
|
||||
{ "com.apple.keylayout.Irish", ENGLISH_IRELAND },
|
||||
{ "com.apple.keylayout.IrishExtended", KBD_IRISH },
|
||||
{ "com.apple.keylayout.Italian", ITALIAN_STANDARD },
|
||||
{ "com.apple.keylayout.Italian-Pro", ITALIAN_STANDARD },
|
||||
{ "com.apple.keylayout.Jawi-QWERTY", ARABIC_SAUDI_ARABIA },
|
||||
{ "com.apple.keylayout.Kannada", KANNADA },
|
||||
{ "com.apple.keylayout.Kannada-QWERTY", KANNADA },
|
||||
{ "com.apple.keylayout.Kazakh", KAZAKH },
|
||||
{ "com.apple.keylayout.Khmer", KBD_KHMER },
|
||||
{ "com.apple.keylayout.Latvian", LATVIAN },
|
||||
{ "com.apple.keylayout.Lithuanian", LITHUANIAN },
|
||||
{ "com.apple.keylayout.Macedonian", MACEDONIAN },
|
||||
{ "com.apple.keylayout.Malayalam", MALAYALAM },
|
||||
{ "com.apple.keylayout.Malayalam-QWERTY", MALAYALAM },
|
||||
{ "com.apple.keylayout.Maltese", MALTESE },
|
||||
{ "com.apple.keylayout.Maori", MAORI },
|
||||
{ "com.apple.keylayout.Myanmar-QWERTY", MYANMAR },
|
||||
{ "com.apple.keylayout.Nepali", NEPALI },
|
||||
{ "com.apple.keylayout.NorthernSami", SAMI_NORTHERN_NORWAY },
|
||||
{ "com.apple.keylayout.Norwegian", NORWEGIAN_BOKMAL },
|
||||
{ "com.apple.keylayout.NorwegianExtended", NORWEGIAN_BOKMAL },
|
||||
{ "com.apple.keylayout.NorwegianSami-PC", NORWEGIAN_BOKMAL },
|
||||
{ "com.apple.keylayout.Oriya", ORIYA },
|
||||
{ "com.apple.keylayout.Persian", KBD_PERSIAN },
|
||||
{ "com.apple.keylayout.Persian-ISIRI2901", KBD_PERSIAN },
|
||||
{ "com.apple.keylayout.Polish", KBD_POLISH_214 },
|
||||
{ "com.apple.keylayout.PolishPro", KBD_POLISH_PROGRAMMERS },
|
||||
{ "com.apple.keylayout.Portuguese", PORTUGUESE_STANDARD },
|
||||
{ "com.apple.keylayout.Romanian", KBD_ROMANIAN },
|
||||
{ "com.apple.keylayout.Romanian-Standard", KBD_ROMANIAN_STANDARD },
|
||||
{ "com.apple.keylayout.Russian", RUSSIAN },
|
||||
{ "com.apple.keylayout.Russian-Phonetic", KBD_RUSSIAN_PHONETIC },
|
||||
{ "com.apple.keylayout.RussianWin", RUSSIAN },
|
||||
{ "com.apple.keylayout.Sami-PC", KBD_SAMI_EXTENDED_FINLAND_SWEDEN },
|
||||
{ "com.apple.keylayout.Serbian", KBD_SERBIAN_CYRILLIC },
|
||||
{ "com.apple.keylayout.Serbian-Latin", KBD_SERBIAN_LATIN },
|
||||
{ "com.apple.keylayout.Sinhala", SINHALA },
|
||||
{ "com.apple.keylayout.Sinhala-QWERTY", SINHALA },
|
||||
{ "com.apple.keylayout.Slovak", SLOVAK },
|
||||
{ "com.apple.keylayout.Slovak-QWERTY", KBD_SLOVAK_QWERTY },
|
||||
{ "com.apple.keylayout.Slovenian", SLOVENIAN },
|
||||
{ "com.apple.keylayout.Spanish", SPANISH_TRADITIONAL_SORT },
|
||||
{ "com.apple.keylayout.Spanish-ISO", KBD_SPANISH },
|
||||
{ "com.apple.keylayout.Swedish", SWEDISH },
|
||||
{ "com.apple.keylayout.Swedish-Pro", SWEDISH },
|
||||
{ "com.apple.keylayout.SwedishSami-PC", SWEDISH },
|
||||
{ "com.apple.keylayout.SwissFrench", FRENCH_SWISS },
|
||||
{ "com.apple.keylayout.SwissGerman", GERMAN_SWISS },
|
||||
{ "com.apple.keylayout.Telugu", TELUGU },
|
||||
{ "com.apple.keylayout.Telugu-QWERTY", TELUGU },
|
||||
{ "com.apple.keylayout.Thai", THAI },
|
||||
{ "com.apple.keylayout.Thai-PattaChote", KBD_THAI_PATTACHOTE },
|
||||
{ "com.apple.keylayout.Tibetan-QWERTY", TIBETAN_PRC },
|
||||
{ "com.apple.keylayout.Tibetan-Wylie", TIBETAN_PRC },
|
||||
{ "com.apple.keylayout.TibetanOtaniUS", TIBETAN_PRC },
|
||||
{ "com.apple.keylayout.Turkish", KBD_TURKISH_F },
|
||||
{ "com.apple.keylayout.Turkish-QWERTY", TURKISH },
|
||||
{ "com.apple.keylayout.Turkish-QWERTY-PC", TURKISH },
|
||||
{ "com.apple.keylayout.US", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.USExtended", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.USInternational-PC", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Ukrainian", UKRAINIAN },
|
||||
{ "com.apple.keylayout.Ukrainian-PC", UKRAINIAN },
|
||||
{ "com.apple.keylayout.UnicodeHexInput", ENGLISH_UNITED_STATES },
|
||||
{ "com.apple.keylayout.Urdu", URDU },
|
||||
{ "com.apple.keylayout.Uyghur", UIGHUR },
|
||||
{ "com.apple.keylayout.Vietnamese", VIETNAMESE },
|
||||
{ "com.apple.keylayout.Welsh", WELSH }
|
||||
};
|
||||
|
||||
int freerdp_detect_keyboard_layout_from_cf(DWORD* keyboardLayoutId)
|
||||
{
|
||||
CFIndex length;
|
||||
char* inputSourceId = nullptr;
|
||||
CFStringRef inputSourceIdRef;
|
||||
TISInputSourceRef inputSrc = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
if (!inputSrc)
|
||||
{
|
||||
DEBUG_KBD("Failed to get current keyboard layout input source!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get current input source id */
|
||||
inputSourceIdRef = (CFStringRef)TISGetInputSourceProperty(inputSrc, kTISPropertyInputSourceID);
|
||||
if (!inputSourceIdRef)
|
||||
{
|
||||
DEBUG_KBD("Failed to get input source id!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* convert it to a C-string */
|
||||
length = CFStringGetLength(inputSourceIdRef);
|
||||
length = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
|
||||
inputSourceId = (char*)malloc(length);
|
||||
if (!inputSourceId)
|
||||
{
|
||||
DEBUG_KBD("Failed to allocate string buffer!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!CFStringGetCString(inputSourceIdRef, inputSourceId, length, kCFStringEncodingUTF8))
|
||||
{
|
||||
DEBUG_KBD("Failed to convert CFString to C-string!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Search for the id in the mapping table */
|
||||
for (size_t i = 0; i < ARRAYSIZE(KEYBOARD_MAPPING_TABLE); ++i)
|
||||
{
|
||||
if (strcmp(inputSourceId, KEYBOARD_MAPPING_TABLE[i].inputSourceId) == 0)
|
||||
{
|
||||
*keyboardLayoutId = KEYBOARD_MAPPING_TABLE[i].code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
free(inputSourceId);
|
||||
CFRelease(inputSrc);
|
||||
if (*keyboardLayoutId > 0)
|
||||
return *keyboardLayoutId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
third_party/FreeRDP/libfreerdp/locale/keyboard_apple.h
vendored
Normal file
28
third_party/FreeRDP/libfreerdp/locale/keyboard_apple.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Apple Core Foundation Keyboard Mapping
|
||||
*
|
||||
* Copyright 2021 Thincast Technologies GmbH
|
||||
* Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
|
||||
*
|
||||
* 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_APPLE_H
|
||||
#define FREERDP_LOCALE_KEYBOARD_APPLE_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL int freerdp_detect_keyboard_layout_from_cf(DWORD* keyboardLayoutId);
|
||||
|
||||
#endif /* FREERDP_LOCALE_KEYBOARD_APPLE_H */
|
||||
1621
third_party/FreeRDP/libfreerdp/locale/keyboard_layout.c
vendored
Normal file
1621
third_party/FreeRDP/libfreerdp/locale/keyboard_layout.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
284
third_party/FreeRDP/libfreerdp/locale/keyboard_sun.c
vendored
Normal file
284
third_party/FreeRDP/libfreerdp/locale/keyboard_sun.c
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Solaris Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "keyboard_x11.h"
|
||||
|
||||
#include "keyboard_sun.h"
|
||||
|
||||
/* OpenSolaris 2008.11 and 2009.06 keyboard layouts
|
||||
*
|
||||
* While OpenSolaris comes with Xorg and XKB, it maintains a set of keyboard layout
|
||||
* names that map directly to a particular keyboard layout in XKB. Fortunately for us,
|
||||
* this way of doing things comes from Solaris, which is XKB unaware. The same keyboard
|
||||
* layout naming system is used in Solaris, so we can use the same XKB configuration as
|
||||
* we would on OpenSolaris and get an accurate keyboard layout detection :)
|
||||
*
|
||||
* We can check for the current keyboard layout using the "kbd -l" command:
|
||||
*
|
||||
* type=6
|
||||
* layout=33 (0x21)
|
||||
* delay(ms)=500
|
||||
* rate(ms)=40
|
||||
*
|
||||
* We can check at runtime if the kbd utility is present, parse the output, and use the
|
||||
* keyboard layout indicated by the index given (in this case, 33, or US-English).
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 type; /* Solaris keyboard type */
|
||||
UINT32 layout; /* Layout */
|
||||
char* xkbType; /* XKB keyboard */
|
||||
UINT32 keyboardLayoutId; /* XKB keyboard layout */
|
||||
} SOLARIS_KEYBOARD;
|
||||
|
||||
static const SOLARIS_KEYBOARD SOLARIS_KEYBOARD_TABLE[] = {
|
||||
{ 4, 0, "sun(type4)", KBD_US }, /* US4 */
|
||||
{ 4, 1, "sun(type4)", KBD_US }, /* US4 */
|
||||
{ 4, 2, "sun(type4tuv)", KBD_FRENCH }, /* FranceBelg4 */
|
||||
{ 4, 3, "sun(type4_ca)", KBD_US }, /* Canada4 */
|
||||
{ 4, 4, "sun(type4tuv)", KBD_DANISH }, /* Denmark4 */
|
||||
{ 4, 5, "sun(type4tuv)", KBD_GERMAN }, /* Germany4 */
|
||||
{ 4, 6, "sun(type4tuv)", KBD_ITALIAN }, /* Italy4 */
|
||||
{ 4, 7, "sun(type4tuv)", KBD_DUTCH }, /* Netherland4 */
|
||||
{ 4, 8, "sun(type4tuv)", KBD_NORWEGIAN }, /* Norway4 */
|
||||
{ 4, 9, "sun(type4tuv)", KBD_PORTUGUESE }, /* Portugal4 */
|
||||
{ 4, 10, "sun(type4tuv)", KBD_SPANISH }, /* SpainLatAm4 */
|
||||
{ 4, 11, "sun(type4tuv)", KBD_SWEDISH }, /* SwedenFin4 */
|
||||
{ 4, 12, "sun(type4tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr4 */
|
||||
{ 4, 13, "sun(type4tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge4 */
|
||||
{ 4, 14, "sun(type4tuv)", KBD_UNITED_KINGDOM }, /* UK4 */
|
||||
{ 4, 16, "sun(type4)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea4 */
|
||||
{ 4, 17, "sun(type4)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan4 */
|
||||
{ 4, 32, "sun(type4jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan4 */
|
||||
{ 4, 19, "sun(type5)", KBD_US }, /* US101A_PC */
|
||||
{ 4, 33, "sun(type5)", KBD_US }, /* US5 */
|
||||
{ 4, 34, "sun(type5unix)", KBD_US }, /* US_UNIX5 */
|
||||
{ 4, 35, "sun(type5tuv)", KBD_FRENCH }, /* France5 */
|
||||
{ 4, 36, "sun(type5tuv)", KBD_DANISH }, /* Denmark5 */
|
||||
{ 4, 37, "sun(type5tuv)", KBD_GERMAN }, /* Germany5 */
|
||||
{ 4, 38, "sun(type5tuv)", KBD_ITALIAN }, /* Italy5 */
|
||||
{ 4, 39, "sun(type5tuv)", KBD_DUTCH }, /* Netherland5 */
|
||||
{ 4, 40, "sun(type5tuv)", KBD_NORWEGIAN }, /* Norway5 */
|
||||
{ 4, 41, "sun(type5tuv)", KBD_PORTUGUESE }, /* Portugal5 */
|
||||
{ 4, 42, "sun(type5tuv)", KBD_SPANISH }, /* Spain5 */
|
||||
{ 4, 43, "sun(type5tuv)", KBD_SWEDISH }, /* Sweden5 */
|
||||
{ 4, 44, "sun(type5tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr5 */
|
||||
{ 4, 45, "sun(type5tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge5 */
|
||||
{ 4, 46, "sun(type5tuv)", KBD_UNITED_KINGDOM }, /* UK5 */
|
||||
{ 4, 47, "sun(type5)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea5 */
|
||||
{ 4, 48, "sun(type5)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan5 */
|
||||
{ 4, 49, "sun(type5jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan5 */
|
||||
{ 4, 50, "sun(type5tuv)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5 */
|
||||
{ 4, 51, "sun(type5tuv)", KBD_HUNGARIAN }, /* Hungary5 */
|
||||
{ 4, 52, "sun(type5tuv)", KBD_POLISH_214 }, /* Poland5 */
|
||||
{ 4, 53, "sun(type5tuv)", KBD_CZECH }, /* Czech5 */
|
||||
{ 4, 54, "sun(type5tuv)", KBD_RUSSIAN }, /* Russia5 */
|
||||
{ 4, 55, "sun(type5tuv)", KBD_LATVIAN }, /* Latvia5 */
|
||||
{ 4, 57, "sun(type5tuv)", KBD_GREEK }, /* Greece5 */
|
||||
{ 4, 59, "sun(type5tuv)", KBD_LITHUANIAN }, /* Lithuania5 */
|
||||
{ 4, 63, "sun(type5tuv)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5_TBITS5 */
|
||||
{ 4, 56, "sun(type5tuv)", KBD_TURKISH_Q }, /* TurkeyQ5 */
|
||||
{ 4, 58, "sun(type5tuv)", KBD_ARABIC_101 }, /* Arabic5 */
|
||||
{ 4, 60, "sun(type5tuv)", KBD_BELGIAN_FRENCH }, /* Belgian5 */
|
||||
{ 4, 62, "sun(type5tuv)", KBD_TURKISH_F }, /* TurkeyF5 */
|
||||
{ 4, 80, "sun(type5hobo)", KBD_US }, /* US5_Hobo */
|
||||
{ 4, 81, "sun(type5hobo)", KBD_US }, /* US_UNIX5_Hobo */
|
||||
{ 4, 82, "sun(type5tuvhobo)", KBD_FRENCH }, /* France5_Hobo */
|
||||
{ 4, 83, "sun(type5tuvhobo)", KBD_DANISH }, /* Denmark5_Hobo */
|
||||
{ 4, 84, "sun(type5tuvhobo)", KBD_GERMAN }, /* Germany5_Hobo */
|
||||
{ 4, 85, "sun(type5tuvhobo)", KBD_ITALIAN }, /* Italy5_Hobo */
|
||||
{ 4, 86, "sun(type5tuvhobo)", KBD_DUTCH }, /* Netherland5_Hobo */
|
||||
{ 4, 87, "sun(type5tuvhobo)", KBD_NORWEGIAN }, /* Norway5_Hobo */
|
||||
{ 4, 88, "sun(type5tuvhobo)", KBD_PORTUGUESE }, /* Portugal5_Hobo */
|
||||
{ 4, 89, "sun(type5tuvhobo)", KBD_SPANISH }, /* Spain5_Hobo */
|
||||
{ 4, 90, "sun(type5tuvhobo)", KBD_SWEDISH }, /* Sweden5_Hobo */
|
||||
{ 4, 91, "sun(type5tuvhobo)", KBD_SWISS_FRENCH }, /* Switzer_Fr5_Hobo */
|
||||
{ 4, 92, "sun(type5tuvhobo)", KBD_SWISS_GERMAN }, /* Switzer_Ge5_Hobo */
|
||||
{ 4, 93, "sun(type5tuvhobo)", KBD_UNITED_KINGDOM }, /* UK5_Hobo */
|
||||
{ 4, 94, "sun(type5hobo)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea5_Hobo */
|
||||
{ 4, 95, "sun(type5hobo)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan5_Hobo */
|
||||
{ 4, 96, "sun(type5jphobo)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan5_Hobo */
|
||||
{ 4, 97, "sun(type5tuvhobo)", KBD_CANADIAN_FRENCH }, /* Canada_Fr5_Hobo */
|
||||
{ 101, 1, "digital_vndr/pc(pc104)", KBD_US }, /* US101A_x86 */
|
||||
{ 101, 34, "digital_vndr/pc(pc104)", KBD_US }, /* J3100_x86 */
|
||||
{ 101, 35, "digital_vndr/pc(pc104)", KBD_FRENCH }, /* France_x86 */
|
||||
{ 101, 36, "digital_vndr/pc(pc104)", KBD_DANISH }, /* Denmark_x86 */
|
||||
{ 101, 37, "digital_vndr/pc(pc104)", KBD_GERMAN }, /* Germany_x86 */
|
||||
{ 101, 38, "digital_vndr/pc(pc104)", KBD_ITALIAN }, /* Italy_x86 */
|
||||
{ 101, 39, "digital_vndr/pc(pc104)", KBD_DUTCH }, /* Netherland_x86 */
|
||||
{ 101, 40, "digital_vndr/pc(pc104)", KBD_NORWEGIAN }, /* Norway_x86 */
|
||||
{ 101, 41, "digital_vndr/pc(pc104)", KBD_PORTUGUESE }, /* Portugal_x86 */
|
||||
{ 101, 42, "digital_vndr/pc(pc104)", KBD_SPANISH }, /* Spain_x86 */
|
||||
{ 101, 43, "digital_vndr/pc(pc104)", KBD_SWEDISH }, /* Sweden_x86 */
|
||||
{ 101, 44, "digital_vndr/pc(pc104)", KBD_SWISS_FRENCH }, /* Switzer_Fr_x86 */
|
||||
{ 101, 45, "digital_vndr/pc(pc104)", KBD_SWISS_GERMAN }, /* Switzer_Ge_x86 */
|
||||
{ 101, 46, "digital_vndr/pc(pc104)", KBD_UNITED_KINGDOM }, /* UK_x86 */
|
||||
{ 101, 47, "digital_vndr/pc(pc104)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea_x86 */
|
||||
{ 101, 48, "digital_vndr/pc(pc104)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan_x86 */
|
||||
{ 101, 49, "digital_vndr/pc(lk411jj)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan_x86 */
|
||||
{ 101, 50, "digital_vndr/pc(pc104)", KBD_CANADIAN_FRENCH }, /* Canada_Fr2_x86 */
|
||||
{ 101, 51, "digital_vndr/pc(pc104)", KBD_HUNGARIAN }, /* Hungary_x86 */
|
||||
{ 101, 52, "digital_vndr/pc(pc104)", KBD_POLISH_214 }, /* Poland_x86 */
|
||||
{ 101, 53, "digital_vndr/pc(pc104)", KBD_CZECH }, /* Czech_x86 */
|
||||
{ 101, 54, "digital_vndr/pc(pc104)", KBD_RUSSIAN }, /* Russia_x86 */
|
||||
{ 101, 55, "digital_vndr/pc(pc104)", KBD_LATVIAN }, /* Latvia_x86 */
|
||||
{ 101, 56, "digital_vndr/pc(pc104)", KBD_TURKISH_Q }, /* Turkey_x86 */
|
||||
{ 101, 57, "digital_vndr/pc(pc104)", KBD_GREEK }, /* Greece_x86 */
|
||||
{ 101, 59, "digital_vndr/pc(pc104)", KBD_LITHUANIAN }, /* Lithuania_x86 */
|
||||
{ 101, 1001, "digital_vndr/pc(pc104)", KBD_US }, /* MS_US101A_x86 */
|
||||
{ 6, 6, "sun(type6tuv)", KBD_DANISH }, /* Denmark6_usb */
|
||||
{ 6, 7, "sun(type6tuv)", KBD_FINNISH }, /* Finnish6_usb */
|
||||
{ 6, 8, "sun(type6tuv)", KBD_FRENCH }, /* France6_usb */
|
||||
{ 6, 9, "sun(type6tuv)", KBD_GERMAN }, /* Germany6_usb */
|
||||
{ 6, 14, "sun(type6tuv)", KBD_ITALIAN }, /* Italy6_usb */
|
||||
{ 6, 15, "sun(type6jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan7_usb */
|
||||
{ 6, 16, "sun(type6)", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* Korea6_usb */
|
||||
{ 6, 18, "sun(type6tuv)", KBD_DUTCH }, /* Netherland6_usb */
|
||||
{ 6, 19, "sun(type6tuv)", KBD_NORWEGIAN }, /* Norway6_usb */
|
||||
{ 6, 22, "sun(type6tuv)", KBD_PORTUGUESE }, /* Portugal6_usb */
|
||||
{ 6, 23, "sun(type6tuv)", KBD_RUSSIAN }, /* Russia6_usb */
|
||||
{ 6, 25, "sun(type6tuv)", KBD_SPANISH }, /* Spain6_usb */
|
||||
{ 6, 26, "sun(type6tuv)", KBD_SWEDISH }, /* Sweden6_usb */
|
||||
{ 6, 27, "sun(type6tuv)", KBD_SWISS_FRENCH }, /* Switzer_Fr6_usb */
|
||||
{ 6, 28, "sun(type6tuv)", KBD_SWISS_GERMAN }, /* Switzer_Ge6_usb */
|
||||
{ 6, 30, "sun(type6)", KBD_CHINESE_TRADITIONAL_PHONETIC }, /* Taiwan6_usb */
|
||||
{ 6, 32, "sun(type6tuv)", KBD_UNITED_KINGDOM }, /* UK6_usb */
|
||||
{ 6, 33, "sun(type6)", KBD_US }, /* US6_usb */
|
||||
{ 6, 1, "sun(type6tuv)", KBD_ARABIC_101 }, /* Arabic6_usb */
|
||||
{ 6, 2, "sun(type6tuv)", KBD_BELGIAN_FRENCH }, /* Belgian6_usb */
|
||||
{ 6, 31, "sun(type6tuv)", KBD_TURKISH_Q }, /* TurkeyQ6_usb */
|
||||
{ 6, 35, "sun(type6tuv)", KBD_TURKISH_F }, /* TurkeyF6_usb */
|
||||
{ 6, 271, "sun(type6jp)", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Japan6_usb */
|
||||
{ 6, 264, "sun(type6tuv)", KBD_ALBANIAN }, /* Albanian6_usb */
|
||||
{ 6, 261, "sun(type6tuv)", KBD_BELARUSIAN }, /* Belarusian6_usb */
|
||||
{ 6, 260, "sun(type6tuv)", KBD_BULGARIAN }, /* Bulgarian6_usb */
|
||||
{ 6, 259, "sun(type6tuv)", KBD_CROATIAN }, /* Croatian6_usb */
|
||||
{ 6, 5, "sun(type6tuv)", KBD_CZECH }, /* Czech6_usb */
|
||||
{ 6, 4, "sun(type6tuv)", KBD_CANADIAN_FRENCH }, /* French-Canadian6_usb */
|
||||
{ 6, 12, "sun(type6tuv)", KBD_HUNGARIAN }, /* Hungarian6_usb */
|
||||
{ 6, 10, "sun(type6tuv)", KBD_GREEK }, /* Greek6_usb */
|
||||
{ 6, 17, "sun(type6)", KBD_LATIN_AMERICAN }, /* Latin-American6_usb */
|
||||
{ 6, 265, "sun(type6tuv)", KBD_LITHUANIAN }, /* Lithuanian6_usb */
|
||||
{ 6, 266, "sun(type6tuv)", KBD_LATVIAN }, /* Latvian6_usb */
|
||||
{ 6, 267, "sun(type6tuv)", KBD_FYRO_MACEDONIAN }, /* Macedonian6_usb */
|
||||
{ 6, 263, "sun(type6tuv)", KBD_MALTESE_47_KEY }, /* Malta_UK6_usb */
|
||||
{ 6, 262, "sun(type6tuv)", KBD_MALTESE_48_KEY }, /* Malta_US6_usb */
|
||||
{ 6, 21, "sun(type6tuv)", KBD_POLISH_214 }, /* Polish6_usb */
|
||||
{ 6, 257, "sun(type6tuv)", KBD_SERBIAN_LATIN }, /* Serbia-And-Montenegro6_usb */
|
||||
{ 6, 256, "sun(type6tuv)", KBD_SLOVENIAN }, /* Slovenian6_usb */
|
||||
{ 6, 24, "sun(type6tuv)", KBD_SLOVAK }, /* Slovakian6_usb */
|
||||
{ 6, 3, "sun(type6)", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Canada_Bi6_usb */
|
||||
{ 6, 272, "sun(type6)", KBD_PORTUGUESE_BRAZILIAN_ABNT } /* Brazil6_usb */
|
||||
};
|
||||
|
||||
int freerdp_get_solaris_keyboard_layout_and_type(int* type, int* layout)
|
||||
{
|
||||
FILE* kbd;
|
||||
char* pch;
|
||||
char* beg;
|
||||
char* end;
|
||||
int rc = -1;
|
||||
char buffer[1024];
|
||||
/*
|
||||
Sample output for "kbd -t -l" :
|
||||
|
||||
USB keyboard
|
||||
type=6
|
||||
layout=3 (0x03)
|
||||
delay(ms)=500
|
||||
rate(ms)=40
|
||||
*/
|
||||
*type = 0;
|
||||
*layout = 0;
|
||||
kbd = popen("kbd -t -l", "r");
|
||||
|
||||
if (!kbd)
|
||||
return -1;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), kbd) != nullptr)
|
||||
{
|
||||
long val;
|
||||
|
||||
if ((pch = strstr(buffer, "type=")) != nullptr)
|
||||
{
|
||||
beg = pch + sizeof("type=") - 1;
|
||||
end = strchr(beg, '\n');
|
||||
end[0] = '\0';
|
||||
errno = 0;
|
||||
val = strtol(beg, nullptr, 0);
|
||||
|
||||
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
|
||||
goto fail;
|
||||
|
||||
*type = val;
|
||||
}
|
||||
else if ((pch = strstr(buffer, "layout=")) != nullptr)
|
||||
{
|
||||
beg = pch + sizeof("layout=") - 1;
|
||||
end = strchr(beg, ' ');
|
||||
end[0] = '\0';
|
||||
errno = 0;
|
||||
val = strtol(beg, nullptr, 0);
|
||||
|
||||
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
|
||||
goto fail;
|
||||
|
||||
*layout = val;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
pclose(kbd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
DWORD freerdp_detect_solaris_keyboard_layout()
|
||||
{
|
||||
int type;
|
||||
int layout;
|
||||
|
||||
if (freerdp_get_solaris_keyboard_layout_and_type(&type, &layout) < 0)
|
||||
return 0;
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(SOLARIS_KEYBOARD_TABLE); i++)
|
||||
{
|
||||
if (SOLARIS_KEYBOARD_TABLE[i].type == type)
|
||||
{
|
||||
if (SOLARIS_KEYBOARD_TABLE[i].layout == layout)
|
||||
return SOLARIS_KEYBOARD_TABLE[i].keyboardLayoutId;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
third_party/FreeRDP/libfreerdp/locale/keyboard_sun.h
vendored
Normal file
28
third_party/FreeRDP/libfreerdp/locale/keyboard_sun.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Solaris Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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_SUN_H
|
||||
#define FREERDP_LOCALE_KEYBOARD_SUN_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD freerdp_detect_solaris_keyboard_layout();
|
||||
|
||||
#endif /* FREERDP_LOCALE_KEYBOARD_SUN_H */
|
||||
144
third_party/FreeRDP/libfreerdp/locale/keyboard_x11.c
vendored
Normal file
144
third_party/FreeRDP/libfreerdp/locale/keyboard_x11.c
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* X11 Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2023 Bernhard Miklautz <bernhard.miklautz@thincast.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
#include "keyboard_x11.h"
|
||||
#include "xkb_layout_ids.h"
|
||||
|
||||
static BOOL parse_xkb_rule_names(char* xkb_rule, unsigned long num_bytes, char** layout,
|
||||
char** variant)
|
||||
{
|
||||
/* Sample output for "Canadian Multilingual Standard"
|
||||
*
|
||||
* _XKB_RULES_NAMES_BACKUP(STRING) = "xorg", "pc105", "ca", "multi", "magic"
|
||||
*
|
||||
* Format: "rules", "model", "layout", "variant", "options"
|
||||
*
|
||||
* Where "xorg" is the set of rules
|
||||
* "pc105" the keyboard model
|
||||
* "ca" the keyboard layout(s) (can also be something like 'us,uk')
|
||||
* "multi" the keyboard layout variant(s) (in the examples, “,winkeys” - which means first
|
||||
* layout uses some “default” variant and second uses “winkeys” variant)
|
||||
* "magic" - configuration option (in the examples,
|
||||
* “eurosign:e,lv3:ralt_switch,grp:rctrl_toggle”
|
||||
* - three options)
|
||||
*/
|
||||
for (size_t i = 0, index = 0; i < num_bytes; i++, index++)
|
||||
{
|
||||
char* ptr = xkb_rule + i;
|
||||
i += strnlen(ptr, num_bytes - i);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: // rules
|
||||
break;
|
||||
case 1: // model
|
||||
break;
|
||||
case 2: // layout
|
||||
{
|
||||
/* If multiple languages are present we just take the first one */
|
||||
char* delimiter = strchr(ptr, ',');
|
||||
if (delimiter)
|
||||
*delimiter = '\0';
|
||||
*layout = ptr;
|
||||
break;
|
||||
}
|
||||
case 3: // variant
|
||||
{
|
||||
/* If multiple variants are present we just take the first one */
|
||||
char* delimiter = strchr(ptr, ',');
|
||||
if (delimiter)
|
||||
*delimiter = '\0';
|
||||
*variant = ptr;
|
||||
}
|
||||
break;
|
||||
case 4: // option
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DWORD kbd_layout_id_from_x_property(Display* display, Window root, char* property_name)
|
||||
{
|
||||
char* layout = nullptr;
|
||||
char* variant = nullptr;
|
||||
char* rule = nullptr;
|
||||
Atom type = None;
|
||||
int item_size = 0;
|
||||
unsigned long items = 0;
|
||||
unsigned long unread_items = 0;
|
||||
DWORD layout_id = 0;
|
||||
|
||||
Atom property = XInternAtom(display, property_name, False);
|
||||
if (property == None)
|
||||
return 0;
|
||||
|
||||
if (XGetWindowProperty(display, root, property, 0, 1024, False, XA_STRING, &type, &item_size,
|
||||
&items, &unread_items, (unsigned char**)&rule) != Success)
|
||||
return 0;
|
||||
|
||||
if (type != XA_STRING || item_size != 8 || unread_items != 0)
|
||||
{
|
||||
XFree(rule);
|
||||
return 0;
|
||||
}
|
||||
|
||||
parse_xkb_rule_names(rule, items, &layout, &variant);
|
||||
|
||||
DEBUG_KBD("%s layout: %s, variant: %s", property_name, layout, variant);
|
||||
layout_id = find_keyboard_layout_in_xorg_rules(layout, variant);
|
||||
|
||||
XFree(rule);
|
||||
|
||||
return layout_id;
|
||||
}
|
||||
|
||||
int freerdp_detect_keyboard_layout_from_xkb(DWORD* keyboardLayoutId)
|
||||
{
|
||||
Display* display = XOpenDisplay(nullptr);
|
||||
|
||||
if (!display)
|
||||
return 0;
|
||||
|
||||
Window root = DefaultRootWindow(display);
|
||||
if (!root)
|
||||
return 0;
|
||||
|
||||
/* We start by looking for _XKB_RULES_NAMES_BACKUP which appears to be used by libxklavier */
|
||||
DWORD id = kbd_layout_id_from_x_property(display, root, "_XKB_RULES_NAMES_BACKUP");
|
||||
|
||||
if (0 == id)
|
||||
id = kbd_layout_id_from_x_property(display, root, "_XKB_RULES_NAMES");
|
||||
|
||||
if (0 != id)
|
||||
*keyboardLayoutId = id;
|
||||
|
||||
XCloseDisplay(display);
|
||||
return (int)id;
|
||||
}
|
||||
29
third_party/FreeRDP/libfreerdp/locale/keyboard_x11.h
vendored
Normal file
29
third_party/FreeRDP/libfreerdp/locale/keyboard_x11.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* X11 Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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_X11_H
|
||||
#define FREERDP_LOCALE_KEYBOARD_X11_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
FREERDP_LOCAL int freerdp_detect_keyboard_layout_from_xkb(DWORD* keyboardLayoutId);
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LOCALE_KEYBOARD_X11_H */
|
||||
511
third_party/FreeRDP/libfreerdp/locale/keyboard_xkbfile.c
vendored
Normal file
511
third_party/FreeRDP/libfreerdp/locale/keyboard_xkbfile.c
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* XKB Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "keyboard_xkbfile.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/input.h>
|
||||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "keyboard_x11.h"
|
||||
#include "xkb_layout_ids.h"
|
||||
#include "liblocale.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBfile.h>
|
||||
#include <X11/extensions/XKBrules.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* xkb_keyname; /* XKB keyname */
|
||||
DWORD rdp_scancode;
|
||||
} XKB_KEY_NAME_SCANCODE;
|
||||
|
||||
static const XKB_KEY_NAME_SCANCODE XKB_KEY_NAME_SCANCODE_TABLE[] = {
|
||||
{ "", RDP_SCANCODE_UNKNOWN }, /* 008: [(null)] */
|
||||
{ "ESC", RDP_SCANCODE_ESCAPE }, /* 009: ESC [Escape] */
|
||||
{ "AE01", RDP_SCANCODE_KEY_1 }, /* 010: AE01 [1] */
|
||||
{ "AE02", RDP_SCANCODE_KEY_2 }, /* 011: AE02 [2] */
|
||||
{ "AE03", RDP_SCANCODE_KEY_3 }, /* 012: AE03 [3] */
|
||||
{ "AE04", RDP_SCANCODE_KEY_4 }, /* 013: AE04 [4] */
|
||||
{ "AE05", RDP_SCANCODE_KEY_5 }, /* 014: AE05 [5] */
|
||||
{ "AE06", RDP_SCANCODE_KEY_6 }, /* 015: AE06 [6] */
|
||||
{ "AE07", RDP_SCANCODE_KEY_7 }, /* 016: AE07 [7] */
|
||||
{ "AE08", RDP_SCANCODE_KEY_8 }, /* 017: AE08 [8] */
|
||||
{ "AE09", RDP_SCANCODE_KEY_9 }, /* 018: AE09 [9] */
|
||||
{ "AE10", RDP_SCANCODE_KEY_0 }, /* 019: AE10 [0] */
|
||||
{ "AE11", RDP_SCANCODE_OEM_MINUS }, /* 020: AE11 [minus] */
|
||||
{ "AE12", RDP_SCANCODE_OEM_PLUS }, /* 021: AE12 [equal] */
|
||||
{ "BKSP", RDP_SCANCODE_BACKSPACE }, /* 022: BKSP [BackSpace] */
|
||||
{ "TAB", RDP_SCANCODE_TAB }, /* 023: TAB [Tab] */
|
||||
{ "AD01", RDP_SCANCODE_KEY_Q }, /* 024: AD01 [q] */
|
||||
{ "AD02", RDP_SCANCODE_KEY_W }, /* 025: AD02 [w] */
|
||||
{ "AD03", RDP_SCANCODE_KEY_E }, /* 026: AD03 [e] */
|
||||
{ "AD04", RDP_SCANCODE_KEY_R }, /* 027: AD04 [r] */
|
||||
{ "AD05", RDP_SCANCODE_KEY_T }, /* 028: AD05 [t] */
|
||||
{ "AD06", RDP_SCANCODE_KEY_Y }, /* 029: AD06 [y] */
|
||||
{ "AD07", RDP_SCANCODE_KEY_U }, /* 030: AD07 [u] */
|
||||
{ "AD08", RDP_SCANCODE_KEY_I }, /* 031: AD08 [i] */
|
||||
{ "AD09", RDP_SCANCODE_KEY_O }, /* 032: AD09 [o] */
|
||||
{ "AD10", RDP_SCANCODE_KEY_P }, /* 033: AD10 [p] */
|
||||
{ "AD11", RDP_SCANCODE_OEM_4 }, /* 034: AD11 [bracketleft] */
|
||||
{ "AD12", RDP_SCANCODE_OEM_6 }, /* 035: AD12 [bracketright] */
|
||||
{ "RTRN", RDP_SCANCODE_RETURN }, /* 036: RTRN [Return] */
|
||||
{ "LCTL", RDP_SCANCODE_LCONTROL }, /* 037: LCTL [Control_L] */
|
||||
{ "AC01", RDP_SCANCODE_KEY_A }, /* 038: AC01 [a] */
|
||||
{ "AC02", RDP_SCANCODE_KEY_S }, /* 039: AC02 [s] */
|
||||
{ "AC03", RDP_SCANCODE_KEY_D }, /* 040: AC03 [d] */
|
||||
{ "AC04", RDP_SCANCODE_KEY_F }, /* 041: AC04 [f] */
|
||||
{ "AC05", RDP_SCANCODE_KEY_G }, /* 042: AC05 [g] */
|
||||
{ "AC06", RDP_SCANCODE_KEY_H }, /* 043: AC06 [h] */
|
||||
{ "AC07", RDP_SCANCODE_KEY_J }, /* 044: AC07 [j] */
|
||||
{ "AC08", RDP_SCANCODE_KEY_K }, /* 045: AC08 [k] */
|
||||
{ "AC09", RDP_SCANCODE_KEY_L }, /* 046: AC09 [l] */
|
||||
{ "AC10", RDP_SCANCODE_OEM_1 }, /* 047: AC10 [semicolon] */
|
||||
{ "AC11", RDP_SCANCODE_OEM_7 }, /* 048: AC11 [dead_acute] */
|
||||
{ "TLDE", RDP_SCANCODE_OEM_3 }, /* 049: TLDE [dead_grave] */
|
||||
{ "LFSH", RDP_SCANCODE_LSHIFT }, /* 050: LFSH [Shift_L] */
|
||||
{ "BKSL", RDP_SCANCODE_OEM_5 }, /* 051: BKSL [backslash] */
|
||||
{ "AB01", RDP_SCANCODE_KEY_Z }, /* 052: AB01 [z] */
|
||||
{ "AB02", RDP_SCANCODE_KEY_X }, /* 053: AB02 [x] */
|
||||
{ "AB03", RDP_SCANCODE_KEY_C }, /* 054: AB03 [c] */
|
||||
{ "AB04", RDP_SCANCODE_KEY_V }, /* 055: AB04 [v] */
|
||||
{ "AB05", RDP_SCANCODE_KEY_B }, /* 056: AB05 [b] */
|
||||
{ "AB06", RDP_SCANCODE_KEY_N }, /* 057: AB06 [n] */
|
||||
{ "AB07", RDP_SCANCODE_KEY_M }, /* 058: AB07 [m] */
|
||||
{ "AB08", RDP_SCANCODE_OEM_COMMA }, /* 059: AB08 [comma] */
|
||||
{ "AB09", RDP_SCANCODE_OEM_PERIOD }, /* 060: AB09 [period] */
|
||||
{ "AB10", RDP_SCANCODE_OEM_2 }, /* 061: AB10 [slash] */
|
||||
{ "RTSH", RDP_SCANCODE_RSHIFT }, /* 062: RTSH [Shift_R] */
|
||||
{ "KPMU", RDP_SCANCODE_MULTIPLY }, /* 063: KPMU [KP_Multiply] */
|
||||
{ "LALT", RDP_SCANCODE_LMENU }, /* 064: LALT [Alt_L] */
|
||||
{ "SPCE", RDP_SCANCODE_SPACE }, /* 065: SPCE [space] */
|
||||
{ "CAPS", RDP_SCANCODE_CAPSLOCK }, /* 066: CAPS [Caps_Lock] */
|
||||
{ "FK01", RDP_SCANCODE_F1 }, /* 067: FK01 [F1] */
|
||||
{ "FK02", RDP_SCANCODE_F2 }, /* 068: FK02 [F2] */
|
||||
{ "FK03", RDP_SCANCODE_F3 }, /* 069: FK03 [F3] */
|
||||
{ "FK04", RDP_SCANCODE_F4 }, /* 070: FK04 [F4] */
|
||||
{ "FK05", RDP_SCANCODE_F5 }, /* 071: FK05 [F5] */
|
||||
{ "FK06", RDP_SCANCODE_F6 }, /* 072: FK06 [F6] */
|
||||
{ "FK07", RDP_SCANCODE_F7 }, /* 073: FK07 [F7] */
|
||||
{ "FK08", RDP_SCANCODE_F8 }, /* 074: FK08 [F8] */
|
||||
{ "FK09", RDP_SCANCODE_F9 }, /* 075: FK09 [F9] */
|
||||
{ "FK10", RDP_SCANCODE_F10 }, /* 076: FK10 [F10] */
|
||||
{ "NMLK", RDP_SCANCODE_NUMLOCK }, /* 077: NMLK [Num_Lock] */
|
||||
{ "SCLK", RDP_SCANCODE_SCROLLLOCK }, /* 078: SCLK [Multi_key] */
|
||||
{ "KP7", RDP_SCANCODE_NUMPAD7 }, /* 079: KP7 [KP_Home] */
|
||||
{ "KP8", RDP_SCANCODE_NUMPAD8 }, /* 080: KP8 [KP_Up] */
|
||||
{ "KP9", RDP_SCANCODE_NUMPAD9 }, /* 081: KP9 [KP_Prior] */
|
||||
{ "KPSU", RDP_SCANCODE_SUBTRACT }, /* 082: KPSU [KP_Subtract] */
|
||||
{ "KP4", RDP_SCANCODE_NUMPAD4 }, /* 083: KP4 [KP_Left] */
|
||||
{ "KP5", RDP_SCANCODE_NUMPAD5 }, /* 084: KP5 [KP_Begin] */
|
||||
{ "KP6", RDP_SCANCODE_NUMPAD6 }, /* 085: KP6 [KP_Right] */
|
||||
{ "KPAD", RDP_SCANCODE_ADD }, /* 086: KPAD [KP_Add] */
|
||||
{ "KP1", RDP_SCANCODE_NUMPAD1 }, /* 087: KP1 [KP_End] */
|
||||
{ "KP2", RDP_SCANCODE_NUMPAD2 }, /* 088: KP2 [KP_Down] */
|
||||
{ "KP3", RDP_SCANCODE_NUMPAD3 }, /* 089: KP3 [KP_Next] */
|
||||
{ "KP0", RDP_SCANCODE_NUMPAD0 }, /* 090: KP0 [KP_Insert] */
|
||||
{ "KPDL", RDP_SCANCODE_DECIMAL }, /* 091: KPDL [KP_Delete] */
|
||||
{ "LVL3", RDP_SCANCODE_RMENU }, /* 092: LVL3 [ISO_Level3_Shift] */
|
||||
{ "", RDP_SCANCODE_UNKNOWN }, /* 093: [(null)] */
|
||||
{ "LSGT", RDP_SCANCODE_OEM_102 }, /* 094: LSGT [backslash] */
|
||||
{ "FK11", RDP_SCANCODE_F11 }, /* 095: FK11 [F11] */
|
||||
{ "FK12", RDP_SCANCODE_F12 }, /* 096: FK12 [F12] */
|
||||
{ "AB11", RDP_SCANCODE_ABNT_C1 }, /* 097: AB11 [(null)] */
|
||||
{ "KATA", RDP_SCANCODE_KANA_HANGUL }, /* 098: KATA [Katakana] */
|
||||
{ "HIRA", RDP_SCANCODE_HIRAGANA }, /* 099: HIRA [Hiragana] */
|
||||
{ "HENK", RDP_SCANCODE_CONVERT_JP }, /* 100: HENK [Henkan_Mode] */
|
||||
{ "HKTG", RDP_SCANCODE_HIRAGANA }, /* 101: HKTG [Hiragana_Katakana] */
|
||||
{ "MUHE", RDP_SCANCODE_NONCONVERT_JP }, /* 102: MUHE [Muhenkan] */
|
||||
{ "JPCM", RDP_SCANCODE_UNKNOWN }, /* 103: JPCM [(null)] */
|
||||
{ "KPEN", RDP_SCANCODE_RETURN_KP }, /* 104: KPEN [KP_Enter] */
|
||||
{ "RCTL", RDP_SCANCODE_RCONTROL }, /* 105: RCTL [Control_R] */
|
||||
{ "KPDV", RDP_SCANCODE_DIVIDE }, /* 106: KPDV [KP_Divide] */
|
||||
{ "PRSC", RDP_SCANCODE_PRINTSCREEN }, /* 107: PRSC [Print] */
|
||||
{ "RALT", RDP_SCANCODE_RMENU }, /* 108: RALT [ISO_Level3_Shift] */
|
||||
{ "LNFD", RDP_SCANCODE_UNKNOWN }, /* 109: LNFD [Linefeed] */
|
||||
{ "HOME", RDP_SCANCODE_HOME }, /* 110: HOME [Home] */
|
||||
{ "UP", RDP_SCANCODE_UP }, /* 111: UP [Up] */
|
||||
{ "PGUP", RDP_SCANCODE_PRIOR }, /* 112: PGUP [Prior] */
|
||||
{ "LEFT", RDP_SCANCODE_LEFT }, /* 113: LEFT [Left] */
|
||||
{ "RGHT", RDP_SCANCODE_RIGHT }, /* 114: RGHT [Right] */
|
||||
{ "END", RDP_SCANCODE_END }, /* 115: END [End] */
|
||||
{ "DOWN", RDP_SCANCODE_DOWN }, /* 116: DOWN [Down] */
|
||||
{ "PGDN", RDP_SCANCODE_NEXT }, /* 117: PGDN [Next] */
|
||||
{ "INS", RDP_SCANCODE_INSERT }, /* 118: INS [Insert] */
|
||||
{ "DELE", RDP_SCANCODE_DELETE }, /* 119: DELE [Delete] */
|
||||
{ "I120", RDP_SCANCODE_UNKNOWN }, /* 120: I120 [(null)] */
|
||||
{ "MUTE", RDP_SCANCODE_VOLUME_MUTE }, /* 121: MUTE [XF86AudioMute] */
|
||||
{ "VOL-", RDP_SCANCODE_VOLUME_DOWN }, /* 122: VOL- [XF86AudioLowerVolume] */
|
||||
{ "VOL+", RDP_SCANCODE_VOLUME_UP }, /* 123: VOL+ [XF86AudioRaiseVolume] */
|
||||
{ "POWR", RDP_SCANCODE_UNKNOWN }, /* 124: POWR [XF86PowerOff] */
|
||||
{ "KPEQ", RDP_SCANCODE_UNKNOWN }, /* 125: KPEQ [KP_Equal] */
|
||||
{ "I126", RDP_SCANCODE_UNKNOWN }, /* 126: I126 [plusminus] */
|
||||
{ "PAUS", RDP_SCANCODE_PAUSE }, /* 127: PAUS [Pause] */
|
||||
{ "I128", RDP_SCANCODE_LAUNCH_MEDIA_SELECT }, /* 128: I128 [XF86LaunchA] */
|
||||
{ "I129", RDP_SCANCODE_ABNT_C2 }, /* 129: I129 [KP_Decimal] */
|
||||
{ "HNGL", RDP_SCANCODE_HANGUL }, /* 130: HNGL [Hangul] */
|
||||
{ "HJCV", RDP_SCANCODE_HANJA }, /* 131: HJCV [Hangul_Hanja] */
|
||||
{ "AE13", RDP_SCANCODE_BACKSLASH_JP }, /* 132: AE13 [(null)] */
|
||||
{ "LWIN", RDP_SCANCODE_LWIN }, /* 133: LWIN [Super_L] */
|
||||
{ "RWIN", RDP_SCANCODE_RWIN }, /* 134: RWIN [Super_R] */
|
||||
{ "COMP", RDP_SCANCODE_APPS }, /* 135: COMP [Menu] */
|
||||
{ "STOP", RDP_SCANCODE_BROWSER_STOP }, /* 136: STOP [Cancel] */
|
||||
{ "AGAI" /* codespell:ignore */, RDP_SCANCODE_UNKNOWN },
|
||||
/* 137: AGAI [Redo] */ /* codespell:ignore */
|
||||
{ "PROP", RDP_SCANCODE_UNKNOWN }, /* 138: PROP [SunProps] */
|
||||
{ "UNDO", RDP_SCANCODE_UNKNOWN }, /* 139: UNDO [Undo] */
|
||||
{ "FRNT", RDP_SCANCODE_UNKNOWN }, /* 140: FRNT [SunFront] */
|
||||
{ "COPY", RDP_SCANCODE_UNKNOWN }, /* 141: COPY [XF86Copy] */
|
||||
{ "OPEN", RDP_SCANCODE_UNKNOWN }, /* 142: OPEN [XF86Open] */
|
||||
{ "PAST", RDP_SCANCODE_UNKNOWN }, /* 143: PAST [XF86Paste] */
|
||||
{ "FIND", RDP_SCANCODE_UNKNOWN }, /* 144: FIND [Find] */
|
||||
{ "CUT", RDP_SCANCODE_UNKNOWN }, /* 145: CUT [XF86Cut] */
|
||||
{ "HELP", RDP_SCANCODE_HELP }, /* 146: HELP [Help] */
|
||||
{ "I147", RDP_SCANCODE_UNKNOWN }, /* 147: I147 [XF86MenuKB] */
|
||||
{ "I148", RDP_SCANCODE_UNKNOWN }, /* 148: I148 [XF86Calculator] */
|
||||
{ "I149", RDP_SCANCODE_UNKNOWN }, /* 149: I149 [(null)] */
|
||||
{ "I150", RDP_SCANCODE_SLEEP }, /* 150: I150 [XF86Sleep] */
|
||||
{ "I151", RDP_SCANCODE_UNKNOWN }, /* 151: I151 [XF86WakeUp] */
|
||||
{ "I152", RDP_SCANCODE_UNKNOWN }, /* 152: I152 [XF86Explorer] */
|
||||
{ "I153", RDP_SCANCODE_UNKNOWN }, /* 153: I153 [XF86Send] */
|
||||
{ "I154", RDP_SCANCODE_UNKNOWN }, /* 154: I154 [(null)] */
|
||||
{ "I155", RDP_SCANCODE_UNKNOWN }, /* 155: I155 [XF86Xfer] */
|
||||
{ "I156", RDP_SCANCODE_LAUNCH_APP1 }, /* 156: I156 [XF86Launch1] */
|
||||
{ "I157", RDP_SCANCODE_LAUNCH_APP2 }, /* 157: I157 [XF86Launch2] */
|
||||
{ "I158", RDP_SCANCODE_BROWSER_HOME }, /* 158: I158 [XF86WWW] */
|
||||
{ "I159", RDP_SCANCODE_UNKNOWN }, /* 159: I159 [XF86DOS] */
|
||||
{ "I160", RDP_SCANCODE_UNKNOWN }, /* 160: I160 [XF86ScreenSaver] */
|
||||
{ "I161", RDP_SCANCODE_UNKNOWN }, /* 161: I161 [XF86RotateWindows] */
|
||||
{ "I162", RDP_SCANCODE_UNKNOWN }, /* 162: I162 [XF86TaskPane] */
|
||||
{ "I163", RDP_SCANCODE_LAUNCH_MAIL }, /* 163: I163 [XF86Mail] */
|
||||
{ "I164", RDP_SCANCODE_BROWSER_FAVORITES }, /* 164: I164 [XF86Favorites] */
|
||||
{ "I165", RDP_SCANCODE_UNKNOWN }, /* 165: I165 [XF86MyComputer] */
|
||||
{ "I166", RDP_SCANCODE_BROWSER_BACK }, /* 166: I166 [XF86Back] */
|
||||
{ "I167", RDP_SCANCODE_BROWSER_FORWARD }, /* 167: I167 [XF86Forward] */
|
||||
{ "I168", RDP_SCANCODE_UNKNOWN }, /* 168: I168 [(null)] */
|
||||
{ "I169", RDP_SCANCODE_UNKNOWN }, /* 169: I169 [XF86Eject] */
|
||||
{ "I170", RDP_SCANCODE_UNKNOWN }, /* 170: I170 [XF86Eject] */
|
||||
{ "I171", RDP_SCANCODE_MEDIA_NEXT_TRACK }, /* 171: I171 [XF86AudioNext] */
|
||||
{ "I172", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 172: I172 [XF86AudioPlay] */
|
||||
{ "I173", RDP_SCANCODE_MEDIA_PREV_TRACK }, /* 173: I173 [XF86AudioPrev] */
|
||||
{ "I174", RDP_SCANCODE_MEDIA_STOP }, /* 174: I174 [XF86AudioStop] */
|
||||
{ "I175", RDP_SCANCODE_UNKNOWN }, /* 175: I175 [XF86AudioRecord] */
|
||||
{ "I176", RDP_SCANCODE_UNKNOWN }, /* 176: I176 [XF86AudioRewind] */
|
||||
{ "I177", RDP_SCANCODE_UNKNOWN }, /* 177: I177 [XF86Phone] */
|
||||
{ "I178", RDP_SCANCODE_UNKNOWN }, /* 178: I178 [(null)] */
|
||||
{ "I179", RDP_SCANCODE_UNKNOWN }, /* 179: I179 [XF86Tools] */
|
||||
{ "I180", RDP_SCANCODE_BROWSER_HOME }, /* 180: I180 [XF86HomePage] */
|
||||
{ "I181", RDP_SCANCODE_BROWSER_REFRESH }, /* 181: I181 [XF86Reload] */
|
||||
{ "I182", RDP_SCANCODE_UNKNOWN }, /* 182: I182 [XF86Close] */
|
||||
{ "I183", RDP_SCANCODE_UNKNOWN }, /* 183: I183 [(null)] */
|
||||
{ "I184", RDP_SCANCODE_UNKNOWN }, /* 184: I184 [(null)] */
|
||||
{ "I185", RDP_SCANCODE_UNKNOWN }, /* 185: I185 [XF86ScrollUp] */
|
||||
{ "I186", RDP_SCANCODE_UNKNOWN }, /* 186: I186 [XF86ScrollDown] */
|
||||
{ "I187", RDP_SCANCODE_UNKNOWN }, /* 187: I187 [parenleft] */
|
||||
{ "I188", RDP_SCANCODE_UNKNOWN }, /* 188: I188 [parenright] */
|
||||
{ "I189", RDP_SCANCODE_UNKNOWN }, /* 189: I189 [XF86New] */
|
||||
{ "I190", RDP_SCANCODE_UNKNOWN }, /* 190: I190 [Redo] */
|
||||
{ "FK13", RDP_SCANCODE_F13 }, /* 191: FK13 [XF86Tools] */
|
||||
{ "FK14", RDP_SCANCODE_F14 }, /* 192: FK14 [XF86Launch5] */
|
||||
{ "FK15", RDP_SCANCODE_F15 }, /* 193: FK15 [XF86Launch6] */
|
||||
{ "FK16", RDP_SCANCODE_F16 }, /* 194: FK16 [XF86Launch7] */
|
||||
{ "FK17", RDP_SCANCODE_F17 }, /* 195: FK17 [XF86Launch8] */
|
||||
{ "FK18", RDP_SCANCODE_F18 }, /* 196: FK18 [XF86Launch9] */
|
||||
{ "FK19", RDP_SCANCODE_F19 }, /* 197: FK19 [(null)] */
|
||||
{ "FK20", RDP_SCANCODE_F20 }, /* 198: FK20 [XF86AudioMicMute] */
|
||||
{ "FK21", RDP_SCANCODE_F21 }, /* 199: FK21 [XF86TouchpadToggle] */
|
||||
{ "FK22", RDP_SCANCODE_F22 }, /* 200: FK22 [XF86TouchpadOn] */
|
||||
{ "FK23", RDP_SCANCODE_F23 }, /* 201: FK23 [XF86TouchpadOff] */
|
||||
{ "FK24", RDP_SCANCODE_F24 }, /* 202: FK24 [(null)] */
|
||||
{ "LVL5", RDP_SCANCODE_UNKNOWN }, /* 203: LVL5 [ISO_Level5_Shift] */
|
||||
{ "ALT", RDP_SCANCODE_LMENU }, /* 204: ALT [(null)] */
|
||||
{ "META", RDP_SCANCODE_LMENU }, /* 205: META [(null)] */
|
||||
{ "SUPR", RDP_SCANCODE_LWIN }, /* 206: SUPR [(null)] */
|
||||
{ "HYPR", RDP_SCANCODE_LWIN }, /* 207: HYPR [(null)] */
|
||||
{ "I208", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 208: I208 [XF86AudioPlay] */
|
||||
{ "I209", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 209: I209 [XF86AudioPause] */
|
||||
{ "I210", RDP_SCANCODE_UNKNOWN }, /* 210: I210 [XF86Launch3] */
|
||||
{ "I211", RDP_SCANCODE_UNKNOWN }, /* 211: I211 [XF86Launch4] */
|
||||
{ "I212", RDP_SCANCODE_UNKNOWN }, /* 212: I212 [XF86LaunchB] */
|
||||
{ "I213", RDP_SCANCODE_UNKNOWN }, /* 213: I213 [XF86Suspend] */
|
||||
{ "I214", RDP_SCANCODE_UNKNOWN }, /* 214: I214 [XF86Close] */
|
||||
{ "I215", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 215: I215 [XF86AudioPlay] */
|
||||
{ "I216", RDP_SCANCODE_MEDIA_NEXT_TRACK }, /* 216: I216 [XF86AudioForward] */
|
||||
{ "I217", RDP_SCANCODE_UNKNOWN }, /* 217: I217 [(null)] */
|
||||
{ "I218", RDP_SCANCODE_UNKNOWN }, /* 218: I218 [Print] */
|
||||
{ "I219", RDP_SCANCODE_UNKNOWN }, /* 219: I219 [(null)] */
|
||||
{ "I220", RDP_SCANCODE_UNKNOWN }, /* 220: I220 [XF86WebCam] */
|
||||
{ "I221", RDP_SCANCODE_UNKNOWN }, /* 221: I221 [XF86AudioPreset] */
|
||||
{ "I222", RDP_SCANCODE_UNKNOWN }, /* 222: I222 [(null)] */
|
||||
{ "I223", RDP_SCANCODE_LAUNCH_MAIL }, /* 223: I223 [XF86Mail] */
|
||||
{ "I224", RDP_SCANCODE_UNKNOWN }, /* 224: I224 [XF86Messenger] */
|
||||
{ "I225", RDP_SCANCODE_BROWSER_SEARCH }, /* 225: I225 [XF86Search] */
|
||||
{ "I226", RDP_SCANCODE_UNKNOWN }, /* 226: I226 [XF86Go] */
|
||||
{ "I227", RDP_SCANCODE_UNKNOWN }, /* 227: I227 [XF86Finance] */
|
||||
{ "I228", RDP_SCANCODE_UNKNOWN }, /* 228: I228 [XF86Game] */
|
||||
{ "I229", RDP_SCANCODE_UNKNOWN }, /* 229: I229 [XF86Shop] */
|
||||
{ "I230", RDP_SCANCODE_UNKNOWN }, /* 230: I230 [(null)] */
|
||||
{ "I231", RDP_SCANCODE_UNKNOWN }, /* 231: I231 [Cancel] */
|
||||
{ "I232", RDP_SCANCODE_UNKNOWN }, /* 232: I232 [XF86MonBrightnessDown] */
|
||||
{ "I233", RDP_SCANCODE_UNKNOWN }, /* 233: I233 [XF86MonBrightnessUp] */
|
||||
{ "I234", RDP_SCANCODE_LAUNCH_MEDIA_SELECT }, /* 234: I234 [XF86AudioMedia] */
|
||||
{ "I235", RDP_SCANCODE_UNKNOWN }, /* 235: I235 [XF86Display] */
|
||||
{ "I236", RDP_SCANCODE_UNKNOWN }, /* 236: I236 [XF86KbdLightOnOff] */
|
||||
{ "I237", RDP_SCANCODE_UNKNOWN }, /* 237: I237 [XF86KbdBrightnessDown] */
|
||||
{ "I238", RDP_SCANCODE_UNKNOWN }, /* 238: I238 [XF86KbdBrightnessUp] */
|
||||
{ "I239", RDP_SCANCODE_UNKNOWN }, /* 239: I239 [XF86Send] */
|
||||
{ "I240", RDP_SCANCODE_UNKNOWN }, /* 240: I240 [XF86Reply] */
|
||||
{ "I241", RDP_SCANCODE_UNKNOWN }, /* 241: I241 [XF86MailForward] */
|
||||
{ "I242", RDP_SCANCODE_UNKNOWN }, /* 242: I242 [XF86Save] */
|
||||
{ "I243", RDP_SCANCODE_UNKNOWN }, /* 243: I243 [XF86Documents] */
|
||||
{ "I244", RDP_SCANCODE_UNKNOWN }, /* 244: I244 [XF86Battery] */
|
||||
{ "I245", RDP_SCANCODE_UNKNOWN }, /* 245: I245 [XF86Bluetooth] */
|
||||
{ "I246", RDP_SCANCODE_UNKNOWN }, /* 246: I246 [XF86WLAN] */
|
||||
{ "I247", RDP_SCANCODE_UNKNOWN }, /* 247: I247 [XF86UWB] */
|
||||
{ "I248", RDP_SCANCODE_UNKNOWN }, /* 248: I248 [(null)] */
|
||||
{ "I249", RDP_SCANCODE_UNKNOWN }, /* 249: I249 [XF86Next_VMode] */
|
||||
{ "I250", RDP_SCANCODE_UNKNOWN }, /* 250: I250 [XF86Prev_VMode] */
|
||||
{ "I251", RDP_SCANCODE_UNKNOWN }, /* 251: I251 [XF86MonBrightnessCycle] */
|
||||
{ "I252", RDP_SCANCODE_UNKNOWN }, /* 252: I252 [XF86BrightnessAuto] */
|
||||
{ "I253", RDP_SCANCODE_UNKNOWN }, /* 253: I253 [XF86DisplayOff] */
|
||||
{ "I254", RDP_SCANCODE_UNKNOWN }, /* 254: I254 [XF86WWAN] */
|
||||
{ "I255", RDP_SCANCODE_UNKNOWN } /* 255: I255 [XF86RFKill] */
|
||||
};
|
||||
|
||||
static int detect_keyboard_layout_from_xkbfile(void* display, DWORD* keyboardLayoutId);
|
||||
static int freerdp_keyboard_load_map_from_xkbfile(void* display, DWORD* x11_keycode_to_rdp_scancode,
|
||||
size_t count);
|
||||
|
||||
static void* freerdp_keyboard_xkb_init(void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
Display* display = XOpenDisplay(nullptr);
|
||||
|
||||
if (!display)
|
||||
return nullptr;
|
||||
|
||||
status = XkbQueryExtension(display, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
if (!status)
|
||||
return nullptr;
|
||||
|
||||
return (void*)display;
|
||||
}
|
||||
|
||||
int freerdp_keyboard_init_xkbfile(DWORD* keyboardLayoutId, DWORD* x11_keycode_to_rdp_scancode,
|
||||
size_t count)
|
||||
{
|
||||
WINPR_ASSERT(keyboardLayoutId);
|
||||
WINPR_ASSERT(x11_keycode_to_rdp_scancode);
|
||||
ZeroMemory(x11_keycode_to_rdp_scancode, sizeof(DWORD) * count);
|
||||
|
||||
void* display = freerdp_keyboard_xkb_init();
|
||||
|
||||
if (!display)
|
||||
{
|
||||
DEBUG_KBD("Error initializing xkb");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*keyboardLayoutId == 0)
|
||||
{
|
||||
detect_keyboard_layout_from_xkbfile(display, keyboardLayoutId);
|
||||
DEBUG_KBD("detect_keyboard_layout_from_xkb: %" PRIu32 " (0x%08" PRIX32 ")",
|
||||
*keyboardLayoutId, *keyboardLayoutId);
|
||||
}
|
||||
|
||||
const int rc =
|
||||
freerdp_keyboard_load_map_from_xkbfile(display, x11_keycode_to_rdp_scancode, count);
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* return substring starting after nth comma, ending at following comma */
|
||||
static char* comma_substring(char* s, size_t n)
|
||||
{
|
||||
char* p = nullptr;
|
||||
|
||||
if (!s)
|
||||
return "";
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
if (!(p = strchr(s, ',')))
|
||||
break;
|
||||
|
||||
s = p + 1;
|
||||
}
|
||||
|
||||
if ((p = strchr(s, ',')))
|
||||
*p = 0;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int detect_keyboard_layout_from_xkbfile(void* display, DWORD* keyboardLayoutId)
|
||||
{
|
||||
DEBUG_KBD("display: %p", display);
|
||||
if (!display)
|
||||
return -2;
|
||||
|
||||
char* rules = nullptr;
|
||||
XkbRF_VarDefsRec rules_names = WINPR_C_ARRAY_INIT;
|
||||
const Bool rc = XkbRF_GetNamesProp(display, &rules, &rules_names);
|
||||
if (!rc)
|
||||
{
|
||||
DEBUG_KBD("XkbRF_GetNamesProp == False");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_KBD("rules: %s", rules ? rules : "");
|
||||
DEBUG_KBD("model: %s", rules_names.model ? rules_names.model : "");
|
||||
DEBUG_KBD("layouts: %s", rules_names.layout ? rules_names.layout : "");
|
||||
DEBUG_KBD("variants: %s", rules_names.variant ? rules_names.variant : "");
|
||||
|
||||
DWORD group = 0;
|
||||
XkbStateRec state = WINPR_C_ARRAY_INIT;
|
||||
XKeyboardState coreKbdState = WINPR_C_ARRAY_INIT;
|
||||
XGetKeyboardControl(display, &coreKbdState);
|
||||
|
||||
if (XkbGetState(display, XkbUseCoreKbd, &state) == Success)
|
||||
group = state.group;
|
||||
|
||||
DEBUG_KBD("group: %u", state.group);
|
||||
|
||||
const char* layout = comma_substring(rules_names.layout, group);
|
||||
const char* variant = comma_substring(rules_names.variant, group);
|
||||
|
||||
DEBUG_KBD("layout: %s", layout ? layout : "");
|
||||
DEBUG_KBD("variant: %s", variant ? variant : "");
|
||||
|
||||
*keyboardLayoutId = find_keyboard_layout_in_xorg_rules(layout, variant);
|
||||
}
|
||||
free(rules_names.model);
|
||||
free(rules_names.layout);
|
||||
free(rules_names.variant);
|
||||
free(rules_names.options);
|
||||
free(rules);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xkb_cmp(const void* pva, const void* pvb)
|
||||
{
|
||||
const XKB_KEY_NAME_SCANCODE* a = pva;
|
||||
const XKB_KEY_NAME_SCANCODE* b = pvb;
|
||||
|
||||
if (!a && !b)
|
||||
return 0;
|
||||
if (!a)
|
||||
return 1;
|
||||
if (!b)
|
||||
return -1;
|
||||
return strcmp(a->xkb_keyname, b->xkb_keyname);
|
||||
}
|
||||
|
||||
static BOOL try_add(size_t offset, const char* xkb_keyname, DWORD* x11_keycode_to_rdp_scancode,
|
||||
|
||||
WINPR_ATTR_UNUSED size_t count)
|
||||
{
|
||||
static BOOL initialized = FALSE;
|
||||
static XKB_KEY_NAME_SCANCODE copy[ARRAYSIZE(XKB_KEY_NAME_SCANCODE_TABLE)] = WINPR_C_ARRAY_INIT;
|
||||
if (!initialized)
|
||||
{
|
||||
memcpy(copy, XKB_KEY_NAME_SCANCODE_TABLE, sizeof(copy));
|
||||
qsort(copy, ARRAYSIZE(copy), sizeof(XKB_KEY_NAME_SCANCODE), xkb_cmp);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
XKB_KEY_NAME_SCANCODE key = WINPR_C_ARRAY_INIT;
|
||||
key.xkb_keyname = xkb_keyname;
|
||||
XKB_KEY_NAME_SCANCODE* found =
|
||||
bsearch(&key, copy, ARRAYSIZE(copy), sizeof(XKB_KEY_NAME_SCANCODE), xkb_cmp);
|
||||
if (found)
|
||||
{
|
||||
DEBUG_KBD("%4s: keycode: 0x%02" PRIuz " -> rdp scancode: 0x%08" PRIx32 "", xkb_keyname,
|
||||
offset, found->rdp_scancode);
|
||||
x11_keycode_to_rdp_scancode[offset] = found->rdp_scancode;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int freerdp_keyboard_load_map_from_xkbfile(void* display, DWORD* x11_keycode_to_rdp_scancode,
|
||||
size_t count)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (!display)
|
||||
return -2;
|
||||
|
||||
XkbDescPtr xkb = XkbGetMap(display, 0, XkbUseCoreKbd);
|
||||
if (!xkb)
|
||||
{
|
||||
DEBUG_KBD("XkbGetMap() == nullptr");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (XkbGetNames(display, XkbKeyNamesMask, xkb) != Success)
|
||||
{
|
||||
DEBUG_KBD("XkbGetNames() != Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
char xkb_keyname[XkbKeyNameLength + 1] = { 42, 42, 42, 42,
|
||||
0 }; /* end-of-string at index 5 */
|
||||
|
||||
DEBUG_KBD("XkbGetNames() == Success, min=%" PRIu8 ", max=%" PRIu8, xkb->min_key_code,
|
||||
xkb->max_key_code);
|
||||
for (size_t i = xkb->min_key_code; i <= MIN(xkb->max_key_code, count); i++)
|
||||
{
|
||||
BOOL found = FALSE;
|
||||
strncpy(xkb_keyname, xkb->names->keys[i].name, XkbKeyNameLength);
|
||||
|
||||
DEBUG_KBD("KeyCode %" PRIuz " -> %s", i, xkb_keyname);
|
||||
if (strnlen(xkb_keyname, ARRAYSIZE(xkb_keyname)) < 1)
|
||||
continue;
|
||||
|
||||
found = try_add(i, xkb_keyname, x11_keycode_to_rdp_scancode, count);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
DEBUG_KBD("%4s: keycode: 0x%02X -> no RDP scancode found", xkb_keyname, i);
|
||||
}
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
XkbFreeKeyboard(xkb, 0, 1);
|
||||
|
||||
return status;
|
||||
}
|
||||
31
third_party/FreeRDP/libfreerdp/locale/keyboard_xkbfile.h
vendored
Normal file
31
third_party/FreeRDP/libfreerdp/locale/keyboard_xkbfile.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* XKB Keyboard Mapping
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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_LIB_LOCALE_KEYBOARD_XKB_H
|
||||
#define FREERDP_LIB_LOCALE_KEYBOARD_XKB_H
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int freerdp_keyboard_init_xkbfile(DWORD* keyboardLayoutId,
|
||||
DWORD* x11_keycode_to_rdp_scancode, size_t count);
|
||||
|
||||
#endif /* FREERDP_LIB_LOCALE_KEYBOARD_XKB_H */
|
||||
39
third_party/FreeRDP/libfreerdp/locale/liblocale.h
vendored
Normal file
39
third_party/FreeRDP/libfreerdp/locale/liblocale.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Localization
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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_LIB_LOCALE_LIB_H
|
||||
#define FREERDP_LIB_LOCALE_LIB_H
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#define KBD_TAG FREERDP_TAG("locale")
|
||||
#ifdef WITH_DEBUG_KBD
|
||||
#define DEBUG_KBD(...) WLog_DBG(KBD_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_KBD(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define TIMEZONE_TAG FREERDP_TAG("timezone")
|
||||
|
||||
#endif /* FREERDP_LIB_LOCALE_LIB_H */
|
||||
894
third_party/FreeRDP/libfreerdp/locale/locale.c
vendored
Normal file
894
third_party/FreeRDP/libfreerdp/locale/locale.c
vendored
Normal file
@@ -0,0 +1,894 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Microsoft Locales
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2021 Thincast Technologies GmbH
|
||||
* Copyright 2021 Martin Fleisz <martin.fleisz@thincast.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <CoreFoundation/CFString.h>
|
||||
#include <CoreFoundation/CFLocale.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/environment.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
|
||||
#include <freerdp/locale/locale.h>
|
||||
|
||||
/*
|
||||
* Refer to MSDN article "Locale Identifier Constants and Strings":
|
||||
* http://msdn.microsoft.com/en-us/library/ms776260.aspx
|
||||
*/
|
||||
|
||||
static const SYSTEM_LOCALE SYSTEM_LOCALE_TABLE[] = {
|
||||
{ "af", "ZA", AFRIKAANS }, /* Afrikaans (South Africa) */
|
||||
{ "sq", "AL", ALBANIAN }, /* Albanian (Albania) */
|
||||
{ "gsw", "FR", ALSATIAN }, /* Windows Vista and later: Alsatian (France) */
|
||||
{ "am", "ET", AMHARIC }, /* Windows Vista and later: Amharic (Ethiopia) */
|
||||
{ "ar", "DZ", ARABIC_ALGERIA }, /* Arabic (Algeria) */
|
||||
{ "ar", "BH", ARABIC_BAHRAIN }, /* Arabic (Bahrain) */
|
||||
{ "ar", "EG", ARABIC_EGYPT }, /* Arabic (Egypt) */
|
||||
{ "ar", "IQ", ARABIC_IRAQ }, /* Arabic (Iraq) */
|
||||
{ "ar", "JO", ARABIC_JORDAN }, /* Arabic (Jordan) */
|
||||
{ "ar", "KW", ARABIC_KUWAIT }, /* Arabic (Kuwait) */
|
||||
{ "ar", "LB", ARABIC_LEBANON }, /* Arabic (Lebanon) */
|
||||
{ "ar", "LY", ARABIC_LIBYA }, /* Arabic (Libya) */
|
||||
{ "ar", "MA", ARABIC_MOROCCO }, /* Arabic (Morocco) */
|
||||
{ "ar", "OM", ARABIC_OMAN }, /* Arabic (Oman) */
|
||||
{ "ar", "QA", ARABIC_QATAR }, /* Arabic (Qatar) */
|
||||
{ "ar", "SA", ARABIC_SAUDI_ARABIA }, /* Arabic (Saudi Arabia) */
|
||||
{ "ar", "SY", ARABIC_SYRIA }, /* Arabic (Syria) */
|
||||
{ "ar", "TN", ARABIC_TUNISIA }, /* Arabic (Tunisia) */
|
||||
{ "ar", "AE", ARABIC_UAE }, /* Arabic (U.A.E.) */
|
||||
{ "ar", "YE", ARABIC_YEMEN }, /* Arabic (Yemen) */
|
||||
{ "az", "AZ", AZERI_LATIN }, /* Azeri (Latin) */
|
||||
{ "az", "Cyrl_AZ", AZERI_CYRILLIC }, /* Azeri (Cyrillic) */
|
||||
{ "hy", "AM", ARMENIAN }, /* Windows 2000 and later: Armenian (Armenia) */
|
||||
{ "as", "IN", ASSAMESE }, /* Windows Vista and later: Assamese (India) */
|
||||
{ "ba", "RU", BASHKIR }, /* Windows Vista and later: Bashkir (Russia) */
|
||||
{ "eu", "ES", BASQUE }, /* Basque (Basque) */
|
||||
{ "be", "BY", BELARUSIAN }, /* Belarusian (Belarus) */
|
||||
{ "bn", "IN", BENGALI_INDIA }, /* Windows XP SP2 and later: Bengali (India) */
|
||||
{ "br", "FR", BRETON }, /* Breton (France) */
|
||||
{ "bs", "BA", BOSNIAN_LATIN }, /* Bosnian (Latin) */
|
||||
{ "bg", "BG", BULGARIAN }, /* Bulgarian (Bulgaria) */
|
||||
{ "ca", "ES", CATALAN }, /* Catalan (Catalan) */
|
||||
{ "zh", "HK", CHINESE_HONG_KONG }, /* Chinese (Hong Kong SAR, PRC) */
|
||||
{ "zh", "MO", CHINESE_MACAU }, /* Windows 98/Me, Windows XP and later: Chinese (Macao SAR) */
|
||||
{ "zh", "CN", CHINESE_PRC }, /* Chinese (PRC) */
|
||||
{ "zh", "SG", CHINESE_SINGAPORE }, /* Chinese (Singapore) */
|
||||
{ "zh", "TW", CHINESE_TAIWAN }, /* Chinese (Taiwan) */
|
||||
{ "hr", "BA", CROATIAN_BOSNIA_HERZEGOVINA }, /* Windows XP SP2 and later: Croatian (Bosnia and
|
||||
Herzegovina, Latin) */
|
||||
{ "hr", "HR", CROATIAN }, /* Croatian (Croatia) */
|
||||
{ "cs", "CZ", CZECH }, /* Czech (Czech Republic) */
|
||||
{ "da", "DK", DANISH }, /* Danish (Denmark) */
|
||||
{ "prs", "AF", DARI }, /* Windows XP and later: Dari (Afghanistan) */
|
||||
{ "dv", "MV", DIVEHI }, /* Windows XP and later: Divehi (Maldives) */
|
||||
{ "nl", "BE", DUTCH_BELGIAN }, /* Dutch (Belgium) */
|
||||
{ "nl", "NL", DUTCH_STANDARD }, /* Dutch (Netherlands) */
|
||||
{ "en", "AU", ENGLISH_AUSTRALIAN }, /* English (Australia) */
|
||||
{ "en", "BZ", ENGLISH_BELIZE }, /* English (Belize) */
|
||||
{ "en", "CA", ENGLISH_CANADIAN }, /* English (Canada) */
|
||||
{ "en", "CB", ENGLISH_CARIBBEAN }, /* English (Caribbean) */
|
||||
{ "en", "IN", ENGLISH_INDIA }, /* Windows Vista and later: English (India) */
|
||||
{ "en", "IE", ENGLISH_IRELAND }, /* English (Ireland) */
|
||||
{ "en", "JM", ENGLISH_JAMAICA }, /* English (Jamaica) */
|
||||
{ "en", "MY", ENGLISH_MALAYSIA }, /* Windows Vista and later: English (Malaysia) */
|
||||
{ "en", "NZ", ENGLISH_NEW_ZEALAND }, /* English (New Zealand) */
|
||||
{ "en", "PH",
|
||||
ENGLISH_PHILIPPINES }, /* Windows 98/Me, Windows 2000 and later: English (Philippines) */
|
||||
{ "en", "SG", ENGLISH_SINGAPORE }, /* Windows Vista and later: English (Singapore) */
|
||||
{ "en", "ZA", ENGLISH_SOUTH_AFRICA }, /* English (South Africa) */
|
||||
{ "en", "TT", ENGLISH_TRINIDAD }, /* English (Trinidad and Tobago) */
|
||||
{ "en", "GB", ENGLISH_UNITED_KINGDOM }, /* English (United Kingdom) */
|
||||
{ "en", "US", ENGLISH_UNITED_STATES }, /* English (United States) */
|
||||
{ "en", "ZW",
|
||||
ENGLISH_ZIMBABWE }, /* Windows 98/Me, Windows 2000 and later: English (Zimbabwe) */
|
||||
{ "et", "EE", ESTONIAN }, /* Estonian (Estonia) */
|
||||
{ "fo", "FO", FAEROESE }, /* Faroese (Faroe Islands) */
|
||||
{ "fil", "PH", FILIPINO }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Filipino (Philippines) */
|
||||
{ "fi", "FI", FINNISH }, /* Finnish (Finland) */
|
||||
{ "fr", "BE", FRENCH_BELGIAN }, /* French (Belgium) */
|
||||
{ "fr", "CA", FRENCH_CANADIAN }, /* French (Canada) */
|
||||
{ "fr", "FR", FRENCH_STANDARD }, /* French (France) */
|
||||
{ "fr", "LU", FRENCH_LUXEMBOURG }, /* French (Luxembourg) */
|
||||
{ "fr", "MC", FRENCH_MONACO }, /* French (Monaco) */
|
||||
{ "fr", "CH", FRENCH_SWISS }, /* French (Switzerland) */
|
||||
{ "fy", "NL", FRISIAN }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Frisian (Netherlands) */
|
||||
{ "gl", "ES", GALICIAN }, /* Windows XP and later: Galician (Spain) */
|
||||
{ "ka", "GE", GEORGIAN }, /* Windows 2000 and later: Georgian (Georgia) */
|
||||
{ "de", "AT", GERMAN_AUSTRIAN }, /* German (Austria) */
|
||||
{ "de", "DE", GERMAN_STANDARD }, /* German (Germany) */
|
||||
{ "de", "LI", GERMAN_LIECHTENSTEIN }, /* German (Liechtenstein) */
|
||||
{ "de", "LU", GERMAN_LUXEMBOURG }, /* German (Luxembourg) */
|
||||
{ "de", "CH", GERMAN_SWISS }, /* German (Switzerland) */
|
||||
{ "el", "GR", GREEK }, /* Greek (Greece) */
|
||||
{ "kl", "GL", GREENLANDIC }, /* Windows Vista and later: Greenlandic (Greenland) */
|
||||
{ "gu", "IN", GUJARATI }, /* Windows XP and later: Gujarati (India) */
|
||||
{ "he", "IL", HEBREW }, /* Hebrew (Israel) */
|
||||
{ "hi", "IN", HINDI }, /* Windows 2000 and later: Hindi (India) */
|
||||
{ "hu", "HU", HUNGARIAN }, /* Hungarian (Hungary) */
|
||||
{ "is", "IS", ICELANDIC }, /* Icelandic (Iceland) */
|
||||
{ "ig", "NG", IGBO }, /* Igbo (Nigeria) */
|
||||
{ "id", "ID", INDONESIAN }, /* Indonesian (Indonesia) */
|
||||
{ "ga", "IE", IRISH }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Irish (Ireland) */
|
||||
{ "it", "IT", ITALIAN_STANDARD }, /* Italian (Italy) */
|
||||
{ "it", "CH", ITALIAN_SWISS }, /* Italian (Switzerland) */
|
||||
{ "ja", "JP", JAPANESE }, /* Japanese (Japan) */
|
||||
{ "kn", "IN", KANNADA }, /* Windows XP and later: Kannada (India) */
|
||||
{ "kk", "KZ", KAZAKH }, /* Windows 2000 and later: Kazakh (Kazakhstan) */
|
||||
{ "kh", "KH", KHMER }, /* Windows Vista and later: Khmer (Cambodia) */
|
||||
{ "qut", "GT", KICHE }, /* Windows Vista and later: K'iche (Guatemala) */
|
||||
{ "rw", "RW", KINYARWANDA }, /* Windows Vista and later: Kinyarwanda (Rwanda) */
|
||||
{ "kok", "IN", KONKANI }, /* Windows 2000 and later: Konkani (India) */
|
||||
{ "ko", "KR", KOREAN }, /* Korean (Korea) */
|
||||
{ "ky", "KG", KYRGYZ }, /* Windows XP and later: Kyrgyz (Kyrgyzstan) */
|
||||
{ "lo", "LA", LAO }, /* Windows Vista and later: Lao (Lao PDR) */
|
||||
{ "lv", "LV", LATVIAN }, /* Latvian (Latvia) */
|
||||
{ "lt", "LT", LITHUANIAN }, /* Lithuanian (Lithuania) */
|
||||
{ "dsb", "DE", LOWER_SORBIAN }, /* Windows Vista and later: Lower Sorbian (Germany) */
|
||||
{ "lb", "LU", LUXEMBOURGISH }, /* Windows XP SP2 and later (downloadable); Windows Vista and
|
||||
later: Luxembourgish (Luxembourg) */
|
||||
{ "mk", "MK", MACEDONIAN }, /* Windows 2000 and later: Macedonian (Macedonia, FYROM) */
|
||||
{ "ms", "BN", MALAY_BRUNEI_DARUSSALAM }, /* Windows 2000 and later: Malay (Brunei Darussalam) */
|
||||
{ "ms", "MY", MALAY_MALAYSIA }, /* Windows 2000 and later: Malay (Malaysia) */
|
||||
{ "ml", "IN", MALAYALAM }, /* Windows XP SP2 and later: Malayalam (India) */
|
||||
{ "mt", "MT", MALTESE }, /* Windows XP SP2 and later: Maltese (Malta) */
|
||||
{ "mi", "NZ", MAORI }, /* Windows XP SP2 and later: Maori (New Zealand) */
|
||||
{ "arn", "CL", MAPUDUNGUN }, /* Windows XP SP2 and later (downloadable); Windows Vista and
|
||||
later: Mapudungun (Chile) */
|
||||
{ "mr", "IN", MARATHI }, /* Windows 2000 and later: Marathi (India) */
|
||||
{ "moh", "CA", MOHAWK }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Mohawk (Canada) */
|
||||
{ "mn", "MN", MONGOLIAN }, /* Mongolian */
|
||||
{ "ne", "NP", NEPALI }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Nepali (Nepal) */
|
||||
{ "nb", "NO", NORWEGIAN_BOKMAL }, /* Norwegian (Bokmal, Norway) */
|
||||
{ "nn", "NO", NORWEGIAN_NYNORSK }, /* Norwegian (Nynorsk, Norway) */
|
||||
{ "oc", "FR", OCCITAN }, /* Occitan (France) */
|
||||
{ "or", "IN", ORIYA }, /* Oriya (India) */
|
||||
{ "ps", "AF", PASHTO }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Pashto (Afghanistan) */
|
||||
{ "fa", "IR", FARSI }, /* Persian (Iran) */
|
||||
{ "pl", "PL", POLISH }, /* Polish (Poland) */
|
||||
{ "pt", "BR", PORTUGUESE_BRAZILIAN }, /* Portuguese (Brazil) */
|
||||
{ "pt", "PT", PORTUGUESE_STANDARD }, /* Portuguese (Portugal) */
|
||||
{ "pa", "IN", PUNJABI }, /* Windows XP and later: Punjabi (India) */
|
||||
{ "quz", "BO", QUECHUA_BOLIVIA }, /* Windows XP SP2 and later: Quechua (Bolivia) */
|
||||
{ "quz", "EC", QUECHUA_ECUADOR }, /* Windows XP SP2 and later: Quechua (Ecuador) */
|
||||
{ "quz", "PE", QUECHUA_PERU }, /* Windows XP SP2 and later: Quechua (Peru) */
|
||||
{ "ro", "RO", ROMANIAN }, /* Romanian (Romania) */
|
||||
{ "rm", "CH", ROMANSH }, /* Windows XP SP2 and later (downloadable); Windows Vista and later:
|
||||
Romansh (Switzerland) */
|
||||
{ "ru", "RU", RUSSIAN }, /* Russian (Russia) */
|
||||
{ "smn", "FI", SAMI_INARI }, /* Windows XP SP2 and later: Sami (Inari, Finland) */
|
||||
{ "smj", "NO", SAMI_LULE_NORWAY }, /* Windows XP SP2 and later: Sami (Lule, Norway) */
|
||||
{ "smj", "SE", SAMI_LULE_SWEDEN }, /* Windows XP SP2 and later: Sami (Lule, Sweden) */
|
||||
{ "se", "FI", SAMI_NORTHERN_FINLAND }, /* Windows XP SP2 and later: Sami (Northern, Finland) */
|
||||
{ "se", "NO", SAMI_NORTHERN_NORWAY }, /* Windows XP SP2 and later: Sami (Northern, Norway) */
|
||||
{ "se", "SE", SAMI_NORTHERN_SWEDEN }, /* Windows XP SP2 and later: Sami (Northern, Sweden) */
|
||||
{ "sms", "FI", SAMI_SKOLT }, /* Windows XP SP2 and later: Sami (Skolt, Finland) */
|
||||
{ "sma", "NO", SAMI_SOUTHERN_NORWAY }, /* Windows XP SP2 and later: Sami (Southern, Norway) */
|
||||
{ "sma", "SE", SAMI_SOUTHERN_SWEDEN }, /* Windows XP SP2 and later: Sami (Southern, Sweden) */
|
||||
{ "sa", "IN", SANSKRIT }, /* Windows 2000 and later: Sanskrit (India) */
|
||||
{ "sr", "SP", SERBIAN_LATIN }, /* Serbian (Latin) */
|
||||
{ "sr", "SIH",
|
||||
SERBIAN_LATIN_BOSNIA_HERZEGOVINA }, /* Serbian (Latin) (Bosnia and Herzegovina) */
|
||||
{ "sr", "Cyrl_SP", SERBIAN_CYRILLIC }, /* Serbian (Cyrillic) */
|
||||
{ "sr", "Cyrl_SIH",
|
||||
SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA }, /* Serbian (Cyrillic) (Bosnia and Herzegovina) */
|
||||
{ "ns", "ZA", SESOTHO_SA_LEBOA }, /* Windows XP SP2 and later: Sesotho sa Leboa/Northern Sotho
|
||||
(South Africa) */
|
||||
{ "tn", "ZA", TSWANA }, /* Windows XP SP2 and later: Setswana/Tswana (South Africa) */
|
||||
{ "si", "LK", SINHALA }, /* Windows Vista and later: Sinhala (Sri Lanka) */
|
||||
{ "sk", "SK", SLOVAK }, /* Slovak (Slovakia) */
|
||||
{ "sl", "SI", SLOVENIAN }, /* Slovenian (Slovenia) */
|
||||
{ "es", "AR", SPANISH_ARGENTINA }, /* Spanish (Argentina) */
|
||||
{ "es", "BO", SPANISH_BOLIVIA }, /* Spanish (Bolivia) */
|
||||
{ "es", "CL", SPANISH_CHILE }, /* Spanish (Chile) */
|
||||
{ "es", "CO", SPANISH_COLOMBIA }, /* Spanish (Colombia) */
|
||||
{ "es", "CR", SPANISH_COSTA_RICA }, /* Spanish (Costa Rica) */
|
||||
{ "es", "DO", SPANISH_DOMINICAN_REPUBLIC }, /* Spanish (Dominican Republic) */
|
||||
{ "es", "EC", SPANISH_ECUADOR }, /* Spanish (Ecuador) */
|
||||
{ "es", "SV", SPANISH_EL_SALVADOR }, /* Spanish (El Salvador) */
|
||||
{ "es", "GT", SPANISH_GUATEMALA }, /* Spanish (Guatemala) */
|
||||
{ "es", "HN", SPANISH_HONDURAS }, /* Spanish (Honduras) */
|
||||
{ "es", "MX", SPANISH_MEXICAN }, /* Spanish (Mexico) */
|
||||
{ "es", "NI", SPANISH_NICARAGUA }, /* Spanish (Nicaragua) */
|
||||
{ "es", "PA", SPANISH_PANAMA }, /* Spanish (Panama) */
|
||||
{ "es", "PY", SPANISH_PARAGUAY }, /* Spanish (Paraguay) */
|
||||
{ "es", "PE", SPANISH_PERU }, /* Spanish (Peru) */
|
||||
{ "es", "PR", SPANISH_PUERTO_RICO }, /* Spanish (Puerto Rico) */
|
||||
{ "es", "ES", SPANISH_MODERN_SORT }, /* Spanish (Spain) */
|
||||
{ "es", "ES", SPANISH_TRADITIONAL_SORT }, /* Spanish (Spain, Traditional Sort) */
|
||||
{ "es", "US", SPANISH_UNITED_STATES }, /* Windows Vista and later: Spanish (United States) */
|
||||
{ "es", "UY", SPANISH_URUGUAY }, /* Spanish (Uruguay) */
|
||||
{ "es", "VE", SPANISH_VENEZUELA }, /* Spanish (Venezuela) */
|
||||
{ "sw", "KE", SWAHILI }, /* Windows 2000 and later: Swahili (Kenya) */
|
||||
{ "sv", "FI", SWEDISH_FINLAND }, /* Swedish (Finland) */
|
||||
{ "sv", "SE", SWEDISH }, /* Swedish (Sweden) */
|
||||
{ "syr", "SY", SYRIAC }, /* Windows XP and later: Syriac (Syria) */
|
||||
{ "ta", "IN", TAMIL }, /* Windows 2000 and later: Tamil (India) */
|
||||
{ "tt", "RU", TATAR }, /* Windows XP and later: Tatar (Russia) */
|
||||
{ "te", "IN", TELUGU }, /* Windows XP and later: Telugu (India) */
|
||||
{ "th", "TH", THAI }, /* Thai (Thailand) */
|
||||
{ "bo", "BT", TIBETAN_BHUTAN }, /* Windows Vista and later: Tibetan (Bhutan) */
|
||||
{ "bo", "CN", TIBETAN_PRC }, /* Windows Vista and later: Tibetan (PRC) */
|
||||
{ "tr", "TR", TURKISH }, /* Turkish (Turkey) */
|
||||
{ "tk", "TM", TURKMEN }, /* Windows Vista and later: Turkmen (Turkmenistan) */
|
||||
{ "ug", "CN", UIGHUR }, /* Windows Vista and later: Uighur (PRC) */
|
||||
{ "uk", "UA", UKRAINIAN }, /* Ukrainian (Ukraine) */
|
||||
{ "wen", "DE", UPPER_SORBIAN }, /* Windows Vista and later: Upper Sorbian (Germany) */
|
||||
{ "tr", "IN", URDU_INDIA }, /* Urdu (India) */
|
||||
{ "ur", "PK", URDU }, /* Windows 98/Me, Windows 2000 and later: Urdu (Pakistan) */
|
||||
{ "uz", "UZ", UZBEK_LATIN }, /* Uzbek (Latin) */
|
||||
{ "uz", "Cyrl_UZ", UZBEK_CYRILLIC }, /* Uzbek (Cyrillic) */
|
||||
{ "vi", "VN", VIETNAMESE }, /* Windows 98/Me, Windows NT 4.0 and later: Vietnamese (Vietnam) */
|
||||
{ "cy", "GB", WELSH }, /* Windows XP SP2 and later: Welsh (United Kingdom) */
|
||||
{ "wo", "SN", WOLOF }, /* Windows Vista and later: Wolof (Senegal) */
|
||||
{ "xh", "ZA", XHOSA }, /* Windows XP SP2 and later: Xhosa/isiXhosa (South Africa) */
|
||||
{ "sah", "RU", YAKUT }, /* Windows Vista and later: Yakut (Russia) */
|
||||
{ "ii", "CN", YI }, /* Windows Vista and later: Yi (PRC) */
|
||||
{ "yo", "NG", YORUBA }, /* Windows Vista and later: Yoruba (Nigeria) */
|
||||
{ "zu", "ZA", ZULU } /* Windows XP SP2 and later: Zulu/isiZulu (South Africa) */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD localeId;
|
||||
const char* name;
|
||||
} LOCALE_NAME;
|
||||
|
||||
static const LOCALE_NAME LOCALE_NAME_TABLE[] = {
|
||||
{ AFRIKAANS, "AFRIKAANS" },
|
||||
{ ALBANIAN, "ALBANIAN" },
|
||||
{ ALSATIAN, "ALSATIAN" },
|
||||
{ AMHARIC, "AMHARIC" },
|
||||
{ ARABIC_SAUDI_ARABIA, "ARABIC_SAUDI_ARABIA" },
|
||||
{ ARABIC_IRAQ, "ARABIC_IRAQ" },
|
||||
{ ARABIC_EGYPT, "ARABIC_EGYPT" },
|
||||
{ ARABIC_LIBYA, "ARABIC_LIBYA" },
|
||||
{ ARABIC_ALGERIA, "ARABIC_ALGERIA" },
|
||||
{ ARABIC_MOROCCO, "ARABIC_MOROCCO" },
|
||||
{ ARABIC_TUNISIA, "ARABIC_TUNISIA" },
|
||||
{ ARABIC_OMAN, "ARABIC_OMAN" },
|
||||
{ ARABIC_YEMEN, "ARABIC_YEMEN" },
|
||||
{ ARABIC_SYRIA, "ARABIC_SYRIA" },
|
||||
{ ARABIC_JORDAN, "ARABIC_JORDAN" },
|
||||
{ ARABIC_LEBANON, "ARABIC_LEBANON" },
|
||||
{ ARABIC_KUWAIT, "ARABIC_KUWAIT" },
|
||||
{ ARABIC_UAE, "ARABIC_UAE" },
|
||||
{ ARABIC_BAHRAIN, "ARABIC_BAHRAIN" },
|
||||
{ ARABIC_QATAR, "ARABIC_QATAR" },
|
||||
{ ARMENIAN, "ARMENIAN" },
|
||||
{ ASSAMESE, "ASSAMESE" },
|
||||
{ AZERI_LATIN, "AZERI_LATIN" },
|
||||
{ AZERI_CYRILLIC, "AZERI_CYRILLIC" },
|
||||
{ BASHKIR, "BASHKIR" },
|
||||
{ BASQUE, "BASQUE" },
|
||||
{ BELARUSIAN, "BELARUSIAN" },
|
||||
{ BENGALI_INDIA, "BENGALI_INDIA" },
|
||||
{ BOSNIAN_LATIN, "BOSNIAN_LATIN" },
|
||||
{ BRETON, "BRETON" },
|
||||
{ BULGARIAN, "BULGARIAN" },
|
||||
{ CATALAN, "CATALAN" },
|
||||
{ CHINESE_TAIWAN, "CHINESE_TAIWAN" },
|
||||
{ CHINESE_PRC, "CHINESE_PRC" },
|
||||
{ CHINESE_HONG_KONG, "CHINESE_HONG_KONG" },
|
||||
{ CHINESE_SINGAPORE, "CHINESE_SINGAPORE" },
|
||||
{ CHINESE_MACAU, "CHINESE_MACAU" },
|
||||
{ CROATIAN, "CROATIAN" },
|
||||
{ CROATIAN_BOSNIA_HERZEGOVINA, "CROATIAN_BOSNIA_HERZEGOVINA" },
|
||||
{ CZECH, "CZECH" },
|
||||
{ DANISH, "DANISH" },
|
||||
{ DARI, "DARI" },
|
||||
{ DIVEHI, "DIVEHI" },
|
||||
{ DUTCH_STANDARD, "DUTCH_STANDARD" },
|
||||
{ DUTCH_BELGIAN, "DUTCH_BELGIAN" },
|
||||
{ ENGLISH_UNITED_STATES, "ENGLISH_UNITED_STATES" },
|
||||
{ ENGLISH_UNITED_KINGDOM, "ENGLISH_UNITED_KINGDOM" },
|
||||
{ ENGLISH_AUSTRALIAN, "ENGLISH_AUSTRALIAN" },
|
||||
{ ENGLISH_CANADIAN, "ENGLISH_CANADIAN" },
|
||||
{ ENGLISH_NEW_ZEALAND, "ENGLISH_NEW_ZEALAND" },
|
||||
{ ENGLISH_INDIA, "ENGLISH_INDIA" },
|
||||
{ ENGLISH_IRELAND, "ENGLISH_IRELAND" },
|
||||
{ ENGLISH_MALAYSIA, "ENGLISH_MALAYSIA" },
|
||||
{ ENGLISH_SOUTH_AFRICA, "ENGLISH_SOUTH_AFRICA" },
|
||||
{ ENGLISH_JAMAICA, "ENGLISH_JAMAICA" },
|
||||
{ ENGLISH_CARIBBEAN, "ENGLISH_CARIBBEAN" },
|
||||
{ ENGLISH_BELIZE, "ENGLISH_BELIZE" },
|
||||
{ ENGLISH_TRINIDAD, "ENGLISH_TRINIDAD" },
|
||||
{ ENGLISH_ZIMBABWE, "ENGLISH_ZIMBABWE" },
|
||||
{ ENGLISH_PHILIPPINES, "ENGLISH_PHILIPPINES" },
|
||||
{ ENGLISH_SINGAPORE, "ENGLISH_SINGAPORE" },
|
||||
{ ESTONIAN, "ESTONIAN" },
|
||||
{ FAEROESE, "FAEROESE" },
|
||||
{ FARSI, "FARSI" },
|
||||
{ FILIPINO, "FILIPINO" },
|
||||
{ FINNISH, "FINNISH" },
|
||||
{ FRENCH_STANDARD, "FRENCH_STANDARD" },
|
||||
{ FRENCH_BELGIAN, "FRENCH_BELGIAN" },
|
||||
{ FRENCH_CANADIAN, "FRENCH_CANADIAN" },
|
||||
{ FRENCH_SWISS, "FRENCH_SWISS" },
|
||||
{ FRENCH_LUXEMBOURG, "FRENCH_LUXEMBOURG" },
|
||||
{ FRENCH_MONACO, "FRENCH_MONACO" },
|
||||
{ FRISIAN, "FRISIAN" },
|
||||
{ GEORGIAN, "GEORGIAN" },
|
||||
{ GALICIAN, "GALICIAN" },
|
||||
{ GERMAN_STANDARD, "GERMAN_STANDARD" },
|
||||
{ GERMAN_SWISS, "GERMAN_SWISS" },
|
||||
{ GERMAN_AUSTRIAN, "GERMAN_AUSTRIAN" },
|
||||
{ GERMAN_LUXEMBOURG, "GERMAN_LUXEMBOURG" },
|
||||
{ GERMAN_LIECHTENSTEIN, "GERMAN_LIECHTENSTEIN" },
|
||||
{ GREEK, "GREEK" },
|
||||
{ GREENLANDIC, "GREENLANDIC" },
|
||||
{ GUJARATI, "GUJARATI" },
|
||||
{ HEBREW, "HEBREW" },
|
||||
{ HINDI, "HINDI" },
|
||||
{ HUNGARIAN, "HUNGARIAN" },
|
||||
{ ICELANDIC, "ICELANDIC" },
|
||||
{ IGBO, "IGBO" },
|
||||
{ INDONESIAN, "INDONESIAN" },
|
||||
{ IRISH, "IRISH" },
|
||||
{ ITALIAN_STANDARD, "ITALIAN_STANDARD" },
|
||||
{ ITALIAN_SWISS, "ITALIAN_SWISS" },
|
||||
{ JAPANESE, "JAPANESE" },
|
||||
{ KANNADA, "KANNADA" },
|
||||
{ KAZAKH, "KAZAKH" },
|
||||
{ KHMER, "KHMER" },
|
||||
{ KICHE, "KICHE" },
|
||||
{ KINYARWANDA, "KINYARWANDA" },
|
||||
{ KONKANI, "KONKANI" },
|
||||
{ KOREAN, "KOREAN" },
|
||||
{ KYRGYZ, "KYRGYZ" },
|
||||
{ LAO, "LAO" },
|
||||
{ LATVIAN, "LATVIAN" },
|
||||
{ LITHUANIAN, "LITHUANIAN" },
|
||||
{ LOWER_SORBIAN, "LOWER_SORBIAN" },
|
||||
{ LUXEMBOURGISH, "LUXEMBOURGISH" },
|
||||
{ MACEDONIAN, "MACEDONIAN" },
|
||||
{ MALAY_MALAYSIA, "MALAY_MALAYSIA" },
|
||||
{ MALAY_BRUNEI_DARUSSALAM, "MALAY_BRUNEI_DARUSSALAM" },
|
||||
{ MALAYALAM, "MALAYALAM" },
|
||||
{ MALTESE, "MALTESE" },
|
||||
{ MAPUDUNGUN, "MAPUDUNGUN" },
|
||||
{ MAORI, "MAORI" },
|
||||
{ MARATHI, "MARATHI" },
|
||||
{ MOHAWK, "MOHAWK" },
|
||||
{ MONGOLIAN, "MONGOLIAN" },
|
||||
{ NEPALI, "NEPALI" },
|
||||
{ NORWEGIAN_BOKMAL, "NORWEGIAN_BOKMAL" },
|
||||
{ NORWEGIAN_NYNORSK, "NORWEGIAN_NYNORSK" },
|
||||
{ OCCITAN, "OCCITAN" },
|
||||
{ ORIYA, "ORIYA" },
|
||||
{ PASHTO, "PASHTO" },
|
||||
{ POLISH, "POLISH" },
|
||||
{ PORTUGUESE_BRAZILIAN, "PORTUGUESE_BRAZILIAN" },
|
||||
{ PORTUGUESE_STANDARD, "PORTUGUESE_STANDARD" },
|
||||
{ PUNJABI, "PUNJABI" },
|
||||
{ QUECHUA_BOLIVIA, "QUECHUA_BOLIVIA" },
|
||||
{ QUECHUA_ECUADOR, "QUECHUA_ECUADOR" },
|
||||
{ QUECHUA_PERU, "QUECHUA_PERU" },
|
||||
{ ROMANIAN, "ROMANIAN" },
|
||||
{ ROMANSH, "ROMANSH" },
|
||||
{ RUSSIAN, "RUSSIAN" },
|
||||
{ SAMI_INARI, "SAMI_INARI" },
|
||||
{ SAMI_LULE_NORWAY, "SAMI_LULE_NORWAY" },
|
||||
{ SAMI_LULE_SWEDEN, "SAMI_LULE_SWEDEN" },
|
||||
{ SAMI_NORTHERN_FINLAND, "SAMI_NORTHERN_FINLAND" },
|
||||
{ SAMI_NORTHERN_NORWAY, "SAMI_NORTHERN_NORWAY" },
|
||||
{ SAMI_NORTHERN_SWEDEN, "SAMI_NORTHERN_SWEDEN" },
|
||||
{ SAMI_SKOLT, "SAMI_SKOLT" },
|
||||
{ SAMI_SOUTHERN_NORWAY, "SAMI_SOUTHERN_NORWAY" },
|
||||
{ SAMI_SOUTHERN_SWEDEN, "SAMI_SOUTHERN_SWEDEN" },
|
||||
{ SANSKRIT, "SANSKRIT" },
|
||||
{ SERBIAN_LATIN, "SERBIAN_LATIN" },
|
||||
{ SERBIAN_LATIN_BOSNIA_HERZEGOVINA, "SERBIAN_LATIN_BOSNIA_HERZEGOVINA" },
|
||||
{ SERBIAN_CYRILLIC, "SERBIAN_CYRILLIC" },
|
||||
{ SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA, "SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA" },
|
||||
{ SESOTHO_SA_LEBOA, "SESOTHO_SA_LEBOA" },
|
||||
{ SINHALA, "SINHALA" },
|
||||
{ SLOVAK, "SLOVAK" },
|
||||
{ SLOVENIAN, "SLOVENIAN" },
|
||||
{ SPANISH_TRADITIONAL_SORT, "SPANISH_TRADITIONAL_SORT" },
|
||||
{ SPANISH_MEXICAN, "SPANISH_MEXICAN" },
|
||||
{ SPANISH_MODERN_SORT, "SPANISH_MODERN_SORT" },
|
||||
{ SPANISH_GUATEMALA, "SPANISH_GUATEMALA" },
|
||||
{ SPANISH_COSTA_RICA, "SPANISH_COSTA_RICA" },
|
||||
{ SPANISH_PANAMA, "SPANISH_PANAMA" },
|
||||
{ SPANISH_DOMINICAN_REPUBLIC, "SPANISH_DOMINICAN_REPUBLIC" },
|
||||
{ SPANISH_VENEZUELA, "SPANISH_VENEZUELA" },
|
||||
{ SPANISH_COLOMBIA, "SPANISH_COLOMBIA" },
|
||||
{ SPANISH_PERU, "SPANISH_PERU" },
|
||||
{ SPANISH_ARGENTINA, "SPANISH_ARGENTINA" },
|
||||
{ SPANISH_ECUADOR, "SPANISH_ECUADOR" },
|
||||
{ SPANISH_CHILE, "SPANISH_CHILE" },
|
||||
{ SPANISH_UNITED_STATES, "SPANISH_UNITED_STATES" },
|
||||
{ SPANISH_URUGUAY, "SPANISH_URUGUAY" },
|
||||
{ SPANISH_PARAGUAY, "SPANISH_PARAGUAY" },
|
||||
{ SPANISH_BOLIVIA, "SPANISH_BOLIVIA" },
|
||||
{ SPANISH_EL_SALVADOR, "SPANISH_EL_SALVADOR" },
|
||||
{ SPANISH_HONDURAS, "SPANISH_HONDURAS" },
|
||||
{ SPANISH_NICARAGUA, "SPANISH_NICARAGUA" },
|
||||
{ SPANISH_PUERTO_RICO, "SPANISH_PUERTO_RICO" },
|
||||
{ SWAHILI, "SWAHILI" },
|
||||
{ SWEDISH, "SWEDISH" },
|
||||
{ SWEDISH_FINLAND, "SWEDISH_FINLAND" },
|
||||
{ SYRIAC, "SYRIAC" },
|
||||
{ TAMIL, "TAMIL" },
|
||||
{ TATAR, "TATAR" },
|
||||
{ TELUGU, "TELUGU" },
|
||||
{ THAI, "THAI" },
|
||||
{ TIBETAN_BHUTAN, "TIBETAN_BHUTAN" },
|
||||
{ TIBETAN_PRC, "TIBETAN_PRC" },
|
||||
{ TSWANA, "TSWANA" },
|
||||
{ UKRAINIAN, "UKRAINIAN" },
|
||||
{ TURKISH, "TURKISH" },
|
||||
{ TURKMEN, "TURKMEN" },
|
||||
{ UIGHUR, "UIGHUR" },
|
||||
{ UPPER_SORBIAN, "UPPER_SORBIAN" },
|
||||
{ URDU, "URDU" },
|
||||
{ URDU_INDIA, "URDU_INDIA" },
|
||||
{ UZBEK_LATIN, "UZBEK_LATIN" },
|
||||
{ UZBEK_CYRILLIC, "UZBEK_CYRILLIC" },
|
||||
{ VIETNAMESE, "VIETNAMESE" },
|
||||
{ WELSH, "WELSH" },
|
||||
{ WOLOF, "WOLOF" },
|
||||
{ XHOSA, "XHOSA" },
|
||||
{ YAKUT, "YAKUT" },
|
||||
{ YI, "YI" },
|
||||
{ YORUBA, "YORUBA" },
|
||||
{ ZULU, "ZULU" }
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD locale; /* Locale ID */
|
||||
DWORD keyboardLayouts[5]; /* array of associated keyboard layouts */
|
||||
} LOCALE_KEYBOARD_LAYOUTS;
|
||||
|
||||
/* TODO: Use KBD_* defines instead of hardcoded values */
|
||||
|
||||
static const LOCALE_KEYBOARD_LAYOUTS LOCALE_KEYBOARD_LAYOUTS_TABLE[] = {
|
||||
{ AFRIKAANS, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ALBANIAN, { 0x0000041c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_SAUDI_ARABIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_IRAQ, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_EGYPT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_LIBYA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_ALGERIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_MOROCCO, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_TUNISIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_OMAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_YEMEN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_SYRIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_JORDAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_LEBANON, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_KUWAIT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_UAE, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_BAHRAIN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARABIC_QATAR, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
|
||||
{ ARMENIAN, { 0x0000042b, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ AZERI_LATIN, { 0x0000042c, 0x0000082c, 0x00000419, 0x0, 0x0 } },
|
||||
{ AZERI_CYRILLIC, { 0x0000082c, 0x0000042c, 0x00000419, 0x0, 0x0 } },
|
||||
{ BASQUE, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ BELARUSIAN, { 0x00000423, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ BENGALI_INDIA, { 0x00000445, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ BOSNIAN_LATIN, { 0x0000141A, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ BULGARIAN, { 0x00000402, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ CATALAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ CHINESE_TAIWAN, { 0x00000404, 0xe0080404, 0xE0010404, 0x0, 0x0 } },
|
||||
{ CHINESE_PRC, { 0x00000804, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } },
|
||||
{ CHINESE_HONG_KONG, { 0x00000409, 0xe0080404, 0x0, 0x0, 0x0 } },
|
||||
{ CHINESE_SINGAPORE, { 0x00000409, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } },
|
||||
{ CHINESE_MACAU, { 0x00000409, 0xe00e0804, 0xe0020404, 0xe0080404 } },
|
||||
{ CROATIAN, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ CROATIAN_BOSNIA_HERZEGOVINA, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ CZECH, { 0x00000405, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ DANISH, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ DIVEHI, { 0x00000409, 0x00000465, 0x0, 0x0, 0x0 } },
|
||||
{ DUTCH_STANDARD, { 0x00020409, 0x00000413, 0x00000409, 0x0, 0x0 } },
|
||||
{ DUTCH_BELGIAN, { 0x00000813, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_UNITED_STATES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_UNITED_KINGDOM, { 0x00000809, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_AUSTRALIAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_CANADIAN, { 0x00000409, 0x00011009, 0x00001009, 0x0, 0x0 } },
|
||||
{ ENGLISH_NEW_ZEALAND, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_IRELAND, { 0x00001809, 0x00011809, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_SOUTH_AFRICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_JAMAICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_CARIBBEAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_BELIZE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_TRINIDAD, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_ZIMBABWE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ENGLISH_PHILIPPINES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ ESTONIAN, { 0x00000425, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ FAEROESE, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FARSI, { 0x00000409, 0x00000429, 0x00000401, 0x0, 0x0 } },
|
||||
{ FINNISH, { 0x0000040b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FRENCH_STANDARD, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FRENCH_BELGIAN, { 0x0000080c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FRENCH_CANADIAN, { 0x00000C0C, 0x00011009, 0x00000409, 0x0, 0x0 } },
|
||||
{ FRENCH_SWISS, { 0x0000100c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FRENCH_LUXEMBOURG, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ FRENCH_MONACO, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GEORGIAN, { 0x00000437, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ GALICIAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GERMAN_STANDARD, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GERMAN_SWISS, { 0x00000807, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GERMAN_AUSTRIAN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GERMAN_LUXEMBOURG, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GERMAN_LIECHTENSTEIN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GREEK, { 0x00000408, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ GUJARATI, { 0x00000409, 0x00000447, 0x00010439, 0x0, 0x0 } },
|
||||
{ HEBREW, { 0x00000409, 0x0000040d, 0x0, 0x0, 0x0 } },
|
||||
{ HINDI, { 0x00000409, 0x00010439, 0x00000439, 0x0, 0x0 } },
|
||||
{ HUNGARIAN, { 0x0000040e, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ICELANDIC, { 0x0000040f, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ INDONESIAN, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ITALIAN_STANDARD, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ ITALIAN_SWISS, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ JAPANESE, { 0xe0010411, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ KANNADA, { 0x00000409, 0x0000044b, 0x00010439, 0x0, 0x0 } },
|
||||
{ KAZAKH, { 0x0000043f, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ KONKANI, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } },
|
||||
{ KOREAN, { 0xE0010412, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ KYRGYZ, { 0x00000440, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ LATVIAN, { 0x00010426, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ LITHUANIAN, { 0x00010427, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ MACEDONIAN, { 0x0000042f, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ MALAY_MALAYSIA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ MALAY_BRUNEI_DARUSSALAM, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ MALAYALAM, { 0x00000409, 0x0000044c, 0x0, 0x0, 0x0 } },
|
||||
{ MALTESE, { 0x00000409, 0x0000043a, 0x0, 0x0, 0x0 } },
|
||||
{ MAORI, { 0x00000409, 0x00000481, 0x0, 0x0, 0x0 } },
|
||||
{ MARATHI, { 0x00000409, 0x0000044e, 0x00000439, 0x0, 0x0 } },
|
||||
{ MONGOLIAN, { 0x00000450, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ NORWEGIAN_BOKMAL, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ NORWEGIAN_NYNORSK, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ POLISH, { 0x00010415, 0x00000415, 0x00000409, 0x0, 0x0 } },
|
||||
{ PORTUGUESE_BRAZILIAN, { 0x00000416, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ PORTUGUESE_STANDARD, { 0x00000816, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ PUNJABI, { 0x00000409, 0x00000446, 0x00010439, 0x0, 0x0 } },
|
||||
{ QUECHUA_BOLIVIA, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
|
||||
{ QUECHUA_ECUADOR, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
|
||||
{ QUECHUA_PERU, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
|
||||
{ ROMANIAN, { 0x00000418, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ RUSSIAN, { 0x00000419, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_INARI, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_LULE_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_LULE_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_NORTHERN_FINLAND, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_NORTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_NORTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_SKOLT, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_SOUTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SAMI_SOUTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SANSKRIT, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } },
|
||||
{ SERBIAN_LATIN, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SERBIAN_LATIN_BOSNIA_HERZEGOVINA, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SERBIAN_CYRILLIC, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SLOVAK, { 0x0000041b, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SLOVENIAN, { 0x00000424, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_TRADITIONAL_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_MEXICAN, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_MODERN_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_GUATEMALA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_COSTA_RICA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_PANAMA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_DOMINICAN_REPUBLIC, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_VENEZUELA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_COLOMBIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_PERU, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_ARGENTINA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_ECUADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_CHILE, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_URUGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_PARAGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_BOLIVIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_EL_SALVADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_HONDURAS, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_NICARAGUA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SPANISH_PUERTO_RICO, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SWAHILI, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
|
||||
{ SWEDISH, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SWEDISH_FINLAND, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ SYRIAC, { 0x00000409, 0x0000045a, 0x0, 0x0, 0x0 } },
|
||||
{ TAMIL, { 0x00000409, 0x00000449, 0x0, 0x0, 0x0 } },
|
||||
{ TATAR, { 0x00000444, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ TELUGU, { 0x00000409, 0x0000044a, 0x00010439, 0x0, 0x0 } },
|
||||
{ THAI, { 0x00000409, 0x0000041e, 0x0, 0x0, 0x0 } },
|
||||
{ TSWANA, { 0x00000409, 0x0000041f, 0x0, 0x0, 0x0 } },
|
||||
{ UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ TURKISH, { 0x0000041f, 0x0000041f, 0x0, 0x0, 0x0 } },
|
||||
{ UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ URDU, { 0x00000401, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
{ UZBEK_LATIN, { 0x00000409, 0x00000843, 0x00000419, 0x0, 0x0 } },
|
||||
{ UZBEK_CYRILLIC, { 0x00000843, 0x00000409, 0x00000419, 0x0, 0x0 } },
|
||||
{ VIETNAMESE, { 0x00000409, 0x0000042a, 0x0, 0x0, 0x0 } },
|
||||
{ WELSH, { 0x00000452, 0x00000809, 0x0, 0x0, 0x0 } },
|
||||
{ XHOSA, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
|
||||
};
|
||||
|
||||
static BOOL freerdp_get_system_language_and_country_codes(char* language, size_t languageLen,
|
||||
char* country, size_t countryLen)
|
||||
{
|
||||
WINPR_ASSERT(language);
|
||||
WINPR_ASSERT(languageLen > 0);
|
||||
WINPR_ASSERT(country);
|
||||
WINPR_ASSERT(countryLen);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
{
|
||||
CFStringRef langRef, countryRef;
|
||||
CFLocaleRef localeRef = CFLocaleCopyCurrent();
|
||||
if (!localeRef)
|
||||
return FALSE;
|
||||
|
||||
langRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleLanguageCode);
|
||||
countryRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleCountryCode);
|
||||
if (!langRef || !countryRef)
|
||||
{
|
||||
CFRelease(localeRef);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CFStringGetCString(langRef, language, languageLen, kCFStringEncodingUTF8) ||
|
||||
!CFStringGetCString(countryRef, country, countryLen, kCFStringEncodingUTF8))
|
||||
{
|
||||
CFRelease(localeRef);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CFRelease(localeRef);
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
{
|
||||
size_t dot = 0;
|
||||
DWORD nSize = 0;
|
||||
size_t underscore = 0;
|
||||
char* env_lang = nullptr;
|
||||
LPCSTR lang = "LANG";
|
||||
/* LANG = <language>_<country>.<encoding> */
|
||||
nSize = GetEnvironmentVariableA(lang, nullptr, 0);
|
||||
|
||||
if (!nSize)
|
||||
return FALSE; /* LANG environment variable was not set */
|
||||
|
||||
env_lang = (char*)malloc(nSize);
|
||||
|
||||
if (!env_lang)
|
||||
return FALSE;
|
||||
|
||||
if (GetEnvironmentVariableA(lang, env_lang, nSize) !=
|
||||
nSize - 1) /* Get locale from environment variable LANG */
|
||||
{
|
||||
free(env_lang);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
underscore = strcspn(env_lang, "_");
|
||||
|
||||
if (underscore > 3)
|
||||
{
|
||||
free(env_lang);
|
||||
return FALSE; /* The language name should not be more than 3 letters long */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get language code */
|
||||
size_t len = MIN(languageLen - 1u, underscore);
|
||||
strncpy(language, env_lang, len);
|
||||
language[len] = '\0';
|
||||
}
|
||||
|
||||
dot = strcspn(env_lang, ".");
|
||||
|
||||
/* Get country code */
|
||||
if (dot > underscore)
|
||||
{
|
||||
size_t len = MIN(countryLen - 1, dot - underscore - 1);
|
||||
strncpy(country, &env_lang[underscore + 1], len);
|
||||
country[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
free(env_lang);
|
||||
return FALSE; /* Invalid locale */
|
||||
}
|
||||
|
||||
free(env_lang);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const SYSTEM_LOCALE* freerdp_detect_system_locale(void)
|
||||
{
|
||||
char language[LOCALE_LANGUAGE_LEN] = WINPR_C_ARRAY_INIT;
|
||||
char country[LOCALE_COUNTRY_LEN] = WINPR_C_ARRAY_INIT;
|
||||
const SYSTEM_LOCALE* locale = nullptr;
|
||||
|
||||
freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
|
||||
ARRAYSIZE(country));
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(SYSTEM_LOCALE_TABLE); i++)
|
||||
{
|
||||
const SYSTEM_LOCALE* current = &SYSTEM_LOCALE_TABLE[i];
|
||||
|
||||
if ((strcmp(language, current->language) == 0) && (strcmp(country, current->country) == 0))
|
||||
{
|
||||
locale = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
DWORD freerdp_get_system_locale_id(void)
|
||||
{
|
||||
const SYSTEM_LOCALE* locale = nullptr;
|
||||
locale = freerdp_detect_system_locale();
|
||||
|
||||
if (locale != nullptr)
|
||||
return locale->code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const SYSTEM_LOCALE* get_locale_from_str(const char* name)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAYSIZE(SYSTEM_LOCALE_TABLE); i++)
|
||||
{
|
||||
char buffer[LOCALE_LANGUAGE_LEN + LOCALE_COUNTRY_LEN + 2] = WINPR_C_ARRAY_INIT;
|
||||
const SYSTEM_LOCALE* current = &SYSTEM_LOCALE_TABLE[i];
|
||||
|
||||
(void)_snprintf(buffer, sizeof(buffer), "%s_%s", current->language, current->country);
|
||||
/* full match, e.g. en_US */
|
||||
if ((strcmp(name, buffer) == 0))
|
||||
return current;
|
||||
/* simple language only match e.g. 'en' */
|
||||
else if ((strcmp(name, current->language) == 0))
|
||||
return current;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static INT64 get_layout_from_locale(const SYSTEM_LOCALE* locale)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAYSIZE(LOCALE_KEYBOARD_LAYOUTS_TABLE); i++)
|
||||
{
|
||||
const LOCALE_KEYBOARD_LAYOUTS* current = &LOCALE_KEYBOARD_LAYOUTS_TABLE[i];
|
||||
WINPR_ASSERT(current);
|
||||
|
||||
if (current->locale == locale->code)
|
||||
{
|
||||
/* Locale found in list of default keyboard layouts */
|
||||
for (size_t j = 0; j < 5; j++)
|
||||
{
|
||||
if (current->keyboardLayouts[j] == ENGLISH_UNITED_STATES)
|
||||
{
|
||||
continue; /* Skip, try to get a more localized keyboard layout */
|
||||
}
|
||||
else if (current->keyboardLayouts[j] == 0)
|
||||
{
|
||||
/*
|
||||
* If we skip the ENGLISH_UNITED_STATES keyboard layout but there are no
|
||||
* other possible keyboard layout for the locale, we end up here with k > 1
|
||||
*/
|
||||
|
||||
if (j >= 1)
|
||||
return ENGLISH_UNITED_STATES;
|
||||
|
||||
/* No more keyboard layouts */
|
||||
break;
|
||||
}
|
||||
else
|
||||
return current->keyboardLayouts[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* freerdp_get_system_locale_name_from_id(DWORD localeId)
|
||||
{
|
||||
for (size_t index = 0; index < ARRAYSIZE(LOCALE_NAME_TABLE); index++)
|
||||
{
|
||||
const LOCALE_NAME* current = &LOCALE_NAME_TABLE[index];
|
||||
|
||||
if (localeId == current->localeId)
|
||||
return current->name;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
INT64 freerdp_get_locale_id_from_string(const char* locale)
|
||||
{
|
||||
const SYSTEM_LOCALE* loc = get_locale_from_str(locale);
|
||||
if (!loc)
|
||||
return -1;
|
||||
return loc->code;
|
||||
}
|
||||
|
||||
int freerdp_detect_keyboard_layout_from_system_locale(DWORD* keyboardLayoutId)
|
||||
{
|
||||
char language[LOCALE_LANGUAGE_LEN] = WINPR_C_ARRAY_INIT;
|
||||
char country[LOCALE_COUNTRY_LEN] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
|
||||
ARRAYSIZE(country));
|
||||
|
||||
char locale[LOCALE_COUNTRY_LEN + LOCALE_LANGUAGE_LEN + 2] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(locale, sizeof(locale), "%s_%s", language, country);
|
||||
const int64_t id = freerdp_detect_keyboard_layout_from_locale(locale);
|
||||
if (id < 0)
|
||||
return -1;
|
||||
*keyboardLayoutId = WINPR_ASSERTING_INT_CAST(uint32_t, id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t freerdp_detect_keyboard_layout_from_locale(const char* localestr)
|
||||
{
|
||||
WINPR_ASSERT(localestr);
|
||||
|
||||
if ((strcmp(localestr, "C") == 0) || (strcmp(localestr, "POSIX") == 0))
|
||||
return ENGLISH_UNITED_STATES; /* U.S. Keyboard Layout */
|
||||
|
||||
const SYSTEM_LOCALE* locale = get_locale_from_str(localestr);
|
||||
|
||||
if (!locale)
|
||||
return -1;
|
||||
|
||||
DEBUG_KBD("Found locale : %s_%s", locale->language, locale->country);
|
||||
return get_layout_from_locale(locale);
|
||||
}
|
||||
|
||||
const SYSTEM_LOCALE* freerdp_get_system_locale_list(size_t* count)
|
||||
{
|
||||
WINPR_ASSERT(count);
|
||||
*count = ARRAYSIZE(SYSTEM_LOCALE_TABLE);
|
||||
return SYSTEM_LOCALE_TABLE;
|
||||
}
|
||||
|
||||
DWORD freerdp_get_keyboard_default_layout_for_locale(DWORD locale)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(LOCALE_KEYBOARD_LAYOUTS_TABLE); x++)
|
||||
{
|
||||
const LOCALE_KEYBOARD_LAYOUTS* cur = &LOCALE_KEYBOARD_LAYOUTS_TABLE[x];
|
||||
if (cur->locale == locale)
|
||||
return cur->keyboardLayouts[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
29
third_party/FreeRDP/libfreerdp/locale/test/CMakeLists.txt
vendored
Normal file
29
third_party/FreeRDP/libfreerdp/locale/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# Test not compatible with package tests, disable
|
||||
if(BUILD_TESTING_INTERNAL)
|
||||
set(MODULE_NAME "TestLocale")
|
||||
set(MODULE_PREFIX "TEST_LOCALE")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(TEST_SRCS TestLocaleKeyboard.c)
|
||||
|
||||
create_test_sourcelist(SRCS ${DRIVER} ${TEST_SRCS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${SRCS})
|
||||
|
||||
add_compile_definitions(TESTING_OUTPUT_DIRECTORY="${PROJECT_BINARY_DIR}")
|
||||
add_compile_definitions(TESTING_SRC_DIRECTORY="${PROJECT_SOURCE_DIR}")
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp winpr freerdp-client)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${TEST_SRCS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Locale/Test")
|
||||
endif()
|
||||
405
third_party/FreeRDP/libfreerdp/locale/test/TestLocaleKeyboard.c
vendored
Normal file
405
third_party/FreeRDP/libfreerdp/locale/test/TestLocaleKeyboard.c
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
#include <stdio.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
static BOOL test_scancode_name(void)
|
||||
{
|
||||
const DWORD scancodes[] = { RDP_SCANCODE_ESCAPE,
|
||||
RDP_SCANCODE_KEY_1,
|
||||
RDP_SCANCODE_KEY_2,
|
||||
RDP_SCANCODE_KEY_3,
|
||||
RDP_SCANCODE_KEY_4,
|
||||
RDP_SCANCODE_KEY_5,
|
||||
RDP_SCANCODE_KEY_6,
|
||||
RDP_SCANCODE_KEY_7,
|
||||
RDP_SCANCODE_KEY_8,
|
||||
RDP_SCANCODE_KEY_9,
|
||||
RDP_SCANCODE_KEY_0,
|
||||
RDP_SCANCODE_OEM_MINUS,
|
||||
RDP_SCANCODE_OEM_PLUS,
|
||||
RDP_SCANCODE_BACKSPACE,
|
||||
RDP_SCANCODE_TAB,
|
||||
RDP_SCANCODE_KEY_Q,
|
||||
RDP_SCANCODE_KEY_W,
|
||||
RDP_SCANCODE_KEY_E,
|
||||
RDP_SCANCODE_KEY_R,
|
||||
RDP_SCANCODE_KEY_T,
|
||||
RDP_SCANCODE_KEY_Y,
|
||||
RDP_SCANCODE_KEY_U,
|
||||
RDP_SCANCODE_KEY_I,
|
||||
RDP_SCANCODE_KEY_O,
|
||||
RDP_SCANCODE_KEY_P,
|
||||
RDP_SCANCODE_OEM_4,
|
||||
RDP_SCANCODE_OEM_6,
|
||||
RDP_SCANCODE_RETURN,
|
||||
RDP_SCANCODE_LCONTROL,
|
||||
RDP_SCANCODE_KEY_A,
|
||||
RDP_SCANCODE_KEY_S,
|
||||
RDP_SCANCODE_KEY_D,
|
||||
RDP_SCANCODE_KEY_F,
|
||||
RDP_SCANCODE_KEY_G,
|
||||
RDP_SCANCODE_KEY_H,
|
||||
RDP_SCANCODE_KEY_J,
|
||||
RDP_SCANCODE_KEY_K,
|
||||
RDP_SCANCODE_KEY_L,
|
||||
RDP_SCANCODE_OEM_1,
|
||||
RDP_SCANCODE_OEM_7,
|
||||
RDP_SCANCODE_OEM_3,
|
||||
RDP_SCANCODE_LSHIFT,
|
||||
RDP_SCANCODE_OEM_5,
|
||||
RDP_SCANCODE_KEY_Z,
|
||||
RDP_SCANCODE_KEY_X,
|
||||
RDP_SCANCODE_KEY_C,
|
||||
RDP_SCANCODE_KEY_V,
|
||||
RDP_SCANCODE_KEY_B,
|
||||
RDP_SCANCODE_KEY_N,
|
||||
RDP_SCANCODE_KEY_M,
|
||||
RDP_SCANCODE_OEM_COMMA,
|
||||
RDP_SCANCODE_OEM_PERIOD,
|
||||
RDP_SCANCODE_OEM_2,
|
||||
RDP_SCANCODE_RSHIFT,
|
||||
RDP_SCANCODE_MULTIPLY,
|
||||
RDP_SCANCODE_LMENU,
|
||||
RDP_SCANCODE_SPACE,
|
||||
RDP_SCANCODE_CAPSLOCK,
|
||||
RDP_SCANCODE_F1,
|
||||
RDP_SCANCODE_F2,
|
||||
RDP_SCANCODE_F3,
|
||||
RDP_SCANCODE_F4,
|
||||
RDP_SCANCODE_F5,
|
||||
RDP_SCANCODE_F6,
|
||||
RDP_SCANCODE_F7,
|
||||
RDP_SCANCODE_F8,
|
||||
RDP_SCANCODE_F9,
|
||||
RDP_SCANCODE_F10,
|
||||
RDP_SCANCODE_NUMLOCK,
|
||||
RDP_SCANCODE_SCROLLLOCK,
|
||||
RDP_SCANCODE_NUMPAD7,
|
||||
RDP_SCANCODE_NUMPAD8,
|
||||
RDP_SCANCODE_NUMPAD9,
|
||||
RDP_SCANCODE_SUBTRACT,
|
||||
RDP_SCANCODE_NUMPAD4,
|
||||
RDP_SCANCODE_NUMPAD5,
|
||||
RDP_SCANCODE_NUMPAD6,
|
||||
RDP_SCANCODE_ADD,
|
||||
RDP_SCANCODE_NUMPAD1,
|
||||
RDP_SCANCODE_NUMPAD2,
|
||||
RDP_SCANCODE_NUMPAD3,
|
||||
RDP_SCANCODE_NUMPAD0,
|
||||
RDP_SCANCODE_DECIMAL,
|
||||
RDP_SCANCODE_SYSREQ,
|
||||
RDP_SCANCODE_OEM_102,
|
||||
RDP_SCANCODE_F11,
|
||||
RDP_SCANCODE_F12,
|
||||
RDP_SCANCODE_SLEEP,
|
||||
RDP_SCANCODE_ZOOM,
|
||||
RDP_SCANCODE_HELP,
|
||||
RDP_SCANCODE_F13,
|
||||
RDP_SCANCODE_F14,
|
||||
RDP_SCANCODE_F15,
|
||||
RDP_SCANCODE_F16,
|
||||
RDP_SCANCODE_F17,
|
||||
RDP_SCANCODE_F18,
|
||||
RDP_SCANCODE_F19,
|
||||
RDP_SCANCODE_F20,
|
||||
RDP_SCANCODE_F21,
|
||||
RDP_SCANCODE_F22,
|
||||
RDP_SCANCODE_F23,
|
||||
RDP_SCANCODE_F24,
|
||||
RDP_SCANCODE_HIRAGANA,
|
||||
RDP_SCANCODE_HANJA_KANJI,
|
||||
RDP_SCANCODE_KANA_HANGUL,
|
||||
RDP_SCANCODE_ABNT_C1,
|
||||
RDP_SCANCODE_F24_JP,
|
||||
RDP_SCANCODE_CONVERT_JP,
|
||||
RDP_SCANCODE_NONCONVERT_JP,
|
||||
RDP_SCANCODE_TAB_JP,
|
||||
RDP_SCANCODE_BACKSLASH_JP,
|
||||
RDP_SCANCODE_ABNT_C2,
|
||||
RDP_SCANCODE_HANJA,
|
||||
RDP_SCANCODE_HANGUL,
|
||||
RDP_SCANCODE_RETURN_KP,
|
||||
RDP_SCANCODE_RCONTROL,
|
||||
RDP_SCANCODE_DIVIDE,
|
||||
RDP_SCANCODE_PRINTSCREEN,
|
||||
RDP_SCANCODE_RMENU,
|
||||
RDP_SCANCODE_PAUSE,
|
||||
RDP_SCANCODE_HOME,
|
||||
RDP_SCANCODE_UP,
|
||||
RDP_SCANCODE_PRIOR,
|
||||
RDP_SCANCODE_LEFT,
|
||||
RDP_SCANCODE_RIGHT,
|
||||
RDP_SCANCODE_END,
|
||||
RDP_SCANCODE_DOWN,
|
||||
RDP_SCANCODE_NEXT,
|
||||
RDP_SCANCODE_INSERT,
|
||||
RDP_SCANCODE_DELETE,
|
||||
RDP_SCANCODE_NULL,
|
||||
RDP_SCANCODE_HELP2,
|
||||
RDP_SCANCODE_LWIN,
|
||||
RDP_SCANCODE_RWIN,
|
||||
RDP_SCANCODE_APPS,
|
||||
RDP_SCANCODE_POWER_JP,
|
||||
RDP_SCANCODE_SLEEP_JP,
|
||||
RDP_SCANCODE_NUMLOCK_EXTENDED,
|
||||
RDP_SCANCODE_RSHIFT_EXTENDED,
|
||||
RDP_SCANCODE_VOLUME_MUTE,
|
||||
RDP_SCANCODE_VOLUME_DOWN,
|
||||
RDP_SCANCODE_VOLUME_UP,
|
||||
RDP_SCANCODE_MEDIA_NEXT_TRACK,
|
||||
RDP_SCANCODE_MEDIA_PREV_TRACK,
|
||||
RDP_SCANCODE_MEDIA_STOP,
|
||||
RDP_SCANCODE_MEDIA_PLAY_PAUSE,
|
||||
RDP_SCANCODE_BROWSER_BACK,
|
||||
RDP_SCANCODE_BROWSER_FORWARD,
|
||||
RDP_SCANCODE_BROWSER_REFRESH,
|
||||
RDP_SCANCODE_BROWSER_STOP,
|
||||
RDP_SCANCODE_BROWSER_SEARCH,
|
||||
RDP_SCANCODE_BROWSER_FAVORITES,
|
||||
RDP_SCANCODE_BROWSER_HOME,
|
||||
RDP_SCANCODE_LAUNCH_MAIL,
|
||||
RDP_SCANCODE_LAUNCH_MEDIA_SELECT,
|
||||
RDP_SCANCODE_LAUNCH_APP1,
|
||||
RDP_SCANCODE_LAUNCH_APP2 };
|
||||
for (size_t x = 0; x < ARRAYSIZE(scancodes); x++)
|
||||
{
|
||||
const DWORD code = scancodes[x];
|
||||
const char* sc = freerdp_keyboard_scancode_name(code);
|
||||
if (!sc)
|
||||
{
|
||||
(void)fprintf(stderr, "Failed to run freerdp_keyboard_scancode_name(%" PRIu32 ")\n",
|
||||
code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_layouts(DWORD types)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
size_t count = 0;
|
||||
RDP_KEYBOARD_LAYOUT* layouts = freerdp_keyboard_get_layouts(types, &count);
|
||||
if (!layouts || (count == 0))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_layouts(type: %" PRIu32 ") -> %" PRIuz
|
||||
" elements, layouts: %p:\n",
|
||||
types, count, layouts);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const RDP_KEYBOARD_LAYOUT* cur = &layouts[x];
|
||||
if ((cur->code == 0) || (!cur->name) || (strnlen(cur->name, 2) == 0))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_layouts(type: %" PRIu32 ") -> %" PRIuz
|
||||
" elements, failed:\n",
|
||||
types, count);
|
||||
(void)fprintf(stderr, "[%" PRIuz "]: code= %" PRIu32 ", name = %s\n", x, cur->code,
|
||||
cur->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
const char* name = freerdp_keyboard_get_layout_name_from_id(cur->code);
|
||||
if (!name)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_layouts(type: %" PRIu32 ") -> %" PRIuz
|
||||
" elements, failed:\n",
|
||||
types, count);
|
||||
(void)fprintf(stderr,
|
||||
"[%" PRIuz "]: freerdp_keyboard_get_layouts(%" PRIu32 ") -> nullptr\n", x,
|
||||
cur->code);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
const DWORD id = freerdp_keyboard_get_layout_id_from_name(cur->name);
|
||||
// if (id != cur->code) {
|
||||
if (id == 0)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_layouts(type: %" PRIu32 ") -> %" PRIuz
|
||||
" elements, failed:\n",
|
||||
types, count);
|
||||
(void)fprintf(stderr,
|
||||
"[%" PRIuz "]: freerdp_keyboard_get_layout_id_from_name(%s) -> %" PRIu32
|
||||
" != %" PRIu32 "\n",
|
||||
x, cur->name, id, cur->code);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
freerdp_keyboard_layouts_free(layouts, count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DWORD get_random(DWORD offset)
|
||||
{
|
||||
DWORD x = 0;
|
||||
if (winpr_RAND(&x, sizeof(x)) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "winpr_RAND failed, retry...\n");
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
exit(-1);
|
||||
}
|
||||
x = x % UINT32_MAX - offset;
|
||||
x += offset;
|
||||
return x;
|
||||
}
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
static BOOL test_scancode_cnv(void)
|
||||
{
|
||||
for (DWORD x = 0; x < UINT8_MAX; x++)
|
||||
{
|
||||
const DWORD sc = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(x);
|
||||
const BOOL ex = RDP_SCANCODE_EXTENDED(sc);
|
||||
const DWORD kk = freerdp_keyboard_get_x11_keycode_from_rdp_scancode(sc, ex);
|
||||
if (sc != kk)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"[%" PRIu32 "]: keycode->scancode->keycode failed: %" PRIu32
|
||||
" -> %" PRIu32 " -> %" PRIu32 "\n",
|
||||
x, sc, ex, kk);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (DWORD x = 0; x < 23; x++)
|
||||
{
|
||||
DWORD x = get_random(UINT8_MAX);
|
||||
|
||||
const DWORD sc = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(x);
|
||||
const DWORD kk = freerdp_keyboard_get_x11_keycode_from_rdp_scancode(sc, FALSE);
|
||||
const DWORD kkex = freerdp_keyboard_get_x11_keycode_from_rdp_scancode(sc, TRUE);
|
||||
if ((sc != 0) || (kk != 0) || (kkex != 0))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"[%" PRIu32 "]: invalid scancode %" PRIu32 ", keycode %" PRIu32
|
||||
" or keycode extended %" PRIu32 " has a value != 0\n",
|
||||
x, sc, kk, kkex);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL test_codepages(void)
|
||||
{
|
||||
|
||||
for (DWORD column = 0; column < 4; column++)
|
||||
{
|
||||
size_t count = 0;
|
||||
RDP_CODEPAGE* cp = freerdp_keyboard_get_matching_codepages(column, nullptr, &count);
|
||||
if (!cp || (count == 0))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_matching_codepages(%" PRIu32 ", nullptr) failed!\n",
|
||||
column);
|
||||
return FALSE;
|
||||
}
|
||||
freerdp_codepages_free(cp);
|
||||
}
|
||||
|
||||
for (DWORD x = 0; x < 23; x++)
|
||||
{
|
||||
DWORD column = get_random(4);
|
||||
size_t count = 0;
|
||||
RDP_CODEPAGE* cp = freerdp_keyboard_get_matching_codepages(column, nullptr, &count);
|
||||
freerdp_codepages_free(cp);
|
||||
if (cp || (count != 0))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"freerdp_keyboard_get_matching_codepages(%" PRIu32
|
||||
", nullptr) returned not nullptr!\n",
|
||||
column);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test with filters set
|
||||
// TODO: Test with invalid filters set
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_init(void)
|
||||
{
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
const DWORD kbd = freerdp_keyboard_init(0);
|
||||
if (kbd == 0)
|
||||
{
|
||||
(void)fprintf(stderr, "freerdp_keyboard_init(0) returned invalid layout 0\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const DWORD kbdex = freerdp_keyboard_init_ex(0, nullptr);
|
||||
if (kbd == 0)
|
||||
{
|
||||
(void)fprintf(stderr, "freerdp_keyboard_init_ex(0, nullptr) returned invalid layout 0\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (kbd != kbdex)
|
||||
{
|
||||
(void)fprintf(
|
||||
stderr,
|
||||
"freerdp_keyboard_init(0) != freerdp_keyboard_init_ex(0, nullptr): returned %" PRIu32
|
||||
" vs %" PRIu32 "\n",
|
||||
kbd, kbdex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO: Test with valid remap list
|
||||
// TODO: Test with invalid remap list
|
||||
// TODO: Test with defaults != 0
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestLocaleKeyboard(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_scancode_name())
|
||||
return -1;
|
||||
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_IME))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT | RDP_KEYBOARD_LAYOUT_TYPE_IME))
|
||||
return -1;
|
||||
if (!test_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT |
|
||||
RDP_KEYBOARD_LAYOUT_TYPE_IME))
|
||||
return -1;
|
||||
if (test_layouts(UINT32_MAX &
|
||||
~(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT |
|
||||
RDP_KEYBOARD_LAYOUT_TYPE_IME)))
|
||||
return -1;
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
if (!test_scancode_cnv())
|
||||
return -1;
|
||||
#endif
|
||||
if (!test_codepages())
|
||||
return -1;
|
||||
if (!test_init())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
871
third_party/FreeRDP/libfreerdp/locale/xkb_layout_ids.c
vendored
Normal file
871
third_party/FreeRDP/libfreerdp/locale/xkb_layout_ids.c
vendored
Normal file
@@ -0,0 +1,871 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Keyboard layout ID detection from common X11 xkb keyboard layout names
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "xkb_layout_ids.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "liblocale.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* variant; /* XKB Keyboard layout variant */
|
||||
INT64 keyboardLayoutID; /* Keyboard Layout ID */
|
||||
} XKB_VARIANT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* layout; /* XKB Keyboard layout */
|
||||
INT64 keyboardLayoutID; /* Keyboard Layout ID */
|
||||
const XKB_VARIANT* variants;
|
||||
} XKB_LAYOUT;
|
||||
|
||||
/* Those have been generated automatically and are waiting to be filled by hand */
|
||||
|
||||
/* USA */
|
||||
static const XKB_VARIANT us_variants[] = {
|
||||
{ "chr", 0 }, /* Cherokee */
|
||||
{ "euro", 0 }, /* With EuroSign on 5 */
|
||||
{ "intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (with dead keys) */
|
||||
{ "alt-intl",
|
||||
KBD_UNITED_STATES_INTERNATIONAL }, /* Alternative international (former us_intl) */
|
||||
{ "colemak", 0 }, /* Colemak */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "dvorak-intl", KBD_UNITED_STATES_DVORAK }, /* Dvorak international */
|
||||
{ "dvorak-l", KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND }, /* Left handed Dvorak */
|
||||
{ "dvorak-r", KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND }, /* Right handed Dvorak */
|
||||
{ "dvorak-classic", KBD_UNITED_STATES_DVORAK }, /* Classic Dvorak */
|
||||
{ "dvp", KBD_UNITED_STATES_DVORAK_PROGRAMMER }, /* Programmer Dvorak */
|
||||
{ "rus", 0 }, /* Russian phonetic */
|
||||
{ "mac", KBD_US }, /* Macintosh */
|
||||
{ "altgr-intl", KBD_UNITED_STATES_INTERNATIONAL }, /* International (AltGr dead keys) */
|
||||
{ "olpc2", KBD_US }, /* Group toggle on multiply/divide key */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Afghanistan */
|
||||
static const XKB_VARIANT af_variants[] = {
|
||||
{ "ps", KBD_PASHTO }, /* Pashto */
|
||||
{ "uz", KBD_UZBEK_CYRILLIC }, /* Southern Uzbek */
|
||||
{ "olpc-ps", KBD_PASHTO }, /* OLPC Pashto */
|
||||
{ "olpc-fa", 0 }, /* OLPC Dari */
|
||||
{ "olpc-uz", KBD_UZBEK_CYRILLIC }, /* OLPC Southern Uzbek */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Arabic */
|
||||
static const XKB_VARIANT ara_variants[] = {
|
||||
{ "azerty", KBD_ARABIC_102_AZERTY }, /* azerty */
|
||||
{ "azerty_digits", KBD_ARABIC_102_AZERTY }, /* azerty/digits */
|
||||
{ "digits", KBD_ARABIC_102_AZERTY }, /* digits */
|
||||
{ "qwerty", KBD_ARABIC_101 }, /* qwerty */
|
||||
{ "qwerty_digits", KBD_ARABIC_101 }, /* qwerty/digits */
|
||||
{ "buckwalter", KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L }, /* Buckwalter */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Armenia */
|
||||
static const XKB_VARIANT am_variants[] = {
|
||||
{ "phonetic", 0 }, /* Phonetic */
|
||||
{ "phonetic-alt", 0 }, /* Alternative Phonetic */
|
||||
{ "eastern", KBD_ARMENIAN_EASTERN }, /* Eastern */
|
||||
{ "western", KBD_ARMENIAN_WESTERN }, /* Western */
|
||||
{ "eastern-alt", KBD_ARMENIAN_EASTERN }, /* Alternative Eastern */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Azerbaijan */
|
||||
static const XKB_VARIANT az_variants[] = {
|
||||
{ "cyrillic", KBD_AZERI_CYRILLIC }, /* Cyrillic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Belarus */
|
||||
static const XKB_VARIANT by_variants[] = {
|
||||
{ "winkeys", KBD_BELARUSIAN }, /* Winkeys */
|
||||
{ "latin", KBD_BELARUSIAN }, /* Latin */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Belgium */
|
||||
static const XKB_VARIANT be_variants[] = {
|
||||
{ "oss", KBD_BELGIAN_FRENCH }, /* Alternative */
|
||||
{ "oss_latin9", KBD_BELGIAN_FRENCH }, /* Alternative, latin-9 only */
|
||||
{ "oss_sundeadkeys", KBD_BELGIAN_PERIOD }, /* Alternative, Sun dead keys */
|
||||
{ "iso-alternate", KBD_BELGIAN_COMMA }, /* ISO Alternate */
|
||||
{ "nodeadkeys", KBD_BELGIAN_COMMA }, /* Eliminate dead keys */
|
||||
{ "sundeadkeys", KBD_BELGIAN_PERIOD }, /* Sun dead keys */
|
||||
{ "wang", KBD_BELGIAN_FRENCH }, /* Wang model 724 azerty */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Bangladesh */
|
||||
static const XKB_VARIANT bd_variants[] = {
|
||||
{ "probhat", KBD_BENGALI_INSCRIPT }, /* Probhat */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* India */
|
||||
static const XKB_VARIANT in_variants[] = {
|
||||
{ "ben", KBD_BENGALI }, /* Bengali */
|
||||
{ "ben_probhat", KBD_BENGALI_INSCRIPT }, /* Bengali Probhat */
|
||||
{ "guj", KBD_GUJARATI }, /* Gujarati */
|
||||
{ "guru", 0 }, /* Gurmukhi */
|
||||
{ "jhelum", 0 }, /* Gurmukhi Jhelum */
|
||||
{ "kan", KBD_KANNADA }, /* Kannada */
|
||||
{ "mal", KBD_MALAYALAM }, /* Malayalam */
|
||||
{ "mal_lalitha", KBD_MALAYALAM }, /* Malayalam Lalitha */
|
||||
{ "ori", 0 }, /* Oriya */
|
||||
{ "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */
|
||||
{ "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */
|
||||
{ "tam_TSCII", KBD_TAMIL }, /* Tamil TSCII Typewriter */
|
||||
{ "tam", KBD_TAMIL }, /* Tamil */
|
||||
{ "tel", KBD_TELUGU }, /* Telugu */
|
||||
{ "urd-phonetic", KBD_URDU }, /* Urdu, Phonetic */
|
||||
{ "urd-phonetic3", KBD_URDU }, /* Urdu, Alternative phonetic */
|
||||
{ "urd-winkeys", KBD_URDU }, /* Urdu, Winkeys */
|
||||
{ "bolnagri", KBD_HINDI_TRADITIONAL }, /* Hindi Bolnagri */
|
||||
{ "hin-wx", KBD_HINDI_TRADITIONAL }, /* Hindi Wx */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Bosnia and Herzegovina */
|
||||
static const XKB_VARIANT ba_variants[] = {
|
||||
{ "alternatequotes", KBD_BOSNIAN }, /* Use guillemets for quotes */
|
||||
{ "unicode", KBD_BOSNIAN }, /* Use Bosnian digraphs */
|
||||
{ "unicodeus", KBD_BOSNIAN }, /* US keyboard with Bosnian digraphs */
|
||||
{ "us", KBD_BOSNIAN_CYRILLIC }, /* US keyboard with Bosnian letters */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Brazil */
|
||||
static const XKB_VARIANT br_variants[] = {
|
||||
{ "nodeadkeys", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "nativo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo */
|
||||
{ "nativo-us", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for USA keyboards */
|
||||
{ "nativo-epo", KBD_PORTUGUESE_BRAZILIAN_ABNT2 }, /* Nativo for Esperanto */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Bulgaria */
|
||||
static const XKB_VARIANT bg_variants[] = {
|
||||
{ "phonetic", KBD_BULGARIAN_LATIN }, /* Traditional Phonetic */
|
||||
{ "bas_phonetic", KBD_BULGARIAN_LATIN }, /* Standard Phonetic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Morocco */
|
||||
static const XKB_VARIANT ma_variants[] = {
|
||||
{ "french", KBD_FRENCH }, /* French */
|
||||
{ "tifinagh", 0 }, /* Tifinagh */
|
||||
{ "tifinagh-alt", 0 }, /* Tifinagh Alternative */
|
||||
{ "tifinagh-alt-phonetic", 0 }, /* Tifinagh Alternative Phonetic */
|
||||
{ "tifinagh-extended", 0 }, /* Tifinagh Extended */
|
||||
{ "tifinagh-phonetic", 0 }, /* Tifinagh Phonetic */
|
||||
{ "tifinagh-extended-phonetic", 0 }, /* Tifinagh Extended Phonetic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Canada */
|
||||
static const XKB_VARIANT ca_variants[] = {
|
||||
{ "fr", KBD_CANADIAN_FRENCH }, /* French Dvorak */
|
||||
{ "fr-dvorak", KBD_UNITED_STATES_DVORAK }, /* French Dvorak */
|
||||
{ "fr-legacy", KBD_CANADIAN_FRENCH_LEGACY }, /* French (legacy) */
|
||||
{ "multix", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual */
|
||||
{ "multi", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, first part */
|
||||
{ "multi-2gr", KBD_CANADIAN_MULTILINGUAL_STANDARD }, /* Multilingual, second part */
|
||||
{ "ike", KBD_INUKTITUT_LATIN }, /* Inuktitut */
|
||||
{ "shs" /* codespell:ignore shs */, 0 }, /* Secwepemctsin */
|
||||
{ "kut", 0 }, /* Ktunaxa */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* China */
|
||||
static const XKB_VARIANT cn_variants[] = {
|
||||
{ "tib", 0 }, /* Tibetan */
|
||||
{ "tib_asciinum", 0 }, /* Tibetan (with ASCII numerals) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Croatia */
|
||||
static const XKB_VARIANT hr_variants[] = {
|
||||
{ "alternatequotes", KBD_CROATIAN }, /* Use guillemets for quotes */
|
||||
{ "unicode", KBD_CROATIAN }, /* Use Croatian digraphs */
|
||||
{ "unicodeus", KBD_CROATIAN }, /* US keyboard with Croatian digraphs */
|
||||
{ "us", KBD_CROATIAN }, /* US keyboard with Croatian letters */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Czechia */
|
||||
static const XKB_VARIANT cz_variants[] = {
|
||||
{ "bksl", KBD_CZECH_PROGRAMMERS }, /* With <\|> key */
|
||||
{ "qwerty", KBD_CZECH_QWERTY }, /* qwerty */
|
||||
{ "qwerty_bksl", KBD_CZECH_QWERTY }, /* qwerty, extended Backslash */
|
||||
{ "ucw", KBD_CZECH }, /* UCW layout (accented letters only) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Denmark */
|
||||
static const XKB_VARIANT dk_variants[] = {
|
||||
{ "nodeadkeys", KBD_DANISH }, /* Eliminate dead keys */
|
||||
{ "mac", KBD_DANISH }, /* Macintosh */
|
||||
{ "mac_nodeadkeys", KBD_DANISH }, /* Macintosh, eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Netherlands */
|
||||
static const XKB_VARIANT nl_variants[] = {
|
||||
{ "sundeadkeys", KBD_SWISS_FRENCH }, /* Sun dead keys */
|
||||
{ "mac", KBD_SWISS_FRENCH }, /* Macintosh */
|
||||
{ "std", KBD_SWISS_FRENCH }, /* Standard */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Estonia */
|
||||
static const XKB_VARIANT ee_variants[] = {
|
||||
{ "nodeadkeys", KBD_US }, /* Eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Estonian letters */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Iran */
|
||||
static const XKB_VARIANT ir_variants[] = {
|
||||
{ "pro", 0 }, /* Pro */
|
||||
{ "keypad", 0 }, /* Keypad */
|
||||
{ "pro_keypad", 0 }, /* Pro Keypad */
|
||||
{ "ku", 0 }, /* Kurdish, Latin Q */
|
||||
{ "ku_f", 0 }, /* Kurdish, (F) */
|
||||
{ "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
|
||||
{ "ku_ara", 0 }, /* Kurdish, Arabic-Latin */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Iraq */
|
||||
static const XKB_VARIANT iq_variants[] = {
|
||||
{ "ku", 0 }, /* Kurdish, Latin Q */
|
||||
{ "ku_f", 0 }, /* Kurdish, (F) */
|
||||
{ "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
|
||||
{ "ku_ara", 0 }, /* Kurdish, Arabic-Latin */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Faroe Islands */
|
||||
static const XKB_VARIANT fo_variants[] = {
|
||||
{ "nodeadkeys", 0 }, /* Eliminate dead keys */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Finland */
|
||||
static const XKB_VARIANT fi_variants[] = {
|
||||
{ "nodeadkeys", 0 }, /* Eliminate dead keys */
|
||||
{ "smi", 0 }, /* Northern Saami */
|
||||
{ "classic", 0 }, /* Classic */
|
||||
{ "mac", 0 }, /* Macintosh */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* France */
|
||||
static const XKB_VARIANT fr_variants[] = {
|
||||
{ "nodeadkeys", 0 }, /* Eliminate dead keys */
|
||||
{ "sundeadkeys", 0 }, /* Sun dead keys */
|
||||
{ "oss", 0 }, /* Alternative */
|
||||
{ "oss_latin9", 0 }, /* Alternative, latin-9 only */
|
||||
{ "oss_nodeadkeys", 0 }, /* Alternative, eliminate dead keys */
|
||||
{ "oss_sundeadkeys", 0 }, /* Alternative, Sun dead keys */
|
||||
{ "latin9", 0 }, /* (Legacy) Alternative */
|
||||
{ "latin9_nodeadkeys", 0 }, /* (Legacy) Alternative, eliminate dead keys */
|
||||
{ "latin9_sundeadkeys", 0 }, /* (Legacy) Alternative, Sun dead keys */
|
||||
{ "bepo", KBD_FRENCH_BEPO }, /* Bepo, ergonomic, Dvorak way */
|
||||
{ "bepo_latin9", 0 }, /* Bepo, ergonomic, Dvorak way, latin-9 only */
|
||||
{ "dvorak", 0 }, /* Dvorak */
|
||||
{ "mac", 0 }, /* Macintosh */
|
||||
{ "bre", 0 }, /* Breton */
|
||||
{ "oci", 0 }, /* Occitan */
|
||||
{ "geo", 0 }, /* Georgian AZERTY Tskapo */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Ghana */
|
||||
static const XKB_VARIANT gh_variants[] = {
|
||||
{ "generic", 0 }, /* Multilingual */
|
||||
{ "akan", 0 }, /* Akan */
|
||||
{ "ewe", 0 }, /* Ewe */
|
||||
{ "fula", 0 }, /* Fula */
|
||||
{ "ga", 0 }, /* Ga */
|
||||
{ "hausa", 0 }, /* Hausa */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Georgia */
|
||||
static const XKB_VARIANT ge_variants[] = {
|
||||
{ "ergonomic", 0 }, /* Ergonomic */
|
||||
{ "mess", 0 }, /* MESS */
|
||||
{ "ru", 0 }, /* Russian */
|
||||
{ "os", 0 }, /* Ossetian */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Germany */
|
||||
static const XKB_VARIANT de_variants[] = {
|
||||
{ "deadacute", KBD_GERMAN }, /* Dead acute */
|
||||
{ "deadgraveacute", KBD_GERMAN }, /* Dead grave acute */
|
||||
{ "nodeadkeys", KBD_GERMAN }, /* Eliminate dead keys */
|
||||
{ "ro", KBD_GERMAN }, /* Romanian keyboard with German letters */
|
||||
{ "ro_nodeadkeys",
|
||||
KBD_GERMAN }, /* Romanian keyboard with German letters, eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "sundeadkeys", KBD_GERMAN }, /* Sun dead keys */
|
||||
{ "neo", KBD_GERMAN_NEO }, /* Neo 2 */
|
||||
{ "mac", KBD_GERMAN }, /* Macintosh */
|
||||
{ "mac_nodeadkeys", KBD_GERMAN }, /* Macintosh, eliminate dead keys */
|
||||
{ "dsb", KBD_GERMAN }, /* Lower Sorbian */
|
||||
{ "dsb_qwertz", KBD_GERMAN }, /* Lower Sorbian (qwertz) */
|
||||
{ "qwerty", KBD_GERMAN_IBM }, /* qwerty */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Greece */
|
||||
static const XKB_VARIANT gr_variants[] = {
|
||||
{ "simple", KBD_GREEK_220 }, /* Simple */
|
||||
{ "extended", KBD_GREEK_319 }, /* Extended */
|
||||
{ "nodeadkeys", KBD_GREEK_319 }, /* Eliminate dead keys */
|
||||
{ "polytonic", KBD_GREEK_POLYTONIC }, /* Polytonic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Hungary */
|
||||
static const XKB_VARIANT hu_variants[] = {
|
||||
{ "standard", KBD_HUNGARIAN_101_KEY }, /* Standard */
|
||||
{ "nodeadkeys", KBD_HUNGARIAN_101_KEY }, /* Eliminate dead keys */
|
||||
{ "qwerty", KBD_HUNGARIAN_101_KEY }, /* qwerty */
|
||||
{ "101_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Dead keys */
|
||||
{ "101_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/comma/Eliminate dead keys */
|
||||
{ "101_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Dead keys */
|
||||
{ "101_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwertz/dot/Eliminate dead keys */
|
||||
{ "101_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Dead keys */
|
||||
{ "101_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/comma/Eliminate dead keys */
|
||||
{ "101_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Dead keys */
|
||||
{ "101_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 101/qwerty/dot/Eliminate dead keys */
|
||||
{ "102_qwertz_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Dead keys */
|
||||
{ "102_qwertz_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/comma/Eliminate dead keys */
|
||||
{ "102_qwertz_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Dead keys */
|
||||
{ "102_qwertz_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwertz/dot/Eliminate dead keys */
|
||||
{ "102_qwerty_comma_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Dead keys */
|
||||
{ "102_qwerty_comma_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/comma/Eliminate dead keys */
|
||||
{ "102_qwerty_dot_dead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Dead keys */
|
||||
{ "102_qwerty_dot_nodead", KBD_HUNGARIAN_101_KEY }, /* 102/qwerty/dot/Eliminate dead keys */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Iceland */
|
||||
static const XKB_VARIANT is_variants[] = {
|
||||
{ "Sundeadkeys", KBD_ICELANDIC }, /* Sun dead keys */
|
||||
{ "nodeadkeys", KBD_ICELANDIC }, /* Eliminate dead keys */
|
||||
{ "mac", KBD_ICELANDIC }, /* Macintosh */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Israel */
|
||||
static const XKB_VARIANT il_variants[] = {
|
||||
{ "lyx", KBD_HEBREW }, /* lyx */
|
||||
{ "phonetic", KBD_HEBREW }, /* Phonetic */
|
||||
{ "biblical", KBD_HEBREW }, /* Biblical Hebrew (Tiro) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Italy */
|
||||
static const XKB_VARIANT it_variants[] = {
|
||||
{ "nodeadkeys", KBD_ITALIAN_142 }, /* Eliminate dead keys */
|
||||
{ "mac", KBD_ITALIAN }, /* Macintosh */
|
||||
{ "geo", KBD_GEORGIAN }, /* Georgian */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Japan */
|
||||
static const XKB_VARIANT jp_variants[] = {
|
||||
{ "kana", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* Kana */
|
||||
{ "OADG109A", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 }, /* OADG 109A */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Kyrgyzstan */
|
||||
static const XKB_VARIANT kg_variants[] = {
|
||||
{ "phonetic", KBD_KYRGYZ_CYRILLIC }, /* Phonetic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Kazakhstan */
|
||||
static const XKB_VARIANT kz_variants[] = {
|
||||
{ "ruskaz", KBD_KAZAKH }, /* Russian with Kazakh */
|
||||
{ "kazrus", KBD_KAZAKH }, /* Kazakh with Russian */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Latin America */
|
||||
static const XKB_VARIANT latam_variants[] = {
|
||||
{ "nodeadkeys", KBD_LATIN_AMERICAN }, /* Eliminate dead keys */
|
||||
{ "deadtilde", KBD_LATIN_AMERICAN }, /* Include dead tilde */
|
||||
{ "sundeadkeys", KBD_LATIN_AMERICAN }, /* Sun dead keys */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Lithuania */
|
||||
static const XKB_VARIANT lt_variants[] = {
|
||||
{ "std", KBD_LITHUANIAN }, /* Standard */
|
||||
{ "us", KBD_LITHUANIAN_IBM }, /* US keyboard with Lithuanian letters */
|
||||
{ "ibm", KBD_LITHUANIAN_IBM }, /* IBM (LST 1205-92) */
|
||||
{ "lekp", KBD_LITHUANIAN }, /* LEKP */
|
||||
{ "lekpa", KBD_LITHUANIAN }, /* LEKPa */
|
||||
{ "balticplus", KBD_LITHUANIAN }, /* Baltic+ */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Latvia */
|
||||
static const XKB_VARIANT lv_variants[] = {
|
||||
{ "apostrophe", KBD_LATVIAN }, /* Apostrophe (') variant */
|
||||
{ "tilde", KBD_LATVIAN }, /* Tilde (~) variant */
|
||||
{ "fkey", KBD_LATVIAN }, /* F-letter (F) variant */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Montenegro */
|
||||
static const XKB_VARIANT me_variants[] = {
|
||||
{ "cyrillic", 0 }, /* Cyrillic */
|
||||
{ "cyrillicyz", 0 }, /* Cyrillic, Z and ZHE swapped */
|
||||
{ "latinunicode", 0 }, /* Latin unicode */
|
||||
{ "latinyz", 0 }, /* Latin qwerty */
|
||||
{ "latinunicodeyz", 0 }, /* Latin unicode qwerty */
|
||||
{ "cyrillicalternatequotes", 0 }, /* Cyrillic with guillemets */
|
||||
{ "latinalternatequotes", 0 }, /* Latin with guillemets */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Macedonia */
|
||||
static const XKB_VARIANT mk_variants[] = {
|
||||
{ "nodeadkeys", KBD_FYRO_MACEDONIAN }, /* Eliminate dead keys */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Malta */
|
||||
static const XKB_VARIANT mt_variants[] = {
|
||||
{ "us", KBD_MALTESE_48_KEY }, /* Maltese keyboard with US layout */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Norway */
|
||||
static const XKB_VARIANT no_variants[] = {
|
||||
{ "nodeadkeys", KBD_NORWEGIAN }, /* Eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "smi", KBD_NORWEGIAN_WITH_SAMI }, /* Northern Saami */
|
||||
{ "smi_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Northern Saami, eliminate dead keys */
|
||||
{ "mac", KBD_NORWEGIAN }, /* Macintosh */
|
||||
{ "mac_nodeadkeys", KBD_SAMI_EXTENDED_NORWAY }, /* Macintosh, eliminate dead keys */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Poland */
|
||||
static const XKB_VARIANT pl_variants[] = {
|
||||
{ "qwertz", KBD_POLISH_214 }, /* qwertz */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "dvorak_quotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on quotemark key */
|
||||
{ "dvorak_altquotes", KBD_UNITED_STATES_DVORAK }, /* Dvorak, Polish quotes on key 1 */
|
||||
{ "csb", 0 }, /* Kashubian */
|
||||
{ "ru_phonetic_dvorak", KBD_UNITED_STATES_DVORAK }, /* Russian phonetic Dvorak */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Portugal */
|
||||
static const XKB_VARIANT pt_variants[] = {
|
||||
{ "nodeadkeys", KBD_PORTUGUESE }, /* Eliminate dead keys */
|
||||
{ "sundeadkeys", KBD_PORTUGUESE }, /* Sun dead keys */
|
||||
{ "mac", KBD_PORTUGUESE }, /* Macintosh */
|
||||
{ "mac_nodeadkeys", KBD_PORTUGUESE }, /* Macintosh, eliminate dead keys */
|
||||
{ "mac_sundeadkeys", KBD_PORTUGUESE }, /* Macintosh, Sun dead keys */
|
||||
{ "nativo", KBD_PORTUGUESE }, /* Nativo */
|
||||
{ "nativo-us", KBD_PORTUGUESE }, /* Nativo for USA keyboards */
|
||||
{ "nativo-epo", KBD_PORTUGUESE }, /* Nativo for Esperanto */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Romania */
|
||||
static const XKB_VARIANT ro_variants[] = {
|
||||
{ "cedilla", KBD_ROMANIAN }, /* Cedilla */
|
||||
{ "std", KBD_ROMANIAN }, /* Standard */
|
||||
{ "std_cedilla", KBD_ROMANIAN }, /* Standard (Cedilla) */
|
||||
{ "winkeys", KBD_ROMANIAN }, /* Winkeys */
|
||||
{ "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
|
||||
{ "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
|
||||
{ "crh_dobruca1", KBD_TATAR }, /* Crimean Tatar (Dobruca-1 Q) */
|
||||
{ "crh_dobruca2", KBD_TATAR }, /* Crimean Tatar (Dobruca-2 Q) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Russia */
|
||||
static const XKB_VARIANT ru_variants[] = {
|
||||
{ "phonetic", KBD_RUSSIAN }, /* Phonetic */
|
||||
{ "phonetic_winkeys", KBD_RUSSIAN }, /* Phonetic Winkeys */
|
||||
{ "typewriter", KBD_RUSSIAN_TYPEWRITER }, /* Typewriter */
|
||||
{ "legacy", KBD_RUSSIAN }, /* Legacy */
|
||||
{ "tt", KBD_TATAR }, /* Tatar */
|
||||
{ "os_legacy", 0 }, /* Ossetian, legacy */
|
||||
{ "os_winkeys", 0 }, /* Ossetian, Winkeys */
|
||||
{ "cv", 0 }, /* Chuvash */
|
||||
{ "cv_latin", 0 }, /* Chuvash Latin */
|
||||
{ "udm", 0 }, /* Udmurt */
|
||||
{ "kom", 0 }, /* Komi */
|
||||
{ "sah", 0 }, /* Yakut */
|
||||
{ "xal", 0 }, /* Kalmyk */
|
||||
{ "dos", 0 }, /* DOS */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Serbia */
|
||||
static const XKB_VARIANT rs_variants[] = {
|
||||
{ "yz", KBD_SERBIAN_CYRILLIC }, /* Z and ZHE swapped */
|
||||
{ "latin", KBD_SERBIAN_LATIN }, /* Latin */
|
||||
{ "latinunicode", KBD_SERBIAN_LATIN }, /* Latin Unicode */
|
||||
{ "latinyz", KBD_SERBIAN_LATIN }, /* Latin qwerty */
|
||||
{ "latinunicodeyz", KBD_SERBIAN_LATIN }, /* Latin Unicode qwerty */
|
||||
{ "alternatequotes", KBD_SERBIAN_CYRILLIC }, /* With guillemets */
|
||||
{ "latinalternatequotes", KBD_SERBIAN_LATIN }, /* Latin with guillemets */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Slovenia */
|
||||
static const XKB_VARIANT si_variants[] = {
|
||||
{ "alternatequotes", KBD_SLOVENIAN }, /* Use guillemets for quotes */
|
||||
{ "us", KBD_UNITED_STATES_INTERNATIONAL }, /* US keyboard with Slovenian letters */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Slovakia */
|
||||
static const XKB_VARIANT sk_variants[] = {
|
||||
{ "bksl", KBD_SLOVAK }, /* Extended Backslash */
|
||||
{ "qwerty", KBD_SLOVAK_QWERTY }, /* qwerty */
|
||||
{ "qwerty_bksl", KBD_SLOVAK_QWERTY }, /* qwerty, extended Backslash */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Spain */
|
||||
static const XKB_VARIANT es_variants[] = {
|
||||
{ "nodeadkeys", KBD_SPANISH_VARIATION }, /* Eliminate dead keys */
|
||||
{ "deadtilde", KBD_SPANISH_VARIATION }, /* Include dead tilde */
|
||||
{ "sundeadkeys", KBD_SPANISH }, /* Sun dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "ast", KBD_SPANISH_VARIATION }, /* Asturian variant with bottom-dot H and bottom-dot L */
|
||||
{ "cat", KBD_SPANISH_VARIATION }, /* Catalan variant with middle-dot L */
|
||||
{ "mac", KBD_SPANISH }, /* Macintosh */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Sweden */
|
||||
static const XKB_VARIANT se_variants[] = {
|
||||
{ "nodeadkeys", KBD_SWEDISH }, /* Eliminate dead keys */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "rus", KBD_RUSSIAN }, /* Russian phonetic */
|
||||
{ "rus_nodeadkeys", KBD_RUSSIAN }, /* Russian phonetic, eliminate dead keys */
|
||||
{ "smi", KBD_SWEDISH_WITH_SAMI }, /* Northern Saami */
|
||||
{ "mac", KBD_SWEDISH }, /* Macintosh */
|
||||
{ "svdvorak", KBD_UNITED_STATES_DVORAK }, /* Svdvorak */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Switzerland */
|
||||
static const XKB_VARIANT ch_variants[] = {
|
||||
{ "de_nodeadkeys", KBD_SWISS_GERMAN }, /* German, eliminate dead keys */
|
||||
{ "de_sundeadkeys", KBD_SWISS_GERMAN }, /* German, Sun dead keys */
|
||||
{ "fr", KBD_SWISS_FRENCH }, /* French */
|
||||
{ "fr_nodeadkeys", KBD_SWISS_FRENCH }, /* French, eliminate dead keys */
|
||||
{ "fr_sundeadkeys", KBD_SWISS_FRENCH }, /* French, Sun dead keys */
|
||||
{ "fr_mac", KBD_SWISS_FRENCH }, /* French (Macintosh) */
|
||||
{ "de_mac", KBD_SWISS_GERMAN }, /* German (Macintosh) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Syria */
|
||||
static const XKB_VARIANT sy_variants[] = {
|
||||
{ "syc", KBD_SYRIAC }, /* Syriac */
|
||||
{ "syc_phonetic", KBD_SYRIAC_PHONETIC }, /* Syriac phonetic */
|
||||
{ "ku", 0 }, /* Kurdish, Latin Q */
|
||||
{ "ku_f", 0 }, /* Kurdish, (F) */
|
||||
{ "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Tajikistan */
|
||||
static const XKB_VARIANT tj_variants[] = {
|
||||
{ "legacy", 0 }, /* Legacy */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Sri Lanka */
|
||||
static const XKB_VARIANT lk_variants[] = {
|
||||
{ "tam_unicode", KBD_TAMIL }, /* Tamil Unicode */
|
||||
{ "tam_TAB", KBD_TAMIL }, /* Tamil TAB Typewriter */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Thailand */
|
||||
static const XKB_VARIANT th_variants[] = {
|
||||
{ "tis", KBD_THAI_KEDMANEE_NON_SHIFTLOCK }, /* TIS-820.2538 */
|
||||
{ "pat", KBD_THAI_PATTACHOTE }, /* Pattachote */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Turkey */
|
||||
static const XKB_VARIANT tr_variants[] = {
|
||||
{ "f", KBD_TURKISH_F }, /* (F) */
|
||||
{ "alt", KBD_TURKISH_Q }, /* Alt-Q */
|
||||
{ "sundeadkeys", KBD_TURKISH_F }, /* Sun dead keys */
|
||||
{ "ku", 0 }, /* Kurdish, Latin Q */
|
||||
{ "ku_f", 0 }, /* Kurdish, (F) */
|
||||
{ "ku_alt", 0 }, /* Kurdish, Latin Alt-Q */
|
||||
{ "intl", KBD_TURKISH_F }, /* International (with dead keys) */
|
||||
{ "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
|
||||
{ "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
|
||||
{ "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Ukraine */
|
||||
static const XKB_VARIANT ua_variants[] = {
|
||||
{ "phonetic", KBD_UKRAINIAN }, /* Phonetic */
|
||||
{ "typewriter", KBD_UKRAINIAN }, /* Typewriter */
|
||||
{ "winkeys", KBD_UKRAINIAN }, /* Winkeys */
|
||||
{ "legacy", KBD_UKRAINIAN }, /* Legacy */
|
||||
{ "rstu", KBD_UKRAINIAN }, /* Standard RSTU */
|
||||
{ "rstu_ru", KBD_UKRAINIAN }, /* Standard RSTU on Russian layout */
|
||||
{ "homophonic", KBD_UKRAINIAN }, /* Homophonic */
|
||||
{ "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
|
||||
{ "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
|
||||
{ "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* United Kingdom */
|
||||
static const XKB_VARIANT gb_variants[] = {
|
||||
{ "extd", KBD_UNITED_KINGDOM_EXTENDED }, /* Extended - Winkeys */
|
||||
{ "intl", KBD_UNITED_KINGDOM_EXTENDED }, /* International (with dead keys) */
|
||||
{ "dvorak", KBD_UNITED_STATES_DVORAK }, /* Dvorak */
|
||||
{ "dvorakukp", KBD_UNITED_STATES_DVORAK }, /* Dvorak (UK Punctuation) */
|
||||
{ "mac", KBD_UNITED_KINGDOM }, /* Macintosh */
|
||||
{ "colemak", 0 }, /* Colemak */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Uzbekistan */
|
||||
static const XKB_VARIANT uz_variants[] = {
|
||||
{ "latin", 0 }, /* Latin */
|
||||
{ "crh", KBD_TATAR }, /* Crimean Tatar (Turkish Q) */
|
||||
{ "crh_f", KBD_TURKISH_F }, /* Crimean Tatar (Turkish F) */
|
||||
{ "crh_alt", KBD_TURKISH_Q }, /* Crimean Tatar (Turkish Alt-Q) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Korea, Republic of */
|
||||
static const XKB_VARIANT kr_variants[] = {
|
||||
{ "kr104", KBD_KOREAN_INPUT_SYSTEM_IME_2000 }, /* 101/104 key Compatible */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Ireland */
|
||||
static const XKB_VARIANT ie_variants[] = {
|
||||
{ "CloGaelach", KBD_GAELIC }, /* CloGaelach */
|
||||
{ "UnicodeExpert", KBD_GAELIC }, /* UnicodeExpert */
|
||||
{ "ogam", KBD_GAELIC }, /* Ogham */
|
||||
{ "ogam_is434", KBD_GAELIC }, /* Ogham IS434 */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Pakistan */
|
||||
static const XKB_VARIANT pk_variants[] = {
|
||||
{ "urd-crulp", 0 }, /* CRULP */
|
||||
{ "urd-nla", 0 }, /* NLA */
|
||||
{ "ara", KBD_ARABIC_101 }, /* Arabic */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Esperanto */
|
||||
static const XKB_VARIANT epo_variants[] = {
|
||||
{ "legacy", 0 }, /* displaced semicolon and quote (obsolete) */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Nigeria */
|
||||
static const XKB_VARIANT ng_variants[] = {
|
||||
{ "igbo", 0 }, /* Igbo */
|
||||
{ "yoruba", 0 }, /* Yoruba */
|
||||
{ "hausa", 0 }, /* Hausa */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Braille */
|
||||
static const XKB_VARIANT brai_variants[] = {
|
||||
{ "left_hand", 0 }, /* Left hand */
|
||||
{ "right_hand", 0 }, /* Right hand */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
/* Turkmenistan */
|
||||
static const XKB_VARIANT tm_variants[] = {
|
||||
{ "alt", KBD_TURKISH_Q }, /* Alt-Q */
|
||||
{ "", 0 },
|
||||
};
|
||||
|
||||
static const XKB_LAYOUT xkbLayouts[] = {
|
||||
{ "us", KBD_US, us_variants }, /* USA */
|
||||
{ "ad", 0, nullptr }, /* Andorra */
|
||||
{ "af", KBD_FARSI, af_variants }, /* Afghanistan */
|
||||
{ "ara", KBD_ARABIC_101, ara_variants }, /* Arabic */
|
||||
{ "al", 0, nullptr }, /* Albania */
|
||||
{ "am", KBD_ARMENIAN_EASTERN, am_variants }, /* Armenia */
|
||||
{ "az", KBD_AZERI_CYRILLIC, az_variants }, /* Azerbaijan */
|
||||
{ "by", KBD_BELARUSIAN, by_variants }, /* Belarus */
|
||||
{ "be", KBD_BELGIAN_FRENCH, be_variants }, /* Belgium */
|
||||
{ "bd", KBD_BENGALI, bd_variants }, /* Bangladesh */
|
||||
{ "in", KBD_HINDI_TRADITIONAL, in_variants }, /* India */
|
||||
{ "ba", KBD_CROATIAN, ba_variants }, /* Bosnia and Herzegovina */
|
||||
{ "br", KBD_PORTUGUESE_BRAZILIAN_ABNT, br_variants }, /* Brazil */
|
||||
{ "bg", KBD_BULGARIAN_LATIN, bg_variants }, /* Bulgaria */
|
||||
{ "ma", KBD_FRENCH, ma_variants }, /* Morocco */
|
||||
{ "mm", 0, nullptr }, /* Myanmar */
|
||||
{ "ca", KBD_US, ca_variants }, /* Canada */
|
||||
{ "cd", 0, nullptr }, /* Congo, Democratic Republic of the */
|
||||
{ "cn", KBD_CHINESE_TRADITIONAL_PHONETIC, cn_variants }, /* China */
|
||||
{ "hr", KBD_CROATIAN, hr_variants }, /* Croatia */
|
||||
{ "cz", KBD_CZECH, cz_variants }, /* Czechia */
|
||||
{ "dk", KBD_DANISH, dk_variants }, /* Denmark */
|
||||
{ "nl", KBD_DUTCH, nl_variants }, /* Netherlands */
|
||||
{ "bt", 0, nullptr }, /* Bhutan */
|
||||
{ "ee", KBD_ESTONIAN, ee_variants }, /* Estonia */
|
||||
{ "ir", 0, ir_variants }, /* Iran */
|
||||
{ "iq", 0, iq_variants }, /* Iraq */
|
||||
{ "fo", 0, fo_variants }, /* Faroe Islands */
|
||||
{ "fi", KBD_FINNISH, fi_variants }, /* Finland */
|
||||
{ "fr", KBD_FRENCH, fr_variants }, /* France */
|
||||
{ "gh", 0, gh_variants }, /* Ghana */
|
||||
{ "gn", 0, nullptr }, /* Guinea */
|
||||
{ "ge", KBD_GEORGIAN, ge_variants }, /* Georgia */
|
||||
{ "at", KBD_GERMAN, de_variants }, /* Austria */
|
||||
{ "de", KBD_GERMAN, de_variants }, /* Germany */
|
||||
{ "gr", KBD_GREEK, gr_variants }, /* Greece */
|
||||
{ "hu", KBD_HUNGARIAN, hu_variants }, /* Hungary */
|
||||
{ "is", KBD_ICELANDIC, is_variants }, /* Iceland */
|
||||
{ "il", KBD_HEBREW, il_variants }, /* Israel */
|
||||
{ "it", KBD_ITALIAN, it_variants }, /* Italy */
|
||||
{ "jp", KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, jp_variants }, /* Japan */
|
||||
{ "kg", 0, kg_variants }, /* Kyrgyzstan */
|
||||
{ "kh", 0, nullptr }, /* Cambodia */
|
||||
{ "kz", KBD_KAZAKH, kz_variants }, /* Kazakhstan */
|
||||
{ "la", 0, nullptr }, /* Laos */
|
||||
{ "latam", KBD_LATIN_AMERICAN, latam_variants }, /* Latin America */
|
||||
{ "lt", KBD_LITHUANIAN, lt_variants }, /* Lithuania */
|
||||
{ "lv", KBD_LATVIAN, lv_variants }, /* Latvia */
|
||||
{ "mao", KBD_MAORI, nullptr }, /* Maori */
|
||||
{ "me", KBD_SERBIAN_LATIN, me_variants }, /* Montenegro */
|
||||
{ "mk", KBD_FYRO_MACEDONIAN, mk_variants }, /* Macedonia */
|
||||
{ "mt", KBD_MALTESE_48_KEY, mt_variants }, /* Malta */
|
||||
{ "mn", KBD_MONGOLIAN_CYRILLIC, nullptr }, /* Mongolia */
|
||||
{ "no", KBD_NORWEGIAN, no_variants }, /* Norway */
|
||||
{ "pl", KBD_POLISH_PROGRAMMERS, pl_variants }, /* Poland */
|
||||
{ "pt", KBD_PORTUGUESE, pt_variants }, /* Portugal */
|
||||
{ "ro", KBD_ROMANIAN, ro_variants }, /* Romania */
|
||||
{ "ru", KBD_RUSSIAN, ru_variants }, /* Russia */
|
||||
{ "rs", KBD_SERBIAN_LATIN, rs_variants }, /* Serbia */
|
||||
{ "si", KBD_SLOVENIAN, si_variants }, /* Slovenia */
|
||||
{ "sk", KBD_SLOVAK, sk_variants }, /* Slovakia */
|
||||
{ "es", KBD_SPANISH, es_variants }, /* Spain */
|
||||
{ "se", KBD_SWEDISH, se_variants }, /* Sweden */
|
||||
{ "ch", KBD_SWISS_GERMAN, ch_variants }, /* Switzerland */
|
||||
{ "sy", KBD_SYRIAC, sy_variants }, /* Syria */
|
||||
{ "tj", 0, tj_variants }, /* Tajikistan */
|
||||
{ "lk", 0, lk_variants }, /* Sri Lanka */
|
||||
{ "th", KBD_THAI_KEDMANEE, th_variants }, /* Thailand */
|
||||
{ "tr", KBD_TURKISH_Q, tr_variants }, /* Turkey */
|
||||
{ "ua", KBD_UKRAINIAN, ua_variants }, /* Ukraine */
|
||||
{ "gb", KBD_UNITED_KINGDOM, gb_variants }, /* United Kingdom */
|
||||
{ "uz", KBD_UZBEK_CYRILLIC, uz_variants }, /* Uzbekistan */
|
||||
{ "vn", KBD_VIETNAMESE, nullptr }, /* Vietnam */
|
||||
{ "kr", KBD_KOREAN_INPUT_SYSTEM_IME_2000, kr_variants }, /* Korea, Republic of */
|
||||
{ "ie", KBD_UNITED_KINGDOM, ie_variants }, /* Ireland */
|
||||
{ "pk", 0, pk_variants }, /* Pakistan */
|
||||
{ "mv", 0, nullptr }, /* Maldives */
|
||||
{ "za", KBD_US, nullptr }, /* South Africa */
|
||||
{ "epo", 0, epo_variants }, /* Esperanto */
|
||||
{ "np", KBD_NEPALI, nullptr }, /* Nepal */
|
||||
{ "ng", 0, ng_variants }, /* Nigeria */
|
||||
{ "et", 0, nullptr }, /* Ethiopia */
|
||||
{ "sn", 0, nullptr }, /* Senegal */
|
||||
{ "brai", 0, brai_variants }, /* Braille */
|
||||
{ "tm", KBD_TURKISH_Q, tm_variants }, /* Turkmenistan */
|
||||
};
|
||||
|
||||
static uint32_t convert(int64_t val)
|
||||
{
|
||||
WINPR_ASSERT(val <= UINT32_MAX);
|
||||
WINPR_ASSERT(val >= INT32_MIN);
|
||||
return WINPR_CXX_COMPAT_CAST(uint32_t, val);
|
||||
}
|
||||
|
||||
static UINT32 find_keyboard_layout_variant(const XKB_LAYOUT* layout, const char* variant)
|
||||
{
|
||||
WINPR_ASSERT(layout);
|
||||
WINPR_ASSERT(variant);
|
||||
|
||||
const XKB_VARIANT* variants = layout->variants;
|
||||
if (variants)
|
||||
{
|
||||
const XKB_VARIANT* var = variants;
|
||||
while (var->variant && (strlen(var->variant) != 0))
|
||||
{
|
||||
if (strcmp(var->variant, variant) == 0)
|
||||
return convert(var->keyboardLayoutID);
|
||||
var++;
|
||||
}
|
||||
}
|
||||
|
||||
return convert(layout->keyboardLayoutID);
|
||||
}
|
||||
|
||||
UINT32 find_keyboard_layout_in_xorg_rules(const char* layout, const char* variant)
|
||||
{
|
||||
if ((layout == nullptr) || (variant == nullptr))
|
||||
return 0;
|
||||
|
||||
DEBUG_KBD("xkbLayout: %s\txkbVariant: %s", layout, variant);
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(xkbLayouts); i++)
|
||||
{
|
||||
const XKB_LAYOUT* cur = &xkbLayouts[i];
|
||||
if (strcmp(cur->layout, layout) == 0)
|
||||
return find_keyboard_layout_variant(cur, variant);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
third_party/FreeRDP/libfreerdp/locale/xkb_layout_ids.h
vendored
Normal file
31
third_party/FreeRDP/libfreerdp/locale/xkb_layout_ids.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Keyboard layout ID detection from common X11 xkb keyboard layout names
|
||||
*
|
||||
* Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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_LIB_LOCALE_XKB_LAYOUT_IDS_H
|
||||
#define FREERDP_LIB_LOCALE_XKB_LAYOUT_IDS_H
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT32 find_keyboard_layout_in_xorg_rules(const char* layout, const char* variant);
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LIB_LOCALE_XKB_LAYOUT_IDS_H */
|
||||
Reference in New Issue
Block a user